Skip to content
docsv0.34.0

DevToolsSource

The ledgers the house already writes, read for the Dev tools section — nothing here runs anything (greenhouse decisions/0205). Five reads of two files: the AGENT SESSIONS, one session's TIMELINE, the DEBT SIGNALS (`session.debt_signaled`, grouped by their four real kinds), the EVIDENCE (`session.evidence_recorded`) — all four from the agent ledger — and a LOG: the file the app DECLARED under `admin.log`, confined to the app root; without a declaration the section says so and invents no path. THE LEDGER IS RESOLVED THE WAY THE `agent` OPERATION RESOLVES IT (`AgentOperations::sessions()`): a container-registered `EventStoreInterface` first, then a registered `SessionStore`, then the file `var/agent-sessions.jsonl` under the kernel's root. The page says which one it is reading — the class name or the path — so nobody reads an empty table as an empty ledger while the agent writes elsewhere. THE LEDGER IS READ ONCE PER SNAPSHOT — `replayAll()` when a store gives it, this class's own tolerant line reader when it is the file — and sessions, debt and evidence are derived from that one pass; the timeline reduces the already-fetched stream with `SessionReducer`. The file reader mirrors `FileEventStore`'s line format exactly (one JSON object per line: `stream_id`, `type`, `payload`, `seq`, optional `recorded_at`; blank lines skipped) and differs in one thing only: a line that does not decode is COUNTED and skipped, never a failure that blanks every block. AUDIT PAINTING FOR WHAT `milpa/agent`'s TRANSCRIPT PROJECTOR DELEGATES TO AUDIT SURFACES: the timeline asks `SessionProjector` first and uses its translation as is. Only an event the projector maps to null AND that is in the explicit, bounded list {@see self::AUDIT_EVENTS} is painted here — the opening (`session.started`), a debt signal (`session.debt_signaled`), the closure verdict (`session.closure_derived`), the trial facts (`session.trial_run_recorded`, `session.trial_promoted`, `session.trial_discarded`), an executed operation (`session.operation_executed`: operation · executed_by/authorized_by · arguments digest) and a paused/resumed sequence (`session.sequence_paused`, `session.sequence_resumed`). Anything else the projector leaves unpainted stays unpainted: the list is the whole of this section's own reading, and growing it is a decision, not a default. The coupling to `milpa/agent` is SOFT, like the capabilities read of the Plugins section: `class_exists` decides, and without the package the snapshot degrades to «not available» naming it. Every block carries its own `error`, so an unreadable log does not blank the sessions. Nothing here appends, ends, answers or deletes.

DevToolsSource::__construct()

public function __construct(Milpa\Interfaces\Di\DIContainerInterface $container, string $agentClass = 'Milpa\Agent\SessionStore'):

Parameters

Parameters of __construct()
NameTypeDescription
$containerMilpa\Interfaces\Di\DIContainerInterface
$agentClassstringthe class whose presence means `milpa/agent` is installed — a name that does not exist makes the absent case testable

DevToolsSource::availability()

public function availability(): array

Whether the agent ledger can be read, and — when it cannot — why: the package, or the kernel. `source` names what would be (or is) read: the registered store's class, or the file's path; null when neither exists.

DevToolsSource::snapshot()

public function snapshot(): array

The overview: the newest sessions with their state, the debt signals by kind, the evidence ledger and the declared log's tail — the ledger read once and the three blocks derived from that pass. Each block carries its own `error` (null when it read) so a derivation failing does not blank the others; the log block is read even when the agent ledger is not available.

DevToolsSource::timeline()

public function timeline(string $sessionId): array

One session's timeline: its row (as the overview lists it) and every painted event of its stream in order — what `SessionProjector` paints, plus the audit facts it leaves to audit surfaces (the class docblock lists them). The stream is the one already fetched by the single read, reduced here with `SessionReducer`. `found` is false when no stream carries that id.

Parameters

Parameters of timeline()
NameTypeDescription
$sessionIdstring

DevToolsSource::log()

public function log(): array

The declared log's tail, CONFINED to the app root: `declared` false when `admin.log` names nothing; `root` the kernel's root, or null when no kernel is in the container — and then nothing is read: a relative path cannot be resolved (never against the working directory) and is reported `missing`, an absolute one cannot be confined and is reported {@see self::LOG_OUTSIDE}. With a root, the path — absolute, or relative to the root — is normalised lexically and through `realpath()`, so neither `..` nor a symlink reaches outside; outside is {@see self::LOG_OUTSIDE}, nothing there is `missing`, not a readable file is `unreadable`; else the last {@see self::LOG_LINES} lines within the last {@see self::LOG_BYTES} bytes, `truncated` when older content exists.