@eyeauras/insight-cli 0.2.2 → 0.2.3

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 (73) hide show
  1. package/.cli-package-build.json +1 -1
  2. package/SKILL.md +1 -1
  3. package/dist/src/budgets.d.ts +2 -0
  4. package/dist/src/budgets.js +13 -0
  5. package/dist/src/cli.js +20 -1
  6. package/dist/src/contexts.js +3 -2
  7. package/dist/src/lifecycle.d.ts +2 -0
  8. package/dist/src/research.d.ts +3 -0
  9. package/dist/src/research.js +36 -6
  10. package/dist/src/server.js +13 -1
  11. package/dist/src/transport.d.ts +2 -1
  12. package/dist/src/transport.js +8 -3
  13. package/dist/src/workspace.d.ts +11 -0
  14. package/dist/src/workspace.js +18 -1
  15. package/package.json +1 -1
  16. package/references/recovery.md +26 -0
  17. package/references/setup.md +17 -0
  18. package/skill-bundle/insight-artifacts/SKILL.md +1 -1
  19. package/skill-bundle/insight-binary/SKILL.md +1 -1
  20. package/skill-bundle/insight-capture/SKILL.md +1 -1
  21. package/skill-bundle/insight-cli/SKILL.md +1 -1
  22. package/skill-bundle/insight-die/SKILL.md +1 -1
  23. package/skill-bundle/insight-dnspy/SKILL.md +1 -1
  24. package/skill-bundle/insight-dotnet-dump/SKILL.md +1 -1
  25. package/skill-bundle/insight-dotnet-stack/SKILL.md +1 -1
  26. package/skill-bundle/insight-dotnet-trace/SKILL.md +1 -1
  27. package/skill-bundle/insight-frida/SKILL.md +1 -1
  28. package/skill-bundle/insight-ghidra/SKILL.md +3 -1
  29. package/skill-bundle/insight-ghidra/references/recovery.md +26 -0
  30. package/skill-bundle/insight-ghidra/references/setup.md +17 -0
  31. package/skill-bundle/insight-ilspy/SKILL.md +1 -1
  32. package/skill-bundle/insight-interop/SKILL.md +1 -1
  33. package/skill-bundle/insight-lldb/SKILL.md +1 -1
  34. package/skill-bundle/insight-llvm/SKILL.md +1 -1
  35. package/skill-bundle/insight-managed-heap/SKILL.md +1 -1
  36. package/skill-bundle/insight-managed-metadata/SKILL.md +1 -1
  37. package/skill-bundle/insight-mitmproxy/SKILL.md +1 -1
  38. package/skill-bundle/insight-overview/SKILL.md +1 -1
  39. package/skill-bundle/insight-procmon/SKILL.md +1 -1
  40. package/skill-bundle/insight-re/SKILL.md +1 -1
  41. package/skill-bundle/insight-re/references/recovery.md +26 -0
  42. package/skill-bundle/insight-sevenzip/SKILL.md +1 -1
  43. package/skill-bundle/insight-strace/SKILL.md +1 -1
  44. package/skill-bundle/insight-tshark/SKILL.md +1 -1
  45. package/skill-bundle/insight-windbg/SKILL.md +1 -1
  46. package/skill-bundle/manifest.json +1 -1
  47. package/skills/insight-artifacts/SKILL.md +1 -1
  48. package/skills/insight-binary/SKILL.md +1 -1
  49. package/skills/insight-capture/SKILL.md +1 -1
  50. package/skills/insight-die/SKILL.md +1 -1
  51. package/skills/insight-dnspy/SKILL.md +1 -1
  52. package/skills/insight-dotnet-dump/SKILL.md +1 -1
  53. package/skills/insight-dotnet-stack/SKILL.md +1 -1
  54. package/skills/insight-dotnet-trace/SKILL.md +1 -1
  55. package/skills/insight-frida/SKILL.md +1 -1
  56. package/skills/insight-ghidra/SKILL.md +3 -1
  57. package/skills/insight-ghidra/references/recovery.md +26 -0
  58. package/skills/insight-ghidra/references/setup.md +17 -0
  59. package/skills/insight-ilspy/SKILL.md +1 -1
  60. package/skills/insight-interop/SKILL.md +1 -1
  61. package/skills/insight-lldb/SKILL.md +1 -1
  62. package/skills/insight-llvm/SKILL.md +1 -1
  63. package/skills/insight-managed-heap/SKILL.md +1 -1
  64. package/skills/insight-managed-metadata/SKILL.md +1 -1
  65. package/skills/insight-mitmproxy/SKILL.md +1 -1
  66. package/skills/insight-overview/SKILL.md +1 -1
  67. package/skills/insight-procmon/SKILL.md +1 -1
  68. package/skills/insight-re/SKILL.md +1 -1
  69. package/skills/insight-re/references/recovery.md +26 -0
  70. package/skills/insight-sevenzip/SKILL.md +1 -1
  71. package/skills/insight-strace/SKILL.md +1 -1
  72. package/skills/insight-tshark/SKILL.md +1 -1
  73. package/skills/insight-windbg/SKILL.md +1 -1
@@ -1 +1 @@
1
- {"version":1,"artifact":"046be98b4da24b7ec169f1c82195fe9285221d9917d4bec0e4635e9b91febaa3"}
1
+ {"version":1,"artifact":"94653e997ccdf18c2e7cb73ac89fc02e746c119ae6971b374cfcafbda087b493"}
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: insight-cli
3
3
  description: Choose and prepare reverse-engineering capabilities from the insight-cli toolbox for binary, managed-code and runtime investigations. Use to discover the appropriate tool or its packaged skill before installing native runtimes.
4
4
  ---
5
5
 
6
- # insight-cli 0.2.2
6
+ # insight-cli 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -0,0 +1,2 @@
1
+ /** Execution policy, deliberately separate from immutable program load settings. */
2
+ export declare function ghidraBudget(values: Record<string, unknown>, phase: 'import' | 'save'): number;
@@ -0,0 +1,13 @@
1
+ import { fail } from './model.js';
2
+ /** Execution policy, deliberately separate from immutable program load settings. */
3
+ export function ghidraBudget(values, phase) {
4
+ const field = phase === 'import' ? 'initialImportSeconds' : 'saveSeconds';
5
+ const fallback = phase === 'import' ? 3600 : 120;
6
+ const value = values[field] === undefined ? fallback : values[field];
7
+ if (typeof value !== 'number' && (typeof value !== 'string' || !/^\d+$/.test(value)))
8
+ fail('configuration', field + ' must be an integer number of seconds.');
9
+ const seconds = Number(value), max = phase === 'import' ? 86400 : 3600;
10
+ if (!Number.isSafeInteger(seconds) || seconds < 1 || seconds > max)
11
+ fail('configuration', field + ' must be between 1 and ' + max + ' seconds.');
12
+ return seconds * 1000;
13
+ }
package/dist/src/cli.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ghidraBudget } from './budgets.js';
1
2
  import { captureCommands } from './capture.js';
2
3
  import { binaryCommands } from './binary.js';
3
4
  import { skillCommand, toolboxCommands } from './toolbox.js';
@@ -194,6 +195,8 @@ const fields = [
194
195
  ['repository', '--repository <name>', 'Repository on the external server'],
195
196
  ['readerUser', '--reader-user <name>', 'Read-only external account'],
196
197
  ['publisherUser', '--publisher-user <name>', 'External publication account'],
198
+ ['initialImportSeconds', '--initial-import-seconds <seconds>', 'Initial import/analysis budget (default 3600, range 1–86400 seconds)'],
199
+ ['saveSeconds', '--save-seconds <seconds>', 'Native save/export budget (default 120, range 1–3600 seconds)'],
197
200
  ['maxContexts', '--max-contexts <count>', 'Concurrent contexts (default 4, maximum 16)'],
198
201
  ['debuggerPython', '--debugger-python <path>', 'Optional Python executable for a configured debugger offer'],
199
202
  ['windbgDir', '--windbg-dir <path>', 'Optional Windows debugger runtime directory'],
@@ -260,7 +263,7 @@ export function createDefinition(options = {}) {
260
263
  name: 'insight-cli', applicationId: 'insight-cli', version: packageVersion, description: 'Isolated research contexts and coordinated Ghidra analysis',
261
264
  resources: [owner], permissions: { categories: [{ name: 'Destructive', description: 'Explicit deletion or replacement of retained research data', enabledByDefault: false }] }, ...(options.runtime ? { runtime: options.runtime } : {}),
262
265
  profile: { fields: fields.map(([name, flags, description]) => ({ name: name, flags: flags, description: description,
263
- ...(name === 'maxContexts' ? { normalize: (value) => number(value, 16, 1) } : {}) })) },
266
+ ...(['maxContexts', 'initialImportSeconds', 'saveSeconds'].includes(name) ? { normalize: (value) => number(value, name === 'maxContexts' ? 16 : name === 'saveSeconds' ? 3600 : 86400, 1) } : {}) })) },
264
267
  auth: {
265
268
  loginOptions: [{ flags: '--role <role>', description: 'External reader, publisher or archive role', defaultValue: 'reader' },
266
269
  { flags: '--password-stdin', description: 'Read the password from stdin' }],
@@ -351,6 +354,22 @@ export function createDefinition(options = {}) {
351
354
  }, { permission: Permission.ReadOnly, options: [{ flags: '--target <id>', description: 'Inspect one target context' }, ...paged] }),
352
355
  ]),
353
356
  command('ghidra', 'Research through an isolated saved context', [
357
+ command('budgets', 'Inspect or configure native execution budgets', [
358
+ command('show', 'Read effective per-request native budgets', (_invocation, c) => ({ profile: c.profile.name, initialImportSeconds: ghidraBudget(c.profile.values, 'import') / 1000, saveSeconds: ghidraBudget(c.profile.values, 'save') / 1000 }), { permission: Permission.ReadOnly }),
359
+ command('set', 'Configure subsequent native requests without invalidating retained research', async ({ options: o }, c) => {
360
+ if (o.initialImportSeconds === undefined && o.saveSeconds === undefined)
361
+ fail('invalid', 'Supply at least one native budget.');
362
+ const store = options.runtime?.profileStore ?? new ProfileStore({ applicationId: c.appArguments.AppName, appArguments: c.appArguments });
363
+ const patch = {
364
+ ...(o.initialImportSeconds === undefined ? {} : { initialImportSeconds: number(o.initialImportSeconds, 86400, 1) }),
365
+ ...(o.saveSeconds === undefined ? {} : { saveSeconds: number(o.saveSeconds, 3600, 1) })
366
+ };
367
+ const { values } = await store.set(c.profile.name, patch);
368
+ return { profile: c.profile.name, state: 'configured', initialImportSeconds: ghidraBudget(values, 'import') / 1000, saveSeconds: ghidraBudget(values, 'save') / 1000, appliesTo: 'subsequent-requests' };
369
+ }, { permission: Permission.Update, options: [{ flags: '--initial-import-seconds <seconds>', description: 'Initial import/analysis: 1–86400 seconds' },
370
+ { flags: '--save-seconds <seconds>', description: 'Native save/export: 1–3600 seconds' }] })
371
+ ]),
372
+ command('abandon', 'Retain an uncertain program attempt and resume its previous saved view', ({ options: o }, c) => owner.selected(c).research.abandon(scope(o), id(o.requestId), Boolean(o.acknowledgeUnknownEffects)), { permission: 'Destructive', options: [...scoped, { flags: '--request-id <id>', description: 'Original unresolved request ID from sessions status', required: true }, { flags: '--acknowledge-unknown-effects', description: 'Acknowledge that the abandoned effect remains unknown; no script is replayed' }] }),
354
373
  command('refresh', 'Receive safe shared changes while retaining local conflicts', ({ options: o }, c) => owner.selected(c).research.refresh(scope(o), o.requestId === undefined ? undefined : id(o.requestId)), { permission: Permission.Update, options: [...scoped, request] }),
355
374
  command('merge', 'Publish the complete selected context or retain every conflict', ({ options: o }, c) => owner.selected(c).research.merge(scope(o), o.requestId === undefined ? undefined : id(o.requestId)), { permission: Permission.Update, options: [...scoped, request] }),
356
375
  command('open [input]', 'Start independent work or continue a context', async ({ args, options: o }, c) => {
@@ -1,3 +1,4 @@
1
+ import { ghidraBudget } from './budgets.js';
1
2
  import { launchProcess, terminateProcess } from './tool-runtime/supervisor.js';
2
3
  import { runTool } from './tool-runtime/run.js';
3
4
  import { verifyGhidraProcess } from './ghidra-processes.js';
@@ -139,7 +140,7 @@ export class GhidraContexts {
139
140
  await log.close();
140
141
  if (!child.pid)
141
142
  fail('launch', 'Owned Ghidra context could not be launched.');
142
- const record = { binding, http: new HttpBridge(binding.endpoint, this.c.fetch, this.c.signal, token), child };
143
+ const record = { binding, http: new HttpBridge(binding.endpoint, this.c.fetch, this.c.signal, token, undefined, ghidraBudget(this.c.profile.values, 'save')), child };
143
144
  this.running.set(root, record);
144
145
  const deadline = Date.now() + 90000;
145
146
  try {
@@ -172,7 +173,7 @@ export class GhidraContexts {
172
173
  if (stable(JSON.parse(await readFile(join(root, 'process.json'), 'utf8'))) !== stable(binding))
173
174
  fail('binding', 'Native context receipt changed.');
174
175
  const token = await this.c.secrets.require(binding.tokenSecret);
175
- const http = new HttpBridge(binding.endpoint, this.c.fetch, this.c.signal, token);
176
+ const http = new HttpBridge(binding.endpoint, this.c.fetch, this.c.signal, token, undefined, ghidraBudget(this.c.profile.values, 'save'));
176
177
  const info = await http.instance();
177
178
  if (info.pid !== binding.pid || info.tcp_port !== Number(new URL(binding.endpoint).port) ||
178
179
  !String(info.project_path ?? '').startsWith(root + sep))
@@ -37,6 +37,8 @@ export declare class Lifecycle {
37
37
  operation: string;
38
38
  state: import("./workspace.js").RequestState;
39
39
  requestId?: string | undefined;
40
+ detail?: {} | undefined;
41
+ id: string;
40
42
  }[];
41
43
  };
42
44
  session: string;
@@ -92,11 +92,14 @@ export declare class Research {
92
92
  operation: string;
93
93
  state: import("./workspace.js").RequestState;
94
94
  requestId?: string | undefined;
95
+ detail?: {} | undefined;
96
+ id: string;
95
97
  }[];
96
98
  };
97
99
  session: string;
98
100
  target: string;
99
101
  };
102
+ abandon(selected: Scope, requestId: string, acknowledged: boolean): Promise<unknown>;
100
103
  open(target: string, session: string | 'new', settings: GhidraLoadSettings, callerId?: string, mode?: ToolMode): Promise<{
101
104
  [k: string]: unknown;
102
105
  } | {
@@ -100,7 +100,29 @@ export class Research {
100
100
  mergeState: model.state === 'unknown' ? 'unknown' : 'idle',
101
101
  conflicts: context.scalars.filter(change => change.conflict).map(change => ({ address: publicAddress(change.address), field: change.field,
102
102
  original: change.original, local: change.local, shared: change.conflict.shared })),
103
- unresolvedRequests: unresolved.map(request => ({ ...(request.callerId ? { requestId: request.callerId } : {}), operation: request.operation, state: request.state })) } };
103
+ unresolvedRequests: unresolved.map(request => ({ id: request.id, ...(request.result ? { detail: request.result } : {}), ...(request.callerId ? { requestId: request.callerId } : {}), operation: request.operation, state: request.state })) } };
104
+ }
105
+ async abandon(selected, requestId, acknowledged) {
106
+ return this.ordered(selected, async () => {
107
+ if (!acknowledged)
108
+ fail('invalid', 'Explicit --acknowledge-unknown-effects is required.');
109
+ const context = this.workspace.context(selected), requests = this.workspace.unresolved(selected);
110
+ const request = this.workspace.scopedRequest(selected, requestId);
111
+ if (request?.state === 'failed' && object(request.result ?? {}).state === 'abandoned')
112
+ return request.result;
113
+ if (!request || !['running', 'unknown'].includes(request.state) || requests.length !== 1 || object(request.execution ?? {}).kind !== 'program')
114
+ fail('blocked', 'Abandon requires exactly one unresolved private program operation.');
115
+ if (this.workspace.activePublication(selected.target) || context.debugger?.connected)
116
+ fail('blocked', 'Publication or a live debugger prevents private abandonment.');
117
+ const execution = object(request.execution), snapshot = context.workingSnapshot;
118
+ if (!snapshot || execution.generation !== context.generation || object(execution.workingSnapshot).id !== snapshot.id)
119
+ fail('binding', 'The previous saved program view no longer matches the attempt.');
120
+ await this.workspace.artifacts.verify(snapshot);
121
+ const backend = await this.backend();
122
+ if (!backend.closed || !await backend.closed(selected))
123
+ fail('busy', 'The original native worker must be stopped before abandoning its uncertain program attempt.');
124
+ return this.workspace.abandonProgramRequest(selected, request.id, context.generation);
125
+ });
104
126
  }
105
127
  async open(target, session, settings, callerId, mode) {
106
128
  // Mode belongs to the request's effective intent. It does not alter target load identity.
@@ -777,6 +799,7 @@ export class Research {
777
799
  const context = this.workspace.context(selected);
778
800
  this.workspace.startRequest(request.id, { kind: 'program', operation, generation: context.generation, workingSnapshot: context.workingSnapshot,
779
801
  savedVerification: !!verifySaved });
802
+ let savedSnapshot, phase = 'operation';
780
803
  try {
781
804
  const raw = await backend.call(selected, operation, parameters), response = raw && typeof raw === 'object' && !Array.isArray(raw) ? object(raw) : { output: raw };
782
805
  if (['rejected', 'partial', 'failed', 'error'].includes(String(response.status)) || response.success === false)
@@ -784,7 +807,10 @@ export class Research {
784
807
  if (!verifySaved && response.success !== true && response.status !== 'success')
785
808
  fail('partial', 'Program operation did not acknowledge its effect.');
786
809
  let value = await verify(backend, response);
810
+ phase = 'save';
787
811
  const snapshot = await backend.saved(selected);
812
+ savedSnapshot = snapshot;
813
+ phase = 'verification';
788
814
  if (verifySaved)
789
815
  value = await verifySaved(backend, snapshot, response);
790
816
  const scalars = await this.savedScalars(context, backend, snapshot), complexChanges = [...context.complexChanges, request.id], result = { ...selected, state: 'applied', sharedState: 'pending',
@@ -797,12 +823,16 @@ export class Research {
797
823
  this.workspace.recordRequest(request.id, 'failed', { ...selected, state: 'rejected', reason: 'native_transaction_rolled_back' });
798
824
  throw error;
799
825
  }
800
- let savedSnapshot;
801
- try {
802
- savedSnapshot = await backend.saved(selected);
826
+ // Retain supported structural candidates after a lost operation reply. Never
827
+ // dispatch another save after a save deadline or an arbitrary script failure.
828
+ if (phase === 'operation' && verifySaved && !['/run_script_inline', '/run_ghidra_script'].includes(operation)) {
829
+ try {
830
+ savedSnapshot = await backend.saved(selected);
831
+ }
832
+ catch { /* Native evidence stays retained. */ }
803
833
  }
804
- catch { /* A failed/dead backend retains its native stage and the last acknowledged snapshot. */ }
805
- this.workspace.recordRequest(request.id, 'unknown', { ...selected, state: 'unknown', ...(savedSnapshot ? { savedSnapshot } : {}) });
834
+ const detail = error instanceof CliError ? { code: error.code, ...(error.result ? { result: error.result } : {}) } : {};
835
+ this.workspace.recordRequest(request.id, 'unknown', { ...selected, state: 'unknown', phase, ...detail, ...(savedSnapshot ? { savedSnapshot } : {}) });
806
836
  throw error;
807
837
  }
808
838
  });
@@ -1,3 +1,5 @@
1
+ import { ghidraBudget } from './budgets.js';
2
+ import { CliError } from '@eyeauras/cli-factory';
1
3
  import { launchProcess, terminateProcess } from './tool-runtime/supervisor.js';
2
4
  import { runTool } from './tool-runtime/run.js';
3
5
  import { randomUUID, randomBytes, createHash } from 'node:crypto';
@@ -199,7 +201,17 @@ export class GhidraServer {
199
201
  async programStatus(binding, path) {
200
202
  return this.run('program-status', 'InsightRepositoryProbe', [binding.repository, path, 'reader'], await this.credentials(binding, 'reader'));
201
203
  }
202
- async initialImport(root) { return this.run('initial-import', 'InsightInitialImport', [root], {}, undefined, [0], 600000); }
204
+ async initialImport(root) {
205
+ const timeoutMilliseconds = ghidraBudget(this.c.profile.values, 'import');
206
+ try {
207
+ return await this.run('initial-import', 'InsightInitialImport', [root], {}, undefined, [0], timeoutMilliseconds);
208
+ }
209
+ catch (error) {
210
+ if (error instanceof CliError)
211
+ throw new CliError(error.message + ' Initial import remains unproved. Increase profile initialImportSeconds and continue the original scope; incomplete private analysis restarts from the retained input.', { code: error.code, result: { phase: 'initial-import', timeoutMilliseconds, budgetSetting: 'initialImportSeconds', outcome: 'unknown', diagnostics: error.result } });
212
+ throw error;
213
+ }
214
+ }
203
215
  async initialPublication(binding, root, operation = 'stage') {
204
216
  return this.run('initial-publication', 'db.InsightInitialPublication', [root, operation], await this.credentials(binding, operation.startsWith('verify') ? 'reader' : 'publisher'));
205
217
  }
@@ -13,8 +13,9 @@ export declare class HttpBridge {
13
13
  private signal?;
14
14
  private token?;
15
15
  private timeoutMilliseconds?;
16
+ private saveTimeoutMilliseconds;
16
17
  private schema?;
17
- constructor(endpoint: string, fetch?: typeof globalThis.fetch, signal?: AbortSignal | undefined, token?: string | undefined, timeoutMilliseconds?: number | undefined);
18
+ constructor(endpoint: string, fetch?: typeof globalThis.fetch, signal?: AbortSignal | undefined, token?: string | undefined, timeoutMilliseconds?: number | undefined, saveTimeoutMilliseconds?: number);
18
19
  private request;
19
20
  instance(): Promise<Record<string, unknown>>;
20
21
  descriptor(path: string): Promise<Descriptor>;
@@ -8,16 +8,20 @@ export class HttpBridge {
8
8
  signal;
9
9
  token;
10
10
  timeoutMilliseconds;
11
+ saveTimeoutMilliseconds;
11
12
  schema;
12
- constructor(endpoint, fetch = globalThis.fetch, signal, token, timeoutMilliseconds) {
13
+ constructor(endpoint, fetch = globalThis.fetch, signal, token, timeoutMilliseconds, saveTimeoutMilliseconds = 120000) {
13
14
  this.endpoint = endpoint;
14
15
  this.fetch = fetch;
15
16
  this.signal = signal;
16
17
  this.token = token;
17
18
  this.timeoutMilliseconds = timeoutMilliseconds;
19
+ this.saveTimeoutMilliseconds = saveTimeoutMilliseconds;
18
20
  const url = new URL(endpoint);
19
21
  if (url.protocol !== 'http:' || url.hostname !== '127.0.0.1' || !url.port || url.username || url.password || url.pathname !== '/')
20
22
  fail('binding', 'Worker bridge must use an explicit loopback HTTP port.');
23
+ if (!Number.isSafeInteger(saveTimeoutMilliseconds) || saveTimeoutMilliseconds < 1000 || saveTimeoutMilliseconds > 3600000)
24
+ fail('invalid', 'Save timeout is outside the supported bound.');
21
25
  if (timeoutMilliseconds !== undefined && (!Number.isSafeInteger(timeoutMilliseconds) || timeoutMilliseconds < 1 || timeoutMilliseconds > 1800000))
22
26
  fail('invalid', 'Bridge timeout is outside the supported bound.');
23
27
  }
@@ -25,13 +29,14 @@ export class HttpBridge {
25
29
  const url = new URL(path, this.endpoint);
26
30
  // Import includes synchronous auto-analysis. Keep discovery/ordinary requests short,
27
31
  // while allowing a real executable to finish its first analysis without losing the reply.
28
- const timeoutMilliseconds = this.timeoutMilliseconds ?? (path === '/import_file' ? 600000 : 30000);
32
+ const saving = path === '/save_program' || path === '/export_program';
33
+ const timeoutMilliseconds = this.timeoutMilliseconds ?? (saving ? this.saveTimeoutMilliseconds : path === '/import_file' ? 600000 : 30000);
29
34
  const signal = this.signal ? AbortSignal.any([this.signal, AbortSignal.timeout(timeoutMilliseconds)]) : AbortSignal.timeout(timeoutMilliseconds);
30
35
  const transportFailure = () => {
31
36
  if (this.signal?.aborted)
32
37
  fail('cancelled', `Ghidra request ${path} was cancelled; its outcome may require reconciliation.`, { operation: path });
33
38
  if (signal.aborted)
34
- fail('timeout', `Ghidra request ${path} exceeded ${timeoutMilliseconds / 1000} seconds; its outcome may require reconciliation.`, { operation: path, timeoutMilliseconds });
39
+ fail('timeout', `Ghidra request ${path} exceeded ${timeoutMilliseconds / 1000} seconds; its outcome may require reconciliation.${saving ? ' Configure profile saveSeconds before future work; inspect sessions status and never replay an uncertain script.' : ''}`, { operation: path, timeoutMilliseconds, ...(saving ? { phase: 'save', budgetSetting: 'saveSeconds', outcome: 'unknown' } : {}) });
35
40
  fail('transport', `Ghidra request ${path} did not complete; its outcome may require reconciliation.`, { operation: path });
36
41
  };
37
42
  for (const [name, value] of Object.entries(query))
@@ -147,6 +147,7 @@ export declare class Workspace {
147
147
  request: ResearchRequest;
148
148
  replay: boolean;
149
149
  };
150
+ scopedRequest(scope: Scope, identity: string): ResearchRequest | undefined;
150
151
  request(request: string): ResearchRequest;
151
152
  reserveAdministration(operation: string, parameters: unknown, callerId?: string): {
152
153
  request: AdministrationRequest;
@@ -190,6 +191,16 @@ export declare class Workspace {
190
191
  rejectPublication(publication: string, result: unknown): Publication;
191
192
  publishedSince(target: string, revision: number): Publication[];
192
193
  saveContext(scope: Scope, expectedGeneration: number, patch: ContextPatch): GhidraContext;
194
+ /** Terminal abandonment retains the previous outcome and saved view atomically. */
195
+ abandonProgramRequest(scope: Scope, request: string, generation: number): {
196
+ state: string;
197
+ outcome: string;
198
+ requestId: string;
199
+ previousResult: {} | null;
200
+ retainedSnapshot: Artifact;
201
+ session: string;
202
+ target: string;
203
+ };
193
204
  /** Snapshot and successful request acknowledgment enter the same durable transaction. */
194
205
  completeSavedRequest(scope: Scope, request: string, expectedGeneration: number, patch: ContextPatch, result: unknown): {
195
206
  context: GhidraContext;
@@ -3,7 +3,7 @@ import { chmodSync, mkdirSync, realpathSync } from 'node:fs';
3
3
  import { basename, join } from 'node:path';
4
4
  import { randomUUID } from 'node:crypto';
5
5
  import { Artifacts } from './artifacts.js';
6
- import { digest, fail, id, stable, text, version } from './model.js';
6
+ import { digest, fail, id, stable, text, version, object } from './model.js';
7
7
  const now = () => new Date().toISOString();
8
8
  function loadSettings(value) {
9
9
  if (typeof value.autoAnalyze !== 'boolean' || Object.keys(value).some(key => !['autoAnalyze', 'language', 'compilerSpec', 'imageBase', 'loader', 'loaderOptions'].includes(key)))
@@ -260,6 +260,10 @@ export class Workspace {
260
260
  return previous ? { request: previous, replay: true } : { request: this.insertRequest(context.id, operation, intent, callerId, hash), replay: false };
261
261
  });
262
262
  }
263
+ scopedRequest(scope, identity) {
264
+ const row = this.db.prepare('SELECT data FROM requests WHERE context=? AND (id=? OR caller_id=?)').get(this.context(scope).id, id(identity), id(identity));
265
+ return row ? JSON.parse(String(row.data)) : undefined;
266
+ }
263
267
  request(request) {
264
268
  const row = this.db.prepare('SELECT data FROM requests WHERE id=?').get(id(request));
265
269
  if (!row)
@@ -483,6 +487,19 @@ export class Workspace {
483
487
  saveContext(scope, expectedGeneration, patch) {
484
488
  return this.transaction(() => this.writeContext(scope, expectedGeneration, patch));
485
489
  }
490
+ /** Terminal abandonment retains the previous outcome and saved view atomically. */
491
+ abandonProgramRequest(scope, request, generation) {
492
+ return this.transaction(() => {
493
+ const previous = this.request(request), context = this.context(scope), execution = object(previous.execution ?? {});
494
+ if (previous.context !== context.id || !['running', 'unknown'].includes(previous.state) || execution.kind !== 'program' || execution.generation !== generation ||
495
+ this.unresolved(scope).length !== 1 || this.activePublication(scope.target) || !context.workingSnapshot || object(execution.workingSnapshot).id !== context.workingSnapshot.id)
496
+ fail('binding', 'Uncertain attempt changed before abandonment.');
497
+ const result = { ...scope, state: 'abandoned', outcome: 'unknown', requestId: previous.callerId ?? previous.id, previousResult: previous.result ?? null, retainedSnapshot: context.workingSnapshot };
498
+ this.writeContext(scope, generation, { state: 'stopped', viewEpoch: (context.viewEpoch ?? 0) + 1 });
499
+ this.writeRequest(request, 'failed', result);
500
+ return result;
501
+ });
502
+ }
486
503
  /** Snapshot and successful request acknowledgment enter the same durable transaction. */
487
504
  completeSavedRequest(scope, request, expectedGeneration, patch, result) {
488
505
  return this.transaction(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eyeauras/insight-cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "Agent-facing durable sessions and isolated Ghidra research contexts",
6
6
  "main": "./dist/src/index.js",
@@ -51,3 +51,29 @@ goto. If its original owned GUI process has exited, continuation reports the unc
51
51
  as disconnected and retains saved program work. It does not recreate the old cursor or re-enable
52
52
  a previous prompt policy. Other unproved live UI effects remain retained until their outcome is
53
53
  established or the original process is known to have ended.
54
+
55
+ ## Abandon an uncertain private program attempt
56
+
57
+ A post-mutation save timeout does not repeat the script or issue another save in the
58
+ error handler. Status exposes the original request identity and retained phase/budget.
59
+ Arbitrary script effects are never inferred from metadata or from an unverified DB.
60
+ After inspecting the retained attempt, explicitly stop only its verified owned worker
61
+ (`tools processes`, then `tools processes kill <process>` if required). Resume the
62
+ last acknowledged private snapshot with:
63
+
64
+ ```sh
65
+ insight-cli permissions grant Destructive
66
+ insight-cli ghidra abandon --session <session> --target <target> \
67
+ --request-id <original-request> --acknowledge-unknown-effects --json
68
+ insight-cli ghidra open --session <session> --target <target> --json
69
+ ```
70
+
71
+ Abandon requires exactly one unresolved private program operation, an unchanged verified
72
+ previous snapshot/generation, a stopped original worker and no active publication or live
73
+ debugger. It retains the native project, candidate artifacts, original intent/execution and
74
+ previous diagnostic result. Its terminal request is `failed` / `state: abandoned` with
75
+ `outcome: unknown`; no effect is marked applied. Repeating abandonment retrieves the same
76
+ result. Earlier saved private edits remain pending. The original changing request ID cannot
77
+ execute again. Abandoning never undoes external effects or establishes what an arbitrary
78
+ script did; the acknowledgement explicitly accepts that uncertainty. Publication recovery,
79
+ initial import, UI and debugger attempts use their own protocols and cannot use this command.
@@ -48,3 +48,20 @@ debugger runtime directory when relevant. These are runtime profile settings, no
48
48
 
49
49
  Archive exchange is opt-in through `archiveUrl`; its optional token uses Factory secrets.
50
50
  See [archive](archive.md) for the service contract and submission recovery behavior.
51
+
52
+ ## Native operation budgets
53
+
54
+ Profile `initialImportSeconds` defaults to 3600 (1–86400 seconds); `saveSeconds`
55
+ defaults to 120 (1–3600 seconds). Configure them with `ghidra budgets set
56
+ --initial-import-seconds 7200 --save-seconds 300`; `ghidra budgets show` reads effective values.
57
+ This uses Factory ProfileStore without invalidating research or stopping native contexts.
58
+ Active requests retain their original budget. Generic `profile set` remains guarded for
59
+ profiles containing research; initial profile creation also accepts these fields. Both are execution policy, independent
60
+ of immutable target/load identity. Save and packed snapshot export use the save budget;
61
+ discovery and ordinary HTTP queries keep their 30-second budget. Each native request has
62
+ its own budget, not a total command deadline. Cancellation remains independent.
63
+
64
+ After an import timeout, wait for the original worker to end, raise its budget and continue
65
+ the original scope. Incomplete private analysis restarts; a completed receipt is reused.
66
+ A save timeout reports `phase: save`, the effective budget and `saveSeconds`. Inspect
67
+ `sessions status`; a native log or broken response stream cannot prove a saved snapshot.
@@ -3,7 +3,7 @@ name: insight-artifacts
3
3
  description: Retain a completed reverse-engineering evidence file or directory as an ordinary checkpoint using insight-cli artifacts save. Use after Ghidra or any external tool; preserve existing project formats and source of truth.
4
4
  ---
5
5
 
6
- # Insight Artifacts 0.2.2
6
+ # Insight Artifacts 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-binary
3
3
  description: Query structured PE, ELF and thin Mach-O headers, sections, imports and exports, or make an explicitly guarded new PE subsystem copy through insight-cli binary. Use for scoped binary structure, linkage and copy-only header edits without target execution.
4
4
  ---
5
5
 
6
- # Insight Binary 0.2.2
6
+ # Insight Binary 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-capture
3
3
  description: Capture one explicitly authorized native program run, exact stdout/stderr and declared file snapshots through insight-cli capture, then inspect or compare retained reports without replay. Use for controlled input/output research, preserving original files and interrupted or unknown outcomes.
4
4
  ---
5
5
 
6
- # Insight Capture 0.2.2
6
+ # Insight Capture 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-cli
3
3
  description: Choose and prepare reverse-engineering capabilities from the insight-cli toolbox for binary, managed-code and runtime investigations. Use to discover the appropriate tool or its packaged skill before installing native runtimes.
4
4
  ---
5
5
 
6
- # insight-cli 0.2.2
6
+ # insight-cli 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-die
3
3
  description: Classify unknown executable or container inputs by format, architecture and compiler/runtime/packer signatures with Detect It Easy before choosing managed or native analysis. Use insight-cli die for static triage and preserve scan uncertainty.
4
4
  ---
5
5
 
6
- # Insight Detect It Easy 0.2.2
6
+ # Insight Detect It Easy 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dnspy
3
3
  description: Debug a managed Windows EXE at an IL breakpoint and read primitive arguments, or change one expected IL Int32 constant in a new assembly copy through insight-cli dnspy. Use when C# decompilation needs observed execution or a controlled binary edit.
4
4
  ---
5
5
 
6
- # Insight dnSpyEx 0.2.2
6
+ # Insight dnSpyEx 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dotnet-dump
3
3
  description: Capture a managed heap dump or inspect compatible .NET dumps with SOS to recover waiting stacks, objects, fields and retention evidence.
4
4
  ---
5
5
 
6
- # Insight .NET Dump 0.2.2
6
+ # Insight .NET Dump 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dotnet-stack
3
3
  description: Inspect live managed thread stacks to identify active or waiting work in an explicitly selected .NET process without taking a dump.
4
4
  ---
5
5
 
6
- # Insight .NET Stack 0.2.2
6
+ # Insight .NET Stack 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dotnet-trace
3
3
  description: Collect and inspect bounded .NET EventPipe traces to identify sampled thread work, waits or runtime activity; distinguish wall-clock samples from CPU consumption.
4
4
  ---
5
5
 
6
- # Insight .NET Trace 0.2.2
6
+ # Insight .NET Trace 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-frida
3
3
  description: Observe native call arguments/results or inspect runtime modules and exports in an explicitly selected authorized process with bounded Frida scripts. Use insight-cli frida to corroborate static findings with actual execution on macOS ARM64.
4
4
  ---
5
5
 
6
- # Insight Frida 0.2.2
6
+ # Insight Frida 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-ghidra
3
3
  description: Inspect or edit native binaries with Ghidra through insight-cli; use isolated contexts, multi-agent merge/refresh, server, GUI or debugger workflows. Choose this for static native behavior and references, not C# recovery from managed IL.
4
4
  ---
5
5
 
6
- # Insight Ghidra 0.2.2
6
+ # Insight Ghidra 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -89,3 +89,5 @@ and step out or over the call to inspect its actual return.
89
89
  Repeat mapping and live breakpoint setup for every new launch. A saved breakpoint bookmark
90
90
  does not prove placement in that new process; check its `trace_location_count` before resuming.
91
91
  Use `new` only when creating a session; subsequent calls take its actual returned ID.
92
+
93
+ Long import/save budgets and stopped-worker abandonment: see [recovery](references/recovery.md) and [setup](references/setup.md). Never replay an uncertain script.
@@ -51,3 +51,29 @@ goto. If its original owned GUI process has exited, continuation reports the unc
51
51
  as disconnected and retains saved program work. It does not recreate the old cursor or re-enable
52
52
  a previous prompt policy. Other unproved live UI effects remain retained until their outcome is
53
53
  established or the original process is known to have ended.
54
+
55
+ ## Abandon an uncertain private program attempt
56
+
57
+ A post-mutation save timeout does not repeat the script or issue another save in the
58
+ error handler. Status exposes the original request identity and retained phase/budget.
59
+ Arbitrary script effects are never inferred from metadata or from an unverified DB.
60
+ After inspecting the retained attempt, explicitly stop only its verified owned worker
61
+ (`tools processes`, then `tools processes kill <process>` if required). Resume the
62
+ last acknowledged private snapshot with:
63
+
64
+ ```sh
65
+ insight-cli permissions grant Destructive
66
+ insight-cli ghidra abandon --session <session> --target <target> \
67
+ --request-id <original-request> --acknowledge-unknown-effects --json
68
+ insight-cli ghidra open --session <session> --target <target> --json
69
+ ```
70
+
71
+ Abandon requires exactly one unresolved private program operation, an unchanged verified
72
+ previous snapshot/generation, a stopped original worker and no active publication or live
73
+ debugger. It retains the native project, candidate artifacts, original intent/execution and
74
+ previous diagnostic result. Its terminal request is `failed` / `state: abandoned` with
75
+ `outcome: unknown`; no effect is marked applied. Repeating abandonment retrieves the same
76
+ result. Earlier saved private edits remain pending. The original changing request ID cannot
77
+ execute again. Abandoning never undoes external effects or establishes what an arbitrary
78
+ script did; the acknowledgement explicitly accepts that uncertainty. Publication recovery,
79
+ initial import, UI and debugger attempts use their own protocols and cannot use this command.
@@ -48,3 +48,20 @@ debugger runtime directory when relevant. These are runtime profile settings, no
48
48
 
49
49
  Archive exchange is opt-in through `archiveUrl`; its optional token uses Factory secrets.
50
50
  See [archive](archive.md) for the service contract and submission recovery behavior.
51
+
52
+ ## Native operation budgets
53
+
54
+ Profile `initialImportSeconds` defaults to 3600 (1–86400 seconds); `saveSeconds`
55
+ defaults to 120 (1–3600 seconds). Configure them with `ghidra budgets set
56
+ --initial-import-seconds 7200 --save-seconds 300`; `ghidra budgets show` reads effective values.
57
+ This uses Factory ProfileStore without invalidating research or stopping native contexts.
58
+ Active requests retain their original budget. Generic `profile set` remains guarded for
59
+ profiles containing research; initial profile creation also accepts these fields. Both are execution policy, independent
60
+ of immutable target/load identity. Save and packed snapshot export use the save budget;
61
+ discovery and ordinary HTTP queries keep their 30-second budget. Each native request has
62
+ its own budget, not a total command deadline. Cancellation remains independent.
63
+
64
+ After an import timeout, wait for the original worker to end, raise its budget and continue
65
+ the original scope. Incomplete private analysis restarts; a completed receipt is reused.
66
+ A save timeout reports `phase: save`, the effective budget and `saveSeconds`. Inspect
67
+ `sessions status`; a native log or broken response stream cannot prove a saved snapshot.
@@ -3,7 +3,7 @@ name: insight-ilspy
3
3
  description: Recover C#, inspect IL/types/metadata, extract resources or export projects from managed .NET assemblies through insight-cli ILSpy. Choose native analysis for NativeAOT or ordinary PE machine code.
4
4
  ---
5
5
 
6
- # Insight ILSpy 0.2.2
6
+ # Insight ILSpy 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-interop
3
3
  description: Trace a .NET P/Invoke declaration to an explicitly supplied native library export and Ghidra function through insight-cli ilspy query, binary query and scoped ghidra APIs. Use for managed/native linkage evidence while keeping static correspondence separate from observed loading or execution.
4
4
  ---
5
5
 
6
- # Insight Interop 0.2.2
6
+ # Insight Interop 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-lldb
3
3
  description: Observe native runtime arguments, return values, registers, stacks and bounded memory at a selected breakpoint using an owned LLDB launch. Use insight-cli lldb on macOS ARM64 when static findings need a concrete execution check.
4
4
  ---
5
5
 
6
- # Insight LLDB 0.2.2
6
+ # Insight LLDB 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-llvm
3
3
  description: Inspect PE, ELF and Mach-O headers, dependencies, exports and symbols; query PDB debug information or a small instruction window with insight-cli LLVM utilities before opening a full analysis project.
4
4
  ---
5
5
 
6
- # Insight LLVM 0.2.2
6
+ # Insight LLVM 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-managed-heap
3
3
  description: Query structured .NET heap objects, primitive fields and managed stacks from a retained CoreCLR dump through insight-cli dotnet-dump query. Use for bounded offline dump investigation with an explicit matching DAC, preserving uncertainty and immutable input identity.
4
4
  ---
5
5
 
6
- # Insight Managed Heap 0.2.2
6
+ # Insight Managed Heap 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-managed-metadata
3
3
  description: Query managed assembly metadata, MethodDef tokens, P/Invoke declarations and bounded IL, or compare two C#/.NET assemblies through insight-cli ilspy query/compare. Use for structured static evidence and changed-method research without executing the target.
4
4
  ---
5
5
 
6
- # Insight Managed Metadata 0.2.2
6
+ # Insight Managed Metadata 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-mitmproxy
3
3
  description: Record, inspect and compare HTTP request/response evidence with insight-cli mitmproxy. Use when an owned client can explicitly use a loopback proxy; read native flow archives or HAR without replaying traffic. System interception and global certificate trust are outside this facade.
4
4
  ---
5
5
 
6
- # Insight mitmproxy 0.2.2
6
+ # Insight mitmproxy 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-overview
3
3
  description: Choose bounded tool overviews and focused drilldown through insight-cli without flooding agent context with whole-program code, traces or dumps. Use for tool discovery, scoped evidence paging and keeping native partial coverage separate from complete results.
4
4
  ---
5
5
 
6
- # Insight Overview 0.2.2
6
+ # Insight Overview 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-procmon
3
3
  description: Observe actual file and registry access by an authorized running Windows process through insight-cli procmon. Use when static paths or configuration guesses need runtime evidence; inspect retained captures without collecting again.
4
4
  ---
5
5
 
6
- # Insight ProcMon 0.2.2
6
+ # Insight ProcMon 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-re
3
3
  description: Investigate shipped programs and binary artifacts with insight-cli and other available tools; retain ordinary research files, coordinate independent agents and publish Ghidra annotations. Use for reverse engineering behavior, not ordinary source-repository browsing.
4
4
  ---
5
5
 
6
- # Insight RE 0.2.2
6
+ # Insight RE 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -51,3 +51,29 @@ goto. If its original owned GUI process has exited, continuation reports the unc
51
51
  as disconnected and retains saved program work. It does not recreate the old cursor or re-enable
52
52
  a previous prompt policy. Other unproved live UI effects remain retained until their outcome is
53
53
  established or the original process is known to have ended.
54
+
55
+ ## Abandon an uncertain private program attempt
56
+
57
+ A post-mutation save timeout does not repeat the script or issue another save in the
58
+ error handler. Status exposes the original request identity and retained phase/budget.
59
+ Arbitrary script effects are never inferred from metadata or from an unverified DB.
60
+ After inspecting the retained attempt, explicitly stop only its verified owned worker
61
+ (`tools processes`, then `tools processes kill <process>` if required). Resume the
62
+ last acknowledged private snapshot with:
63
+
64
+ ```sh
65
+ insight-cli permissions grant Destructive
66
+ insight-cli ghidra abandon --session <session> --target <target> \
67
+ --request-id <original-request> --acknowledge-unknown-effects --json
68
+ insight-cli ghidra open --session <session> --target <target> --json
69
+ ```
70
+
71
+ Abandon requires exactly one unresolved private program operation, an unchanged verified
72
+ previous snapshot/generation, a stopped original worker and no active publication or live
73
+ debugger. It retains the native project, candidate artifacts, original intent/execution and
74
+ previous diagnostic result. Its terminal request is `failed` / `state: abandoned` with
75
+ `outcome: unknown`; no effect is marked applied. Repeating abandonment retrieves the same
76
+ result. Earlier saved private edits remain pending. The original changing request ID cannot
77
+ execute again. Abandoning never undoes external effects or establishes what an arbitrary
78
+ script did; the acknowledgement explicitly accepts that uncertainty. Publication recovery,
79
+ initial import, UI and debugger attempts use their own protocols and cannot use this command.
@@ -3,7 +3,7 @@ name: insight-sevenzip
3
3
  description: Inventory, integrity-check and recover files from archives and supported containers with insight-cli 7-Zip, then hand recovered binaries or configuration to the appropriate research tool.
4
4
  ---
5
5
 
6
- # Insight 7-Zip 0.2.2
6
+ # Insight 7-Zip 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-strace
3
3
  description: Observe actual file reads, writes, process creation and network syscalls in an authorized owned native Linux launch using insight-cli strace. Use when static inference needs concrete operating-system interaction evidence.
4
4
  ---
5
5
 
6
- # Insight strace 0.2.2
6
+ # Insight strace 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-tshark
3
3
  description: Inspect an offline PCAP or PCAPNG with insight-cli tshark to identify protocols, HTTP/DNS/TLS fields, packet evidence and reconstructed TCP/UDP streams. Use for captured traffic questions; live acquisition and TLS decryption are separate tasks.
4
4
  ---
5
5
 
6
- # Insight TShark 0.2.2
6
+ # Insight TShark 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-windbg
3
3
  description: Investigate Windows native user-mode minidumps using bounded stacks, threads, registers, modules, memory and disassembly through insight-cli windbg. Use on Windows x64 when a captured runtime state needs native debugger evidence.
4
4
  ---
5
5
 
6
- # Insight WinDbg 0.2.2
6
+ # Insight WinDbg 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "package": "@eyeauras/insight-cli",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "skills": [
6
6
  "insight-cli",
7
7
  "insight-re",
@@ -3,7 +3,7 @@ name: insight-artifacts
3
3
  description: Retain a completed reverse-engineering evidence file or directory as an ordinary checkpoint using insight-cli artifacts save. Use after Ghidra or any external tool; preserve existing project formats and source of truth.
4
4
  ---
5
5
 
6
- # Insight Artifacts 0.2.2
6
+ # Insight Artifacts 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-binary
3
3
  description: Query structured PE, ELF and thin Mach-O headers, sections, imports and exports, or make an explicitly guarded new PE subsystem copy through insight-cli binary. Use for scoped binary structure, linkage and copy-only header edits without target execution.
4
4
  ---
5
5
 
6
- # Insight Binary 0.2.2
6
+ # Insight Binary 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-capture
3
3
  description: Capture one explicitly authorized native program run, exact stdout/stderr and declared file snapshots through insight-cli capture, then inspect or compare retained reports without replay. Use for controlled input/output research, preserving original files and interrupted or unknown outcomes.
4
4
  ---
5
5
 
6
- # Insight Capture 0.2.2
6
+ # Insight Capture 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-die
3
3
  description: Classify unknown executable or container inputs by format, architecture and compiler/runtime/packer signatures with Detect It Easy before choosing managed or native analysis. Use insight-cli die for static triage and preserve scan uncertainty.
4
4
  ---
5
5
 
6
- # Insight Detect It Easy 0.2.2
6
+ # Insight Detect It Easy 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dnspy
3
3
  description: Debug a managed Windows EXE at an IL breakpoint and read primitive arguments, or change one expected IL Int32 constant in a new assembly copy through insight-cli dnspy. Use when C# decompilation needs observed execution or a controlled binary edit.
4
4
  ---
5
5
 
6
- # Insight dnSpyEx 0.2.2
6
+ # Insight dnSpyEx 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dotnet-dump
3
3
  description: Capture a managed heap dump or inspect compatible .NET dumps with SOS to recover waiting stacks, objects, fields and retention evidence.
4
4
  ---
5
5
 
6
- # Insight .NET Dump 0.2.2
6
+ # Insight .NET Dump 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dotnet-stack
3
3
  description: Inspect live managed thread stacks to identify active or waiting work in an explicitly selected .NET process without taking a dump.
4
4
  ---
5
5
 
6
- # Insight .NET Stack 0.2.2
6
+ # Insight .NET Stack 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-dotnet-trace
3
3
  description: Collect and inspect bounded .NET EventPipe traces to identify sampled thread work, waits or runtime activity; distinguish wall-clock samples from CPU consumption.
4
4
  ---
5
5
 
6
- # Insight .NET Trace 0.2.2
6
+ # Insight .NET Trace 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-frida
3
3
  description: Observe native call arguments/results or inspect runtime modules and exports in an explicitly selected authorized process with bounded Frida scripts. Use insight-cli frida to corroborate static findings with actual execution on macOS ARM64.
4
4
  ---
5
5
 
6
- # Insight Frida 0.2.2
6
+ # Insight Frida 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-ghidra
3
3
  description: Inspect or edit native binaries with Ghidra through insight-cli; use isolated contexts, multi-agent merge/refresh, server, GUI or debugger workflows. Choose this for static native behavior and references, not C# recovery from managed IL.
4
4
  ---
5
5
 
6
- # Insight Ghidra 0.2.2
6
+ # Insight Ghidra 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -89,3 +89,5 @@ and step out or over the call to inspect its actual return.
89
89
  Repeat mapping and live breakpoint setup for every new launch. A saved breakpoint bookmark
90
90
  does not prove placement in that new process; check its `trace_location_count` before resuming.
91
91
  Use `new` only when creating a session; subsequent calls take its actual returned ID.
92
+
93
+ Long import/save budgets and stopped-worker abandonment: see [recovery](references/recovery.md) and [setup](references/setup.md). Never replay an uncertain script.
@@ -51,3 +51,29 @@ goto. If its original owned GUI process has exited, continuation reports the unc
51
51
  as disconnected and retains saved program work. It does not recreate the old cursor or re-enable
52
52
  a previous prompt policy. Other unproved live UI effects remain retained until their outcome is
53
53
  established or the original process is known to have ended.
54
+
55
+ ## Abandon an uncertain private program attempt
56
+
57
+ A post-mutation save timeout does not repeat the script or issue another save in the
58
+ error handler. Status exposes the original request identity and retained phase/budget.
59
+ Arbitrary script effects are never inferred from metadata or from an unverified DB.
60
+ After inspecting the retained attempt, explicitly stop only its verified owned worker
61
+ (`tools processes`, then `tools processes kill <process>` if required). Resume the
62
+ last acknowledged private snapshot with:
63
+
64
+ ```sh
65
+ insight-cli permissions grant Destructive
66
+ insight-cli ghidra abandon --session <session> --target <target> \
67
+ --request-id <original-request> --acknowledge-unknown-effects --json
68
+ insight-cli ghidra open --session <session> --target <target> --json
69
+ ```
70
+
71
+ Abandon requires exactly one unresolved private program operation, an unchanged verified
72
+ previous snapshot/generation, a stopped original worker and no active publication or live
73
+ debugger. It retains the native project, candidate artifacts, original intent/execution and
74
+ previous diagnostic result. Its terminal request is `failed` / `state: abandoned` with
75
+ `outcome: unknown`; no effect is marked applied. Repeating abandonment retrieves the same
76
+ result. Earlier saved private edits remain pending. The original changing request ID cannot
77
+ execute again. Abandoning never undoes external effects or establishes what an arbitrary
78
+ script did; the acknowledgement explicitly accepts that uncertainty. Publication recovery,
79
+ initial import, UI and debugger attempts use their own protocols and cannot use this command.
@@ -48,3 +48,20 @@ debugger runtime directory when relevant. These are runtime profile settings, no
48
48
 
49
49
  Archive exchange is opt-in through `archiveUrl`; its optional token uses Factory secrets.
50
50
  See [archive](archive.md) for the service contract and submission recovery behavior.
51
+
52
+ ## Native operation budgets
53
+
54
+ Profile `initialImportSeconds` defaults to 3600 (1–86400 seconds); `saveSeconds`
55
+ defaults to 120 (1–3600 seconds). Configure them with `ghidra budgets set
56
+ --initial-import-seconds 7200 --save-seconds 300`; `ghidra budgets show` reads effective values.
57
+ This uses Factory ProfileStore without invalidating research or stopping native contexts.
58
+ Active requests retain their original budget. Generic `profile set` remains guarded for
59
+ profiles containing research; initial profile creation also accepts these fields. Both are execution policy, independent
60
+ of immutable target/load identity. Save and packed snapshot export use the save budget;
61
+ discovery and ordinary HTTP queries keep their 30-second budget. Each native request has
62
+ its own budget, not a total command deadline. Cancellation remains independent.
63
+
64
+ After an import timeout, wait for the original worker to end, raise its budget and continue
65
+ the original scope. Incomplete private analysis restarts; a completed receipt is reused.
66
+ A save timeout reports `phase: save`, the effective budget and `saveSeconds`. Inspect
67
+ `sessions status`; a native log or broken response stream cannot prove a saved snapshot.
@@ -3,7 +3,7 @@ name: insight-ilspy
3
3
  description: Recover C#, inspect IL/types/metadata, extract resources or export projects from managed .NET assemblies through insight-cli ILSpy. Choose native analysis for NativeAOT or ordinary PE machine code.
4
4
  ---
5
5
 
6
- # Insight ILSpy 0.2.2
6
+ # Insight ILSpy 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-interop
3
3
  description: Trace a .NET P/Invoke declaration to an explicitly supplied native library export and Ghidra function through insight-cli ilspy query, binary query and scoped ghidra APIs. Use for managed/native linkage evidence while keeping static correspondence separate from observed loading or execution.
4
4
  ---
5
5
 
6
- # Insight Interop 0.2.2
6
+ # Insight Interop 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-lldb
3
3
  description: Observe native runtime arguments, return values, registers, stacks and bounded memory at a selected breakpoint using an owned LLDB launch. Use insight-cli lldb on macOS ARM64 when static findings need a concrete execution check.
4
4
  ---
5
5
 
6
- # Insight LLDB 0.2.2
6
+ # Insight LLDB 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-llvm
3
3
  description: Inspect PE, ELF and Mach-O headers, dependencies, exports and symbols; query PDB debug information or a small instruction window with insight-cli LLVM utilities before opening a full analysis project.
4
4
  ---
5
5
 
6
- # Insight LLVM 0.2.2
6
+ # Insight LLVM 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-managed-heap
3
3
  description: Query structured .NET heap objects, primitive fields and managed stacks from a retained CoreCLR dump through insight-cli dotnet-dump query. Use for bounded offline dump investigation with an explicit matching DAC, preserving uncertainty and immutable input identity.
4
4
  ---
5
5
 
6
- # Insight Managed Heap 0.2.2
6
+ # Insight Managed Heap 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-managed-metadata
3
3
  description: Query managed assembly metadata, MethodDef tokens, P/Invoke declarations and bounded IL, or compare two C#/.NET assemblies through insight-cli ilspy query/compare. Use for structured static evidence and changed-method research without executing the target.
4
4
  ---
5
5
 
6
- # Insight Managed Metadata 0.2.2
6
+ # Insight Managed Metadata 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-mitmproxy
3
3
  description: Record, inspect and compare HTTP request/response evidence with insight-cli mitmproxy. Use when an owned client can explicitly use a loopback proxy; read native flow archives or HAR without replaying traffic. System interception and global certificate trust are outside this facade.
4
4
  ---
5
5
 
6
- # Insight mitmproxy 0.2.2
6
+ # Insight mitmproxy 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-overview
3
3
  description: Choose bounded tool overviews and focused drilldown through insight-cli without flooding agent context with whole-program code, traces or dumps. Use for tool discovery, scoped evidence paging and keeping native partial coverage separate from complete results.
4
4
  ---
5
5
 
6
- # Insight Overview 0.2.2
6
+ # Insight Overview 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-procmon
3
3
  description: Observe actual file and registry access by an authorized running Windows process through insight-cli procmon. Use when static paths or configuration guesses need runtime evidence; inspect retained captures without collecting again.
4
4
  ---
5
5
 
6
- # Insight ProcMon 0.2.2
6
+ # Insight ProcMon 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-re
3
3
  description: Investigate shipped programs and binary artifacts with insight-cli and other available tools; retain ordinary research files, coordinate independent agents and publish Ghidra annotations. Use for reverse engineering behavior, not ordinary source-repository browsing.
4
4
  ---
5
5
 
6
- # Insight RE 0.2.2
6
+ # Insight RE 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -51,3 +51,29 @@ goto. If its original owned GUI process has exited, continuation reports the unc
51
51
  as disconnected and retains saved program work. It does not recreate the old cursor or re-enable
52
52
  a previous prompt policy. Other unproved live UI effects remain retained until their outcome is
53
53
  established or the original process is known to have ended.
54
+
55
+ ## Abandon an uncertain private program attempt
56
+
57
+ A post-mutation save timeout does not repeat the script or issue another save in the
58
+ error handler. Status exposes the original request identity and retained phase/budget.
59
+ Arbitrary script effects are never inferred from metadata or from an unverified DB.
60
+ After inspecting the retained attempt, explicitly stop only its verified owned worker
61
+ (`tools processes`, then `tools processes kill <process>` if required). Resume the
62
+ last acknowledged private snapshot with:
63
+
64
+ ```sh
65
+ insight-cli permissions grant Destructive
66
+ insight-cli ghidra abandon --session <session> --target <target> \
67
+ --request-id <original-request> --acknowledge-unknown-effects --json
68
+ insight-cli ghidra open --session <session> --target <target> --json
69
+ ```
70
+
71
+ Abandon requires exactly one unresolved private program operation, an unchanged verified
72
+ previous snapshot/generation, a stopped original worker and no active publication or live
73
+ debugger. It retains the native project, candidate artifacts, original intent/execution and
74
+ previous diagnostic result. Its terminal request is `failed` / `state: abandoned` with
75
+ `outcome: unknown`; no effect is marked applied. Repeating abandonment retrieves the same
76
+ result. Earlier saved private edits remain pending. The original changing request ID cannot
77
+ execute again. Abandoning never undoes external effects or establishes what an arbitrary
78
+ script did; the acknowledgement explicitly accepts that uncertainty. Publication recovery,
79
+ initial import, UI and debugger attempts use their own protocols and cannot use this command.
@@ -3,7 +3,7 @@ name: insight-sevenzip
3
3
  description: Inventory, integrity-check and recover files from archives and supported containers with insight-cli 7-Zip, then hand recovered binaries or configuration to the appropriate research tool.
4
4
  ---
5
5
 
6
- # Insight 7-Zip 0.2.2
6
+ # Insight 7-Zip 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-strace
3
3
  description: Observe actual file reads, writes, process creation and network syscalls in an authorized owned native Linux launch using insight-cli strace. Use when static inference needs concrete operating-system interaction evidence.
4
4
  ---
5
5
 
6
- # Insight strace 0.2.2
6
+ # Insight strace 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-tshark
3
3
  description: Inspect an offline PCAP or PCAPNG with insight-cli tshark to identify protocols, HTTP/DNS/TLS fields, packet evidence and reconstructed TCP/UDP streams. Use for captured traffic questions; live acquisition and TLS decryption are separate tasks.
4
4
  ---
5
5
 
6
- # Insight TShark 0.2.2
6
+ # Insight TShark 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-windbg
3
3
  description: Investigate Windows native user-mode minidumps using bounded stacks, threads, registers, modules, memory and disassembly through insight-cli windbg. Use on Windows x64 when a captured runtime state needs native debugger evidence.
4
4
  ---
5
5
 
6
- # Insight WinDbg 0.2.2
6
+ # Insight WinDbg 0.2.3
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized