@guilz-dev/belay 0.6.0 → 0.7.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.
Files changed (143) hide show
  1. package/README.md +20 -1
  2. package/dist/adapters/claude/runtime-entry.js +54 -25
  3. package/dist/adapters/shared/gate-runtime.d.ts +7 -0
  4. package/dist/adapters/shared/gate-runtime.js +420 -220
  5. package/dist/bundle/claude-runtime.mjs +13215 -8864
  6. package/dist/bundle/codex-runtime.mjs +10771 -6453
  7. package/dist/bundle/cursor-runtime.mjs +10797 -6484
  8. package/dist/cli.js +37 -1
  9. package/dist/commands/approve.js +34 -10
  10. package/dist/commands/doctor.js +51 -0
  11. package/dist/commands/recovery-checkpoints.d.ts +164 -0
  12. package/dist/commands/recovery-checkpoints.js +347 -0
  13. package/dist/commands/revoke.js +19 -7
  14. package/dist/commands/status.js +7 -0
  15. package/dist/config-io.js +49 -18
  16. package/dist/conformance/guarantee-table.js +6 -0
  17. package/dist/conformance/types.d.ts +1 -0
  18. package/dist/core/approval-replay.d.ts +1 -1
  19. package/dist/core/approval-replay.js +4 -1
  20. package/dist/core/approval-service.d.ts +6 -1
  21. package/dist/core/approval-service.js +86 -27
  22. package/dist/core/approval.d.ts +2 -0
  23. package/dist/core/approval.js +6 -3
  24. package/dist/core/audit-types.d.ts +13 -0
  25. package/dist/core/capability/approval-state-mutation.d.ts +19 -0
  26. package/dist/core/capability/approval-state-mutation.js +76 -3
  27. package/dist/core/capability/approval-v3.d.ts +18 -1
  28. package/dist/core/capability/approval-v3.js +63 -23
  29. package/dist/core/capability/attestation.d.ts +3 -0
  30. package/dist/core/capability/attestation.js +7 -0
  31. package/dist/core/capability/boundary-driver-container.d.ts +12 -0
  32. package/dist/core/capability/boundary-driver-container.js +101 -34
  33. package/dist/core/capability/boundary-driver.js +1 -0
  34. package/dist/core/capability/boundary-grant-materialize.d.ts +1 -0
  35. package/dist/core/capability/boundary-grant-materialize.js +15 -0
  36. package/dist/core/capability/boundary-run.d.ts +25 -0
  37. package/dist/core/capability/boundary-run.js +37 -9
  38. package/dist/core/capability/boundary-session.d.ts +4 -0
  39. package/dist/core/capability/boundary-session.js +9 -0
  40. package/dist/core/capability/boundary-workspace-mount.d.ts +5 -0
  41. package/dist/core/capability/boundary-workspace-mount.js +68 -0
  42. package/dist/core/capability/gate-policy-shadow.js +23 -1
  43. package/dist/core/capability/grant-consumption.d.ts +4 -0
  44. package/dist/core/capability/grant-consumption.js +11 -0
  45. package/dist/core/capability/grant-lease.d.ts +36 -1
  46. package/dist/core/capability/grant-lease.js +213 -16
  47. package/dist/core/capability/grant-match.js +3 -0
  48. package/dist/core/capability/index.d.ts +1 -1
  49. package/dist/core/capability/index.js +1 -1
  50. package/dist/core/capability/policy-engine.d.ts +7 -0
  51. package/dist/core/capability/policy-engine.js +202 -15
  52. package/dist/core/capability/request.d.ts +3 -0
  53. package/dist/core/config.d.ts +20 -0
  54. package/dist/core/config.js +62 -0
  55. package/dist/core/effect-ir/audit.d.ts +9 -0
  56. package/dist/core/effect-ir/audit.js +86 -0
  57. package/dist/core/effect-ir/build.d.ts +31 -0
  58. package/dist/core/effect-ir/build.js +277 -0
  59. package/dist/core/effect-ir/index.d.ts +8 -0
  60. package/dist/core/effect-ir/index.js +7 -0
  61. package/dist/core/effect-ir/normalize.d.ts +4 -0
  62. package/dist/core/effect-ir/normalize.js +104 -0
  63. package/dist/core/effect-ir/package-exec-eval.d.ts +8 -0
  64. package/dist/core/effect-ir/package-exec-eval.js +152 -0
  65. package/dist/core/effect-ir/package-exec.d.ts +29 -0
  66. package/dist/core/effect-ir/package-exec.js +292 -0
  67. package/dist/core/effect-ir/policy.d.ts +13 -0
  68. package/dist/core/effect-ir/policy.js +77 -0
  69. package/dist/core/effect-ir/types.d.ts +55 -0
  70. package/dist/core/effect-ir/types.js +1 -0
  71. package/dist/core/egress/allowlist.d.ts +1 -0
  72. package/dist/core/egress/allowlist.js +8 -0
  73. package/dist/core/egress-approval.js +45 -51
  74. package/dist/core/gate-contract.d.ts +2 -0
  75. package/dist/core/gate-contract.js +2 -0
  76. package/dist/core/gate-engine.js +26 -9
  77. package/dist/core/index.d.ts +3 -1
  78. package/dist/core/index.js +2 -1
  79. package/dist/core/judge-cloud-consent.js +29 -15
  80. package/dist/core/network-endpoint.d.ts +10 -0
  81. package/dist/core/network-endpoint.js +51 -0
  82. package/dist/core/process-runner.d.ts +10 -0
  83. package/dist/core/process-runner.js +124 -0
  84. package/dist/core/recover-advice.js +2 -1
  85. package/dist/core/recovery/artifact-store.d.ts +29 -0
  86. package/dist/core/recovery/artifact-store.js +336 -0
  87. package/dist/core/recovery/checkpoint.d.ts +25 -0
  88. package/dist/core/recovery/checkpoint.js +260 -0
  89. package/dist/core/recovery/index.d.ts +3 -1
  90. package/dist/core/recovery/index.js +2 -0
  91. package/dist/core/recovery/operator-guidance.d.ts +7 -0
  92. package/dist/core/recovery/operator-guidance.js +39 -0
  93. package/dist/core/recovery/reconcile.d.ts +3 -0
  94. package/dist/core/recovery/reconcile.js +48 -0
  95. package/dist/core/recovery/resource-identity.d.ts +4 -0
  96. package/dist/core/recovery/resource-identity.js +34 -0
  97. package/dist/core/recovery/restore.d.ts +13 -0
  98. package/dist/core/recovery/restore.js +114 -0
  99. package/dist/core/recovery/snapshot-node.d.ts +27 -0
  100. package/dist/core/recovery/snapshot-node.js +261 -0
  101. package/dist/core/recovery/types.d.ts +85 -1
  102. package/dist/core/transactional/apply-observed-changes.d.ts +13 -0
  103. package/dist/core/transactional/apply-observed-changes.js +275 -0
  104. package/dist/core/transactional/backend-selector.d.ts +8 -0
  105. package/dist/core/transactional/backend-selector.js +118 -0
  106. package/dist/core/transactional/backend.d.ts +55 -0
  107. package/dist/core/transactional/backend.js +1 -0
  108. package/dist/core/transactional/file-checkpoint-backend.d.ts +3 -0
  109. package/dist/core/transactional/file-checkpoint-backend.js +278 -0
  110. package/dist/core/transactional/file-checkpoint-git.d.ts +11 -0
  111. package/dist/core/transactional/file-checkpoint-git.js +217 -0
  112. package/dist/core/transactional/file-checkpoint-staging.d.ts +13 -0
  113. package/dist/core/transactional/file-checkpoint-staging.js +54 -0
  114. package/dist/core/transactional/file-clone.d.ts +15 -0
  115. package/dist/core/transactional/file-clone.js +139 -0
  116. package/dist/core/transactional/file-tree-path.d.ts +7 -0
  117. package/dist/core/transactional/file-tree-path.js +50 -0
  118. package/dist/core/transactional/file-tree.d.ts +41 -0
  119. package/dist/core/transactional/file-tree.js +186 -0
  120. package/dist/core/transactional/git-worktree-backend.d.ts +2 -0
  121. package/dist/core/transactional/git-worktree-backend.js +50 -0
  122. package/dist/core/transactional/git-worktree.d.ts +9 -11
  123. package/dist/core/transactional/git-worktree.js +24 -119
  124. package/dist/core/transactional/index.d.ts +11 -0
  125. package/dist/core/transactional/index.js +10 -0
  126. package/dist/core/transactional/reasons.js +1 -0
  127. package/dist/core/transactional/runner.js +157 -25
  128. package/dist/core/transactional/snapshot-node.d.ts +26 -0
  129. package/dist/core/transactional/snapshot-node.js +87 -0
  130. package/dist/core/transactional/types.d.ts +17 -1
  131. package/dist/core/types.d.ts +10 -1
  132. package/dist/core/verdict/adapter.js +8 -0
  133. package/dist/core/verdict/launcher-resolve.js +2 -20
  134. package/dist/core/verdict/shell-policy.d.ts +1 -0
  135. package/dist/core/verdict/shell-policy.js +1 -1
  136. package/dist/core/verdict/types.d.ts +5 -0
  137. package/dist/core/verdict/verdict.js +37 -20
  138. package/dist/types.d.ts +11 -0
  139. package/dist/version.d.ts +1 -1
  140. package/dist/version.js +1 -1
  141. package/package.json +1 -1
  142. package/skills/belay/SKILL.md +8 -3
  143. package/skills/belay/belay-approve.md +10 -7
package/dist/cli.js CHANGED
@@ -10,6 +10,7 @@ import { formatHarvestReport, harvestApplyProject, harvestListProject } from './
10
10
  import { formatMetricsReport, metricsProject } from './commands/metrics.js';
11
11
  import { formatQualityReport, qualityCheck } from './commands/quality.js';
12
12
  import { formatRecoverReport, recoverProject } from './commands/recover.js';
13
+ import { formatRecoveryCheckpointResult, recoveryCheckpointCommand, } from './commands/recovery-checkpoints.js';
13
14
  import { formatReport, reportProject } from './commands/report.js';
14
15
  import { revokeApproval } from './commands/revoke.js';
15
16
  import { formatSessionStatusReport, sessionStartProject, sessionStatusProject, } from './commands/session.js';
@@ -433,6 +434,23 @@ function parseArgs(argv) {
433
434
  }
434
435
  throw new Error('harvest requires subcommand: list or apply');
435
436
  }
437
+ if (command === 'recover' && !options.recoverSubcommand) {
438
+ if (token === 'advice' ||
439
+ token === 'status' ||
440
+ token === 'list' ||
441
+ token === 'show' ||
442
+ token === 'apply') {
443
+ options.recoverSubcommand = token;
444
+ continue;
445
+ }
446
+ throw new Error('recover requires subcommand: advice, status, list, show, or apply');
447
+ }
448
+ if (command === 'recover' &&
449
+ (options.recoverSubcommand === 'show' || options.recoverSubcommand === 'apply') &&
450
+ !options.recoverCheckpointId) {
451
+ options.recoverCheckpointId = token;
452
+ continue;
453
+ }
436
454
  if (command === 'judge' && !options.judgeSubcommand) {
437
455
  if (token === 'status' ||
438
456
  token === 'list' ||
@@ -527,8 +545,10 @@ Usage:
527
545
  ${c} metrics [--target <dir>] [--json]
528
546
  ${c} quality [--target <dir>] [--corpus <path>] [--json]
529
547
  ${c} report [--target <dir>] [--since <iso>] [--until <iso>] [--limit <n>] [--json]
530
- ${c} recover [--target <dir>] [--since <iso>] [--fingerprint <fp>] [--command "<text>"] [--limit <n>] [--json]
548
+ ${c} recover [advice] [--target <dir>] [--since <iso>] [--fingerprint <fp>] [--command "<text>"] [--limit <n>] [--json]
531
549
  (--limit picks the Nth recover candidate after priority ranking: local_mutation first, then recency; 1 = highest priority, default 1)
550
+ ${c} recover <status|list> [--target <dir>] [--json]
551
+ ${c} recover <show|apply> <checkpoint-id> [--target <dir>] [--json]
532
552
  ${c} audit <query|summarize|replay> [--target <dir>] [--json] [--since <iso>] [--until <iso>] [--verdict <v>] [--reason <r>] [--kind <k>] [--fingerprint <fp>] [--event <e>] [--location <v>] [--opacity <v>] [--effect <v>] [--confidence <v>] [--limit <n>] [--config <path>]
533
553
  ${c} simulate --config <path> [--target <dir>] [--json]
534
554
  ${c} status [--target <dir>] [--json]
@@ -825,6 +845,22 @@ async function main() {
825
845
  throw new Error('harvest requires subcommand: list or apply');
826
846
  }
827
847
  if (command === 'recover') {
848
+ if (options.recoverSubcommand && options.recoverSubcommand !== 'advice') {
849
+ const result = await recoveryCheckpointCommand({
850
+ targetDir: options.targetDir,
851
+ subcommand: options.recoverSubcommand,
852
+ checkpointId: options.recoverCheckpointId,
853
+ });
854
+ if (options.json) {
855
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
856
+ }
857
+ else {
858
+ process.stdout.write(formatRecoveryCheckpointResult(result));
859
+ }
860
+ if (!result.ok)
861
+ process.exitCode = 2;
862
+ return;
863
+ }
828
864
  const report = await recoverProject({
829
865
  targetDir: options.targetDir,
830
866
  since: options.since,
@@ -1,10 +1,12 @@
1
1
  import path from 'node:path';
2
2
  import { loadApprovalState, loadConfigFile } from '../config-io.js';
3
- import { canAutoReplay, getExecutionLeaseMs, replayShellCommand } from '../core/approval-replay.js';
4
- import { consumeApprovedAfterCliReplay, createGateApprovalStore, recordApproval, } from '../core/approval-service.js';
3
+ import { canAutoReplay, getExecutionLeaseMs } from '../core/approval-replay.js';
4
+ import { claimApprovedForReplay, createGateApprovalStore, recordApproval, } from '../core/approval-service.js';
5
+ import { runBoundaryAgentCommand } from '../core/capability/boundary-session.js';
5
6
  import { JUDGE_CLOUD_CONSENT_REASON } from '../core/capability/reasons.js';
6
7
  import { recordCapabilityApproval } from '../core/capability-approval.js';
7
8
  import { recordEgressApproval } from '../core/egress-approval.js';
9
+ import { RECOVERY_RESTORE_REASON } from '../core/recovery/checkpoint.js';
8
10
  import { createEgressApprovalStore } from '../services/egress-service.js';
9
11
  import { createCapabilityApprovalStore } from '../services/sandbox-service.js';
10
12
  export async function approvePending(options) {
@@ -12,6 +14,19 @@ export async function approvePending(options) {
12
14
  const config = await loadConfigFile(repoRoot);
13
15
  const pending = await loadApprovalState(repoRoot, 'pending-approvals.json', config);
14
16
  const match = pending.approvals.find((approval) => approval.approvalId === options.approvalId);
17
+ if (match?.reason === RECOVERY_RESTORE_REASON) {
18
+ if (options.scope && options.scope !== 'once') {
19
+ return { ok: false, message: 'Recovery restore approvals support one-shot scope only.' };
20
+ }
21
+ const result = await recordApproval({
22
+ approvalId: options.approvalId,
23
+ config,
24
+ token: options.token,
25
+ requireSignedToken: true,
26
+ store: createGateApprovalStore(repoRoot, config),
27
+ });
28
+ return { ok: result.ok, message: result.message };
29
+ }
15
30
  if (match?.reason === JUDGE_CLOUD_CONSENT_REASON) {
16
31
  const result = await recordCapabilityApproval({
17
32
  approvalId: options.approvalId,
@@ -73,22 +88,31 @@ export async function approvePending(options) {
73
88
  message: 'CLI replay is only supported for shell approvals. Retry the original tool or subagent action manually.',
74
89
  };
75
90
  }
76
- const replayResult = await replayShellCommand(approval.input, approval.cwd ?? repoRoot, getExecutionLeaseMs(config));
77
- const output = [replayResult.stdout, replayResult.stderr].filter(Boolean).join('\n').trim();
91
+ const claimed = await claimApprovedForReplay({
92
+ approvalId: options.approvalId,
93
+ store: approvalStore,
94
+ });
95
+ if (!claimed) {
96
+ return { ok: false, message: 'Approval could not be claimed for replay.' };
97
+ }
98
+ const replayResult = await runBoundaryAgentCommand({
99
+ repoRoot,
100
+ config,
101
+ command: claimed.input ?? approval.input,
102
+ cwd: claimed.cwd ?? repoRoot,
103
+ timeoutMs: getExecutionLeaseMs(config),
104
+ runOptions: { mountReadOnly: false },
105
+ });
78
106
  if (replayResult.exitCode === 0) {
79
- await consumeApprovedAfterCliReplay({
80
- approvalId: options.approvalId,
81
- store: approvalStore,
82
- });
83
107
  return {
84
108
  ok: true,
85
- message: `Belay replay succeeded for ${options.approvalId}. Do not retry via hooks; the one-shot grant was consumed.${output ? `\n${output}` : ''}`,
109
+ message: `Belay replay succeeded for ${options.approvalId}. Do not retry via hooks; the one-shot grant was consumed.`,
86
110
  };
87
111
  }
88
112
  const timeoutNote = replayResult.timedOut ? ' Replay timed out.' : '';
89
113
  return {
90
114
  ok: false,
91
- message: `Belay replay failed for ${options.approvalId} (exit ${replayResult.exitCode}).${timeoutNote} Approval remains active for one hook retry.${output ? `\n${output}` : ''}`,
115
+ message: `Belay replay failed for ${options.approvalId} (exit ${replayResult.exitCode}).${timeoutNote} The one-shot approval was consumed before replay and was not re-armed.`,
92
116
  };
93
117
  }
94
118
  return { ok: result.ok, message: result.message };
@@ -7,6 +7,7 @@ import { getAdapterLayout } from '../adapters/layouts/index.js';
7
7
  import { resolveScopedPaths } from '../adapters/layouts/scope.js';
8
8
  import { cleanupOrphanApprovalState } from '../cleanup-orphans.js';
9
9
  import { approvedApprovalsPath, belayStateDir, detectAdapterName, loadLayeredConfig, pendingApprovalsPath, repoLocalStateDirFor, } from '../config-io.js';
10
+ import { approvalSigningKeyPath } from '../core/approval-token.js';
10
11
  import { detectFenceDrift, summarizeAuditVisibility } from '../core/audit-summary.js';
11
12
  import { inspectBoundaryAttestationFile } from '../core/capability/boundary-attestation-sign.js';
12
13
  import { boundaryAttestationPath, boundarySessionStatus, } from '../core/capability/boundary-session.js';
@@ -14,6 +15,9 @@ import { defaultControlPlaneDir } from '../core/config.js';
14
15
  import { verifyIntegrityManifest } from '../core/integrity.js';
15
16
  import { diagnoseJudge, stopJudgeSessionBrokers } from '../core/judge-doctor.js';
16
17
  import { resolveJudgeTransport } from '../core/judge-runtime-detection.js';
18
+ import { listRecoveryCheckpoints } from '../core/recovery/checkpoint.js';
19
+ import { recoveryApprovalSetupNotes, recoveryNotificationConfigured, recoveryNotificationSetupWarning, summarizeRecoveryCheckpointDiagnostics, } from '../core/recovery/operator-guidance.js';
20
+ import { probeFileCloneStrategy } from '../core/transactional/file-clone.js';
17
21
  import { getManagedHookEntries } from '../defaults.js';
18
22
  import { resolveNodeBinary } from '../node-resolution.js';
19
23
  import { egressStatus } from '../services/egress-service.js';
@@ -290,6 +294,45 @@ export async function doctorProject(options = {}) {
290
294
  warnings.push('Transactional execution is enabled but this directory is not a git repository. Transactional worktrees will be skipped until git is available.');
291
295
  }
292
296
  }
297
+ const fileCheckpoint = loadedConfig.policy.transactional.fileCheckpoint;
298
+ if (fileCheckpoint.enabled) {
299
+ const copyStrategy = await probeFileCloneStrategy();
300
+ notes.push(`File checkpoint: enabled (copyStrategy=${copyStrategy}, non-Git=${fileCheckpoint.allowNonGit}, maxFiles=${fileCheckpoint.maxFiles}, maxSourceBytes=${fileCheckpoint.maxSourceBytes}, maxWorkspaceBytes=${fileCheckpoint.maxWorkspaceBytes}, prepareTimeoutMs=${fileCheckpoint.prepareTimeoutMs}, copyConcurrency=${fileCheckpoint.copyConcurrency}).`);
301
+ if (!loadedConfig.policy.transactional.enabled) {
302
+ warnings.push('File checkpoint is enabled but transactional execution is disabled; dirty Git workspaces cannot use the backend.');
303
+ }
304
+ if (!loadedConfig.policy.transactional.checkpoint?.enabled) {
305
+ warnings.push('File checkpoint is enabled but durable Recovery checkpointing is disabled; backend selection will fail closed.');
306
+ }
307
+ }
308
+ if (loadedConfig.policy.transactional.checkpoint?.enabled) {
309
+ notes.push('Recovery checkpoint: enabled — repo-local pre-images are persisted before observed-safe transactional apply.');
310
+ notes.push(...recoveryApprovalSetupNotes());
311
+ if (!recoveryNotificationConfigured(loadedConfig)) {
312
+ warnings.push(recoveryNotificationSetupWarning());
313
+ }
314
+ const signingKeyPath = approvalSigningKeyPath(loadedConfig.controlPlane.enabled
315
+ ? belayStateDir(loadedConfig, repoLocalDir)
316
+ : (loadedConfig.controlPlane.configDir ?? defaultControlPlaneDir()));
317
+ if (!existsSync(signingKeyPath)) {
318
+ notes.push(`Approval signing key not yet created at ${signingKeyPath}; it will be generated on the first signed recovery approval request.`);
319
+ }
320
+ if (!loadedConfig.policy.transactional.enabled) {
321
+ warnings.push('Recovery checkpoint is enabled but transactional execution is disabled; checkpoints will not be created until transactional execution is enabled.');
322
+ }
323
+ try {
324
+ const stateDir = belayStateDir(loadedConfig, repoLocalDir);
325
+ const checkpoints = await listRecoveryCheckpoints(stateDir, repoRoot);
326
+ if (checkpoints.length > 0) {
327
+ notes.push(`Recovery checkpoints in this repository: ${checkpoints.length}.`);
328
+ }
329
+ const advisories = summarizeRecoveryCheckpointDiagnostics(checkpoints);
330
+ warnings.push(...advisories);
331
+ }
332
+ catch {
333
+ // Checkpoint inspection is advisory only.
334
+ }
335
+ }
293
336
  if (loadedConfig.sandbox.enabled) {
294
337
  const sandbox = await sandboxStatus({ targetDir: repoRoot });
295
338
  notes.push(`Sandbox capability broker: enabled (runtime=${loadedConfig.sandbox.runtime}, fs-scope entries=${sandbox.fsScopeAllowlistCount}, full-isolation=${sandbox.l1FullActive}).`);
@@ -305,6 +348,10 @@ export async function doctorProject(options = {}) {
305
348
  }
306
349
  const boundaryDriver = loadedConfig.capability?.boundaryDriver ??
307
350
  (loadedConfig.sandbox.runtime === 'container' ? 'container' : null);
351
+ if (loadedConfig.policy.transactional.fileCheckpoint.enabled &&
352
+ boundaryDriver !== 'container') {
353
+ warnings.push('File checkpoint requires an attested workspace-isolating boundary driver; configure the container boundary and run belay session start.');
354
+ }
308
355
  if (loadedConfig.capability || boundaryDriver === 'container') {
309
356
  const attestationPath = boundaryAttestationPath(repoRoot, loadedConfig);
310
357
  const attestationFormat = await inspectBoundaryAttestationFile(attestationPath);
@@ -323,6 +370,10 @@ export async function doctorProject(options = {}) {
323
370
  else if (!session.fresh) {
324
371
  warnings.push('Boundary attestation is stale or expired. Run belay session start to refresh.');
325
372
  }
373
+ else if (loadedConfig.policy.transactional.fileCheckpoint.enabled &&
374
+ session.attestation.isolatesWorkspaceMounts !== true) {
375
+ warnings.push('File checkpoint is enabled but the fresh boundary attestation does not prove workspace-mount isolation. Run belay session start with a compatible boundary.');
376
+ }
326
377
  else if (session.attestation.probeSignals.includes('repo-mount-ro-default')) {
327
378
  notes.push('Container boundary defaults to read-only directory mounts; predicted writes use read-write mounts for the working directory only.');
328
379
  }
@@ -0,0 +1,164 @@
1
+ export type RecoveryCheckpointSubcommand = 'status' | 'list' | 'show' | 'apply';
2
+ export declare function recoveryCheckpointCommand(options: {
3
+ targetDir?: string;
4
+ subcommand: RecoveryCheckpointSubcommand;
5
+ checkpointId?: string;
6
+ }): Promise<{
7
+ ok: boolean;
8
+ subcommand: string;
9
+ repoRoot: string;
10
+ backend: string;
11
+ availableBackends: string[];
12
+ backendCounts: {
13
+ [k: string]: number;
14
+ };
15
+ fileCheckpoint: {
16
+ enabled: boolean;
17
+ allowNonGit: boolean;
18
+ isolation: string | null;
19
+ copyStrategy: import("../core/transactional/file-clone.js").FileCloneStrategy | undefined;
20
+ probe: string;
21
+ };
22
+ enabled: boolean;
23
+ checkpointCount: number;
24
+ storageBytes: number;
25
+ recoverableCount: number;
26
+ needsManualRepairCount: number;
27
+ verifiedReceiptCount: number;
28
+ states: {
29
+ [k: string]: number;
30
+ };
31
+ advisories: string[];
32
+ limits: {
33
+ enabled: boolean;
34
+ appliedRetentionHours: number;
35
+ restoredRetentionHours: number;
36
+ maxCheckpoints: number;
37
+ maxBytes: number;
38
+ };
39
+ checkpoints?: undefined;
40
+ manifest?: undefined;
41
+ state?: undefined;
42
+ manifestHash?: undefined;
43
+ receipt?: undefined;
44
+ verdict?: undefined;
45
+ checkpointId?: undefined;
46
+ approvalId?: undefined;
47
+ paths?: undefined;
48
+ auditRecorded?: undefined;
49
+ message?: undefined;
50
+ } | {
51
+ ok: boolean;
52
+ subcommand: string;
53
+ repoRoot: string;
54
+ checkpoints: import("../core/index.js").RecoveryCheckpointSummary[];
55
+ backend?: undefined;
56
+ availableBackends?: undefined;
57
+ backendCounts?: undefined;
58
+ fileCheckpoint?: undefined;
59
+ enabled?: undefined;
60
+ checkpointCount?: undefined;
61
+ storageBytes?: undefined;
62
+ recoverableCount?: undefined;
63
+ needsManualRepairCount?: undefined;
64
+ verifiedReceiptCount?: undefined;
65
+ states?: undefined;
66
+ advisories?: undefined;
67
+ limits?: undefined;
68
+ manifest?: undefined;
69
+ state?: undefined;
70
+ manifestHash?: undefined;
71
+ receipt?: undefined;
72
+ verdict?: undefined;
73
+ checkpointId?: undefined;
74
+ approvalId?: undefined;
75
+ paths?: undefined;
76
+ auditRecorded?: undefined;
77
+ message?: undefined;
78
+ } | {
79
+ ok: boolean;
80
+ subcommand: string;
81
+ manifest: import("../core/index.js").RecoveryCheckpointManifest;
82
+ state: import("../core/recovery/types.js").RecoveryCheckpointStateV1;
83
+ manifestHash: string;
84
+ receipt: import("../core/index.js").RecoveryReceiptV1 | undefined;
85
+ repoRoot?: undefined;
86
+ backend?: undefined;
87
+ availableBackends?: undefined;
88
+ backendCounts?: undefined;
89
+ fileCheckpoint?: undefined;
90
+ enabled?: undefined;
91
+ checkpointCount?: undefined;
92
+ storageBytes?: undefined;
93
+ recoverableCount?: undefined;
94
+ needsManualRepairCount?: undefined;
95
+ verifiedReceiptCount?: undefined;
96
+ states?: undefined;
97
+ advisories?: undefined;
98
+ limits?: undefined;
99
+ checkpoints?: undefined;
100
+ verdict?: undefined;
101
+ checkpointId?: undefined;
102
+ approvalId?: undefined;
103
+ paths?: undefined;
104
+ auditRecorded?: undefined;
105
+ message?: undefined;
106
+ } | {
107
+ ok: boolean;
108
+ subcommand: string;
109
+ verdict: string;
110
+ checkpointId: string;
111
+ approvalId: string;
112
+ manifestHash: string;
113
+ paths: string[];
114
+ auditRecorded: boolean;
115
+ message: string;
116
+ repoRoot?: undefined;
117
+ backend?: undefined;
118
+ availableBackends?: undefined;
119
+ backendCounts?: undefined;
120
+ fileCheckpoint?: undefined;
121
+ enabled?: undefined;
122
+ checkpointCount?: undefined;
123
+ storageBytes?: undefined;
124
+ recoverableCount?: undefined;
125
+ needsManualRepairCount?: undefined;
126
+ verifiedReceiptCount?: undefined;
127
+ states?: undefined;
128
+ advisories?: undefined;
129
+ limits?: undefined;
130
+ checkpoints?: undefined;
131
+ manifest?: undefined;
132
+ state?: undefined;
133
+ receipt?: undefined;
134
+ } | {
135
+ auditRecorded: boolean;
136
+ message: string;
137
+ manifestHash: string;
138
+ changeCount: number;
139
+ ok: boolean;
140
+ subcommand: string;
141
+ verdict: string;
142
+ checkpointId: string;
143
+ repoRoot?: undefined;
144
+ backend?: undefined;
145
+ availableBackends?: undefined;
146
+ backendCounts?: undefined;
147
+ fileCheckpoint?: undefined;
148
+ enabled?: undefined;
149
+ checkpointCount?: undefined;
150
+ storageBytes?: undefined;
151
+ recoverableCount?: undefined;
152
+ needsManualRepairCount?: undefined;
153
+ verifiedReceiptCount?: undefined;
154
+ states?: undefined;
155
+ advisories?: undefined;
156
+ limits?: undefined;
157
+ checkpoints?: undefined;
158
+ manifest?: undefined;
159
+ state?: undefined;
160
+ receipt?: undefined;
161
+ approvalId?: undefined;
162
+ paths?: undefined;
163
+ }>;
164
+ export declare function formatRecoveryCheckpointResult(result: Record<string, unknown>): string;