LightSOPLang Execution Monitoring
How the interpreter tracks command execution, enforces limits, and how to extend the monitoring hooks.
DefaultExecutionMonitor at a Glance
The interpreter ships with DefaultExecutionMonitor, imported via lightSOPLang/index.mjs. It captures three primary signals:
- Command lifecycle:
beforeExecuteCommand(command, humanReadableInput),reportCommandFailure(command, message). - Regeneration events:
beforeRegenerateScript(context)fires before an English-mode regeneration prompt is sent to the LLM. - Execution limits: The default monitor accepts options such as
failureLimitandcommandLimit. If either threshold is exceeded, it throws an error that halts the interpreter. This guards against infinite retries or runaway scripts.
These hooks give downstream analytics (or tests) visibility into every command attempt, while the limit checks prevent denial-of-service cascades when scripts misbehave.
Custom Monitors
You can pass a custom monitor via the executionMonitor option when constructing LightSOPLangInterpreter. The interpreter validates the monitor with ensureExecutionMonitor, which simply checks for the methods it intends to call:
beforeExecuteCommand(commandName, rawInput)reportCommandFailure(commandName, message)beforeRegenerateScript({ prompt, request })
Any additional state—metrics, tracing, feature flags—is up to the implementer. Because these hooks run synchronously, keep handlers fast and avoid throwing unless you explicitly want to abort execution.
Data Passed to Hooks
The interpreter sends structured data at each step:
- beforeExecuteCommand: Receives the command name and the fully rendered token string so monitors log what the interpreter will execute.
- reportCommandFailure: Supplies the command name and the failure message (either from the response.fail payload or exception text).
- beforeRegenerateScript: Receives an object containing the LLM prompt, the instructions, a snapshot of variables (
name,status,value), prior code, failure list, and attempt count.
Together, these snapshots let monitoring layers reconstruct the narrative of an execution: which commands fired in what order, where it failed, when the LLM took over, and what payload it received.
Practical Limits
The default monitor uses a simple counter to cap command executions (commandLimit) and failure events (failureLimit) per interpreter instance. If your scripts may legitimately exceed these caps—say, iterative planners—provide a monitor with higher thresholds or custom logic (e.g., per-variable quotas). For safety, still consider logging when limits are approached so you can distinguish expected retries from stuck scripts.
Extending Beyond Defaults
Because monitors are plain objects, it is easy to integrate with observability stacks:
- Emit structured logs or telemetry whenever
beforeExecuteCommandfires. - Record latency by capturing timestamps in
beforeExecuteCommandand clearing them when the command resolves. - Route
beforeRegenerateScriptpayloads to compliance storage to audit English→LightSOPLang translations.
Just remember that monitor callbacks run in the same event loop as the interpreter. Keep side effects non-blocking or move heavy work to async tasks.