praxis-agent 0.46.0 → 0.46.2

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.
@@ -100,6 +100,32 @@ export function projectTuiDecisionSurface(input) {
100
100
  cancellation,
101
101
  };
102
102
  }
103
+ if (input.kind === 'cd-trust') {
104
+ const selectedIndex = normalizeIndex(input.selectedIndex, 2);
105
+ const options = projectedOptions([{ label: 'No, stay put' }, { label: 'Yes, move here' }], selectedIndex);
106
+ return {
107
+ kind: 'cd-trust',
108
+ heading: 'Moving to a new directory:',
109
+ canonicalPath: input.canonicalPath,
110
+ explanation: "This session hasn't worked here before. Is this a directory you created or one you trust?",
111
+ scope: 'Praxis can read, edit, and execute files in this directory.',
112
+ securityGuide: 'Security guide: https://code.claude.com/docs/en/security',
113
+ options,
114
+ selectedIndex,
115
+ range: range(options.length),
116
+ actions: [
117
+ {
118
+ visualLabel: 'Enter to confirm',
119
+ screenReaderLabel: 'Enter to confirm',
120
+ },
121
+ { screenReaderLabel: 'Use up and down arrows to change selection' },
122
+ { screenReaderLabel: 'Press 1 or 2 to choose directly' },
123
+ { screenReaderLabel: 'Press y to move here' },
124
+ { screenReaderLabel: 'Press n to stay put' },
125
+ ],
126
+ cancellation,
127
+ };
128
+ }
103
129
  const count = input.questions.length;
104
130
  const questionIndex = normalizeIndex(input.questionIndex, count);
105
131
  if (count === 0)
@@ -31,8 +31,11 @@ function PlanSurface({ model, screenReader, }) {
31
31
  function QuestionSurface({ model, screenReader, }) {
32
32
  return (_jsxs(DialogFrame, { title: model.heading, screenReader: screenReader, children: [_jsx(Text, { children: model.progress }), model.emptyState ? _jsx(Text, { dimColor: true, children: model.emptyState }) : null, model.options.map((option) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [option.index, ". ", option.label, option.description ? ` — ${option.description}` : ''] }), option.preview ? _jsx(Text, { dimColor: true, children: option.preview }) : null] }, `${option.index}-${option.label}`))), _jsxs(Text, { children: [screenReader ? 'Current answer: ' : '› ', model.answer || (screenReader ? '(empty)' : '')] }), _jsx(Footer, { ...model, screenReader: screenReader })] }));
33
33
  }
34
+ function CdTrustSurface({ model, screenReader, }) {
35
+ return (_jsxs(DialogFrame, { title: model.heading, screenReader: screenReader, children: [_jsx(Text, { children: model.canonicalPath }), _jsx(Text, { dimColor: true, children: model.explanation }), _jsx(Text, { dimColor: true, children: model.scope }), _jsx(Text, { dimColor: true, children: model.securityGuide }), model.options.map((option) => (_jsx(Option, { option: option, screenReader: screenReader }, option.index))), _jsx(Footer, { ...model, screenReader: screenReader })] }));
36
+ }
34
37
  export function DecisionSurface({ model, width, screenReader, }) {
35
- const content = model.kind === 'plan-approval' ? (_jsx(PlanSurface, { model: model, screenReader: screenReader })) : (_jsx(QuestionSurface, { model: model, screenReader: screenReader }));
38
+ const content = model.kind === 'plan-approval' ? (_jsx(PlanSurface, { model: model, screenReader: screenReader })) : model.kind === 'question' ? (_jsx(QuestionSurface, { model: model, screenReader: screenReader })) : (_jsx(CdTrustSurface, { model: model, screenReader: screenReader }));
36
39
  const normalizedWidth = Number.isFinite(width)
37
40
  ? Math.min(100, Math.max(1, Math.trunc(width)))
38
41
  : 100;
@@ -1,2 +1,12 @@
1
- export declare function openTuiUrl(url: string): Promise<void>;
1
+ type OpenUrlOptions = {
2
+ timeout: number;
3
+ shell: false;
4
+ };
5
+ type OpenUrlExecutor = (command: string, args: string[], options: OpenUrlOptions, callback: (error?: Error | null) => void) => unknown;
6
+ type OpenUrlDependencies = {
7
+ platform?: NodeJS.Platform;
8
+ execFile?: OpenUrlExecutor;
9
+ };
10
+ export declare function openTuiUrl(url: string, dependencies?: OpenUrlDependencies): Promise<void>;
11
+ export {};
2
12
  //# sourceMappingURL=open-url.d.ts.map
@@ -1,13 +1,33 @@
1
1
  import { execFile } from 'node:child_process';
2
- export async function openTuiUrl(url) {
3
- const command = process.platform === 'darwin'
2
+ const defaultExecFile = (command, args, options, callback) => execFile(command, args, options, callback);
3
+ export async function openTuiUrl(url, dependencies = {}) {
4
+ let parsedUrl;
5
+ try {
6
+ parsedUrl = new URL(url);
7
+ }
8
+ catch {
9
+ throw new Error('TUI URL must be an absolute HTTP(S) URL');
10
+ }
11
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:')
12
+ throw new Error('TUI URL must be an absolute HTTP(S) URL');
13
+ const canonicalUrl = parsedUrl.href;
14
+ const platform = dependencies.platform ?? process.platform;
15
+ const command = platform === 'darwin'
4
16
  ? 'open'
5
- : process.platform === 'win32'
6
- ? 'cmd'
17
+ : platform === 'win32'
18
+ ? 'rundll32.exe'
7
19
  : 'xdg-open';
8
- const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
9
- await new Promise((resolvePromise) => {
10
- execFile(command, args, { timeout: 10_000 }, () => resolvePromise());
20
+ const args = platform === 'win32'
21
+ ? ['url.dll,FileProtocolHandler', canonicalUrl]
22
+ : [canonicalUrl];
23
+ const executor = dependencies.execFile ?? defaultExecFile;
24
+ await new Promise((resolvePromise, rejectPromise) => {
25
+ try {
26
+ executor(command, args, { timeout: 10_000, shell: false }, (error) => error == null ? resolvePromise() : rejectPromise(error));
27
+ }
28
+ catch (error) {
29
+ rejectPromise(error);
30
+ }
11
31
  });
12
32
  }
13
33
  //# sourceMappingURL=open-url.js.map
@@ -176,6 +176,17 @@ function decision(surface, density, sr) {
176
176
  explicitFooter('quiet:plan:footer', '↑/↓ select Enter confirm Esc cancel', 'Use up and down arrows to select. Press Enter to confirm. Press Escape to cancel.'),
177
177
  ];
178
178
  }
179
+ if (surface.kind === 'cd-trust') {
180
+ out.push(row('quiet:cd-trust:path', surface.canonicalPath, 'body'));
181
+ out.push(row('quiet:cd-trust:explanation', surface.explanation, 'muted'));
182
+ out.push(row('quiet:cd-trust:scope', surface.scope, 'muted'));
183
+ out.push(row('quiet:cd-trust:security-guide', surface.securityGuide, 'muted'));
184
+ out.push(...optionsRows(surface.options, 'quiet:cd-trust:option', density, sr));
185
+ return [
186
+ ...out,
187
+ explicitFooter('quiet:cd-trust:footer', '↑/↓ select Enter confirm Esc cancel', 'Use up and down arrows to select. Press Enter to confirm. Press Escape to cancel.'),
188
+ ];
189
+ }
179
190
  if (surface.progress)
180
191
  out.push(row('quiet:question:progress', surface.progress, 'muted'));
181
192
  if (surface.question)
@@ -291,7 +302,9 @@ export function projectQuietChoiceRows(surface, options) {
291
302
  row('quiet:exit:heading', 'Exit Praxis?', 'heading'),
292
303
  explicitFooter('quiet:exit:footer', 'Enter confirm Esc cancel', 'Press Enter to confirm. Press Escape to cancel.'),
293
304
  ];
294
- if (surface.kind === 'plan-approval' || surface.kind === 'question')
305
+ if (surface.kind === 'plan-approval' ||
306
+ surface.kind === 'question' ||
307
+ surface.kind === 'cd-trust')
295
308
  return decision(surface, options.density, sr);
296
309
  if (surface.kind === 'session-picker' ||
297
310
  surface.kind === 'command-palette' ||
@@ -1,8 +1,16 @@
1
1
  import type { SandboxDependencyCheck } from '@anthropic-ai/sandbox-runtime';
2
2
  import type { JsonResource } from '../../core/resources.js';
3
+ import { type ClaudeSandboxPlatform } from '../../sandbox/claude-sandbox-runtime.js';
3
4
  import { type ClaudeSandboxSettings } from '../../sandbox/claude-sandbox-settings.js';
4
5
  export type TuiSandboxMode = 'auto-allow' | 'regular' | 'disabled';
5
6
  export type TuiSandboxTab = 'mode' | 'dependencies' | 'overrides' | 'config';
7
+ export interface TuiSandboxRuntime {
8
+ initialize(settings: ClaudeSandboxSettings): Promise<void>;
9
+ unavailableReason(settings: ClaudeSandboxSettings): string | undefined;
10
+ platformName(): ClaudeSandboxPlatform;
11
+ dependencyCheck(settings: ClaudeSandboxSettings): SandboxDependencyCheck;
12
+ isSupportedPlatform(): boolean;
13
+ }
6
14
  export interface TuiSandboxSnapshot {
7
15
  settings: ClaudeSandboxSettings;
8
16
  dependencies: SandboxDependencyCheck;
@@ -22,11 +30,12 @@ export interface TuiSandboxStore {
22
30
  }>;
23
31
  }
24
32
  export declare function linuxGlobPatternWarnings(resources: readonly JsonResource[], platform: 'macos' | 'linux' | 'windows' | 'wsl'): string[];
25
- export declare function createTuiSandboxStore({ configRoot, cwd, homeDirectory, additionalDirectories, environment, }: {
33
+ export declare function createTuiSandboxStore({ configRoot, cwd, homeDirectory, additionalDirectories, environment, runtime, }: {
26
34
  configRoot: string;
27
35
  cwd: string;
28
36
  homeDirectory: string;
29
37
  additionalDirectories?: readonly string[];
30
38
  environment?: NodeJS.ProcessEnv;
39
+ runtime?: TuiSandboxRuntime;
31
40
  }): TuiSandboxStore;
32
41
  //# sourceMappingURL=sandbox-settings.d.ts.map
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { join, relative } from 'node:path';
3
3
  import { writeFileAtomically } from '../../platform/atomic-write.js';
4
4
  import { loadNativeSharedResources } from '../../persistence/native-resources.js';
5
- import { claudeSandboxRuntime } from '../../sandbox/claude-sandbox-runtime.js';
5
+ import { claudeSandboxRuntime, } from '../../sandbox/claude-sandbox-runtime.js';
6
6
  import { nativeSandboxTempDirectory, loadClaudeSandboxSettings, } from '../../sandbox/claude-sandbox-settings.js';
7
7
  function isRecord(value) {
8
8
  return typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -75,7 +75,7 @@ export function linuxGlobPatternWarnings(resources, platform) {
75
75
  }
76
76
  return [...new Set(warnings)];
77
77
  }
78
- export function createTuiSandboxStore({ configRoot, cwd, homeDirectory, additionalDirectories = [], environment = process.env, }) {
78
+ export function createTuiSandboxStore({ configRoot, cwd, homeDirectory, additionalDirectories = [], environment = process.env, runtime = claudeSandboxRuntime, }) {
79
79
  const localSettingsPath = join(cwd, '.praxis', 'settings.local.json');
80
80
  const load = async () => {
81
81
  const resources = (await loadNativeSharedResources({ root: configRoot, cwd })).settings;
@@ -87,13 +87,13 @@ export function createTuiSandboxStore({ configRoot, cwd, homeDirectory, addition
87
87
  additionalDirectories,
88
88
  tempDirectory: nativeSandboxTempDirectory(environment),
89
89
  });
90
- await claudeSandboxRuntime.initialize(settings);
91
- const unavailableReason = claudeSandboxRuntime.unavailableReason(settings);
92
- const platform = claudeSandboxRuntime.platformName();
90
+ await runtime.initialize(settings);
91
+ const unavailableReason = runtime.unavailableReason(settings);
92
+ const platform = runtime.platformName();
93
93
  return {
94
94
  settings,
95
- dependencies: claudeSandboxRuntime.dependencyCheck(settings),
96
- supported: claudeSandboxRuntime.isSupportedPlatform(),
95
+ dependencies: runtime.dependencyCheck(settings),
96
+ supported: runtime.isSupportedPlatform(),
97
97
  platform,
98
98
  globPatternWarnings: linuxGlobPatternWarnings(resources, platform),
99
99
  ...(unavailableReason ? { unavailableReason } : {}),
@@ -7,6 +7,7 @@ export interface TuiFocusProjectionInput {
7
7
  readonly pendingPrefix: boolean;
8
8
  readonly permission: boolean;
9
9
  readonly planApproval: boolean;
10
+ readonly cdTrust?: boolean;
10
11
  readonly question: boolean;
11
12
  readonly elicitation: 'plain' | 'url-waiting' | 'expanded-options' | false;
12
13
  readonly selectingSession: boolean;
@@ -19,6 +19,12 @@ export function projectTuiFocusStack(input) {
19
19
  layer: { kind: 'cancelable', target: 'plan-approval' },
20
20
  };
21
21
  }
22
+ else if (input.cdTrust) {
23
+ higher = {
24
+ id: 'cd-trust',
25
+ layer: { kind: 'cancelable', target: 'cd-trust' },
26
+ };
27
+ }
22
28
  else if (input.question) {
23
29
  higher = {
24
30
  id: 'question',
@@ -1,7 +1,7 @@
1
1
  import { type ComposerKeyProjection } from './composer-key-router.js';
2
2
  import type { ComposerEditorState } from './composer-editor.js';
3
3
  export type TuiScrollIntent = 'page-older' | 'page-newer' | 'half-page-older' | 'half-page-newer' | 'line-older' | 'line-newer' | 'none';
4
- export type TuiCancellationTarget = 'permission' | 'plan-approval' | 'question' | 'elicitation' | 'elicitation-url-waiting' | 'elicitation-options' | 'file-picker' | 'command-palette';
4
+ export type TuiCancellationTarget = 'permission' | 'plan-approval' | 'cd-trust' | 'question' | 'elicitation' | 'elicitation-url-waiting' | 'elicitation-options' | 'file-picker' | 'command-palette';
5
5
  export type TuiInteractionLayer = {
6
6
  readonly kind: 'none';
7
7
  } | {
@@ -44,7 +44,8 @@ export function routeTuiInteraction(snapshot, input) {
44
44
  if (snapshot.layer.kind === 'delegated')
45
45
  return delegated(confirmationEffects);
46
46
  const viewport = snapshot.viewport;
47
- if (viewport.enabled && input.scrollIntent !== 'none') {
47
+ const scrollIsIncidental = input.action === undefined || input.action.startsWith('scroll:');
48
+ if (viewport.enabled && input.scrollIntent !== 'none' && scrollIsIncidental) {
48
49
  const pageRows = finiteNonNegativeInteger(viewport.pageRows);
49
50
  const offset = finiteNonNegativeInteger(viewport.offset);
50
51
  const maxOffset = finiteNonNegativeInteger(viewport.maxOffset);
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { type ForkResult, type ManualCompactResult, type ManualCompactSelection, type RewindPoint, type SessionForkCheckpoint, type SessionInspection, type SessionRunResult, type SessionSummary, type SideQuestionForkResult, type SideQuestionResult } from './application/session-service.js';
2
+ import { type CwdInspection, type ForkResult, type ManualCompactResult, type ManualCompactSelection, type RewindPoint, type SessionForkCheckpoint, type SessionInspection, type SessionRunResult, type SessionSummary, type SideQuestionForkResult, type SideQuestionResult } from './application/session-service.js';
3
3
  import type { TeamLeadOperations } from './application/team-lead-operations.js';
4
4
  import type { ClaudeSessionCostSnapshot } from './application/session-cost-tracker.js';
5
5
  import { type AgentColorName, type AgentColorSelection } from './core/agent-color.js';
@@ -43,7 +43,8 @@ interface SessionCommands {
43
43
  setPermissionMode?(sessionId: string, mode: ClaudePermissionMode): Promise<void>;
44
44
  rewindFiles?(sessionId: string, userMessageId: string): Promise<void>;
45
45
  rewindPoints?(sessionId: string): Promise<RewindPoint[]>;
46
- changeCwd?(sessionId: string | undefined, cwd: string): Promise<string>;
46
+ changeCwd?(sessionId: string | undefined, cwd: string, expectedCanonicalTarget?: string): Promise<string>;
47
+ inspectCwd?(cwd: string): Promise<CwdInspection>;
47
48
  notify?(sessionId: string | undefined, message: string, notificationType: string, title?: string): void;
48
49
  recordCdUsage?(sessionId: string): Promise<void>;
49
50
  approveRecentlyDenied?(sessionId: string, display: string): Promise<void>;
@@ -2049,7 +2049,8 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
2049
2049
  setPermissionMode: (sessionId, permissionMode) => service.setPermissionMode(sessionId, permissionMode),
2050
2050
  rewindFiles: (sessionId, userMessageId) => service.rewindFiles(sessionId, userMessageId),
2051
2051
  rewindPoints: (sessionId) => service.rewindPoints(sessionId),
2052
- changeCwd: (sessionId, cwd) => service.changeCwd(sessionId, cwd),
2052
+ changeCwd: (sessionId, cwd, expectedCanonicalTarget) => service.changeCwd(sessionId, cwd, expectedCanonicalTarget),
2053
+ inspectCwd: (cwd) => service.inspectCwd(cwd),
2053
2054
  notify: (sessionId, message, notificationType, title) => service.notifyDetached(sessionId, message, notificationType, title),
2054
2055
  recordCdUsage: (sessionId) => service.recordCdUsage(sessionId),
2055
2056
  approveRecentlyDenied: (sessionId, display) => service.approveRecentlyDenied(sessionId, display),
@@ -7,8 +7,4 @@
7
7
  export type NativeTranscriptEntry = Record<string, unknown> & {
8
8
  type: string;
9
9
  };
10
- export declare function isNativeForkableEntryType(type: string): boolean;
11
- /** Copy only projection metadata; persisted native events are copied by
12
- * NativeSessionTranscript.forkTo and retain their event identity semantics. */
13
- export declare function copyNativeEntryWithSessionId(entry: NativeTranscriptEntry, sessionId: string): NativeTranscriptEntry;
14
10
  //# sourceMappingURL=schema.d.ts.map
@@ -1,24 +1,2 @@
1
- const FORKABLE_ENTRY_TYPES = new Set([
2
- 'agent-color',
3
- 'agent-name',
4
- 'agent-setting',
5
- 'ai-title',
6
- 'assistant',
7
- 'attachment',
8
- 'custom-title',
9
- 'last-prompt',
10
- 'mode',
11
- 'permission-mode',
12
- 'pr-link',
13
- 'system',
14
- 'user',
15
- ]);
16
- export function isNativeForkableEntryType(type) {
17
- return FORKABLE_ENTRY_TYPES.has(type);
18
- }
19
- /** Copy only projection metadata; persisted native events are copied by
20
- * NativeSessionTranscript.forkTo and retain their event identity semantics. */
21
- export function copyNativeEntryWithSessionId(entry, sessionId) {
22
- return { ...entry, sessionId };
23
- }
1
+ export {};
24
2
  //# sourceMappingURL=schema.js.map
@@ -304,11 +304,12 @@ function validate(input, name) {
304
304
  for (const member of input.roster) {
305
305
  if (!member || typeof member !== 'object' || Array.isArray(member))
306
306
  throw new Error('Invalid Team member');
307
- objectInput(member, [
308
- 'name',
309
- 'agentType',
310
- 'access',
311
- ]);
307
+ const value = member;
308
+ objectInput(value, ['name', 'agentType', 'access']);
309
+ stringValue(value, 'name');
310
+ stringValue(value, 'agentType');
311
+ if (value.access !== 'read-only' && value.access !== 'write')
312
+ throw new Error('Invalid Team member access');
312
313
  }
313
314
  for (const task of input.tasks) {
314
315
  if (!task || typeof task !== 'object' || Array.isArray(task))
@@ -321,6 +322,12 @@ function validate(input, name) {
321
322
  'blockedBy',
322
323
  'claims',
323
324
  ]);
325
+ stringValue(value, 'id');
326
+ stringValue(value, 'description');
327
+ stringValue(value, 'assignee');
328
+ if (!Array.isArray(value.blockedBy) ||
329
+ value.blockedBy.some((entry) => typeof entry !== 'string' || entry.trim() === ''))
330
+ throw new Error('Invalid Team blockedBy');
324
331
  if (!value.claims ||
325
332
  typeof value.claims !== 'object' ||
326
333
  Array.isArray(value.claims))
@@ -332,6 +339,18 @@ function validate(input, name) {
332
339
  'migrations',
333
340
  'mergeTargets',
334
341
  ]);
342
+ for (const key of [
343
+ 'files',
344
+ 'publicContracts',
345
+ 'generatedArtifacts',
346
+ 'migrations',
347
+ 'mergeTargets',
348
+ ]) {
349
+ const entries = value.claims[key];
350
+ if (!Array.isArray(entries) ||
351
+ entries.some((entry) => typeof entry !== 'string' || entry.trim() === ''))
352
+ throw new Error(`Invalid Team claim list: ${key}`);
353
+ }
335
354
  }
336
355
  return input;
337
356
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praxis-agent",
3
- "version": "0.46.0",
3
+ "version": "0.46.2",
4
4
  "description": "Local-first, single-user general agent for the command line.",
5
5
  "license": "MIT",
6
6
  "author": "wuqisen",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "scripts": {
31
31
  "build": "tsc -p tsconfig.build.json",
32
- "check": "npm run format:check && npm run lint && npm run test:docs && npm run verify:release-automation && npm run verify:ci-coverage && npm run check:boundaries && npm run typecheck && npm run build:native && npm run build && npm test",
32
+ "check": "npm run format:check && npm run lint && npm run test:docs && npm run verify:release-automation && npm run verify:ci-coverage && npm run verify:fixture-contracts && npm run check:boundaries && npm run typecheck && npm run build:native && npm run build && npm test",
33
33
  "check:boundaries": "node scripts/check-boundaries.mjs",
34
34
  "dev": "tsx src/cli.ts",
35
35
  "format": "prettier --write .",
@@ -44,11 +44,11 @@
44
44
  "release:artifacts": "node scripts/build-release-artifacts.mjs",
45
45
  "release:verify": "node scripts/verify-release-ref.mjs",
46
46
  "test": "vitest run",
47
- "test:coverage": "vitest run --coverage",
47
+ "test:coverage": "vitest run --coverage && node scripts/verify-nonzero-runtime-coverage.mjs",
48
48
  "test:docs": "node scripts/verify-docs.mjs",
49
49
  "test:tui:pty": "npm run build && node scripts/verify-fullscreen-rendering.mjs && node scripts/verify-interactive-ansi.mjs",
50
50
  "test:self-update": "npm run build && node scripts/verify-self-update-contract.mjs",
51
- "test:core-completion": "npm run build && node scripts/verify-core-completion-audit.mjs",
51
+ "test:core-completion": "npm run test:fixtures",
52
52
  "test:performance": "npm run build && node scripts/verify-projection-scaling.mjs && node scripts/verify-projection-regression.mjs && node scripts/verify-quiet-frame-performance.mjs",
53
53
  "test:performance:projection": "npm run build && node scripts/verify-projection-scaling.mjs",
54
54
  "test:performance:projection-regression": "npm run build && node scripts/verify-projection-regression.mjs",
@@ -56,9 +56,12 @@
56
56
  "test:prompt-suggestions": "npm run build && node scripts/verify-prompt-suggestions.mjs",
57
57
  "test:mcp-oauth-serve": "npm run build && node scripts/verify-mcp-oauth-serve.mjs",
58
58
  "test:package": "npm run build && node scripts/verify-native-release-package.mjs",
59
+ "test:security": "npm audit --omit=dev",
59
60
  "typecheck": "tsc --noEmit",
60
61
  "verify:release-automation": "node scripts/verify-release-automation.mjs",
61
- "verify:ci-coverage": "node scripts/verify-ci-coverage.mjs"
62
+ "verify:ci-coverage": "node scripts/verify-ci-coverage.mjs",
63
+ "verify:fixture-contracts": "node scripts/verify-fixture-contracts.mjs",
64
+ "test:fixtures": "node scripts/run-fixture-contracts.mjs"
62
65
  },
63
66
  "engines": {
64
67
  "node": ">=24"
@@ -1,9 +0,0 @@
1
- import { type NativeTranscriptEntry } from './schema.js';
2
- export interface ClaudeNativeForkOptions {
3
- source: readonly NativeTranscriptEntry[];
4
- sourceSessionId: string;
5
- sessionId: string;
6
- resumeSessionAt?: string;
7
- }
8
- export declare function createClaudeNativeFork({ source, sourceSessionId, sessionId, resumeSessionAt, }: ClaudeNativeForkOptions): NativeTranscriptEntry[];
9
- //# sourceMappingURL=fork.d.ts.map