Imported from JUNERDD/skills (
skills/debug/SKILL.md). Install upstream withnpx skills add JUNERDD/skills --skill debug. Copyright stays with the author.
Debug
Maximize information gained per failing reproduction. Treat code reading, tests, static analysis, and existing telemetry as hypothesis inputs; require runtime evidence to prove the originating fault, its propagation, and the reported symptom.
Use one coverage-first workflow. Scale probe breadth with reproduction cost, residual ambiguity, privacy risk, and observer cost. Treat “one pass” as the initial failing reproduction only; allow a targeted blind-spot run and a separate post-repair verification run when needed.
Broad first-pass breakpoint batch
- When a supported native debugger is attached and pausing is safe, derive the complete first-pass breakpoint set from the causal map before any
runorcontinue. Install every safe, nonredundant initial breakpoint in one setup phase. If the debugger accepts one location per call, issue all set-breakpoint calls back-to-back without resuming between them. Never default to one or two exploratory breakpoints while additional material locations are already justified. - Cover the failing-flow ingress and symptom boundary, both sides of transformations and ownership transfers, discriminating branches, before/after mutations, async schedule/start/settle/cancel points, cache/persistence/external-call boundaries, exception/fallback paths, invariants, and the terminal or observation checkpoint. Map each breakpoint to a concrete question plus the stack frames, locals, or expressions to inspect. Do not add redundant locations merely to inflate the count.
- Map a breakpoint to one or more causal boundaries. When one physical paused frame genuinely exposes multiple boundaries, keep one breakpoint and require a concrete
sharedBoundaryRationale; otherwise use distinct locations rather than a catch-all mapping. Treat the same normalized sourcelocationas one physical breakpoint regardless of condition: combine any conditions and merge its boundary and hypothesis mappings instead of duplicating entries or inflating the reported batch count. - On every debugger pause, inspect the planned state first. If the stack, dynamic dispatch, or concrete runtime type reveals more material locations, install the entire newly justified upstream/downstream batch before the next
continue; do not advance one breakpoint at a time through an already-visible causal interval. - Use validated non-pausing structured probes instead when pauses could hide a timing, concurrency, lifecycle, hot-path, or long-lived-stream failure. Keep every
debuggerStrategy.breakpointsentry at fixedkind: "pause". Treat a native debugger logpoint as formal evidence only when it is represented as a plan probe and emits through the same validated runtime adapter; otherwise it is supplemental. MarkdebuggerStrategy.modeasunavailableorunsafewith a concrete reason when native breakpoints cannot be installed. - Enumerate the full concrete candidate breakpoint batch even in
unavailableorunsafemode, but mark every candidatedeferred. Give every deferred entry anactivateWhenplus the matching structureddeferReason:tool-unavailable,observer-risk, orprivacy-risk. A dynamically unresolved site is not yet a breakpoint entry because every entry requires a concrete sourcepath:line; record it incoverage.residualAmbiguities, map its boundary and hypothesis to the nearest concrete upstream or downstream surrogate breakpoint, then add the full newly resolved batch and revalidate before continuing. Residual ambiguity never waives concrete breakpoint coverage. Never use “try the earlier breakpoint first,” low rank, or cheap reproduction as a deferral reason. - Treat pause-only breakpoints as supplemental evidence. They do not satisfy the all-occurrence event contract, and a breakpoint that did not pause cannot prove absence unless independently bracketed by complete structured evidence. Set
coverage.firstPassBreakpointBatchReviewedonly after the full initial batch and every explicit deferral have been reviewed.
Non-negotiable event cardinality
- Once a probe is active for a run, emit exactly one immutable logical event for every execution occurrence of that probe. Preserve the contract
N source occurrences -> N accepted writes -> N persisted NDJSON recordsthrough the checkpoint; both missing and duplicate events violate it. - Never sample, throttle, debounce, first-N, change-gate, once-per-key, anomaly-gate, aggregate, merge, coalesce, overwrite, deduplicate, or otherwise suppress active probe occurrences. Choose fewer or better probe locations before the run when observer cost is too high; never reduce occurrences after activating a probe.
- Bound fields, strings, arrays, stacks, and network-frame bytes without changing event count. A multi-event envelope may carry multiple independently serialized events, but it must preserve their identities, ordering, and record count.
- Treat duplicate producer installation, serialization failure, byte rejection, a rejected or ambiguous write, missing persistence confirmation, or a source-sequence gap as an incomplete run. Never convert it into a silent no-op or successful capture.
Existing debug process
- Inspect and continue project-owned debug instrumentation, logger, ledger, and the ledger's exact active collector session before creating anything. Repair the existing path when it violates this skill instead of adding a parallel emitter or collector.
- Prefer, in order, an authoritative host or project logger, the target runtime's standard HTTP client posting structured JSON to the collector, then direct NDJSON append only as an explicit collector-free fallback with a single writer or process-safe lock. Never introduce a bundled language-specific client into an unrelated project.
- Keep the collector protocol language-neutral and single-endpoint:
/ingestaccepts either one JSON event or an exact{"events": [...]}multi-event envelope. The collector appends every accepted event as its own NDJSON record and does not own retry, deduplication, envelope identity, correlation, or application lifecycle policy. - Give every replaceable wrapper, listener, timer, subscription, or other probe producer one explicit owner. Detach the old producer before replacement or hot reload, preserve any required source sequence in project-owned state, and use the analysis recording lock below to close collection.
Temporary source markers
- Wrap every contiguous source block added only for the current investigation—including structured probes, inserted
debuggerstatements, debug-only imports, endpoint constants, adapters, wrappers, and helpers—in balanced, non-nested comment regions. Preserve one of the exact start payloads#region agent logor#region agent log configand the exact end payload#endregion; render those payloads with comment syntax valid for the target language. The canonical JavaScript/TypeScript spellings are// #region agent log,// #region agent log config, and// #endregion. - Use
agent logfor executable probe or inserted-breakpoint blocks andagent log configfor shared debug-only setup. Keep permanent product behavior and the eventual repair outside these regions. Do not add source markers for native debugger breakpoints that do not edit source; keep those indebuggerStrategyinstead. - Keep each region as small as the temporary source edit permits. Reuse an existing matching agent-log region instead of nesting another one, and never let one region span unrelated product code merely to reduce marker count.
- Before the runtime gate and again before cleanup, search every instrumented path for
#region agent log. Require each start to pair with the nearest valid#endregionin the same file, require no temporary source edit to remain unmarked, and revalidate plan locations after marker insertion moves line numbers. - During cleanup, remove the complete paired region, including both markers, for every retired temporary block. Never delete or rewrite a standalone
#endregionby global replacement because it may belong to project-owned folding regions.
Debug-only helper references
- Keep helper placement and reference resolution language-neutral: reuse an existing project logger first, inline a small adapter when only one source file owns it, and create a shared helper only when multiple instrumented files or one explicit lifecycle owner justify it. Match the target repository's language, package/module system, source roots, aliases, and client/server build boundaries.
- Create the helper at its final real path before adding any reference to it. Never guess a relative reference from visual directory depth or copy one import/include string across source files at different depths. Resolve each importer independently from the importing file's parent to the exact helper file.
- Prefer an existing source-root alias only after reading the repository's authoritative resolver configuration and confirming that every applicable build target understands it. Never invent or modify a permanent alias solely for temporary instrumentation.
- For module systems that use slash-delimited file-relative references, optionally run
scripts/debug_import_path.pyafter both files exist to compute and verify the path. This helper does not model package names, namespaces, Python dotted imports, Go modules, Rust modules, Java/C# packages, or repository aliases; validate those with the target project's native resolver, compiler, type checker, or build tool. - Before the runtime gate, enumerate every temporary cross-file reference inside agent-log regions, prove that it resolves to the intended existing helper, and run the narrowest relevant native resolution, syntax, type, compile, or build check. A missing helper, wrong target, ambiguous alias, or unverified reference blocks reproduction.
Completion scope
- Treat a request to debug, troubleshoot, fix, repair, resolve, address, or make the failing behavior work as authorization for the full prove-repair-verify-cleanup loop. Do not ask for a second repair approval after proving the cause.
- Treat the work as diagnosis-only only when the user explicitly asks to diagnose, analyze, investigate, explain, collect evidence, recommend a fix, avoid edits, or otherwise stop before behavior changes.
- When repair is in scope, treat a root-cause finding or repair proposal as an intermediate update, not a terminal result. Continue until the causal mechanism is repaired, the original failure contract passes in a separate verification run, temporary instrumentation is removed, and owned artifacts are cleaned up.
- Keep one evolving investigation ledger whenever repair is in scope or the work crosses a reproduction handoff, context compaction, or multiple runs. Record the validated plan, evidence transitions, hypothesis dispositions, repair, verification, and cleanup in the same ledger. Omit the ledger only for short, agent-owned, diagnosis-only work that finishes in one turn.
- Treat lifecycle scope as
investigation > collector session > run: one reported bug and its evolving ledger form the investigation; one collector session owns an exact ready file, endpoint, port, dashboard, and evidence file; each failing, blind-spot, or verification pass is a run with its ownrunId. A user reply, evidence-analysis turn, context compaction, repair transition, or newrunIdcontinues the same investigation and does not create a new collector session. - On every continuation, read the current investigation ledger and run
scripts/debug_session.py resume --ready-file <READY_FILE>with its exact active ready file before anystart. If resume succeeds, reuse that collector and dashboard without callingstartor reopening the dashboard.resumemust not open browser UI, and session recovery must never scan the workspace for an arbitrary ready file. Start a replacement only when the recorded ready file is missing or its collector is unreachable, or when the user or host explicitly requires isolation or replacement; preserve prior evidence and record the session transition in the same ledger. - Treat recording mode as collector-session state, not tab or run state.
Freezeremains active across dashboard tabs, reloads, user replies, analysis turns, and new run IDs;Cleardoes not unfreeze it. Only an explicit recording Resume transition—the UI control or CLIresume-recording—reopens the collector write gate for future requests. - Pause for the default user-owned failing reproduction and post-repair verification, unavailable authority or dependency, or another concrete blocker. Treat each pause as a checkpoint and resume the same workflow when the blocker clears.
Analysis recording lock
- The agent owns collection shutdown after a completed reproduction handoff. A contextually clear user completion message starts this work immediately in the same run and collector session; an injected terminal, checkpoint, or seal event is not a prerequisite for acting on the message. Use only already-authorized runtime controls; closing collection does not grant additional browser access or delegate another reproduction.
- Before handoff, arrange automatic checkpoint capture at the natural product boundary and identify the available agent-controlled cleanup path. Prefer to detach every run-owned producer, await finite pending operations, and flush the selected logger or runtime adapter before freezing.
- If the checkpoint is missing, producer shutdown is unavailable, or delivery cannot be completed or confirmed with the available controls, freeze the collector to preserve the records already persisted and classify capture as incomplete. Record the cutoff, missing checkpoint or counts, unresolved producer/flush state, and rejected or ambiguous writes. Do not wait indefinitely for a debug-only sentinel, fabricate one from the user's report, or ask the user for an extra click, blur, navigation, console command, or Dashboard Stop/Freeze solely to finish collection.
- For either path, run
scripts/debug_session.py freeze-recording --ready-file <READY_FILE>against the exact active session, refreshdashboard-status, and requirerecording: frozenbefore summarization, raw-evidence reading, or causal interpretation. Then reconcile source occurrences, accepted writes, and persisted NDJSON records through the available checkpoint to determine capture completeness. Record the lock and completeness separately in the ledger. If the exact session cannot be frozen or recording state remains unknown, report that concrete blocker; do not turn collector operation into another reproduction step for the user. - Analyze the usable persisted evidence even when capture is incomplete. Missing or uncertain delivery cannot prove that a product event did not occur. Request another run only after identifying a material causal or verification gap in the saved evidence, not merely because an instrumentation-only seal is absent. Keep recording frozen throughout analysis, repair, and next-run planning; Freeze proves only the write cutoff, never product completion or lossless delivery. Any active-probe event rejected at the cutoff is a capture limitation, not an event to replay later.
- Before the next failing, blind-spot, or verification run, finish the prior analysis and ledger transition, preserve required evidence, detach any remaining prior-run producers, update instrumentation, and clear stale logs while recording remains frozen. Only then run
resume-recording, requirerecording: live, and initialize the freshrunIdand runtime adapter state. Never Resume merely because the user replied, analysis continued, or repair began.
Reproduction runs
- Scope
run.reproductionOwnerandrun.reproductionDelegationto exactlyrun.runId. Default every new failing, blind-spot, and verification run to the user-handoff path unless a still-applicable explicit delegation covers it. - Before the first failing run, enter the agent-autonomous path when the current user explicitly assigns the runtime investigation to the agent, for example, “have the agent investigate this” or “investigate this yourself.” Treat that pre-run assignment as
scope: "remaining-runs"unless the user limits it to one run; do not require a separate instruction about reproduction. - After a run completes, resume evidence analysis automatically. Treat “now have the agent investigate” or “analyze this” as an instruction to analyze the completed evidence, not as reproduction delegation. Never rerun, relabel, or change the owner of a completed run, and never change a future run owner from an evidence-analysis request.
- Change a future run from user ownership only when the current user explicitly delegates that future reproduction or verification, or explicitly delegates all remaining runtime runs. Create the new
runIdbefore applying the delegation; never apply it retroactively. - For non-user ownership, store
run.reproductionDelegationwithtarget,scope(single-runorremaining-runs),effectiveRunIdequal to the currentrun.runId, andcurrentUserDirectivecontaining a faithful summary of the current user's instruction. Omit the object for user ownership. The validator checks structure and run consistency; the agent remains responsible for verifying the directive's source and scope. - Never infer delegation from reproduction cost, deterministic tests or harnesses, agent capability, a headless environment, time pressure, user unavailability, or repository rules that prohibit agent-operated browser testing. Asking the user to reproduce in their own browser is not agent browser automation. If the user cannot reproduce but has not delegated an applicable future run, report the blocker.
- Keep reproduction ownership separate from dashboard startup. For a user-owned run on a browser-capable local host, leave dashboard auto-open enabled. Waiting for the user, lacking agent browser control, or prohibiting agent-operated product browsing is not a headless condition and never justifies
--no-open-dashboardor--headless. - Agent-run experiments may inform hypotheses before a user handoff, but they do not replace a required user-owned canonical run and must not be presented as the user's reproduction.
- Before planning another run, record the completed run's ID, purpose, owner, delegation, evidence, and status in the investigation ledger. Default post-repair verification to user ownership unless a still-applicable
remaining-runsdelegation or a new explicit verification delegation selects another owner. Useexternalonly when the current user explicitly designates an external operator. - A new
runIdnever implies a new collector session. Reuse the ledger's active ready file across failing, blind-spot, and verification runs while that collector remains reachable.
Interpreting reproduction replies
Determine the next action from the meaning of the user's reply in the ongoing investigation: what the handoff asked them to do, what they now report, and what they want to happen next. Use that combined understanding to judge whether the reason for waiting still applies. Do not substitute keyword matching, similarity to example replies, or a fixed catalog of reply types for this judgment.
When the reply means the reproduction is complete—for example, “已复现” in response to a reproduction handoff—end the wait and perform the agent-owned shutdown, recording lock, and evidence analysis above. No separate manual end-of-capture action, prescribed wording, or repeated confirmation is required. A status question, report of an intermediate observation, or statement that the user is still reproducing does not by itself end the handoff. Clarify only when the unresolved meaning would materially change the next action.
User intent resolves the conversational handoff; runtime evidence establishes capture completeness and reproduction outcome. Verify the checkpoint, producer shutdown, adapter flush, and persisted records independently, preserving incomplete evidence as such. Keep the existing scope and reproduction ownership.
Mandatory user-reproduction output gate
If the current response asks the user to perform a reproduction, the response is invalid unless it renders as the exact Markdown structure below. Begin with Dashboard:; put no heading, greeting, readiness claim, or other prose before it. Never replace the actual URL with wording such as “opened successfully.” Emit the template as ordinary Markdown, not as a code block.
Dashboard: <status> — <dashboardUrl-or-unavailable> (frontend confirmed: <true|false|unknown>; recording: <live|frozen|unknown>) [— error: <non-empty error>]
### Failure contract
- **Expected:** <expected behavior>
- **Observed:** <observed behavior>
- **Trigger:** <smallest realistic trigger>
### Coverage
- **Hypotheses:** <material hypothesis-family and mapped-coverage summary>
- **Probes and boundaries:** <initial/deferred breakpoint counts, probe count, shared probes, and causal-boundary coverage>
- **Observer controls:** <volume, privacy, and perturbation controls>
### Residual ambiguities
- <`None.` or one explicit ambiguity per bullet>
### Reproduction
1. <exact step>
2. <additional exact step when needed>
3. <observe the specified product result, then briefly report whether reproduction is complete and what happened in an ordinary user message>
Keep three concepts separate: the checkpoint is an observable product or flow boundary; the user's completion message ends the conversational wait and tells the agent to close collection; persisted-record reconciliation determines capture completeness. Before handoff, attach terminal or checkpoint instrumentation to the natural boundary so it records automatically. An existing host completion control may be offered as an alternative to a message, never as an additional required action. Do not add product interactions solely to emit a debug checkpoint or seal; actual bug-triggering actions remain valid reproduction steps. Never create or expose an instrumentation-only window or globalThis helper, ask the user to open DevTools, or ask them to evaluate JavaScript merely to start or end the run, emit a sentinel, checkpoint or flush the adapter, or signal completion. Allow a console step only when the failure contract itself requires console interaction or the current user explicitly chooses that path after receiving a no-console alternative, and still verify persistence independently.
Derive the dashboard values mechanically: use frontend_confirmed and true when a URL exists and the frontend callback is recorded; disabled and false when a URL exists and auto-open is disabled; frontend_not_confirmed and false when a URL exists otherwise; and unavailable, unavailable, and unknown when no URL exists. Derive recording independently from authoritative collector state as live, frozen, or unknown; never infer it from frontend confirmation or collector health. Append the normalized error only when non-empty. Normalize embedded newlines in the dashboard status or error to spaces. For a newly established browser-capable local session, treat disabled as an accidental opt-out: run open-dashboard, refresh dashboard-status, and surface the refreshed line. If that bounded recovery fails, include its exact URL and error without blocking reproduction, even when the refreshed status remains disabled. For a healthy session recovered from the investigation ledger with resume, preserve its existing dashboard state, do not call open-dashboard, and surface the refreshed status and exact URL. Skip recovery and proceed directly with disabled when the collector host is verified to have no usable local graphical browser. Immediately before a deliberate recording pass, if dashboard-status reports recording: frozen, run scripts/debug_session.py resume-recording --ready-file <READY_FILE>, rerun dashboard-status, and require recording: live before handing off reproduction. Session resume only reuses and health-checks the collector; it never changes recording mode. If recording remains unknown, refresh authoritative state and report the exact error rather than claiming the gate is live.
Make ### Reproduction the final section and stop for the user's completion signal. Before sending, verify that the first character begins Dashboard:, a blank line separates the dashboard paragraph and every subsequent section, the four headings appear exactly once in the shown order, every heading is followed by a blank line and its list, the URL is literal or unavailable, and no text follows the reproduction list. Do not rely on soft line breaks, trailing spaces, raw HTML, or renderer-specific behavior. Rewrite the response if any check fails.
Read selectively
- Read coverage-first-debugging.md before creating the causal map, hypotheses, or coverage plan.
- Read runtime-debugging.md before resolving the plan validator, starting a session, or operating the bundled collector.
- Read browser-debugging.md only for browser instrumentation, complete application-
fetchcapture, long-lived or high-frequency client streams, or page-lifecycle boundaries. - Read root-cause-document.md before creating or updating the investigation ledger.
Workflow
- Resolve scope and authority. Apply the completion-scope and reproduction-run rules above without seeking redundant confirmation. Before the first run, an explicit assignment of runtime investigation to the agent may establish a
remaining-runsautonomous path. After a completed run, treat requests for agent investigation as evidence analysis unless the current user explicitly delegates a future reproduction or verification. Default every otherwise uncovered run to user ownership. - Define the failure contract. Record expected and observed behavior, smallest realistic trigger, affected scope and environment, frequency, timing, last-known-good boundary, reproduction cost, and constraints. State whether the flow terminates or is intentionally long-lived. For a long-lived flow, define a bounded observable checkpoint condition that closes the evidence window without claiming the business stream ended.
- Inspect before instrumenting. Read the relevant execution path, tests, configuration, deployment boundaries, and existing logs. Reuse authoritative trace, request, operation, job, transaction, and version identifiers when available.
- Build the causal map. Trace backward from the symptom through outputs, state transitions, branches, async boundaries, persistence, caches, dependencies, configuration, and inputs. Mark causal cuts and the earliest boundary where a correct value can become incorrect.
- Enumerate material hypotheses. Cover applicable cause families, name concrete falsifiable mechanisms, and merge only observationally equivalent variants. Treat a hypothesis as material when it is code- or architecture-grounded and requires distinct evidence or a distinct repair. Record unsupported families as exclusions rather than inventing probes.
- Create the coverage plan. Write one coverage-plan JSON file containing the failure contract, reviewed cause-family exclusions with reasons, the current planned run, explicit completion mode, causal boundaries, hypotheses, the strict
debuggerStrategy, probes, the fixed all-occurrence cardinality contract, structured payload-only bounds, privacy review, logging-path checks, the first-pass breakpoint-batch review, and residual ambiguities. Do not express occurrence selection or event-count policy in free text or an extra field elsewhere in the plan; the schema rejects unknown keys at every object. Setrun.reproductionOwnertouserby default. Foragentorexternal, include an owner-matchedrun.reproductionDelegationwhoseeffectiveRunIdequals the currentrun.runId. Use the same file for validation, location sync, and expected-probe analysis. If writes are not authorized, present the plan without claiming the coverage gate passed. - Validate the plan and start the ledger. Run
scripts/debug_plan.py validate <PLAN_FILE>with the resolved Python 3 interpreter. Require every material hypothesis to define both confirming and rejecting evidence, every hypothesis and boundary to map to structured probes, a flow-start sentinel plus the configuredflow-terminalorobservation-checkpointsentinel, and every gate flag to pass. Require every debugger mode to enumerate candidate breakpoints covering every declared boundary and hypothesis. Inattachedmode, require at least one initial breakpoint; inunavailableorunsafemode, require every candidate to be deferred with a mode-compatible reason. The machine validator closes the structural policy surface; separately verify that the initial breakpoint batch is maximal for the safe reviewed set and every deferral has a concrete activation condition. Then read every free-text failure-contract, exclusion, step, breakpoint rationale/activation, evidence, redaction, and ambiguity field and fail semantic review if a deferral merely stages one-breakpoint-at-a-time exploration or any text instructs instrumentation to sample, filter, suppress, aggregate, deduplicate, or cap occurrences. For a user-owned run, also reject any step that requires an extra product interaction, Dashboard Stop/Freeze, DevTools, or an injected page-global action solely to close collection; verify that the agent can apply the Analysis recording lock policy after an ordinary completion message. Allow console interaction only when the failure contract requires it or the current user explicitly chose it after receiving a no-console alternative. Product behavior may mention otherwise-forbidden mechanisms as the bug under investigation, but prose never overridesevery-execution/all-occurrences. Fix validation or semantic-review errors before editing product code. After both pass, create or resume the evolving investigation ledger when the completion-scope rules require it. - Install the native breakpoint batch and finalize structured probes. Apply the broad breakpoint-batch rules above and install every initial native breakpoint before the first debugger
continueor failing reproduction. Finalize the structured-probe sites before collector wiring: prefer shared causal cuts and invariants over repeated snapshots while covering boundary entry/exit, branch decisions, state before/after mutation, async schedule/start/finish/cancel, cache and persistence operations, external calls, exception/fallback paths, and configured flow sentinels. Wrap every temporary source insertion in the required agent-log marker pair as it is added. Resolve every debug-only helper reference from its actual importer to an already-created target, using the target project's module system and native resolver; never reuse a guessed relative path across importers. For cardinality-sensitive producers, place the source probe at the authoritative callback or dispatch before any existing throttle, debounce, filter, deduplication, or aggregation; a downstream probe cannot prove how many upstream occurrences were removed. After a structured probe is activated, emit every occurrence. For a real-time stream, probe open/headers, every source event with its source sequence, close/cancel/error, and observation checkpoints at the real dispatch, decoder, or reader-loop boundary. - Bound payload and observer cost without reducing events. Estimate dynamic event count and bytes before the run. Move or remove low-value probe sites before validation if the projected observer effect is unsafe. For every retained probe, keep each payload compact and redacted while preserving every occurrence; do not add runtime gates, sampling, aggregation, or suppression.
- Establish or resume and instrument the collector session. On a continuing investigation, read the ledger's exact active ready file and run
scripts/debug_session.py resume --ready-file <READY_FILE>before any start attempt; never discover a session by scanning.debug-logs/or other workspace files. A successful resume is authoritative: preserve its endpoint, session ID, port, token, dashboard, evidence path, and cleanup ownership, and do not callstartoropen-dashboard. If there is no recorded active session, reuse an authoritative logging session supplied by the host or user; otherwise runscripts/debug_session.py start. Start a replacement only for a missing or unreachable recorded session or an explicit isolation or replacement directive, then append the old and new session details and reason to the same ledger. In a newly started browser-capable local session, let startup attempt to open and confirm the dashboard by default. Pass--no-open-dashboardonly when the collector host is verified to have no usable local graphical browser, such as CI, container-only, or remote operation. Capture the returned ready file anddashboardRecoverystatus. Select the least invasive runtime-native adapter: reuse the project logger when it can preserve the planned fields, otherwise use the target language's standard HTTP client to send one event or an exact{"events": [...]}envelope to/ingest. Use direct NDJSON append only without collector lifecycle controls and with safe writer ownership. Use stable probe IDs; add correlation fields only at actual async, process, service, queue, persistence, or lifecycle boundaries. Read browser-debugging.md only for browser-specific lifecycle constraints. Do not add correlation headers or wrappers when they could change CORS, caching, routing, signing, authorization, or product behavior. - Pass the runtime gate. Validate the plan again, enumerate and resolve every temporary cross-file helper reference, run the narrowest relevant native resolution/compile/typecheck/test for the instrumentation, verify collector health, send a smoke event through the chosen adapter, sync locations from the plan, and confirm that the NDJSON record preserved every required field under the canonical field names. Inspect the complete temporary instrumentation source set for unmatched or nested agent-log markers, unmarked temporary source edits, missing or misresolved helpers, duplicate producers, swallowed serialization or delivery errors, behavior-changing wrappers, and occurrence suppression. Require every active probe occurrence to create one independently serialized event; matching source, accepted-write, and persisted-record counts at the checkpoint is the criterion for complete capture, not a prerequisite for closing an incomplete run after the user reports completion. Treat the multi-event envelope as ordinary framing: it supplies no retry, deduplication, replay, or envelope-identity guarantee. Never automatically retry an ambiguous response, a request rejected while recording is frozen, or an in-flight request rejected because it crossed a Freeze/Resume transition; mark that interval incomplete or use an authoritative project logger. Before clearing a reused session, finish the prior run's summary and ledger transition, preserve any raw evidence that must survive truncation, remove superseded temporary probes, debug logging calls, and breakpoints, and sync the exact remaining active locations; then clear stale collector logs and use a unique run ID in the same healthy collector session.
Clearremains valid while recording is frozen and does not change recording mode. Retain only discriminating probes that the next planned or verification run still requires. For a continuous stream, reconcile a bounded source-occurrence prefix with the persisted NDJSON prefix; do not wait for the business stream to end. Immediately before every user-owned reproduction handoff, runscripts/debug_session.py dashboard-status --ready-file <READY_FILE>. If it reportsrecording: frozen, runscripts/debug_session.py resume-recording --ready-file <READY_FILE>and rerundashboard-status; requirerecording: livebefore reproduction. Do not substitute sessionresume, which never opens the recording gate. For a newly established browser-capable local session that reportsdisabled, runscripts/debug_session.py open-dashboard --ready-file <READY_FILE>, refreshdashboard-status, and only then copy itslineas the handoff's first line. After a healthy ledger-based resume, do not callopen-dashboard; use the existing dashboard status and URL. Dashboard visibility is operator UX, never evidence or a reproduction prerequisite; a bounded open failure does not block the run. - Collect one failing run or observation window, then close it automatically. Hand off the exact reproduction steps and pause when ownership is user, which is the default. Execute them directly only for a validated agent-autonomous plan; coordinate with the designated operator for external ownership. Keep setup traffic and exploratory activity outside the run. For an intentionally open stream, stop at the plan's observable checkpoint condition, record the checkpoint sentinel and source-occurrence count, detach the run-owned probes without stopping the business stream, and flush the selected logger or runtime adapter when possible; reconcile the persisted prefix after freezing. Preserve deterministic fault seeds and authoritative before-state when the reproduction uses controlled timing or dependency failures. A user completion message ends the handoff and starts agent-owned shutdown immediately. Apply Analysis recording lock: finish a complete seal when possible, otherwise freeze the persisted records as an explicitly incomplete capture without asking for another user action. Require
recording: frozenand record the lock, cutoff, and completeness in the ledger before analysis. - Summarize and classify while frozen. Resume evidence analysis automatically after the completed handoff and confirmed analysis lock, including usable evidence from an incomplete capture; do not resume collector recording. Treat any request for the agent to investigate at this point as confirmation to analyze the existing evidence, not as reproduction delegation. Require authoritative state to remain
recording: frozen, run the bundled summarizer with the plan as--expected-probes-file, filter by run and relevant correlation fields, inspect configured sentinels, expected occurrence counts, source-sequence gaps, rejected or ambiguous writes, persisted record counts, and residual ambiguities, then read only the raw events needed to mark every hypothesisCONFIRMED,REJECTED,INCONCLUSIVE, orNOT_REACHED. - Prove or narrow. Claim a root cause only when evidence identifies the earliest invalid state, decision, ordering, or external result and traces it through propagation to the symptom. If evidence is insufficient, preserve the ledger and add only probes that close the smallest unresolved causal interval.
- Complete the requested terminal condition. For diagnosis-only work, preserve requested evidence, remove temporary instrumentation and owned runtime artifacts, then report the proven cause and a causally sufficient repair recommendation without changing behavior. When repair is in scope, immediately eliminate the proven mechanism and restore the violated invariant at the owning boundary; reject smaller symptom masks that leave the mechanism active. Update the ledger instead of ending at the diagnosis.
- Verify and clean up the repair. Keep discriminating probes for a separate post-repair run with a new run ID. Default verification to user ownership; apply a still-valid
remaining-runsdelegation or a new explicit verification delegation only to the new verification run. Compare the same invariants and probe IDs, and pause for a canonical user handoff when ownership is user. Continue iterating if the failure contract still fails. Only after verification succeeds, remove every complete agent-log marker region plus any remaining temporary probe, debug logging call, native breakpoint, helper, and logging-adapter hook; sync an empty location set for an owned session; clear or stop owned collector logging according to retention policy; follow host ownership policy for shared sessions; delete only owned ephemeral artifacts; and record terminal status in the ledger.
Evidence contract
- Keep
probeIdstable across failing and verification runs. - Map every active probe occurrence to exactly one independently serialized event. Require source occurrence count, accepted-write count, and persisted NDJSON count to agree through each completed checkpoint.
- Require
runId,probeId,location,event, andtimestampfor every planned event. - Require correlation and ordering fields whenever work crosses async, concurrent, process, service, queue, persistence, or browser-lifecycle boundaries.
- Give every active real-time event a monotonic logging
sequencethat is contiguous within itsrunIdandcorrelationIdand survives deliberate producer replacement. When the domain source has a different ordinal or scope, record it separately in boundeddatainstead of overloading the logging sequence. Preserve each event as a distinct envelope item and NDJSON record. - Treat a successful collector response as confirmation only after the event has been flushed to the NDJSON file. Treat a timeout or other ambiguous response as incomplete; the collector does not deduplicate a retry.
- Record compact identities, versions, hashes, counts, branch operands, durations, attempts, and invariant results instead of full payloads or state trees.
- Interpret a missing interior event only when enclosing sentinels, collector continuity, current instrumentation, expected occurrence counts, and available source/emitted/persisted counts prove that absence.
- Separate root cause, enabling conditions, downstream symptoms, and unresolved alternatives.
Guardrails
- Never promise that one reproduction will always identify the cause; report first-pass coverage and residual ambiguity.
- Never resume execution after installing only a token breakpoint set when more safe, nonredundant first-pass locations are already justified; install the full batch or record each concrete deferral.
- Never count a pause-only native breakpoint as an all-occurrence structured probe or use a non-hit alone to prove absence.
- Never use raw debugger-console logpoints as complete evidence; route an evidence-bearing logpoint through the validated structured-probe plan and runtime adapter.
- Never equate correlation, overlap, or a single suspicious value with causation.
- Never log secrets, credentials, tokens, authorization headers, passwords, payment data, or unnecessary PII.
- Never sample, first-N, change-gate, once-per-key, anomaly-gate, aggregate, merge, coalesce, overwrite, deduplicate, or silently discard any active probe occurrence.
- Never fire and forget collector ingestion, use
keepaliveorsendBeaconas a persistence guarantee, or swallow adapter errors. - Never stack wrappers, listeners, timers, or other probe producers during hot reload, and never let a stale disposer detach the current producer.
- Never claim complete capture without verified producer shutdown, logger or adapter completion, and persisted-record reconciliation. If these cannot be established, use the incomplete-capture path under Analysis recording lock instead of requiring another user completion action.
- Never claim lossless completion across reload, navigation, tab/process termination, memory exhaustion, or storage exhaustion without an authoritative durable producer-side logger.
- Never let instrumentation block, throw into, or materially alter the product path.
- Never inject a guessed relative import/include/reference for a temporary helper, reuse one across differently nested importers, or claim a debug wiring gate passed before the target project's native resolver or compiler accepts every temporary cross-file edge.
- Never use sleeps, arbitrary delays, retries, guards, fallbacks, or coercions as a repair unless they eliminate the proven mechanism and restore the violated contract.
- Never apply a repair when the user requested diagnosis only.
- Never rewrite a completed run's owner or treat a request to analyze completed evidence as delegation of a future reproduction.
- Never start a second collector or reopen its dashboard for a continuing investigation after the ledger's exact active ready file resumes successfully; a new turn, phase, or
runIdis not a session boundary. - Never begin collector-evidence analysis before the exact active session is confirmed frozen. A missing seal or unavailable runtime cleanup does not prevent freezing an explicitly incomplete capture.
- Never treat dashboard
FROZENas disconnection, collector-health failure, evidence completion, or a persistence checkpoint. It is the analysis lock and collector-wide HTTP write gate: the UI keeps polling, while new ingest requests are rejected without entering NDJSON or the index.Clearremains available and does not unfreeze recording. Keep the gate frozen through analysis and repair; useresume-recordingonly after next-run preparation and recheckdashboard-statusbefore the deliberate recording pass. Sessionresumeonly reuses the existing collector. - Never assume the collector recording gate protects a direct append to
logFile; direct file writers bypass HTTP pause/resume controls. - Never remove discriminating probes before in-scope repair verification succeeds.
- Never analyze collector stdout when structured evidence is available, and never load an unbounded raw log before summarization.
- Never leave temporary probes, debug logging calls, breakpoints or debugger statements, stale endpoints, collector-owned files, or debug-only adapter code after successful cleanup.
Visible handoffs
Use scannable rendered Markdown for every user-visible checkpoint and terminal response. Never serialize multiple named sections into one paragraph or depend on single newlines to create visual separation. Use short ### headings, leave a blank line after each heading and before every bullet or numbered list, and keep one evidence claim or action per bullet. Prefer lists over tables so handoffs remain readable in narrow viewports. Omit empty optional sections instead of filling them with prose.
The mandatory output gate above applies to every user-owned reproduction request; never send a steps-only handoff. After collection, use this shape:
### Evidence outcome
- **Status:** <root cause proven | smallest unresolved interval>
- **Recording lock:** <frozen; capture complete | incomplete with stated gaps>
- **Earliest divergence:** <boundary and cited evidence>
- **Propagation:** <origin-to-symptom chain>
### Hypothesis disposition
- `<hypothesis ID> — <CONFIRMED | REJECTED | INCONCLUSIVE | NOT_REACHED>`: <cited evidence>
### Artifacts
- <ledger and bounded evidence paths>
### Next action
- <repair action or smallest additional evidence action>
When repair is in scope, make the evidence result a progress handoff and continue directly into repair rather than ending with a recommendation or request for redundant approval. After verification, use this shape without dumping the raw log:
### Repair
- **Mechanism changed:** <causally sufficient change>
- **Invariant restored:** <owning-boundary invariant>
### Verification
- **Failure contract:** <PASS | FAIL>
- **Independent run:** <new run ID and decisive evidence>
- **Regression checks:** <relevant checks and results>
### Cleanup
- **Instrumentation:** <removed or explicitly retained with reason>
- **Ledger:** <terminal status and path>
- **Owned artifacts:** <cleanup status>