Understanding the files Noēsis produces: summary.json, state.json, events.jsonl, and more.
Every Noēsis episode produces a set of structured artifacts that capture the complete cognitive trace. These files enable replay, debugging, auditing, and analysis.
Episode IDs use ULID format (monotonic, sortable, 48-bit timestamp + 80-bit entropy). Directive and governance IDs use deterministic UUIDv5 for reproducible lineage tracking.
Paused approval workflows are intentionally not sealed. While a run is waiting
for approval, expect events.jsonl, state.json, learn.jsonl, and checkpoint
or tool-invocation records to exist, but not terminal-only files such as
final.json, summary.json, or manifest.json. Those terminal artifacts are
written after the run resumes and completes.
Protocol-first tool integrations persist review and idempotency state under the
episode directory:
Path
Purpose
tool_invocations/prepared/*.json
Reviewable prepared tool intent keyed by run_id + draft_id
tool_invocations/approvals/*.json
Human or policy decisions bound to the reviewed draft
tool_invocations/idempotency/*.json
Execution fingerprints used to replay or reject duplicate side effects
For approval-gated subprocess tools, the runtime bridge prepares the draft,
emits tool.approval.pending, interrupts the run, and writes a checkpoint. After
an approved ToolApprovalDecision is persisted, ns.resume_run(...) continues
the same run and executes the existing draft without re-preparing it.Constraints to check during incident response:
there should be exactly one pending_approval prepared draft for the run
unsupported bridge protocols (http, mcp) fail before draft persistence on
prepare or before run.resume is emitted on resume
missing final.json or manifest.json is expected until the resumed run
reaches a terminal state
Event metrics always include started_at, completed_at, and duration_ms, which you can aggregate for per-phase latency.Plan derivability contract: state.json.plan can be reconstructed from the latest plan event (steps + step_records + source) plus subsequent act events carrying step_id and step_status.
import noesis as nsepisode_id = ns.last()events = list(ns.events.read(episode_id))# Filter by phaseplan_events = [e for e in events if e["phase"] == "plan"]act_events = [e for e in events if e["phase"] == "act"]# Reconstruct causal chainfor event in events: print(f"{event['phase']}: caused_by={event.get('caused_by', 'none')}")
import jsonfrom pathlib import Pathlearn_path = Path(f".noesis/episodes/{episode_id}/learn.jsonl")if learn_path.exists(): with open(learn_path) as f: proposals = [json.loads(line) for line in f] for p in proposals: print(f"Proposal: {p['type']} -> {p.get('target', p.get('key'))}")
Experimental feature (ADR-005): Enable prompt logging carefully—prompts may contain sensitive data. Use ns.set(log_prompts=True) only when needed for debugging or compliance.
import noesis as nsns.set(label="production")# Artifacts go to .noesis/episodes/production/ep_.../ns.set(label="staging")# Artifacts go to .noesis/episodes/staging/ep_.../
from noesis.episode import EpisodeIndexstore = EpisodeIndex("./.noesis/episodes/_episodes", ttl_days=14)store.vacuum() # Remove episodes older than 14 days