ek9_debug_session
Runs a program under the debugger - several inputs at once with a change journal (sweep), one run to its end, or step by step - and reports, waits on or ends THE debug session (one per server); answers status, runState, sequence, the stops, breakpoints and nextStep.
When to use it
'Why does this input fail when that one works?' is ONE call: {action:'sweep', inputs:[[<failing args>], [<passing args>]], journal:{property:'Type.field', hypothesis}} - every change to the value, on every object, recorded in each run, and the runs compared. 'Run it and tell me what happened' is ONE call too: {action:'launch', run:'toEnd', journal:{property, hypothesis}}. Neither stops the program; ek9_debug_inspect then reads the journals (leadingTo, compare, report). 'Debug this program' step by step starts with {action:'launch'} (breakpoints optional); the debuggee waits at its start until ek9_debug_control continues it or ek9_debug_observe runs it, and {action:'wait', since:N} returns when the session changes.
When not to use it
- Just running a program for its output - use
ek9_run_program. - Running @Test programs - use
ek9_run_tests.
Details
One current session (no ids). launch builds the project with debug information in-process and starts the debuggee with a debug thread cap (maxThreads, default 64). wait blocks until the session's sequence moves past 'since' (by default the last sequence a debug tool answered), or its time limit (default 30 s, at most 100 s); the dispatcher is serial, so nothing else is served while it waits. Every time limit counts from when the call reached the server - a build, a launch and any wait behind another call included; an answer that queued says so (queued). An edit to any source of the jar ends the session (stale); 15 minutes without a debug call ends it too. sweep builds the project ONCE and runs it to its end once per input set, one after another, each with its own journal, within one time limit (timeoutMs, default and at most 100 s, for the whole sweep); sets it had no time for are listed as notRun, to sweep again. Every call is recorded in .ek9/debug-questions.jsonl.
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
action | string: launch | status | wait | terminate | sweep | launch a new session, report it, wait for it to change, or end it; sweep runs the program once per input set and compares the runs. | |
args | array of string | launch: the program's arguments, as strings, one per parameter; a count that does not fit is refused, naming the parameters. | |
breakpoints | array of object | EK9 source lines, each {file:'main.ek9', line:12}; the file is its path from projectDir ('orders/main.ek9'), or just its name when only one source has it. | |
env | object | launch: environment variables for the debuggee only. | |
failing | string: uncaught | anySymptom | exitCode | changeCheck | sweep: what makes a run a failing one (default uncaught: an Exception or Panic the program did not catch; changeCheck: its journal.changeCheck broke) - as compare judges it. | |
inputs | array of array of string | sweep: the input sets, each the program's arguments as strings, one per parameter - every set is checked against the program before any run starts. | |
journal | object | launch, sweep: record every change to this property, on every instance, from the start of the run - before, after, the line and the EK9 stack that made it - into .ek9/debug-journal/<runId>.jsonl, never stopping the program. Caught at every line the compiler says can change it (ek9_query_references' writeSites); a store from any other line is recorded too, marked gap (gapNet). A line stops being journalled after siteCap hits (a capped row; capped in the answers), so a hot loop cannot use up the run's time. The answers carry journal:{file, changes, gaps, bySite, byRoute, missed}. Every row has a tick: cite the ticks of the rows that show each claim you make, and never infer a value from the code alone. | |
maxThreads | integer | launch: the debug thread cap - at most this many task threads alive (default 64). | |
program | string | launch: module::Program (or a bare name only one program has) when the project declares several; a program that is not there is refused, listing the programs. | |
projectDir | string | Project root holding the .ek9 sources - absolute, or relative to the workspace root. Omit to use the workspace root itself (the first root ek9_compile was given). | |
run | string: toEnd | launch: 'toEnd' starts it and answers once - when the program has ended (with the journal's counts and, if something failed, its leadingTo account), when a breakpoint of yours stops it, or at timeoutMs. Exceptions do not stop it unless stopOnExceptions is given; a journal records them as symptoms. | |
seed | integer | launch, sweep: the random seed the program's SystemRandom and OS.random draw from, so a run can be repeated exactly (a sweep gives every set the same one). Left out, one is chosen; every answer says which (seed), and a journal records it as an input row. To check a cause, launch again with the same seed and the suspected input changed. | |
since | integer | wait: the sequence to wait past (default: the last one a debug tool answered, so a stop that landed before the wait arrived is answered at once). | |
stopOnExceptions | string: none | uncaught | all | launch: stop on an EK9 Exception or Panic where it is thrown - only when nothing in the program catches it, every one, or none. | |
timeoutMs | integer | wait: how long to wait (default 30000, at most 100000); launch with run: and sweep, for every run together (default and at most 100000). Counted from when the call reached the server. | |
until | string: all | firstFailure | sweep: run every set, or stop after the first failing run. |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it.
Launch waits at its start
Request
{
"action" : "launch",
"projectDir" : "<workspace-root>"
}
Response
{
"breakpoints" : [ ],
"meta" : {
"serverMs" : "<timing>"
},
"nextStep" : "ek9_debug_control {action:'continue'} to run it, or ek9_debug_observe to run and observe",
"runState" : "waiting-to-start",
"seed" : "<seed>",
"sequence" : "<sequence>",
"started" : false,
"status" : "ok",
"stopOnExceptions" : "uncaught",
"stops" : [ ],
"summary" : "launched; the debuggee waits at its start"
}
See also
- Show me in the IDE: Chapter 23: the game, built and played
- Show me in the IDE: The Journal: a new investigation
- Part of the investigate_runtime_defect workflow: A runtime failure whose cause is earlier: journal the value over failing AND passing runs -> compare -> leadingTo -> firstWhere -> confirm with one input changed -> report with a finding.