@maximtop/opencode-debug-mode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/ATTRIBUTION.md +5 -0
  2. package/CONTRIBUTING.md +48 -0
  3. package/LICENSE +21 -0
  4. package/README.md +76 -0
  5. package/SECURITY.md +17 -0
  6. package/assets/debug-agent.md +71 -0
  7. package/dist/chunk-2PCBVVWX.js +20 -0
  8. package/dist/chunk-2PCBVVWX.js.map +1 -0
  9. package/dist/cleanup/export.d.ts +23 -0
  10. package/dist/cleanup/service.d.ts +33 -0
  11. package/dist/cleanup/types.d.ts +235 -0
  12. package/dist/collector/auth.d.ts +3 -0
  13. package/dist/collector/body.d.ts +7 -0
  14. package/dist/collector/ingest.d.ts +8 -0
  15. package/dist/collector/router.d.ts +8 -0
  16. package/dist/collector/server.d.ts +25 -0
  17. package/dist/core/clock.d.ts +5 -0
  18. package/dist/core/constants.d.ts +20 -0
  19. package/dist/core/errors.d.ts +12 -0
  20. package/dist/core/result.d.ts +24 -0
  21. package/dist/core/schemas.d.ts +9 -0
  22. package/dist/errors-IQTPGK5R.js +7 -0
  23. package/dist/errors-IQTPGK5R.js.map +1 -0
  24. package/dist/evidence/read.d.ts +8 -0
  25. package/dist/evidence/sanitize.d.ts +9 -0
  26. package/dist/evidence/store.d.ts +65 -0
  27. package/dist/evidence/types.d.ts +83 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +3652 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/investigation/schema.d.ts +184 -0
  32. package/dist/investigation/store.d.ts +30 -0
  33. package/dist/plugin.d.ts +8 -0
  34. package/dist/probes/extension-permissions.d.ts +8 -0
  35. package/dist/probes/helper.d.ts +22 -0
  36. package/dist/probes/registry.d.ts +18 -0
  37. package/dist/probes/remove.d.ts +16 -0
  38. package/dist/probes/template.d.ts +21 -0
  39. package/dist/probes/types.d.ts +24 -0
  40. package/dist/process/line-decoder.d.ts +26 -0
  41. package/dist/process/protocol.d.ts +40 -0
  42. package/dist/process/service.d.ts +46 -0
  43. package/dist/process/tree.d.ts +16 -0
  44. package/dist/process-supervisor.js +276 -0
  45. package/dist/process-supervisor.js.map +1 -0
  46. package/dist/run/service.d.ts +21 -0
  47. package/dist/session/atomic-json.d.ts +1 -0
  48. package/dist/session/manifest-store.d.ts +22 -0
  49. package/dist/session/orphan-recovery.d.ts +16 -0
  50. package/dist/session/paths.d.ts +11 -0
  51. package/dist/session/registry.d.ts +48 -0
  52. package/dist/session/secret-store.d.ts +7 -0
  53. package/dist/session/types.d.ts +296 -0
  54. package/dist/tools/cleanup-tool.d.ts +4 -0
  55. package/dist/tools/collector-tools.d.ts +17 -0
  56. package/dist/tools/common.d.ts +4 -0
  57. package/dist/tools/evidence-tools.d.ts +4 -0
  58. package/dist/tools/index.d.ts +30 -0
  59. package/dist/tools/probe-tools.d.ts +5 -0
  60. package/dist/tools/run-tools.d.ts +12 -0
  61. package/dist/tools/session-tools.d.ts +4 -0
  62. package/dist/tools/state-tools.d.ts +4 -0
  63. package/docs/architecture.md +15 -0
  64. package/docs/lifecycle.md +11 -0
  65. package/examples/chrome-extension/background.js +5 -0
  66. package/examples/chrome-extension/content.js +3 -0
  67. package/examples/cli/run.mjs +3 -0
  68. package/examples/firefox-extension/background.js +4 -0
  69. package/examples/firefox-extension/content.js +3 -0
  70. package/examples/web/app.js +5 -0
  71. package/package.json +80 -0
@@ -0,0 +1,296 @@
1
+ import { z } from "zod";
2
+ export declare const EvidenceCountersSchema: z.ZodObject<{
3
+ accepted: z.ZodNumber;
4
+ rejected: z.ZodNumber;
5
+ sampled: z.ZodNumber;
6
+ truncated: z.ZodNumber;
7
+ dropped: z.ZodNumber;
8
+ requests: z.ZodNumber;
9
+ }, z.core.$strict>;
10
+ export declare const CollectorManifestSchema: z.ZodObject<{
11
+ id: z.ZodString;
12
+ host: z.ZodEnum<{
13
+ "127.0.0.1": "127.0.0.1";
14
+ "::1": "::1";
15
+ }>;
16
+ port: z.ZodNumber;
17
+ status: z.ZodEnum<{
18
+ draining: "draining";
19
+ failed: "failed";
20
+ ready: "ready";
21
+ starting: "starting";
22
+ stopped: "stopped";
23
+ }>;
24
+ startedAt: z.ZodString;
25
+ stoppedAt: z.ZodOptional<z.ZodString>;
26
+ }, z.core.$strict>;
27
+ export declare const RunManifestSchema: z.ZodObject<{
28
+ id: z.ZodString;
29
+ label: z.ZodEnum<{
30
+ "post-fix": "post-fix";
31
+ "pre-fix": "pre-fix";
32
+ }>;
33
+ reproduction: z.ZodString;
34
+ status: z.ZodEnum<{
35
+ cancelled: "cancelled";
36
+ completed: "completed";
37
+ failed: "failed";
38
+ planned: "planned";
39
+ running: "running";
40
+ timed_out: "timed_out";
41
+ waiting: "waiting";
42
+ }>;
43
+ createdAt: z.ZodString;
44
+ completedAt: z.ZodOptional<z.ZodString>;
45
+ }, z.core.$strict>;
46
+ export declare const ProcessManifestSchema: z.ZodObject<{
47
+ id: z.ZodString;
48
+ runId: z.ZodString;
49
+ commandSummary: z.ZodString;
50
+ supervisorPid: z.ZodOptional<z.ZodNumber>;
51
+ targetPid: z.ZodOptional<z.ZodNumber>;
52
+ ownerNonceHash: z.ZodString;
53
+ status: z.ZodEnum<{
54
+ cancelled: "cancelled";
55
+ exited: "exited";
56
+ failed: "failed";
57
+ running: "running";
58
+ starting: "starting";
59
+ terminated: "terminated";
60
+ timed_out: "timed_out";
61
+ }>;
62
+ startedAt: z.ZodString;
63
+ completedAt: z.ZodOptional<z.ZodString>;
64
+ exitCode: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
65
+ signal: z.ZodOptional<z.ZodNullable<z.ZodString>>;
66
+ }, z.core.$strict>;
67
+ export declare const ProbeManifestSchema: z.ZodObject<{
68
+ id: z.ZodString;
69
+ runId: z.ZodString;
70
+ hypothesisId: z.ZodString;
71
+ sourceFile: z.ZodString;
72
+ sourceLine: z.ZodNumber;
73
+ sourceColumn: z.ZodOptional<z.ZodNumber>;
74
+ message: z.ZodString;
75
+ transport: z.ZodEnum<{
76
+ "extension-background": "extension-background";
77
+ "extension-content": "extension-content";
78
+ "http-web": "http-web";
79
+ process: "process";
80
+ }>;
81
+ captures: z.ZodArray<z.ZodObject<{
82
+ label: z.ZodString;
83
+ path: z.ZodString;
84
+ }, z.core.$strict>>;
85
+ sampling: z.ZodDiscriminatedUnion<[z.ZodObject<{
86
+ mode: z.ZodLiteral<"every">;
87
+ n: z.ZodNumber;
88
+ }, z.core.$strict>, z.ZodObject<{
89
+ mode: z.ZodLiteral<"aggregate">;
90
+ windowMs: z.ZodNumber;
91
+ }, z.core.$strict>], "mode">;
92
+ status: z.ZodEnum<{
93
+ active: "active";
94
+ ambiguous: "ambiguous";
95
+ planned: "planned";
96
+ registered: "registered";
97
+ removed: "removed";
98
+ validated: "validated";
99
+ }>;
100
+ validationStatus: z.ZodEnum<{
101
+ failed: "failed";
102
+ pending: "pending";
103
+ validated: "validated";
104
+ }>;
105
+ markerStart: z.ZodString;
106
+ markerEnd: z.ZodString;
107
+ expectedBlock: z.ZodOptional<z.ZodString>;
108
+ expectedHash: z.ZodOptional<z.ZodString>;
109
+ }, z.core.$strict>;
110
+ export declare const OwnedFileManifestSchema: z.ZodObject<{
111
+ path: z.ZodString;
112
+ sha256: z.ZodString;
113
+ bytes: z.ZodNumber;
114
+ kind: z.ZodEnum<{
115
+ temporary: "temporary";
116
+ "transport-helper": "transport-helper";
117
+ }>;
118
+ }, z.core.$strict>;
119
+ export declare const PermissionChangeSchema: z.ZodObject<{
120
+ manifestPath: z.ZodString;
121
+ property: z.ZodEnum<{
122
+ host_permissions: "host_permissions";
123
+ permissions: "permissions";
124
+ }>;
125
+ matchPattern: z.ZodString;
126
+ addedBySession: z.ZodBoolean;
127
+ }, z.core.$strict>;
128
+ export declare const CleanupProgressSchema: z.ZodObject<{
129
+ status: z.ZodEnum<{
130
+ complete: "complete";
131
+ not_started: "not_started";
132
+ partial: "partial";
133
+ running: "running";
134
+ }>;
135
+ completedResources: z.ZodArray<z.ZodString>;
136
+ }, z.core.$strict>;
137
+ export declare const ManifestSchema: z.ZodObject<{
138
+ package: z.ZodLiteral<"opencode-debug-mode">;
139
+ schemaVersion: z.ZodLiteral<1>;
140
+ revision: z.ZodNumber;
141
+ sessionId: z.ZodString;
142
+ trustedSessionHash: z.ZodString;
143
+ projectRoot: z.ZodString;
144
+ sessionDir: z.ZodString;
145
+ status: z.ZodEnum<{
146
+ active: "active";
147
+ cleaned: "cleaned";
148
+ cleaning: "cleaning";
149
+ partial: "partial";
150
+ }>;
151
+ createdAt: z.ZodString;
152
+ lastActivityAt: z.ZodString;
153
+ expiresAt: z.ZodString;
154
+ waitingForReproduction: z.ZodBoolean;
155
+ keepArtifacts: z.ZodBoolean;
156
+ retentionDestination: z.ZodOptional<z.ZodString>;
157
+ collector: z.ZodNullable<z.ZodObject<{
158
+ id: z.ZodString;
159
+ host: z.ZodEnum<{
160
+ "127.0.0.1": "127.0.0.1";
161
+ "::1": "::1";
162
+ }>;
163
+ port: z.ZodNumber;
164
+ status: z.ZodEnum<{
165
+ draining: "draining";
166
+ failed: "failed";
167
+ ready: "ready";
168
+ starting: "starting";
169
+ stopped: "stopped";
170
+ }>;
171
+ startedAt: z.ZodString;
172
+ stoppedAt: z.ZodOptional<z.ZodString>;
173
+ }, z.core.$strict>>;
174
+ runs: z.ZodArray<z.ZodObject<{
175
+ id: z.ZodString;
176
+ label: z.ZodEnum<{
177
+ "post-fix": "post-fix";
178
+ "pre-fix": "pre-fix";
179
+ }>;
180
+ reproduction: z.ZodString;
181
+ status: z.ZodEnum<{
182
+ cancelled: "cancelled";
183
+ completed: "completed";
184
+ failed: "failed";
185
+ planned: "planned";
186
+ running: "running";
187
+ timed_out: "timed_out";
188
+ waiting: "waiting";
189
+ }>;
190
+ createdAt: z.ZodString;
191
+ completedAt: z.ZodOptional<z.ZodString>;
192
+ }, z.core.$strict>>;
193
+ processes: z.ZodArray<z.ZodObject<{
194
+ id: z.ZodString;
195
+ runId: z.ZodString;
196
+ commandSummary: z.ZodString;
197
+ supervisorPid: z.ZodOptional<z.ZodNumber>;
198
+ targetPid: z.ZodOptional<z.ZodNumber>;
199
+ ownerNonceHash: z.ZodString;
200
+ status: z.ZodEnum<{
201
+ cancelled: "cancelled";
202
+ exited: "exited";
203
+ failed: "failed";
204
+ running: "running";
205
+ starting: "starting";
206
+ terminated: "terminated";
207
+ timed_out: "timed_out";
208
+ }>;
209
+ startedAt: z.ZodString;
210
+ completedAt: z.ZodOptional<z.ZodString>;
211
+ exitCode: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
212
+ signal: z.ZodOptional<z.ZodNullable<z.ZodString>>;
213
+ }, z.core.$strict>>;
214
+ probes: z.ZodArray<z.ZodObject<{
215
+ id: z.ZodString;
216
+ runId: z.ZodString;
217
+ hypothesisId: z.ZodString;
218
+ sourceFile: z.ZodString;
219
+ sourceLine: z.ZodNumber;
220
+ sourceColumn: z.ZodOptional<z.ZodNumber>;
221
+ message: z.ZodString;
222
+ transport: z.ZodEnum<{
223
+ "extension-background": "extension-background";
224
+ "extension-content": "extension-content";
225
+ "http-web": "http-web";
226
+ process: "process";
227
+ }>;
228
+ captures: z.ZodArray<z.ZodObject<{
229
+ label: z.ZodString;
230
+ path: z.ZodString;
231
+ }, z.core.$strict>>;
232
+ sampling: z.ZodDiscriminatedUnion<[z.ZodObject<{
233
+ mode: z.ZodLiteral<"every">;
234
+ n: z.ZodNumber;
235
+ }, z.core.$strict>, z.ZodObject<{
236
+ mode: z.ZodLiteral<"aggregate">;
237
+ windowMs: z.ZodNumber;
238
+ }, z.core.$strict>], "mode">;
239
+ status: z.ZodEnum<{
240
+ active: "active";
241
+ ambiguous: "ambiguous";
242
+ planned: "planned";
243
+ registered: "registered";
244
+ removed: "removed";
245
+ validated: "validated";
246
+ }>;
247
+ validationStatus: z.ZodEnum<{
248
+ failed: "failed";
249
+ pending: "pending";
250
+ validated: "validated";
251
+ }>;
252
+ markerStart: z.ZodString;
253
+ markerEnd: z.ZodString;
254
+ expectedBlock: z.ZodOptional<z.ZodString>;
255
+ expectedHash: z.ZodOptional<z.ZodString>;
256
+ }, z.core.$strict>>;
257
+ ownedFiles: z.ZodArray<z.ZodObject<{
258
+ path: z.ZodString;
259
+ sha256: z.ZodString;
260
+ bytes: z.ZodNumber;
261
+ kind: z.ZodEnum<{
262
+ temporary: "temporary";
263
+ "transport-helper": "transport-helper";
264
+ }>;
265
+ }, z.core.$strict>>;
266
+ permissionChanges: z.ZodArray<z.ZodObject<{
267
+ manifestPath: z.ZodString;
268
+ property: z.ZodEnum<{
269
+ host_permissions: "host_permissions";
270
+ permissions: "permissions";
271
+ }>;
272
+ matchPattern: z.ZodString;
273
+ addedBySession: z.ZodBoolean;
274
+ }, z.core.$strict>>;
275
+ counters: z.ZodObject<{
276
+ accepted: z.ZodNumber;
277
+ rejected: z.ZodNumber;
278
+ sampled: z.ZodNumber;
279
+ truncated: z.ZodNumber;
280
+ dropped: z.ZodNumber;
281
+ requests: z.ZodNumber;
282
+ }, z.core.$strict>;
283
+ cleanup: z.ZodObject<{
284
+ status: z.ZodEnum<{
285
+ complete: "complete";
286
+ not_started: "not_started";
287
+ partial: "partial";
288
+ running: "running";
289
+ }>;
290
+ completedResources: z.ZodArray<z.ZodString>;
291
+ }, z.core.$strict>;
292
+ }, z.core.$strict>;
293
+ export type CleanupManifest = z.infer<typeof ManifestSchema>;
294
+ export type ManifestProbe = z.infer<typeof ProbeManifestSchema>;
295
+ export type ManifestRun = z.infer<typeof RunManifestSchema>;
296
+ export type EvidenceCounters = z.infer<typeof EvidenceCountersSchema>;
@@ -0,0 +1,4 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { CleanupService } from "../cleanup/service.js";
3
+ import type { DebugSession, SessionRegistry } from "../session/registry.js";
4
+ export declare function createCleanupTool(registry: SessionRegistry, cleanupFor: (session: DebugSession) => CleanupService): ToolDefinition;
@@ -0,0 +1,17 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { DebugSession, SessionRegistry } from "../session/registry.js";
3
+ export interface PublicCollectorService {
4
+ start(input: {
5
+ runtime: "web" | "extension-background";
6
+ transportTargetPath?: string;
7
+ extensionManifestPath?: string;
8
+ }): Promise<{
9
+ collectorId: string;
10
+ host: "127.0.0.1" | "::1";
11
+ port: number;
12
+ status: string;
13
+ helperImport?: string;
14
+ helperPath?: string;
15
+ }>;
16
+ }
17
+ export declare function createCollectorStartTool(registry: SessionRegistry, collectorFor: (session: DebugSession) => PublicCollectorService): ToolDefinition;
@@ -0,0 +1,4 @@
1
+ import { type ToolResultEnvelope } from "../core/result.js";
2
+ export declare function jsonSuccess<T>(value: T): string;
3
+ export declare function jsonFailure(error: unknown, fallback?: string): string;
4
+ export declare function serializeEnvelope<T>(value: ToolResultEnvelope<T>): string;
@@ -0,0 +1,4 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { EvidenceStore } from "../evidence/store.js";
3
+ import type { DebugSession, SessionRegistry } from "../session/registry.js";
4
+ export declare function createEvidenceReadTool(registry: SessionRegistry, evidenceFor: (session: DebugSession) => EvidenceStore): ToolDefinition;
@@ -0,0 +1,30 @@
1
+ import type { ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { CleanupService } from "../cleanup/service.js";
3
+ import type { EvidenceStore } from "../evidence/store.js";
4
+ import type { ProbeRegistry } from "../probes/registry.js";
5
+ import type { RunService } from "../run/service.js";
6
+ import type { DebugSession, SessionRegistry } from "../session/registry.js";
7
+ import { type PublicCollectorService } from "./collector-tools.js";
8
+ import { type RunToolDependencies } from "./run-tools.js";
9
+ export interface DebugToolDependencies extends RunToolDependencies {
10
+ registry: SessionRegistry;
11
+ runFor(session: DebugSession): RunService;
12
+ collectorFor(session: DebugSession): PublicCollectorService;
13
+ probesFor(session: DebugSession): ProbeRegistry;
14
+ evidenceFor(session: DebugSession): EvidenceStore;
15
+ cleanupFor(session: DebugSession): CleanupService;
16
+ }
17
+ export type DebugTools = {
18
+ debug_session_start: ToolDefinition;
19
+ debug_session_status: ToolDefinition;
20
+ debug_state_read: ToolDefinition;
21
+ debug_state_checkpoint: ToolDefinition;
22
+ debug_run_start: ToolDefinition;
23
+ debug_process_capture: ToolDefinition;
24
+ debug_collector_start: ToolDefinition;
25
+ debug_probe_prepare: ToolDefinition;
26
+ debug_probe_register: ToolDefinition;
27
+ debug_evidence_read: ToolDefinition;
28
+ debug_cleanup: ToolDefinition;
29
+ };
30
+ export declare function createDebugTools(dependencies: DebugToolDependencies): DebugTools;
@@ -0,0 +1,5 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { ProbeRegistry } from "../probes/registry.js";
3
+ import type { DebugSession, SessionRegistry } from "../session/registry.js";
4
+ export declare function createProbePrepareTool(registry: SessionRegistry, probesFor: (session: DebugSession) => ProbeRegistry): ToolDefinition;
5
+ export declare function createProbeRegisterTool(registry: SessionRegistry, probesFor: (session: DebugSession) => ProbeRegistry): ToolDefinition;
@@ -0,0 +1,12 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { ProbeRegistry } from "../probes/registry.js";
3
+ import type { ProcessService } from "../process/service.js";
4
+ import type { RunService } from "../run/service.js";
5
+ import type { DebugSession, SessionRegistry } from "../session/registry.js";
6
+ export interface RunToolDependencies {
7
+ registry: Pick<SessionRegistry, "requireOwned">;
8
+ processFor(session: DebugSession): Pick<ProcessService, "capture">;
9
+ probesFor(session: DebugSession): Pick<ProbeRegistry, "validate" | "requireValidatedForRun">;
10
+ }
11
+ export declare function createProcessCaptureTool(dependencies: RunToolDependencies): ToolDefinition;
12
+ export declare function createRunStartTool(registry: SessionRegistry, runFor: (session: DebugSession) => RunService): ToolDefinition;
@@ -0,0 +1,4 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { SessionRegistry } from "../session/registry.js";
3
+ export declare function createSessionStartTool(registry: SessionRegistry): ToolDefinition;
4
+ export declare function createSessionStatusTool(registry: SessionRegistry): ToolDefinition;
@@ -0,0 +1,4 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { SessionRegistry } from "../session/registry.js";
3
+ export declare function createStateReadTool(registry: SessionRegistry): ToolDefinition;
4
+ export declare function createStateCheckpointTool(registry: SessionRegistry): ToolDefinition;
@@ -0,0 +1,15 @@
1
+ # Architecture
2
+
3
+ The package exports one OpenCode plugin. Its config hook installs the `debug` primary agent and routing-only command. Every public tool derives ownership from `ToolContext.sessionID`; public arguments cannot select a different session.
4
+
5
+ Each session receives a random directory under the package OS-temporary base. The strict revisioned manifest inventories runs, processes, collectors, markers, helper hashes, permission entries, counters, and cleanup progress. The separate strict checkpoint stores conclusions and stable evidence references. A serialized NDJSON writer stores sanitized evidence within event and byte limits.
6
+
7
+ CLI capture forks a package-owned Node supervisor over IPC. The supervisor starts the target detached without a shell, forwards bounded streams, and kills the descendant tree on timeout, explicit termination, or parent disconnect.
8
+
9
+ Web and extension-background capture uses a Node HTTP server bound explicitly to `127.0.0.1`, with `::1` as the only availability fallback. Exact routes provide authenticated ingestion and minimal health. The per-session credential never appears in tool output.
10
+
11
+ Probe preparation produces deterministic JS/TS marker blocks. Web/background credentials exist only in a newly created exact-hash helper. Extension content probes use messaging and never fetch loopback directly.
12
+
13
+ Cleanup drains the collector, terminates processes, removes exact markers, removes session-added permissions and exact-hash helpers, runs an optional clean check, optionally stages a sanitized bundle, removes the secret, and deletes the ephemeral directory. Each resource reports success, already-clean, skipped, or failed.
14
+
15
+ Future transports should implement the conceptual `EvidenceBackend` boundary—start, ingest/capture, status, and cleanup—without changing the canonical event, ownership, state, or tool contracts. v1 intentionally has no backend registry.
@@ -0,0 +1,11 @@
1
+ # Investigation lifecycle
2
+
3
+ The durable phases are intake, hypotheses, baseline, instrumenting, waiting for reproduction, analyzing, fixing, verifying, cleaning, and a terminal completed/abandoned/escalated outcome.
4
+
5
+ Every meaningful transition uses revision compare-and-swap. A resumed turn and compaction hook require state reading before another action. Missing, malformed, oversized, stale, or unsupported state returns an explicit recovery result; the package never invents lost conclusions.
6
+
7
+ A process lease and an explicit waiting-for-reproduction lease suppress idle expiry. Unauthenticated collector traffic does not update activity. The next active tool action ends an obsolete wait. Idle unleased sessions are cleaned after 30 minutes.
8
+
9
+ Normal completion and all terminal paths use the same idempotent cleanup. Session deletion, plugin disposal, collector failure, timeout, cancellation, and verified expired startup recovery also converge on teardown. Recovery scans only direct package-owned `session-*` children and ignores active, unrelated, invalid, or symlinked entries.
10
+
11
+ With default deletion, the lifecycle ends with no session directory. With explicit retention, sanitized public files are staged before ephemeral deletion and finalized only after a secret scan.
@@ -0,0 +1,5 @@
1
+ chrome.runtime.onMessage.addListener((message) => {
2
+ if (message.type !== "opencode-debug-event") return undefined
3
+ // The temporary package-owned background helper accepts the bounded event.
4
+ return globalThis.__opencodeDebugEmit?.(message.event)
5
+ })
@@ -0,0 +1,3 @@
1
+ export function relayDebugEvent(event) {
2
+ return chrome.runtime.sendMessage({ type: "opencode-debug-event", event })
3
+ }
@@ -0,0 +1,3 @@
1
+ // Start a debug session, create a pre-fix run, then let debug_process_capture
2
+ // execute the target with an executable plus argument array.
3
+ console.log("Run the target application's normal deterministic reproduction here")
@@ -0,0 +1,4 @@
1
+ browser.runtime.onMessage.addListener((message) => {
2
+ if (message.type !== "opencode-debug-event") return undefined
3
+ return globalThis.__opencodeDebugEmit?.(message.event)
4
+ })
@@ -0,0 +1,3 @@
1
+ export function relayDebugEvent(event) {
2
+ return browser.runtime.sendMessage({ type: "opencode-debug-event", event })
3
+ }
@@ -0,0 +1,5 @@
1
+ // The debug agent supplies this import only while the owned helper exists.
2
+ // import { __opencodeDebugEmit } from "./debug-transport.mjs"
3
+ export function reproduce(value) {
4
+ return value
5
+ }
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@maximtop/opencode-debug-mode",
3
+ "version": "0.1.0",
4
+ "description": "Hypothesis-driven runtime debugging agent for OpenCode",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/maximtop/opencode-debug-mode.git"
9
+ },
10
+ "homepage": "https://github.com/maximtop/opencode-debug-mode#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/maximtop/opencode-debug-mode/issues"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "registry": "https://registry.npmjs.org/",
17
+ "provenance": true
18
+ },
19
+ "type": "module",
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "assets",
31
+ "docs",
32
+ "examples",
33
+ "README.md",
34
+ "SECURITY.md",
35
+ "CONTRIBUTING.md",
36
+ "ATTRIBUTION.md",
37
+ "LICENSE"
38
+ ],
39
+ "sideEffects": false,
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "peerDependencies": {
44
+ "@opencode-ai/plugin": ">=1.17.0 <2"
45
+ },
46
+ "dependencies": {
47
+ "jsonc-parser": "^3.3.1",
48
+ "zod": "^4.4.3"
49
+ },
50
+ "overrides": {
51
+ "esbuild": "0.28.1"
52
+ },
53
+ "devDependencies": {
54
+ "@biomejs/biome": "^2.5.3",
55
+ "@opencode-ai/plugin": "^1.17.19",
56
+ "@types/node": "^20.19.25",
57
+ "@vitest/coverage-v8": "^4.1.10",
58
+ "tsup": "^8.5.1",
59
+ "typescript": "^7.0.2",
60
+ "vitest": "^4.1.10"
61
+ },
62
+ "scripts": {
63
+ "build": "tsup && tsc -p tsconfig.build.json",
64
+ "typecheck": "tsc --noEmit",
65
+ "lint": "biome check .",
66
+ "format": "biome check --write .",
67
+ "test": "vitest run tests/unit",
68
+ "test:integration": "vitest run tests/integration",
69
+ "test:e2e": "vitest run tests/e2e",
70
+ "coverage": "npm run build && vitest run --coverage",
71
+ "check": "npm run lint && npm run typecheck && npm run test && npm run build && npm run test:integration"
72
+ },
73
+ "keywords": [
74
+ "opencode",
75
+ "debugging",
76
+ "agent",
77
+ "runtime",
78
+ "observability"
79
+ ]
80
+ }