diff --git a/docs/explanation/artifacts.mdx b/docs/explanation/artifacts.mdx index e27739f..dbaceb1 100644 --- a/docs/explanation/artifacts.mdx +++ b/docs/explanation/artifacts.mdx @@ -230,6 +230,36 @@ print(f"Steps: {len(state['plan']['steps'])}") print(f"Status: {state['outcomes']['status']}") ``` +### Authority model + +`state.json` is a snapshot assembled from multiple authorities. Use the source +that owns a field when debugging drift: + +| State slice | Authority | Operational note | +| --- | --- | --- | +| `episode.started_at` | `start` event timestamp | Stable across continuation | +| `plan` | Latest `plan` event plus later `act.step_status` evidence | Reconstruct with `noesis.runtime.plan_projection.project_plan_state(...)` | +| `outcomes` and `links` | `run.state_projection` runtime event | Terminal values mirror persisted `state.json` | +| `process` | Process registry allocation | Use `noesis processes` for current liveness | +| `beliefs` and `memory` | Runtime state repository | Treat as persisted state, not trace-derived evidence | + +For process-scoped runs, Noēsis copies the registry allocation into both +`summary.json` and `state.json`: + +```json +{ + "process": { + "id": "c0ffee123456", + "name": "release-notes", + "kind": "oneshot", + "run_index": 3 + } +} +``` + +`process.run_index` is monotonic inside one process. It is required for same-run +continuation and should not be interpreted as a global episode sequence. + ## events.jsonl The event timeline records every phase transition with timing and lineage. diff --git a/docs/reference/cli.mdx b/docs/reference/cli.mdx index 0305b08..7bb4efe 100644 --- a/docs/reference/cli.mdx +++ b/docs/reference/cli.mdx @@ -35,6 +35,7 @@ Most commands accept: | Command | Purpose | | --- | --- | +| `noesis` | Show the compact home screen and recent-run shortcuts | | `noesis run` | Start a baseline episode | | `noesis view` | Inspect an episode by ID or path | | `noesis ps` | List recent episodes | @@ -51,6 +52,19 @@ Most commands accept: ## Core workflows +### Open the home screen + +```bash +# Compact dashboard, exits 0 +noesis + +# Include detailed config and recent-run sections +noesis --full +``` + +The home screen is safe for empty workspaces: failures while reading recent +episodes are treated as empty results. + ### Run an episode ```bash @@ -122,13 +136,41 @@ noesis events ep_01JH6Z2V9Q2K6Y6N0QZ7K2QW8C --phase governance ### Process-oriented inspection ```bash -# Process liveness and metadata -noesis processes --limit 20 +# Group a run under a stable process label +noesis run "Backfill invoice summaries" --process billing-sync + +# Process liveness and metadata, optionally filtered by exact id or name +noesis processes --process billing-sync --json | jq '.processes[0]' -# Runs for a specific process +# Recent episodes for one process id or name +noesis ps --process billing-sync --json | jq '.episodes[].process' + +# Runs for a specific process id or name noesis runs --process alpha --limit 20 ``` +Process identity is derived from the resolved workspace plus the optional label +passed to `--process`. If no label is supplied, Noēsis derives a display name +from the workspace directory and the process id prefix. + +`processes` reads the registry and reports liveness fields: + +| Field | Meaning | +| --- | --- | +| `process_id` | Opaque stable id | +| `process_name` | Human label or auto-derived workspace label | +| `kind` | Process type; runtime-created runs currently use `oneshot` | +| `status` | `running`, `idle`, `stale`, or `error` | +| `last_seen_at` | Last registry update | +| `last_heartbeat_at` | Last running-process heartbeat | +| `active_run_id` | Current episode id when a run is active | +| `last_run_outcome` | Outcome from the most recent finished run | +| `next_run_index` | Next one-based index to allocate inside this process | + +`ps --process` and `runs --process` filter episodes by exact `process.id` or +`process.name` from run summaries. `runs --json` returns the filtered episode +array directly; `ps --json` wraps rows in a `cli/1.1` envelope. + ### Diagnostics and integrity ```bash @@ -177,9 +219,10 @@ The verification parser enforces: ### JSON output shape by command -- `run --json` emits a run-result envelope (`episode_id`, `episode_dir`, `artifacts`, `outcome`, `verification`, `capabilities`) +- `run --json` emits a run-result envelope (`episode_id`, `episode_dir`, `artifacts`, `outcome`, `verification`, `capabilities`, and `process` when present) - `ps --json` emits `{"episodes":[...], ...}` - `processes --json` emits `{"processes":[...], ...}` +- `runs --json --process NAME` emits a filtered episode array - `events --json` emits JSONL (one event per line) - `events --envelope` emits one JSON object containing all selected events @@ -207,6 +250,18 @@ Fix: - pass a direct episode directory path to `noesis view` - inspect available episodes with `noesis ps` +### `noesis runs --process ` returns no rows + +Cause: the process filter matches exact `process.id` or `process.name` values +stored in run summaries; it does not fuzzy-match task text or tags. + +Fix: + +- inspect registry names with `noesis processes` +- run future episodes with an explicit label, for example + `noesis run "task" --process ` +- verify that the same `NOESIS_RUNS_DIR` / runtime config is active + ### `error: corrupted events.jsonl at ...` Cause: the episode trace failed integrity checks (for example malformed JSON, invalid UTF-8, or a truncated record). diff --git a/docs/reference/python-api.mdx b/docs/reference/python-api.mdx index 6f699ad..a36d794 100644 --- a/docs/reference/python-api.mdx +++ b/docs/reference/python-api.mdx @@ -29,6 +29,7 @@ episode_id = ns.run( tags: dict[str, object] | None = None, context: Any | None = None, workspace: str | Path | None = None, + process: str | None = None, verify: VerifySpec | Sequence[VerifySpec] | None = None, ) -> str ``` @@ -57,6 +58,11 @@ Optional runtime context. If provided, execution bypasses the default session. Workspace root to snapshot for verification. + +Optional process label for grouping related episodes in `summary.json`, +`state.json`, and CLI process views. + + Verification assertions to evaluate against the workspace. @@ -70,6 +76,7 @@ import noesis as ns episode_id = ns.run("Draft release notes") episode_id = ns.run("Draft release notes", intuition=False, tags={"env": "staging"}) +episode_id = ns.run("Draft release notes", process="release-notes") ``` **Runtime context example**: @@ -99,6 +106,7 @@ episode_id = ns.solve( tags: dict[str, object] | None = None, context: Any | None = None, workspace: str | Path | None = None, + process: str | None = None, verify: VerifySpec | Sequence[VerifySpec] | None = None, ) -> str ``` @@ -118,6 +126,7 @@ def to_upper(task: str) -> dict: episode_id = ns.solve("process this", using=to_upper) episode_id = ns.solve("process this", using="my.module:adapter_fn") +episode_id = ns.solve("process this", using=to_upper, process="batch-transform") ``` ### Run lifecycle APIs @@ -519,13 +528,18 @@ from noesis import SessionBuilder session = SessionBuilder.from_env().build() ep = session.run("Process customer request") +grouped_ep = session.run("Process customer request", process="support-triage") # Read artifacts using the session's RuntimeContext import noesis as ns summary = ns.summary.read(ep, context=session.context) ``` -`SessionBuilder` reads config from env/TOML; you can also inject ports before building. Within a session, `run`/`solve` behave like the module-level helpers but share the session’s config and runtime context. +`SessionBuilder` reads config from env/TOML; you can also inject ports before +building. Within a session, `run`/`solve` behave like the module-level helpers +but share the session’s config and runtime context. The optional `process` label +uses the session workspace/config to derive the same stable process identity used +by CLI process views. ## Module facades diff --git a/docs/reference/state.mdx b/docs/reference/state.mdx index 4fea933..3039f63 100644 --- a/docs/reference/state.mdx +++ b/docs/reference/state.mdx @@ -12,6 +12,7 @@ The `state.json` artifact captures cognitive state snapshots during execution an "version": "1.0", "state_schema_version": "1.0.0", "episode": { ... }, + "process": { ... }, "goal": { ... }, "beliefs": [ ... ], "plan": { ... }, @@ -36,6 +37,11 @@ Relative artifact paths for this run (for example `events.jsonl`, `learn.jsonl`, `summary.json`, `manifest.json`). Keys vary by lifecycle state. + +Stable process identity for grouping related episodes. Present for runtime-created +episodes and required for same-run continuation. + + ## Episode Episode metadata and timestamps. @@ -80,6 +86,48 @@ Intuition posture for the episode (advisory | interventive | hybrid). Runs creat with older Noēsis versions may omit this field (default advisory). +## Process + +`process` ties an episode to the filesystem-backed process registry used by +operator views. + +```json +{ + "process": { + "id": "c0ffee123456", + "name": "release-notes", + "run_index": 3, + "kind": "oneshot" + } +} +``` + + +Opaque stable identifier derived from the resolved workspace identity plus the +optional process label. + + + +Human-readable process label. When no label is supplied, Noēsis derives a name +from the workspace directory and process id prefix. + + + +Monotonic, one-based counter allocated by the process registry for this process. +It orders runs inside one process and is not a global episode count. + + + +Execution style for the process. Runtime-created CLI and Python runs currently +use `"oneshot"`. + + + +`state.process` is a snapshot of registry allocation, not a value reconstructed +from `events.jsonl`. `resume_run` requires `process.id` and `process.run_index` +in `state.json`. + + ## Artifact links `links` points to run-local artifacts in the episode directory. @@ -409,6 +457,9 @@ Outcome metrics (e.g., total duration). - `episode.started_at` is aligned to the `start` event timestamp and remains stable across continuation. +- `process` is registry-backed metadata captured at run allocation time. Use it + to group and resume runs, but use the process registry/CLI for current + liveness. - Whenever `state.json` is persisted, runtime emits `phase="runtime"`, `event_type="run.state_projection"` with projection evidence for outcomes and links. @@ -428,6 +479,12 @@ Outcome metrics (e.g., total duration). "using": "baseline", "started_at": "2024-01-15T10:30:00Z" }, + "process": { + "id": "c0ffee123456", + "name": "release-notes", + "run_index": 3, + "kind": "oneshot" + }, "goal": { "task": "Draft release notes for v1.2.0", "type": "task"