Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
"pages": [
"reference/events",
"reference/state",
"reference/summary"
"reference/summary",
"reference/final"
]
},
{
Expand Down
62 changes: 56 additions & 6 deletions docs/explanation/artifacts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Every Noēsis episode produces a set of structured artifacts that capture the co
events.jsonl # cognitive event timeline with lineage
summary.json # metrics and KPIs (insight.metrics)
state.json # plan, beliefs, memory, outcomes
final.json # terminal seal marker
manifest.json # SHA-256 catalog + optional HMAC
learn.jsonl # learning signals (optional)
prompts.jsonl # prompt provenance (opt-in, ADR-005)
Expand Down Expand Up @@ -334,6 +335,49 @@ noesis events ep_abc123 --phase act
noesis events ep_abc123 -j | jq '.[] | select(.phase == "plan")'
```

## final.json

`final.json` is the terminal seal marker for an episode. If it exists, Noēsis treats the run as finalized and blocks lifecycle mutations such as checkpoint or resume.

### Schema

Current final schema version: `final/2.0.0` ([JSON schema](/schema/final/2.0.0.json)).

```json
{
"schema_version": "final/2.0.0",
"episode_id": "ep_2024_abc123_s0",
"process_id": "proc_abc123",
"run_index": 1,
"finalized_at": "2024-01-15T10:30:05Z",
"outcome": "success",
"verification_status": "unverified"
}
```

| Field | Description |
| --- | --- |
| `schema_version` | Final marker schema (`final/2.0.0`) |
| `episode_id` | Episode/run ID being sealed |
| `process_id` | Process lineage ID for the run |
| `run_index` | 1-based run number within the process |
| `finalized_at` | ISO 8601 timestamp for finalization |
| `outcome` | One of `success`, `failed`, `vetoed`, `cancelled`, `interrupted`, `error` |
| `verification_status` | One of `verified`, `unverified`, `not_applicable` |

### Sealing contract

Terminal runs seal in a fixed order:

1. Write `final.json`.
2. Write `manifest.json` with a checksum entry for `final.json`.

If manifest writing fails, Noēsis removes `final.json` so the run is not left in a falsely sealed state. A second seal attempt raises an immutability error and leaves existing artifacts unchanged.

<Info>
Pause-on-veto runs (`governance_pause_on_veto=true`) stay unsealed: they emit lifecycle evidence such as `run.interrupt` and `run.checkpoint`, but do not write `final.json` or `manifest.json` until continuation or explicit termination.
</Info>

## manifest.json

The manifest provides integrity verification for all artifacts with SHA-256 hashes and optional signatures.
Expand All @@ -348,7 +392,8 @@ The manifest provides integrity verification for all artifacts with SHA-256 hash
"files": [
{"name": "summary.json", "sha256": "sha256:abc123...", "size_bytes": 1234, "kind": "summary"},
{"name": "state.json", "sha256": "sha256:def456...", "size_bytes": 5678, "kind": "state"},
{"name": "events.jsonl", "sha256": "sha256:ghi789...", "size_bytes": 9012, "kind": "events"}
{"name": "events.jsonl", "sha256": "sha256:ghi789...", "size_bytes": 9012, "kind": "events"},
{"name": "final.json", "sha256": "sha256:jkl012...", "size_bytes": 234, "kind": "attachment"}
],
"signature": {
"alg": "hs256",
Expand All @@ -365,6 +410,8 @@ The manifest provides integrity verification for all artifacts with SHA-256 hash
| `files` | Array of files with `name`, `sha256`, `size_bytes`, `kind` (`summary`, `state`, `events`, `learn`, `attachment`, `custom`) |
| `signature` | Optional signature block with algorithm, key ID, value, timestamp |

For sealed terminal runs, verifiers should expect both `final.json` and `manifest.json`. `manifest.json` is not the seal marker by itself; `final.json` is.

### Artifact immutability guarantees

All artifacts are written atomically using this pattern:
Expand All @@ -389,16 +436,16 @@ def verify_manifest(episode_dir: Path) -> bool:
with open(manifest_path) as f:
manifest = json.load(f)

for filename, info in manifest["files"].items():
file_path = episode_dir / filename
for info in manifest["files"]:
file_path = episode_dir / info["name"]

# Check size
if file_path.stat().st_size != info["size"]:
if file_path.stat().st_size != info["size_bytes"]:
return False

# Check hash
with open(file_path, "rb") as f:
actual_hash = hashlib.sha256(f.read()).hexdigest()
actual_hash = "sha256:" + hashlib.sha256(f.read()).hexdigest()

if actual_hash != info["sha256"]:
return False
Expand Down Expand Up @@ -517,7 +564,7 @@ store.vacuum() # Remove episodes older than 14 days
</Warning>

<Info>
**Use manifests for compliance.** The SHA-256 checksums in manifest.json provide tamper evidence for audits.
**Use manifests with final markers for compliance.** `final.json` marks a terminal seal; the SHA-256 checksums in `manifest.json` provide tamper evidence for the sealed bundle.
</Info>

## Next steps
Expand All @@ -535,4 +582,7 @@ store.vacuum() # Remove episodes older than 14 days
<Card title="Summary reference" icon="file" href="/reference/summary">
Complete summary schema documentation.
</Card>
<Card title="Final reference" icon="stamp" href="/reference/final">
Final marker schema and sealing semantics.
</Card>
</CardGroup>
7 changes: 6 additions & 1 deletion docs/explanation/core-concepts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ Every episode produces structured **artifacts** that capture the full cognitive
summary.json # metrics and outcomes
state.json # cognitive state
events.jsonl # timeline
final.json # terminal seal marker
manifest.json # integrity checksums
learn.jsonl # learning signals (optional)
```
Expand Down Expand Up @@ -256,11 +257,14 @@ The manifest provides integrity verification:
"created_at": "2024-01-15T10:30:05Z",
"files": [
{"name": "summary.json", "sha256": "sha256:abc123...", "size_bytes": 1234, "kind": "summary"},
{"name": "events.jsonl", "sha256": "sha256:def456...", "size_bytes": 5678, "kind": "events"}
{"name": "events.jsonl", "sha256": "sha256:def456...", "size_bytes": 5678, "kind": "events"},
{"name": "final.json", "sha256": "sha256:ghi789...", "size_bytes": 234, "kind": "attachment"}
]
}
```

Terminal runs also write `final.json` before `manifest.json`. The final marker is the seal; the manifest records checksums for the sealed bundle, including `final.json`.

## Adapters

**Adapters** connect Noēsis to your existing agent runtimes. They're simply callables that Noēsis wraps with cognition:
Expand Down Expand Up @@ -344,6 +348,7 @@ flowchart TD
A --> SUM[summary.json]
A --> ST[state.json]
A --> EV[events.jsonl]
A --> FIN[final.json]
```

1. A **task** creates an **episode**
Expand Down
3 changes: 2 additions & 1 deletion docs/guides/adopting-noesis.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ It's practical and opinionated: what to do, what to avoid, and how to fit Noēsi
## 1) What Noēsis actually adds

- **Episodes**: every run is a cognitive episode with a stable ID.
- **Artifacts**: `events.jsonl`, `summary.json`, `state.json`, `manifest.json`, optional `prompts.jsonl`.
- **Artifacts**: `events.jsonl`, `summary.json`, `state.json`, `final.json`, `manifest.json`, optional `prompts.jsonl`.
- **Cognitive phases**: `observe → intuition → interpret → plan → direction → governance → act → reflect → learn → terminate → insight → memory`.
- **Governance & direction**: policies that hint, intervene, or veto, with explicit flags in summary + events.
- **Determinism controls**: seeds, deterministic clocks/IDs, replay support.
Expand Down Expand Up @@ -46,6 +46,7 @@ You don’t need a perfect “episode store” on day one—pick **one** place t
events.jsonl
summary.json
state.json
final.json
manifest.json
```

Expand Down
1 change: 1 addition & 0 deletions docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Every run produces a clean artifact structure:
summary.json # metrics and outcomes
state.json # current plan and episode state
events.jsonl # timeline with causal IDs
final.json # terminal seal marker
manifest.json # SHA-256 + size ledger for tamper evidence
learn.jsonl # optional learning payloads
```
Expand Down
1 change: 1 addition & 0 deletions docs/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Every episode creates a structured artifact directory (written under `.noesis/ep
summary.json # metrics + rollups
state.json # final state snapshot
events.jsonl # append-only timeline
final.json # terminal seal marker
manifest.json # SHA-256 + size ledger
learn.jsonl # optional learning payloads
_episodes/ # optional episode index (best-effort)
Expand Down
144 changes: 144 additions & 0 deletions docs/reference/final.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
title: "Final schema"
description: "Complete reference for the Noesis final.json seal marker."
---

The `final.json` artifact marks an episode run as terminal and sealed. It is small by design: consumers can check one file to decide whether a run may accept lifecycle mutations, then use `manifest.json` to verify the sealed bundle.

Current final schema version: `final/2.0.0` ([JSON schema](/schema/final/2.0.0.json)).

## Schema overview

```json
{
"schema_version": "final/2.0.0",
"episode_id": "ep_2024_abc123_s0",
"process_id": "proc_abc123",
"run_index": 1,
"finalized_at": "2024-01-15T10:30:05Z",
"outcome": "success",
"verification_status": "unverified"
}
```

## Root fields

<ResponseField name="schema_version" type="string" required>
Final marker schema. Currently `"final/2.0.0"`.
</ResponseField>

<ResponseField name="episode_id" type="string" required>
Episode/run ID being finalized.
</ResponseField>

<ResponseField name="process_id" type="string" required>
Stable process lineage ID for the run.
</ResponseField>

<ResponseField name="run_index" type="integer" required>
1-based run number within the process lineage.
</ResponseField>

<ResponseField name="finalized_at" type="string" required>
ISO 8601 timestamp when the final marker was written.
</ResponseField>

<ResponseField name="outcome" type="string" required>
Terminal outcome class.

| Value | Meaning |
| --- | --- |
| `success` | The run reached a successful terminal state |
| `failed` | Verification completed and the goal was not achieved |
| `vetoed` | Governance enforced a veto before side effects completed |
| `cancelled` | The run was cancelled |
| `interrupted` | The run ended as interrupted |
| `error` | The run ended due to an execution or runtime error |
</ResponseField>

<ResponseField name="verification_status" type="string" required>
Verification result class.

| Value | Meaning |
| --- | --- |
| `verified` | Verification assertions ran and passed or failed deterministically |
| `unverified` | The run succeeded without verification assertions |
| `not_applicable` | Verification does not apply, such as veto or error outcomes |
</ResponseField>

## Sealing contract

Noesis treats `final.json` as the canonical seal marker. Once it exists, lifecycle writes and resume attempts fail with `RunSealedError`. The artifact immutability guard also blocks later writes, except for the single `manifest.json` seal write that completes finalization.

Terminal sealing is ordered:

1. Write `final.json`.
2. Write `manifest.json`, including a checksum entry for `final.json`.

If manifest writing fails, Noesis removes `final.json` so the episode is not left in a falsely sealed state. Double-seal attempts raise `ImmutabilityError` and do not mutate the existing final marker or manifest.

## Lifecycle constraints

Terminal runs include both `final.json` and `manifest.json`. This covers successful runs, failed verification, errors, and enforced vetoes that terminate the episode.

Paused runs are intentionally unsealed. For example, `governance_pause_on_veto=true` emits `run.interrupt` and `run.checkpoint` lifecycle events, but does not write `final.json` or `manifest.json` until the run continues or terminates.

## Examples

### Successful unverified run

```json
{
"schema_version": "final/2.0.0",
"episode_id": "ep_2024_success_s0",
"process_id": "proc_success",
"run_index": 1,
"finalized_at": "2024-01-15T10:30:05Z",
"outcome": "success",
"verification_status": "unverified"
}
```

### Enforced veto

```json
{
"schema_version": "final/2.0.0",
"episode_id": "ep_2024_veto_s0",
"process_id": "proc_veto",
"run_index": 1,
"finalized_at": "2024-01-15T10:30:05Z",
"outcome": "vetoed",
"verification_status": "not_applicable"
}
```

## Reading final markers

### File access

```bash
EP_DIR=$(noesis view ep_abc123 --json | jq -r '.episode_dir')
jq '.outcome, .verification_status' "$EP_DIR/final.json"
```

### Sealed check

```python
from pathlib import Path


def is_sealed(episode_dir: Path) -> bool:
return (episode_dir / "final.json").exists()
```

## Next steps

<CardGroup cols={2}>
<Card title="Artifacts" icon="files" href="/explanation/artifacts">
Learn how final markers and manifests seal evidence bundles.
</Card>
<Card title="State schema" icon="database" href="/reference/state">
See lifecycle links for terminal and non-terminal runs.
</Card>
</CardGroup>
Loading