@principles/pd-cli 1.154.1 → 1.155.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.
@@ -47,4 +47,25 @@ export type TrajectoryEvidenceAcquisition = {
47
47
  * - `empty_trajectory` — real session, no usable evidence rows.
48
48
  */
49
49
  export declare function acquireTrajectoryEvidenceFromDb(stateDir: string, sessionId: string | undefined, workspaceDir?: string): TrajectoryEvidenceAcquisition;
50
+ /**
51
+ * PRI-941 Option A (Owner-approved) — Codex-scoped evidence acquisition for
52
+ * `pd pain record --host codex`.
53
+ *
54
+ * Boundary discipline (PRI-940/941 audits): this function reads ONLY the
55
+ * `tool_calls` failure rows (the already-authorized PRI-624 tool-governance
56
+ * evidence surface) for the caller-supplied Codex root session. Conversation
57
+ * tables (`user_turns` / `assistant_turns`) are NEVER queried here — they
58
+ * remain ingestion-exclusive behind the G2A consent boundary — and rollout
59
+ * transcript files are never opened. Binding authority stays with the
60
+ * caller-supplied PRI-743 lineage tuple: no sessions-table check runs, so an
61
+ * `unavailable` result never carries a binding claim.
62
+ *
63
+ * Outcomes:
64
+ * - `available` — ≥1 failure row → real behavior-trace entries;
65
+ * - `trajectory_unavailable` — no trajectory.db in this workspace;
66
+ * - `evidence_read_failed` — the DB exists but cannot be opened/read;
67
+ * - `empty_trajectory` — DB readable, zero failure rows for the session
68
+ * (detail: `codex_tool_calls_empty`).
69
+ */
70
+ export declare function acquireCodexToolFailureEvidenceFromDb(stateDir: string, sessionId: string | undefined, workspaceDir?: string): TrajectoryEvidenceAcquisition;
50
71
  //# 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;;;;;;;;;;;;;;GAcG;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;IACf,OAAO,EAAE,UAAU,GAAG,YAAY,CAAC;CACpC,CAAC;AA6JN;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,6BAA6B,CAgF/B"}
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;;;;;;;;;;;;;;GAcG;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;IACf,OAAO,EAAE,UAAU,GAAG,YAAY,CAAC;CACpC,CAAC;AAqMN;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,6BAA6B,CAgF/B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,6BAA6B,CAyD/B"}
@@ -20,6 +20,51 @@ const PLACEHOLDER_SOURCE_REFS = new Set([
20
20
  'tool_call_failure:unavailable',
21
21
  'trajectory:empty',
22
22
  ]);
23
+ /**
24
+ * PRI-941 Option A — the SINGLE reader of `tool_calls` failure rows, shared by
25
+ * the OpenClaw acquisition (collectEvidenceFromDb) and the Codex-scoped
26
+ * acquisition (acquireCodexToolFailureEvidenceFromDb) so the two hosts can
27
+ * never drift. Never throws: a missing/unreadable `tool_calls` table is
28
+ * reported through `readFailed` and the caller owns placeholder handling.
29
+ */
30
+ function readToolFailureEvidence(db, sessionId, workspaceDir) {
31
+ const entries = [];
32
+ let readFailed = false;
33
+ try {
34
+ const failedToolCalls = db.prepare(`
35
+ SELECT tool_name, error_type, exit_code, result_preview, created_at
36
+ FROM (
37
+ SELECT tool_name, error_type, exit_code, result_preview, created_at
38
+ FROM tool_calls
39
+ WHERE session_id = ? AND outcome = 'failure'
40
+ ORDER BY created_at DESC
41
+ LIMIT 3
42
+ )
43
+ ORDER BY created_at ASC
44
+ `).all(sessionId);
45
+ for (const tc of failedToolCalls) {
46
+ const toolName = typeof tc.tool_name === 'string' ? tc.tool_name : 'unknown';
47
+ const errorType = typeof tc.error_type === 'string' ? tc.error_type : 'unknown';
48
+ const exitCode = tc.exit_code != null ? String(tc.exit_code) : 'N/A';
49
+ // Enhanced: append resultPreview when available. PRI-941 Owner review:
50
+ // the preview enters UNSLICED — every truncation (redact-then-bound)
51
+ // is owned by sanitizeString on the COMPLETE composed note. Pre-slicing
52
+ // here could cut a credential across the sanitizer's token-pattern
53
+ // threshold and let the fragment escape redaction.
54
+ const resultPreview = typeof tc.result_preview === 'string' ? tc.result_preview : null;
55
+ const previewSuffix = resultPreview ? ` | ${resultPreview}` : '';
56
+ const note = `Tool ${toolName} failed: ${errorType} (exitCode: ${exitCode})${previewSuffix}`;
57
+ entries.push({
58
+ sourceRef: `tool_call_failure:${String(tc.created_at ?? 'unknown')}`,
59
+ note: sanitizeString(note, workspaceDir),
60
+ });
61
+ }
62
+ }
63
+ catch {
64
+ readFailed = true;
65
+ }
66
+ return { entries, readFailed };
67
+ }
23
68
  /**
24
69
  * Collect evidence entries from an open trajectory.db for one session.
25
70
  * Shared by the typed acquisition API and the legacy array wrapper so the
@@ -95,36 +140,26 @@ function collectEvidenceFromDb(db, sessionId, workspaceDir) {
95
140
  }
96
141
  // PRI-358: Try to read failed tool_calls (last 3 failures, chronological order)
97
142
  try {
98
- const failedToolCalls = db.prepare(`
99
- SELECT tool_name, error_type, exit_code, result_preview, created_at
100
- FROM (
101
- SELECT tool_name, error_type, exit_code, result_preview, created_at
102
- FROM tool_calls
103
- WHERE session_id = ? AND outcome = 'failure'
104
- ORDER BY created_at DESC
105
- LIMIT 3
106
- )
107
- ORDER BY created_at ASC
108
- `).all(sessionId);
109
- for (const tc of failedToolCalls) {
143
+ const toolFailure = readToolFailureEvidence(db, sessionId, workspaceDir);
144
+ for (const entry of toolFailure.entries) {
110
145
  if (evidence.length >= MAX_EVIDENCE_ENTRIES)
111
146
  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
- });
147
+ evidence.push(entry);
148
+ }
149
+ if (toolFailure.readFailed) {
150
+ readFailed = true;
151
+ // tool_calls table may not exist — degrade gracefully (only when no other evidence)
152
+ if (evidence.length === 0) {
153
+ evidence.push({
154
+ sourceRef: 'tool_call_failure:unavailable',
155
+ note: 'trajectory_tool_calls_unavailable',
156
+ });
157
+ }
123
158
  }
124
159
  }
125
160
  catch {
161
+ // defensive: readToolFailureEvidence never throws (internally caught)
126
162
  readFailed = true;
127
- // tool_calls table may not exist — degrade gracefully (only when no other evidence)
128
163
  if (evidence.length === 0) {
129
164
  evidence.push({
130
165
  sourceRef: 'tool_call_failure:unavailable',
@@ -236,4 +271,81 @@ export function acquireTrajectoryEvidenceFromDb(stateDir, sessionId, workspaceDi
236
271
  db.close();
237
272
  }
238
273
  }
274
+ /**
275
+ * PRI-941 Option A (Owner-approved) — Codex-scoped evidence acquisition for
276
+ * `pd pain record --host codex`.
277
+ *
278
+ * Boundary discipline (PRI-940/941 audits): this function reads ONLY the
279
+ * `tool_calls` failure rows (the already-authorized PRI-624 tool-governance
280
+ * evidence surface) for the caller-supplied Codex root session. Conversation
281
+ * tables (`user_turns` / `assistant_turns`) are NEVER queried here — they
282
+ * remain ingestion-exclusive behind the G2A consent boundary — and rollout
283
+ * transcript files are never opened. Binding authority stays with the
284
+ * caller-supplied PRI-743 lineage tuple: no sessions-table check runs, so an
285
+ * `unavailable` result never carries a binding claim.
286
+ *
287
+ * Outcomes:
288
+ * - `available` — ≥1 failure row → real behavior-trace entries;
289
+ * - `trajectory_unavailable` — no trajectory.db in this workspace;
290
+ * - `evidence_read_failed` — the DB exists but cannot be opened/read;
291
+ * - `empty_trajectory` — DB readable, zero failure rows for the session
292
+ * (detail: `codex_tool_calls_empty`).
293
+ */
294
+ export function acquireCodexToolFailureEvidenceFromDb(stateDir, sessionId, workspaceDir) {
295
+ if (!sessionId || sessionId === 'cli' || sessionId === 'unknown') {
296
+ return {
297
+ status: 'unavailable',
298
+ reasonCode: 'session_not_found',
299
+ detail: sessionId ? `sentinel_session_id:${sessionId}` : 'missing_session_id',
300
+ binding: 'unverified',
301
+ };
302
+ }
303
+ const dbPath = path.join(stateDir, 'trajectory.db');
304
+ if (!fs.existsSync(dbPath)) {
305
+ return {
306
+ status: 'unavailable',
307
+ reasonCode: 'trajectory_unavailable',
308
+ detail: 'trajectory_db_missing',
309
+ binding: 'unverified',
310
+ };
311
+ }
312
+ let db;
313
+ try {
314
+ db = new Database(dbPath, { readonly: true });
315
+ }
316
+ catch (err) {
317
+ return {
318
+ status: 'unavailable',
319
+ reasonCode: 'evidence_read_failed',
320
+ detail: `trajectory_db_unreadable: ${err instanceof Error ? err.message : String(err)}`,
321
+ binding: 'unverified',
322
+ };
323
+ }
324
+ try {
325
+ const toolFailure = readToolFailureEvidence(db, sessionId, workspaceDir);
326
+ // PRI-941 review F2 (rc-9 precision): a missing/unreadable tool_calls
327
+ // table is a DIFFERENT fact from "zero failure rows" — report it as
328
+ // evidence_read_failed, mirroring the sibling OpenClaw acquisition.
329
+ if (toolFailure.readFailed) {
330
+ return {
331
+ status: 'unavailable',
332
+ reasonCode: 'evidence_read_failed',
333
+ detail: 'codex_tool_calls_unreadable',
334
+ binding: 'unverified',
335
+ };
336
+ }
337
+ if (toolFailure.entries.length === 0) {
338
+ return {
339
+ status: 'unavailable',
340
+ reasonCode: 'empty_trajectory',
341
+ detail: 'codex_tool_calls_empty',
342
+ binding: 'unverified',
343
+ };
344
+ }
345
+ return { status: 'available', entries: toolFailure.entries };
346
+ }
347
+ finally {
348
+ db.close();
349
+ }
350
+ }
239
351
  //# sourceMappingURL=build-trajectory-evidence.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-trajectory-evidence.js","sourceRoot":"","sources":["../../src/commands/build-trajectory-evidence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-trajectory-evidence.js","sourceRoot":"","sources":["../../src/commands/build-trajectory-evidence.ts"],"names":[],"mappings":"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"}
@@ -95,10 +95,12 @@ export declare function handleCandidateReview(opts: CandidateReviewOptions): Pro
95
95
  /**
96
96
  * pd candidate audit --workspace <path> [--json]
97
97
  *
98
- * Reads workspace/.pd/state.db principle_candidates and
99
- * the workspace ledger (same file used by OpenClaw plugin).
100
- * Checks each consumed candidate has a ledger entry.
101
- * Exits non-zero if any consumed candidate is missing from ledger.
98
+ * Delegates the judgment to the core auditCandidateLedgerConsistency so every
99
+ * surface (pd candidate audit, pd health, operator health) applies the SAME
100
+ * reuse-aware rules (PRI-917 / R7): reuse resolutions and non-Principle-Ledger
101
+ * kinds are not "missing"; only a consumed principle-kind candidate with no
102
+ * resolution anywhere is true drift.
103
+ * Exits non-zero if any consumed candidate is truly missing from the ledger.
102
104
  */
103
105
  export declare function handleCandidateAudit(opts: CandidateAuditOptions): Promise<void>;
104
106
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"candidate.d.ts","sourceRoot":"","sources":["../../src/commands/candidate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"candidate.d.ts","sourceRoot":"","sources":["../../src/commands/candidate.ts"],"names":[],"mappings":"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"}
@@ -14,14 +14,15 @@
14
14
  */
15
15
  import { randomUUID } from 'crypto';
16
16
  import * as path from 'path';
17
- import { RuntimeStateManager, SqliteConnection, candidateList, candidateShow, CandidateIntakeService, CandidateIntakeError, INTAKE_ERROR_CODES, decideInternalizationRoute, buildDreamerSeedFromCandidate, findExistingDreamerTask, parseSeedSourcePainId, PrincipleTreeLedgerAdapter,
17
+ import { RuntimeStateManager, candidateList, candidateShow, CandidateIntakeService, CandidateIntakeError, INTAKE_ERROR_CODES, decideInternalizationRoute, buildDreamerSeedFromCandidate, findExistingDreamerTask, parseSeedSourcePainId, PrincipleTreeLedgerAdapter,
18
18
  // PRI-917 PR3A: the review surface consumes the SAME proposal/semantics
19
19
  // machinery as the intake gate (audit C4 — one implementation, no drift).
20
- buildReuseProposal, buildReuseShortlist, extractIntakeRecommendation, isPrincipleLedgerEligibleKind, resolveOwnerIdentity, defaultOwnerIdentityHomeDir, ReuseEvaluationRunner, ReuseEvaluationError, } from '@principles/core/runtime-v2';
20
+ buildReuseProposal, buildReuseShortlist, extractIntakeRecommendation, isPrincipleLedgerEligibleKind, resolveOwnerIdentity, defaultOwnerIdentityHomeDir, ReuseEvaluationRunner, ReuseEvaluationError, createBridgeTelemetryEventEmitter, auditCandidateLedgerConsistency, } from '@principles/core/runtime-v2';
21
21
  import { loadLedger, getLedgerFilePathPublic } from '@principles/core/principle-tree-ledger';
22
22
  import { resolveWorkspaceDir } from '../resolve-workspace.js';
23
23
  import { createWorkspaceTelemetryEmitter } from '../services/workspace-telemetry.js';
24
24
  import { loadPdConfig } from '../services/pd-config-loader.js';
25
+ import { createReuseGatedIntakeService } from '../services/reuse-gated-intake.js';
25
26
  import { resolveRuntimeAdapterFromConfig } from '../services/runtime-adapter-resolver.js';
26
27
  import { resolvePromptFullPipelineSeedMode } from '../services/pd-config-loader.js';
27
28
  import { createRemediationResult, remediationAction } from './remediation-output.js';
@@ -456,6 +457,60 @@ async function reportReuseResolution(opts) {
456
457
  console.log(` Candidate Status: ${consumedState === 'already_consumed' ? 'already consumed (INV-R07 replay)' : 'consumed'}`);
457
458
  console.log(' Evidence: recorded on the Principle\'s reuseEvidence (append-only)\n');
458
459
  }
460
+ // ── Shared park reporting (R7 gate-bypass fix, adhoc-20261007) ────────────────
461
+ /**
462
+ * Emit the park observation (`reuse_gate_triggered`) on the durable
463
+ * workspace telemetry sink, mirroring the bridge / diagnose / pain-retry
464
+ * paths (PRI-939 Option A). A manual-command park must be observable in the
465
+ * same place the automatic ones are — telemetry is how parked candidates are
466
+ * audited (R7 Wave-2 gate audit).
467
+ */
468
+ function emitReuseGateParkedTelemetry(workspaceDir, candidateId, recommended) {
469
+ createBridgeTelemetryEventEmitter(createWorkspaceTelemetryEmitter(workspaceDir)).emitTelemetry({
470
+ eventType: 'reuse_gate_triggered',
471
+ traceId: candidateId,
472
+ timestamp: new Date().toISOString(),
473
+ payload: {
474
+ candidateId,
475
+ ...(recommended?.selectedPrincipleId !== undefined ? { selectedPrincipleId: recommended.selectedPrincipleId } : {}),
476
+ ...(recommended ? { confidence: recommended.confidence, recommendation: recommended.recommendation } : {}),
477
+ },
478
+ });
479
+ }
480
+ /**
481
+ * Report a `reuse_pending_owner` intake result from the MANUAL paths
482
+ * (`pd candidate intake` / `pd candidate repair`): the gate suspects a
483
+ * semantic duplicate, so nothing was written and the candidate awaits the
484
+ * Owner. Exit code stays 0 — a park is the gate working, not a command
485
+ * failure (same posture as diagnose / pain-retry / the bridge: park is not
486
+ * counted as intake failure). cli-6: the result carries a structured reason
487
+ * and the executable next action (`pd candidate review --decide`).
488
+ */
489
+ function reportReusePark(opts) {
490
+ const recommended = opts.result.reuseRecommendation?.status === 'recommended' ? opts.result.reuseRecommendation : undefined;
491
+ emitReuseGateParkedTelemetry(opts.workspaceDir, opts.candidateId, recommended);
492
+ const review = {
493
+ candidateId: opts.candidateId,
494
+ status: 'review_required',
495
+ reason: 'reuse_review_required',
496
+ reusedPrincipleId: recommended?.selectedPrincipleId,
497
+ ...(recommended ? { confidence: recommended.confidence } : {}),
498
+ message: opts.result.message,
499
+ nextAction: `pd candidate review --candidate-id ${opts.candidateId} --decide reuse|create --reason "..."`,
500
+ };
501
+ if (opts.json) {
502
+ console.log(JSON.stringify(review, null, 2));
503
+ return;
504
+ }
505
+ console.log(`\nPrinciple Candidate ${opts.commandLabel}: ${opts.candidateId} — reuse review required\n`);
506
+ console.log(` Candidate: ${opts.candidateId}`);
507
+ if (recommended?.selectedPrincipleId !== undefined) {
508
+ console.log(` Suspected Duplicate Of: ${recommended.selectedPrincipleId} (confidence ${recommended.confidence})`);
509
+ }
510
+ console.log(` Status: review_required (no Principle was created)`);
511
+ console.log(` Message: ${review.message}`);
512
+ console.log(` Next Action: ${review.nextAction}\n`);
513
+ }
459
514
  async function evaluateReuseProposal(workspaceDir, claim, entries) {
460
515
  const configLoad = loadPdConfig(workspaceDir);
461
516
  const effective = configLoad.ok ? configLoad.effective : configLoad.defaults;
@@ -640,7 +695,12 @@ export async function handleCandidateIntake(opts) {
640
695
  try {
641
696
  await stateManager.initialize();
642
697
  const ledgerAdapter = new PrincipleTreeLedgerAdapter({ stateDir: path.join(workspaceDir, '.state') });
643
- const service = new CandidateIntakeService({ stateManager, ledgerAdapter });
698
+ // R7 gate-bypass fix (adhoc-20261007): construct through the shared gated
699
+ // assembly so the manual intake path runs the Reuse Review Gate exactly
700
+ // like diagnose / pain-retry / the bridge. A bare construction left
701
+ // reuseCheck='not_configured' and let semantic duplicates go straight to
702
+ // CREATE (R7 Wave-2 audit D-1, P0).
703
+ const service = createReuseGatedIntakeService({ stateManager, ledgerAdapter, workspaceDir });
644
704
  // Fetch candidate once for admission gate check and downstream paths.
645
705
  const candidate = await stateManager.getCandidate(opts.candidateId);
646
706
  if (!candidate) {
@@ -721,6 +781,20 @@ export async function handleCandidateIntake(opts) {
721
781
  await reportReuseResolution({ stateManager, candidateId: opts.candidateId, result: intakeResult, json: opts.json === true });
722
782
  return;
723
783
  }
784
+ if (intakeResult.outcome === 'refused' && intakeResult.reason === 'reuse_pending_owner') {
785
+ // R7 gate-bypass fix: the Reuse Review Gate parked this candidate as a
786
+ // suspected duplicate. No ledger entry was written and the candidate
787
+ // stays pending for the Owner — do NOT mark it consumed. cli-5: this
788
+ // path performs no state mutation at all.
789
+ reportReusePark({
790
+ workspaceDir,
791
+ candidateId: opts.candidateId,
792
+ result: intakeResult,
793
+ json: opts.json === true,
794
+ commandLabel: 'Intake',
795
+ });
796
+ return;
797
+ }
724
798
  if (intakeResult.outcome === 'refused') {
725
799
  throw new CandidateIntakeError(INTAKE_ERROR_CODES.INPUT_INVALID, `Principle Ledger write refused: ${intakeResult.message}`, { candidateId: opts.candidateId, reason: intakeResult.reason });
726
800
  }
@@ -1028,35 +1102,32 @@ export async function handleCandidateReview(opts) {
1028
1102
  /**
1029
1103
  * pd candidate audit --workspace <path> [--json]
1030
1104
  *
1031
- * Reads workspace/.pd/state.db principle_candidates and
1032
- * the workspace ledger (same file used by OpenClaw plugin).
1033
- * Checks each consumed candidate has a ledger entry.
1034
- * Exits non-zero if any consumed candidate is missing from ledger.
1105
+ * Delegates the judgment to the core auditCandidateLedgerConsistency so every
1106
+ * surface (pd candidate audit, pd health, operator health) applies the SAME
1107
+ * reuse-aware rules (PRI-917 / R7): reuse resolutions and non-Principle-Ledger
1108
+ * kinds are not "missing"; only a consumed principle-kind candidate with no
1109
+ * resolution anywhere is true drift.
1110
+ * Exits non-zero if any consumed candidate is truly missing from the ledger.
1035
1111
  */
1036
1112
  export async function handleCandidateAudit(opts) {
1037
1113
  const workspaceDir = resolveWorkspaceDir(opts.workspace);
1038
- let conn;
1039
1114
  try {
1040
1115
  const dbPath = path.join(workspaceDir, '.pd', 'state.db');
1041
1116
  const ledgerStateDir = path.join(workspaceDir, '.state');
1042
1117
  const ledgerPath = getLedgerFilePathPublic(ledgerStateDir);
1043
- conn = new SqliteConnection({ workspaceDir, readonly: true });
1044
- const db = conn.getDb();
1045
- const consumedRows = db.prepare("SELECT candidate_id FROM principle_candidates WHERE status = 'consumed'").all();
1046
- const consumedIds = consumedRows.map(r => r.candidate_id);
1047
- const ledger = loadLedger(ledgerStateDir);
1048
- const ledgerPrinciples = ledger.tree.principles;
1049
- const missingLedgerEntryIds = [];
1050
- for (const candidateId of consumedIds) {
1051
- const found = Object.values(ledgerPrinciples).some((p) => p.derivedFromPainIds.includes(candidateId));
1052
- if (!found) {
1053
- missingLedgerEntryIds.push(candidateId);
1054
- }
1118
+ const audit = await auditCandidateLedgerConsistency(workspaceDir);
1119
+ if (audit.status === 'error') {
1120
+ console.error(`Audit failed: ${audit.reason ?? 'could not read candidate/ledger state'}`);
1121
+ console.error('Next action: open this workspace once with the PD runtime to create/migrate state.db, then retry the audit.');
1122
+ process.exit(1);
1123
+ return;
1055
1124
  }
1056
1125
  const result = {
1057
- status: missingLedgerEntryIds.length === 0 ? 'ok' : 'degraded',
1058
- consumedCount: consumedIds.length,
1059
- missingLedgerEntryIds,
1126
+ status: audit.status,
1127
+ consumedCount: audit.consumedCount,
1128
+ missingLedgerEntryIds: audit.missingLedgerEntryIds ?? [],
1129
+ reusedResolvedCount: audit.reusedResolvedCount ?? 0,
1130
+ nonLedgerKindCount: audit.nonLedgerKindCount ?? 0,
1060
1131
  checkedLedgerPath: ledgerPath,
1061
1132
  checkedDbPath: dbPath,
1062
1133
  };
@@ -1066,6 +1137,8 @@ export async function handleCandidateAudit(opts) {
1066
1137
  else {
1067
1138
  console.log(`\nCandidate Audit Results\n`);
1068
1139
  console.log(` consumedCount: ${result.consumedCount}`);
1140
+ console.log(` reusedResolvedCount: ${result.reusedResolvedCount}`);
1141
+ console.log(` nonLedgerKindCount: ${result.nonLedgerKindCount}`);
1069
1142
  console.log(` checkedLedgerPath: ${result.checkedLedgerPath}`);
1070
1143
  console.log(` checkedDbPath: ${result.checkedDbPath}`);
1071
1144
  console.log(` status: ${result.status}`);
@@ -1074,7 +1147,7 @@ export async function handleCandidateAudit(opts) {
1074
1147
  result.missingLedgerEntryIds.forEach(id => console.log(` - ${id}`));
1075
1148
  }
1076
1149
  else {
1077
- console.log(`\n All consumed candidates have ledger entries.`);
1150
+ console.log(`\n All consumed candidates have ledger resolutions.`);
1078
1151
  }
1079
1152
  console.log('');
1080
1153
  }
@@ -1086,12 +1159,6 @@ export async function handleCandidateAudit(opts) {
1086
1159
  console.error(`Audit failed: ${err instanceof Error ? err.message : String(err)}`);
1087
1160
  process.exit(1);
1088
1161
  }
1089
- finally {
1090
- try {
1091
- conn?.close();
1092
- }
1093
- catch { /* best-effort close */ }
1094
- }
1095
1162
  }
1096
1163
  // ── Repair ─────────────────────────────────────────────────────────────────────
1097
1164
  /**
@@ -1142,7 +1209,11 @@ export async function handleCandidateRepair(opts) {
1142
1209
  return;
1143
1210
  }
1144
1211
  const ledgerAdapter = new PrincipleTreeLedgerAdapter({ stateDir: path.join(workspaceDir, '.state') });
1145
- const service = new CandidateIntakeService({ stateManager, ledgerAdapter });
1212
+ // R7 gate-bypass fix (adhoc-20261007): repair re-intakes through the same
1213
+ // gated assembly — otherwise "restore the missing ledger entry" became an
1214
+ // unconditional duplicate-CREATE for orphaned cleanup candidates (R7
1215
+ // Wave-2 audit D-1 §3.3).
1216
+ const service = createReuseGatedIntakeService({ stateManager, ledgerAdapter, workspaceDir });
1146
1217
  // Check if already in ledger
1147
1218
  const existing = ledgerAdapter.existsForCandidate(opts.candidateId);
1148
1219
  if (existing) {
@@ -1168,6 +1239,20 @@ export async function handleCandidateRepair(opts) {
1168
1239
  // a write-boundary refusal means the candidate is not principle-eligible —
1169
1240
  // fail loud rather than reporting a "repaired" entry that does not exist.
1170
1241
  const intakeResult = await service.intake(opts.candidateId);
1242
+ if (intakeResult.outcome === 'refused' && intakeResult.reason === 'reuse_pending_owner') {
1243
+ // R7 gate-bypass fix: the gate suspects a semantic duplicate — restoring
1244
+ // the entry would recreate a near-duplicate Principle. No write happened;
1245
+ // the Owner resolves it via the review channel. cli-5: no mutation on
1246
+ // this path (candidate stays consumed, ledger untouched).
1247
+ reportReusePark({
1248
+ workspaceDir,
1249
+ candidateId: opts.candidateId,
1250
+ result: intakeResult,
1251
+ json: opts.json === true,
1252
+ commandLabel: 'Repair',
1253
+ });
1254
+ return;
1255
+ }
1171
1256
  if (intakeResult.outcome === 'refused') {
1172
1257
  throw new CandidateIntakeError(INTAKE_ERROR_CODES.INPUT_INVALID, `Ledger repair refused: ${intakeResult.message}`, { candidateId: opts.candidateId, reason: intakeResult.reason });
1173
1258
  }
@@ -1357,7 +1442,11 @@ export async function handleCandidateInternalizationBackfill(opts) {
1357
1442
  }
1358
1443
  }
1359
1444
  const ledgerAdapter = new PrincipleTreeLedgerAdapter({ stateDir: path.join(workspaceDir, '.state') });
1360
- const intakeService = new CandidateIntakeService({ stateManager, ledgerAdapter });
1445
+ // R7 gate-bypass fix (adhoc-20261007): --include-pending intakes parked
1446
+ // (reuse_review_required) candidates too — the worst bypass, because it
1447
+ // consumed the very state the gate created to await the Owner (R7 Wave-2
1448
+ // audit D-1 §3.4). Same gated assembly as every other intake path.
1449
+ const intakeService = createReuseGatedIntakeService({ stateManager, ledgerAdapter, workspaceDir });
1361
1450
  for (const row of pendingRows) {
1362
1451
  const candidateId = row.candidate_id;
1363
1452
  const candidate = await stateManager.getCandidate(candidateId);
@@ -1421,6 +1510,29 @@ export async function handleCandidateInternalizationBackfill(opts) {
1421
1510
  // Statuses are deliberately reused from the existing model (SPEC v2.1 §7
1422
1511
  // "禁止执行者自行创造新状态"): 'deferred' + 'skipped' rather than a new
1423
1512
  // status value.
1513
+ //
1514
+ // R7 gate-bypass fix: a park (reuse_pending_owner) is a DIFFERENT
1515
+ // refusal — the candidate is a suspected duplicate awaiting the Owner.
1516
+ // It must NOT be reported as "no action required" and must NOT be
1517
+ // counted as an intake failure: the gate worked. The candidate stays
1518
+ // pending; only `pd candidate review --decide` resolves it (cli-6).
1519
+ if (intakeResult.outcome === 'refused' && intakeResult.reason === 'reuse_pending_owner') {
1520
+ const recommended = intakeResult.reuseRecommendation?.status === 'recommended' ? intakeResult.reuseRecommendation : undefined;
1521
+ emitReuseGateParkedTelemetry(workspaceDir, candidateId, recommended);
1522
+ output.deferred++;
1523
+ output.results.push({
1524
+ candidateId,
1525
+ route: decision.route,
1526
+ status: 'deferred',
1527
+ reason: `reuse_review_required: candidate is a suspected duplicate${recommended?.selectedPrincipleId !== undefined ? ` of Principle ${recommended.selectedPrincipleId}` : ''} — parked for Owner review`,
1528
+ statusBefore: 'pending',
1529
+ statusAfter: 'pending',
1530
+ intakeDecision: 'skipped',
1531
+ seedDecision: 'skipped',
1532
+ nextAction: `pd candidate review --candidate-id ${candidateId} --decide reuse|create --reason "..."`,
1533
+ });
1534
+ continue;
1535
+ }
1424
1536
  if (intakeResult.outcome === 'refused') {
1425
1537
  output.results.push({ candidateId, route: decision.route, status: 'deferred', reason: intakeResult.message, statusBefore: 'pending', statusAfter: 'pending', intakeDecision: 'skipped', seedDecision: 'skipped', nextAction: 'No action required: this candidate kind does not target the Principle Ledger.' });
1426
1538
  continue;