# Lamina — full documentation export > Design how it works. Transactional product-knowledge graph for AI coding agents. Invoke /lamina-init, /lamina-design, and /lamina-verify to publish intended behavior, source observations, and isolated Persona Mission evidence. Lamina is an Apache-2.0 transactional product graph. Ladybug stores canonical Resources, Statements, versions, sessions, and Runs; CocoIndex incrementally supplies explicit source Observations through graphd. Positioning: Product-design skill for developers who build with AI — know what to build, iterate faster. Who it's for: Developers using AI coding agents (Cursor, Claude Code, Codex, Gemini, Pi) — not designers or PMs. The loop: /lamina-init → /lamina-design → implement → /lamina-verify → fix. Run slash commands explicitly in agent chat — Lamina does not activate passively after install. Slash commands produce `.lamina/` artifacts; your coding agent implements app source; Lamina verifies the live build. Lamina (lamina.dev) is an open-source product-design skill for AI coding agents — not uselamina.ai (creative API for media generation). Key facts: - Not a UI library — never writes app source or picks your component library - Not an app builder — does not generate stack-locked apps like v0 or Lovable - Not a pixel skill — Impeccable and frontend-design polish how it looks; Lamina designs how it works - Open-source Apache-2.0 — https://github.com/aryaniyaps/lamina - Install: `curl -fsSL https://github.com/aryaniyaps/lamina/releases/latest/download/install.sh | sh && npx skills add aryaniyaps/lamina --skill '*' -a -y` - Commands: /lamina-init, /lamina-design, /lamina-verify, /lamina (optional router) - Atomic, versioned product behavior with semantic branch diffs - Independent Missions for every active Persona - Epistemically separated intent, observations, simulation, and runtime evidence - Fits any stack — framework, database, language, UI library, and AI coding tool - Creator: Aryan Iyappan (https://aryaniyappan.com) - Contact: https://github.com/aryaniyaps/lamina/issues --- Generated from docs/content. Prefer per-page URLs for citations when possible. ## index URL: https://lamina.dev/docs # Lamina Lamina gives AI coding agents a centralized, transactional product graph: one place to publish product intent, observe the implementation, and attach verification evidence without collapsing those kinds of knowledge together. Ladybug is the canonical local knowledge graph. It stores stable Resources, normalized Statements, versions, branch/session/observation views, Missions, Runs, and evidence. Git identifies source revisions and branches but does not store graph changes. Read the architecture from left to right: - The managed worker turns repository files into rebuildable **observations**. - Agents stage typed **proposals** in explicit graph sessions. - Mission adapters normalize live product events into **runtime evidence**. - Every write crosses `graphd`. It is the only process that opens Ladybug read-write, and it publishes graph changes transactionally. ## Start ```bash curl -fsSL https://github.com/aryaniyaps/lamina/releases/latest/download/install.sh | sh npx skills add aryaniyaps/lamina --skill '*' -a -y lamina doctor --json /lamina-init # then use ordinary product requests ``` Setup also runs `lamina setup --agent `. Use `lamina graph status` to inspect the resolved GraphVersion and `lamina context status` to inspect the derived hybrid-retrieval generation. ## Why it is different - Serializable sessions publish completely or leave the branch unchanged. - Intent, observations, agent inference, Persona simulation, human evidence, and runtime evidence stay separate. - Conflicts remain inspectable as Contradictions. - Every active Persona receives an independent Mission and Run. - Every implementation obligation is mapped to code and verification before edits. - UI verification requires functional, visual, responsive, and accessibility evidence. - Source changes update an observation view without mutating canonical Claims. - Hybrid retrieval selects Workflow roots and source symbols without replacing graph authority. - Existing legacy run files are ignored by the runtime. Continue with [The product loop](https://lamina.dev/docs/concepts/the-loop), or inspect the [transactional graph](https://lamina.dev/docs/reference/transactional-graph) in detail. --- ## getting-started/first-run URL: https://lamina.dev/docs/getting-started/first-run # First graph session Run `/lamina-init`, then `/lamina-design` with a concrete workflow. Inspect the published result with `lamina graph status` and `lamina graph query --at HEAD`. Application source is implemented separately. `/lamina-verify` then compiles every active Persona Mission, stages normalized runtime evidence in independent sessions, and explicitly publishes the accepted sessions. --- ## Installation URL: https://lamina.dev/docs/getting-started/installation Summary: Install the Lamina CLI and skills independently # Installation Lamina works with any AI coding agent and any stack. Install once in your **shell**, then invoke Lamina with **slash commands in agent chat** — not with passive natural-language prompting. Installation does not cause Lamina to activate. After install, open your project root and start a **fresh agent session**, then run `/lamina-init` directly. ## Quick path 1. **Shell** — install the CLI, then install the skills for your agent 2. Open your project root and start a **fresh agent session** so the skills load 3. **Agent chat** — run `/lamina-init ` Continue with [Quickstart](https://lamina.dev/docs/getting-started/quickstart) for the full design → implement → verify loop. ## Quick install ```bash curl -fsSL https://github.com/aryaniyaps/lamina/releases/latest/download/install.sh | sh lamina doctor --json npx skills add aryaniyaps/lamina --skill '*' -a -y ``` Use one active-agent target: `codex`, `claude-code`, or `cursor`. Do not use `-a '*'`; it creates configuration for agents that are not part of this project. The CLI and skill set have independent release and installation lifecycles. The CLI provides `lamina`; the GitHub install provides 10 public skills: four workflow entrypoints and six grouped product capabilities. Focused craft guidance is progressively loaded from references inside each capability. Either component can be installed alone, but graph-backed workflows require CLI API 1. ## Agent-specific installs ### Cursor ```bash npx skills add https://github.com/aryaniyaps/lamina --skill '*' -a cursor -y ``` ### Claude Code ```bash npx skills add https://github.com/aryaniyaps/lamina --skill '*' -a claude-code -y ``` ### Codex / Pi / generic ```bash npx skills add https://github.com/aryaniyaps/lamina --skill '*' -a codex -a pi -y ``` ## Prerequisites - An AI coding agent (Cursor, Claude Code, Codex, Gemini, Pi, or similar) - Any framework, database, and UI library — Lamina is stack-agnostic - No Node.js or npm is required for the standalone `lamina` executable Node.js/npm are required only for `npx skills add`. If the compatible CLI is absent, a graph-backed workflow stops before mutation and prints: ```text Install the standalone Lamina CLI from GitHub Releases, then run lamina doctor --json. ``` The skills never invoke `npx` for the runtime and never auto-install it. The installer verifies the release checksum and writes to `~/.local/bin` on macOS/Linux or `%LOCALAPPDATA%\\Lamina\\bin` on Windows. Add that directory to your user PATH if it is not already present. Unsupported platforms fail before installing anything. ## After install 1. Open the intended **project root** in your coding agent 2. Start a **fresh agent session** — the complete skill set loads at session start 3. Run init directly in agent chat: ``` /lamina-init ``` Successful init produces and validates both `.lamina/business-context.md` and `.lamina/personas.json`. Run init **once per project or domain**; use `/lamina-init update` only when the business use case, market, scope, or actor cast materially changes. If the directory is not a Git project, `/lamina-init` runs `git init -b main` before creating evidence. It creates no initial commit and never stages files. Not sure which command to run? `/lamina ` is an optional router for discovery — not a required setup step and not a substitute for `/lamina-init`. ## Update Update the components independently: ```bash curl -fsSL https://github.com/aryaniyaps/lamina/releases/latest/download/install.sh | sh npx skills add aryaniyaps/lamina --skill '*' -a -y ``` Start a new agent session after updating. ## Migrate from the old linked repository package If an older npm-installed CLI is present, remove it once, then install the standalone executable: ```bash npm uninstall -g @laminadev/cli curl -fsSL https://github.com/aryaniyaps/lamina/releases/latest/download/install.sh | sh ``` Do not delete `.git/lamina`. Existing `graph.lbdb` data is retained; the new graphd creates its authentication token beside that database. ## .gitignore guidance Lamina writes evidence inputs and optional projections to `.lamina/`. The canonical Ladybug graph remains clone-local under `.git/lamina` and is never shared by committing `.lamina/`. | Approach | When | |----------|------| | Commit selected `.lamina/` files | Team wants shared business evidence or non-canonical projections | | Gitignore `.lamina/` | Personal experiments; regenerate locally | To exclude: ```gitignore .lamina/ ``` ## Uninstall Remove the Lamina skills using your agent's skill management tooling, or delete the installed `lamina*` skill directories. Remove the CLI by deleting `~/.local/bin/lamina` (or `%LOCALAPPDATA%\\Lamina\\bin\\lamina.exe`). `.lamina/` artifacts and `.git/lamina` graph data are not removed automatically. ## Source Lamina is open source under the Apache License 2.0: [github.com/aryaniyaps/lamina](https://github.com/aryaniyaps/lamina) Full documentation: [lamina.dev](https://lamina.dev) ## Next steps - [Quickstart](https://lamina.dev/docs/getting-started/quickstart) — run your first cycle - [Troubleshooting](https://lamina.dev/docs/getting-started/troubleshooting) — if commands are not recognized or init is blocked - [What is Lamina?](https://lamina.dev/docs/concepts/what-is-lamina) — understand what you installed --- ## getting-started/quickstart URL: https://lamina.dev/docs/getting-started/quickstart # Quickstart ```bash curl -fsSL https://github.com/aryaniyaps/lamina/releases/latest/download/install.sh | sh npx skills add aryaniyaps/lamina --skill '*' -a -y lamina doctor --json /lamina-init /lamina-design lamina graph status # implement the resolved GraphVersion in a normal coding session /lamina-verify ``` Use the current agent target (`codex`, `claude-code`, or `cursor`). On a fresh folder, `/lamina-init` creates Git metadata without staging or committing files. Run `lamina graph observe` after source changes. Use `lamina graph diff --base main --head HEAD` for a semantic branch diff. --- ## getting-started/troubleshooting URL: https://lamina.dev/docs/getting-started/troubleshooting # Troubleshooting - `LAMINA_COMPARE_AND_SWAP_FAILED`: rebase the session, query the new head, revalidate, and publish. - CLI missing or incompatible: reinstall the standalone binary from GitHub Releases, ensure its install directory is on PATH, then run `lamina doctor --json`. Do not use `sudo`. - New folder is not a Git project: `/lamina-init` initializes an unborn `main` branch automatically. It does not stage or commit files. - graphd unavailable: rerun `lamina graph status`; incompatible protocol daemons restart and stale locks recover without rewriting `graph.lbdb`. - observation update incomplete: rerun `lamina graph observe`; the managed runtime reconciles the active source-key set and replaces superseded observations. If the managed runtime assets are corrupted, reinstall the standalone release. - stale readiness: inspect missing evidence, source snapshot changes, artifact digests, and Contradictions with `lamina graph validate`. --- ## concepts/brownfield-and-greenfield URL: https://lamina.dev/docs/concepts/brownfield-and-greenfield # Brownfield and greenfield Greenfield design begins with intended Resources and Statements plus explicit assumptions. Brownfield discovery uses managed source Observations from routes, commands, schemas, tests, documentation, permissions, events, configuration, and existing Persona material. Extractors never promote observations into intended or approved Claims. Absence of an Observation is not proof of absence. Both use the same graph, Mission, Run, and evidence model. --- ## concepts/contracts-and-runs URL: https://lamina.dev/docs/concepts/contracts-and-runs # GraphVersions and Runs A GraphVersion is the immutable, validated state of a branch view. A session stages typed mutations against a base GraphVersion and publishes with compare-and-swap in one Ladybug transaction. A Run is runtime product knowledge tied to its starting GraphVersion, source revision, Persona Mission, adapter context, and HarnessResult. Runs are isolated until publication. Human implementation, report, and fix documents are optional query projections. They never become canonical inputs. --- ## concepts/personas URL: https://lamina.dev/docs/concepts/personas # Personas and Missions Personas are stable Resources. Actors express authority; typed Statements connect Personas to Actors they can assume. Before implementation, `lamina design prepare-walk` creates an independent, coverage-bound design task for every active Persona. Isolated walkers inspect every proposed operation node—including denied and inapplicable nodes—and expand the graph until no walk discovers another required node, permission, state, Scenario, Invariant, recovery path, or edge case. Each node must cover the canonical state matrix plus every product-specific state declared on its Operation or Surfaces. `record-walk` stores the current `persona_walk` Resource and replaces that Persona's previous active walk for the Workflow. The digest covers canonical Resource data and relevant Statements, so permission or product-data changes invalidate the walk even if ids do not change. Experience Cases compile directly from these records. After implementation, `lamina mission compile` queries the converged workflow/operation closure, invariants, recovery paths, Surfaces, adapter capabilities, proofs, evidence, budgets, and isolation. It creates an independent runtime Mission for every active Persona without a cap. Persona interpretation is simulated. Engine-recorded design walks are simulated evidence; only adapter-observed Mission events become runtime evidence. --- ## concepts/the-loop URL: https://lamina.dev/docs/concepts/the-loop # The loop Lamina separates the product contract, the code that implements it, and the evidence that proves it works. Use the loop whenever you introduce or change a user-facing flow. ## From intent to evidence 1. **Ground the repository.** Run `/lamina-init` once. It records business evidence and publishes inferred Product, Actor, and Persona proposals grounded in explicit user input. 2. **Walk every Persona before building.** For new or changed behavior, the provider prepares one coverage-bound design task per active Persona. Isolated walks traverse every proposed node and expand missing permissions, states, branches, Scenarios, Invariants, recovery, and edge cases into the graph until a current round returns an empty discovery matrix. No implementation is required. 3. **Prepare context.** The provider rule runs `lamina work prepare` over the expanded graph to compile Persona-bound cases, direct provenance, ranked source candidates, and stable obligations. 4. **Map and implement.** Lamina mechanically scaffolds every obligation and Experience Case row, then the agent resolves each row to immutable file entries. `action: modify` names an existing file; `action: create` names a planned file. Roles distinguish implementation from tests before the agent edits source in your existing stack. 5. **Exercise the live product.** The agent creates an isolated Mission and Run for every active Persona. UI work requires functional, visual, responsive, and accessibility artifacts, not merely a screenshot or passing unit test. 6. **Decide from evidence.** Published Mission events are the sole case proof; the WorkMap remains unchanged. Inspect the findings and semantic diff, then accept the evidence, fix the implementation, or change the contract. Verification findings have two different destinations: - An **implementation defect** returns to ordinary coding. Fix the product and run the same verification mission again. - A **contract gap** is published transactionally before implementing and verifying it. This distinction keeps a failing implementation from silently redefining the product contract. ## What Lamina changes The Lamina CLI publishes graph state, packets, receipts, and evidence. It does not edit application source, choose a framework, or replace your coding agent. The provider rule gives that coding agent the graph context automatically. Human-readable implementation, report, and fix documents are optional projections from the resolved graph; the `GraphVersion` is canonical. Use `lamina graph status` to inspect the active version and `lamina graph diff --base --head ` to review the semantic change. --- ## concepts/what-is-lamina URL: https://lamina.dev/docs/concepts/what-is-lamina # What is Lamina? Lamina is a local, centralized product-knowledge graph for agents. It gives product intent, source observations, agent inference, Persona simulation, human evidence, and runtime evidence distinct epistemic classes. Ladybug stores canonical versioned knowledge. Lamina's managed runtime incrementally observes source. graphd enforces transactions, provenance, validation, sessions, branches, Missions, and evidence. --- ## commands/index URL: https://lamina.dev/docs/commands/index # Commands | Command | Purpose | |---|---| | `/lamina-init` | Establish business evidence and Product/Persona/Actor Resources | | `/lamina-design` | Validate and publish intended product behavior | | `/lamina-verify` | Run every active Persona Mission | | `/lamina` | Route focused product work | Runtime operations use `lamina graph`, `lamina session`, and `lamina mission`. See [Transactional graph](https://lamina.dev/docs/reference/transactional-graph). --- ## commands/lamina URL: https://lamina.dev/docs/commands/lamina # `/lamina` Routes explicit init, design, verify, and focused product questions. Canonical context comes from graph queries; legacy files are never selected as runtime state. Ordinary implementation requests use `lamina work prepare`. It automatically synchronizes the local hybrid-retrieval index, selects relevant Workflow roots, and then compiles their exact graph closure. Retrieval diagnostics are intentionally small: ```bash lamina context status lamina context rebuild ``` `status` is read-only. `rebuild` discards and reconstructs only `.git/lamina/context/retrieval.lbdb`; it never mutates the canonical product graph. --- ## commands/lamina-design URL: https://lamina.dev/docs/commands/lamina-design # `/lamina-design` Shapes intended product behavior in an explicit graph session. 1. Requires valid business context. 2. Seeds a minimal proposed Workflow for brand-new functionality. 3. Prepares one coverage-bound design task per active Persona. 4. Runs and records every Persona in an isolated subagent/context. 5. Unions discovered permissions, nodes, states, Scenarios, Invariants, and edge cases into the graph and repeats until coverage converges. 6. Validates the graph-resident walks and compiles Experience Cases directly from them. No separate Experience Contract is authored. ```bash lamina graph status lamina design prepare-walk --workflow --persona --request-file --output lamina design record-walk --task --result lamina session start lamina graph validate --at lamina session publish ``` On a stale coverage digest, rerun every affected Persona walk. On a stale-base session error, rebase, re-query, and revalidate. Explicit `/lamina-design` remains graph-only; ordinary feature work continues into mapping and implementation. Any implementation Markdown is a query projection tied to a GraphVersion. Each walk returns explicit arrays for discovered Personas, Actors, Operations, Scenarios, Invariants, Surfaces, branches, and open decisions. Any non-empty array blocks implementation readiness until those findings are added to the graph and a complete rerun returns an empty discovery matrix. --- ## /lamina-init URL: https://lamina.dev/docs/commands/lamina-init Summary: Establish or update the domain charter and actor cast # /lamina-init Answer the business questions product design depends on and persist them in `.lamina/`. Run once per project, or again when the business use case changes. ## Quick path 1. Run `/lamina-init` with your domain description 2. Inspect `.lamina/business-context.md` and `.lamina/personas.json` 3. Proceed to `/lamina-design` ## When to use - Starting a new project or major feature area - Before `/lamina-design` on an unfamiliar domain - When pivoting scope, market, or actor cast (`update` mode) - Before any verify on a greenfield project ## Modes | Mode | Command | Behavior | |------|---------|----------| | `establish` (default) | `/lamina-init ` | First-time bootstrap | | `update` | `/lamina-init update ` | Merge changelog on pivot; preserve prior decisions | ### Establish ``` /lamina-init Exam hall ticket system for universities ``` ``` /lamina-init Boutique hotel booking marketplace in the United States ``` ### Update Use when the business use case changes — new market, scope pivot, or actor cast shift: ``` /lamina-init update Expanding to business travelers with corporate billing ``` Update mode appends to the changelog in `business-context.md` and revises affected sections without discarding prior work. ## What it produces | File | Content | |------|---------| | `.lamina/business-context.md` | Domain charter — problem, goals, scope, constraints | | `.lamina/personas.json` | Actor cast — roles, goals, permissions, constraints | See [Global artifacts](https://lamina.dev/docs/reference/global-artifacts) for field-level detail. ## Brownfield scanning On existing codebases, `/lamina-init` may perform a bounded repo scan to infer domain context. The scan is read-only — Lamina never edits app source during init. **Advanced:** Brownfield scanning follows the field-research pattern. It reads source files and may walk the live UI to ground `business-context.md` in what already exists. ## Init gate `/lamina-design` and `/lamina-verify` are blocked until a valid `business-context.md` exists. This gate cannot be bypassed. ## What to do next Run `/lamina-design` with a specific feature or flow within the chartered domain: ``` /lamina-design Hall ticket download with payment gate and venue assignment ``` ## Tips - Be specific — "e-commerce" is too broad; "university exam hall ticketing" is right - Include primary actors: "for students, invigilators, and admin staff" - One init per domain — design individual flows with `/lamina-design`, not repeated inits - For brownfield projects, mention the existing app: "init for our existing Next.js booking app" ## Next steps - [/lamina-design](https://lamina.dev/docs/commands/lamina-design) — design a contract - [Global artifacts](https://lamina.dev/docs/reference/global-artifacts) — `business-context.md` and `personas.json` reference - [Brownfield and greenfield](https://lamina.dev/docs/concepts/brownfield-and-greenfield) — existing vs new projects --- ## commands/lamina-verify URL: https://lamina.dev/docs/commands/lamina-verify # `/lamina-verify` Verifies graph-backed product Missions against the actual product. ```bash lamina mission compile --workflow lamina mission run --events events.json lamina session query lamina session publish lamina graph validate --at HEAD ``` Every active Persona runs independently with isolated mutable state. Adapters emit normalized runtime events and store large artifacts in the evidence CAS. Missing/corrupt artifacts, stale source snapshots, capability failures, and Contradictions invalidate approval. `mission run` stages the Run and HarnessResult in an isolated session. Inspect and explicitly publish that session; concurrent Runs never become visible merely because an adapter finished. The command reports GraphVersion, source revision, Run/HarnessResult ids, evidence gaps, Contradictions, and a verified/not-verified verdict. It does not edit application source. --- ## guides/demo-havenstay URL: https://lamina.dev/docs/guides/demo-havenstay # HavenStay legacy demo This archived walkthrough predates the transactional graph and is not a current runtime guide. Current demos must use graphd sessions, GraphVersions, CocoIndex Observations, and independent Persona Missions. --- ## guides/pair-with URL: https://lamina.dev/docs/guides/pair-with # Pair Lamina with coding tools Use Lamina to publish product behavior, query an implementation projection for your coding tool, then publish runtime verification evidence. The projection must cite its GraphVersion and never becomes canonical input. --- ## guides/pair-with-spec-kit URL: https://lamina.dev/docs/guides/pair-with-spec-kit # Pair with Spec Kit Generate a Spec Kit input as a read-only query projection of a resolved GraphVersion. Implement normally, then use `/lamina-verify` to execute Persona Missions. Do not import generated specification prose back as graph truth. --- ## Pair with UI skills URL: https://lamina.dev/docs/guides/pair-with-ui-skills Summary: Lamina for behavior, UI skills for pixels — recommended workflow # Pair with UI skills Lamina and UI design skills solve different problems. Use them together — Lamina owns product behavior, UI skills own how it looks. ## Quick path 1. `/lamina-init ` → domain charter 2. `/lamina-design` → behavior contract 3. Implement and `/lamina-verify` 4. UI skill pass → visual polish 5. `/lamina-verify` again → confirm behavior still holds ## The split | Layer | Skill examples | Output | |-------|---------------|--------| | **Behavior** | Lamina | States, roles, flows, invariants, verification | | **Pixels** | Impeccable, UI UX Pro Max, frontend-design | Typography, spacing, components, visual polish | Lamina never writes styling, colors, typography, or component libraries. UI skills never define permission matrices or state machines. ## Recommended workflow | Step | Action | Result | |---|---|---| | 1 | `/lamina-init ` | Grounded product, actor, and persona knowledge | | 2 | `/lamina-design ` | Validated `GraphVersion` plus an implementation projection | | 3 | Implement with your coding agent | App source in your existing stack | | 4 | `/lamina-verify guest checkout at http://localhost:3000` | Behavioral findings backed by runtime evidence | | 5 | Run a UI skill | Visual and interaction polish | | 6 | Repeat the verification mission | Evidence that the behavior still holds | ## Compatible UI skills | Skill | What it adds | |-------|-------------| | **Impeccable** | Design system enforcement, component quality | | **UI UX Pro Max** | UX patterns, accessibility, responsive layouts | | **frontend-design** | Visual design, typography, color systems | ## Why not UI skills alone? UI skills polish how it looks. They do not: - Define permission matrices across actors - Specify state machines with recovery paths - Catch impossible states (cancelled + confirmed simultaneously) - Verify behavior on a live running app That is Lamina's job. ## Conflict resolution **Advanced:** If a UI skill changes behavior while polishing — adding a step, removing a gate, or altering a flow — re-verify immediately. Styling passes can accidentally break invariants. When UI changes affect behavior: 1. Run `/lamina-verify` to catch regressions 2. If findings appear, fix the accepted behavior findings first 3. Then continue visual polish 4. Re-verify after each significant UI pass ## Example pairing Design guest checkout with Lamina (after `/lamina-init`): ``` /lamina-design Guest checkout with hold, pay, cancel ``` Implement and verify. Then run your UI skill on the checkout page for visual polish. Re-verify with `/lamina-verify` to confirm behavior was not broken by styling changes. ## Next steps - [What is Lamina?](https://lamina.dev/docs/concepts/what-is-lamina) — full comparison with UI skills - [What to pair](https://lamina.dev/docs/guides/pair-with) — broader pairing guide - [Demo: HavenStay](https://lamina.dev/docs/guides/demo-havenstay) — behavior gaps UI skills miss --- ## guides/working-with-findings URL: https://lamina.dev/docs/guides/working-with-findings # Working with findings Findings are graph knowledge tied to source revision, GraphVersion, Mission Run, and evidence. Separate product defects, intended-contract contradictions, and operational/capability limitations. Fix application code in a normal coding session and rerun the affected Missions. --- ## reference/artifacts URL: https://lamina.dev/docs/reference/artifacts # Storage and projections Canonical runtime state lives in the Git common directory’s `lamina/` folder: Ladybug database, CocoIndex tracking, evidence CAS, lock, and socket. Business context, Persona JSON, source documentation, and old Lamina files are indexable source evidence. They are not graph state. Markdown deliverables are generated from a resolved GraphVersion query and must name the GraphVersion and source revision. They are never read back into the runtime. --- ## reference/global-artifacts URL: https://lamina.dev/docs/reference/global-artifacts # Evidence-source files `.lamina/business-context.md` and `.lamina/personas.json` remain convenient human-editable evidence inputs. Lamina's managed observer observes them like other source documents. Canonical Product, Persona, Actor, and Statement knowledge is published to Ladybug through graphd. Renaming a source alias does not replace stable Resource identity. --- ## reference/glossary URL: https://lamina.dev/docs/reference/glossary # Glossary **Resource** — stable opaque product-knowledge identity with a generic kind. **Statement** — normalized subject/predicate/object-or-literal fact with optional scope and qualifiers. **GraphVersion** — immutable version delta and validation receipt. **GraphView** — branch, session, observation, or historical view. **Contradiction** — Resource referencing incompatible Statements or alias identities. **Mission** — Persona-specific executable verification plan. **Run** — isolated Mission execution tied to a starting GraphVersion and source revision. **HarnessResult** — normalized adapter event sequence. **Observation** — CocoIndex-derived source evidence with explicit reproducible provenance. --- ## reference/hybrid-retrieval URL: https://lamina.dev/docs/reference/hybrid-retrieval # Hybrid retrieval Lamina uses retrieval to choose relevant Workflow roots and locate source symbols. Retrieval never defines product behavior. After selection, graphd traverses the canonical product graph for ordered Operations, Actors, authority, states, Invariants, Scenarios, Surfaces, risks, and proof requirements. ## Two stores, two authority levels | Store | Path | Role | Recovery | |---|---|---|---| | Product graph | `.git/lamina/graph.lbdb` | Canonical product knowledge and evidence | Preserve, checkpoint, back up, and restore | | Retrieval index | `.git/lamina/context/retrieval.lbdb` | Derived Workflow documents, source chunks, BM25 text, and embeddings | Delete or run `lamina context rebuild` | graphd is the only process that writes either Ladybug database. The native worker reads repository files, creates syntax-aware chunks and embeddings, and sends authenticated batches to graphd. ## Automatic synchronization `lamina work prepare` compares the active index manifest with: - GraphVersion; - source and repository revision; - branch and worktree identity; - retrieval schema version; and - model digest. If any value changed, the worker creates a pending generation. Unchanged documents reuse their content-addressed versions; changed documents are upserted; removed files or symbols are absent from the new membership. graphd activates the generation only when committed membership and digest match the declared expected values. An interrupted generation cannot replace the last complete current generation. ## Ranking Workflow selection gives an exact id or alias match absolute priority. Otherwise it combines Ladybug BM25 and cosine rankings with fixed reciprocal-rank fusion, filters inactive roots, and applies small deterministic boosts for direct Actor, Persona, Entity, Surface, state, or Operation terms. The result is explicit: - `selected`; - `multi_workflow`; - `ambiguous`; or - `new_workflow_required`. Source localization uses the same BM25, dense, and fusion policy over syntax-aware chunks. Packet v5 records file, enclosing symbol, line range, score, and short match reasons. Overlapping chunks from one symbol are deduplicated. An explicit `--workflow ` bypasses semantic Workflow selection, but it still performs exact graph traversal and source retrieval. ## Offline runtime and integrity The release pins `jinaai/jina-embeddings-v2-base-code` to one immutable revision and publishes its dynamic-INT8 ONNX weights as a separate checksummed asset. The platform worker contains ONNX Runtime, the tokenizer, and matching Ladybug FTS and vector extensions. Installation extracts these assets into the same private versioned runtime as the worker. Lamina never downloads a model or extension during normal execution. Missing, corrupt, or mismatched assets return `LAMINA_RETRIEVAL_INTEGRITY` with reinstall guidance. ## Diagnostics and recovery ```bash lamina context status lamina context rebuild ``` `status` reports generation, freshness, model and index digests, Workflow and source-chunk counts, pending state, and the last failure. `rebuild` invalidates the current derived generation for this branch/worktree identity and reconstructs it synchronously. Automatic Workflow selection fails closed when dense retrieval is unavailable. With an explicit Workflow id, exact graph closure may continue and source localization can use BM25 alone; packet v5 marks that state `lexical_degraded`. Source comments and source text remain untrusted retrieval data. They cannot change the selected Workflow's graph instructions or packet obligations. --- ## Skill map URL: https://lamina.dev/docs/reference/skill-map Summary: The 10 public Lamina workflow and product capability skills # Skill map Lamina installs as exactly 10 public skills. Four are workflow entrypoints and six group related product capabilities. Each capability keeps its focused guidance as topic references that agents load only when relevant. ## Workflow skills | Skill | Use it for | |---|---| | `lamina` | Route ordinary product implementation and focused questions | | `lamina-init` | Initialize a project's business context and provider rules | | `lamina-design` | Run the explicit graph-only design phase | | `lamina-verify` | Run the explicit source-read-only verification phase | Ordinary product work starts through `lamina`; design and verification phases run implicitly. `/lamina-design` and `/lamina-verify` remain advanced explicit overrides. ## Capability skills | Skill | Topics inside it | |---|---| | `lamina-research` | Evidence scoping, actor walks, grounding, interviews, task analysis, synthesis, communication | | `lamina-product-discovery` | Problem framing, business context, stakeholders, feature discovery and priority, requirements, tradeoffs, decisions | | `lamina-ux` | Flows, IA, navigation, content, forms, controls, onboarding, feedback, errors, accessibility, disclosure, trust, edge cases | | `lamina-product-behavior` | Represented models, platform posture, side effects, invariants, consistency, concurrency, time, dependencies, boundaries, multi-view integrity | | `lamina-systems` | System structure, feedback loops, traps, leverage points, evolutionary rules | | `lamina-evaluation` | Persona usability evaluation, heuristic review, quantitative validation | Install with `--skill '*'`. All 10 public entrypoints and their nested references arrive together, so an audit profile can name an exact topic without exposing dozens of focused skills to the user. ## Progressive loading Start with one public skill. Read its `SKILL.md` topic index, then load only the references required by the request or audit profile. Internal orchestration lives under `skills/lamina/orchestrator/`; it is packaged with `lamina` but is not separately discoverable. Old focused skill names are not aliases. The machine-readable [`skills/migration-map.json`](https://github.com/aryaniyaps/lamina/blob/main/skills/migration-map.json) maps each former name to its compact skill and exact topic. ## Examples ```text /lamina What invariants should a booking hold enforce? ``` Routes to `lamina-product-behavior` and its invariants topic. ```text /lamina How should permission denial appear during checkout? ``` Routes to `lamina-ux` edge-case and error-handling topics, plus product behavior when authorization rules need clarification. ## Next steps - [/lamina command](https://lamina.dev/docs/commands/lamina) — router and ordinary mode - [Orchestrator](https://lamina.dev/docs/advanced/orchestrator) — audit-profile coordination - [Glossary](https://lamina.dev/docs/reference/glossary) — product graph terms --- ## reference/transactional-graph URL: https://lamina.dev/docs/reference/transactional-graph # Transactional graph ## Storage All worktrees in a clone connect to one `graphd` at `$(git rev-parse --git-common-dir)/lamina/`. Linux and macOS use a Unix socket; Windows uses a repository-specific named pipe. Every request carries the random token stored in that runtime directory. Only graphd opens Ladybug read-write. ## Resources and Statements Resources use stable opaque ids and generic kinds. Human names are aliases. A Statement has subject, namespaced predicate, exactly one object or typed literal, optional scope, and semantic qualifiers. The Statement id is a hash of normalized semantic identity. Duplicate proposals are idempotent. Evidence attaches to the same Statement. Reverse relationships are queried. Competing values for the same functional fact create one canonical Contradiction without deleting either side; independent qualified facts, such as workflow steps at different positions, remain distinct. ## Versions and sessions Every Git branch resolves to a GraphView and head GraphVersion. Explicit sessions stage several mutations against a base version. Publication compares the session base with the current branch head, validates, creates a version delta, updates materialized membership, and moves the head in one transaction. | Phase | What happens | |---|---| | Start | Capture the branch's resolved head as the session base. | | Stage | Add, patch, link, or retire typed facts without changing the branch view. | | Validate | Check the affected closure, including references, policy, cycles, evidence rules, and contradictions. | | Publish | Compare the session base with the current head and commit the complete delta atomically. | | Rebase | If the head moved, reconcile the session with the new base, inspect conflicts, and retry. | Failed validation or publication never leaves a partial GraphVersion. A stale session remains inspectable until it is rebased or discarded. A Git merge reconciles every parent GraphVersion. Compatible memberships are combined, while incompatible parent facts produce the same canonical Contradiction as a directly proposed conflict. ```bash lamina session start lamina session publish lamina session rebase ``` ## CLI surface ```bash lamina graph status lamina graph query --at HEAD lamina graph propose --input resource.json --session lamina graph patch --input statement.json --session lamina graph link --as --session lamina graph validate --at lamina graph diff --base --head lamina graph backup --output graph.backup.json lamina graph restore --input graph.backup.json lamina graph rebuild-observations lamina context status lamina context rebuild lamina design prepare-walk --workflow --persona --request-file --output lamina design record-walk --task --result lamina work prepare --request-file --workflow --output lamina work map --packet --output lamina work check --packet --map lamina work verify --packet --map ``` All mutation commands accept typed inputs and return deterministic JSON. Raw Cypher is not an agent-facing interface. Backup files are integrity-checked logical exports for disaster recovery and evaluator evidence; they are never runtime inputs during normal operation. ## Implementation context Before `work prepare`, one engine-recorded design walk per active Persona must match the current Workflow coverage digest. Walks are independent of runtime Missions and can expand a feature graph before source exists. The digest hashes canonical covered Resource data and relevant Statements. Recording a walk replaces that Persona's previous active walk for the Workflow. Experience Cases compile directly from current walks; there is no separate authored Experience Contract. `work prepare` is a read-only compiler over the converged selected workflow closure. It returns the relevant actors, authority, ordered operations, invariants, scenarios, surfaces, proofs, Persona-bound Experience Cases, direct provenance, and stable obligation ids. Before traversal, one disposable local index combines exact aliases, Ladybug BM25, code-aware embeddings, and reciprocal-rank fusion to select Workflow roots and source symbols. Retrieval is never graph authority. See [Hybrid retrieval](https://lamina.dev/docs/reference/hybrid-retrieval). Automatic selection fails closed as `ambiguous` or `new_workflow_required` rather than attaching a plausible but weak Workflow. Explicit `--workflow` bypasses semantic selection and may use BM25-only source localization when dense inference is unavailable; packet v5 records `lexical_degraded`. Preparation fails closed for stale source identity, contradictions, stale or missing Persona walks, missing authority, incomplete operation contracts, missing invariants/scenarios, or a UI surface without a proof specification. `work map` mechanically creates one unresolved row for every packet obligation and Experience Case; the agent resolves status and files without authoring requirement identities. `work check` then requires `lamina.work-map/v4`: every changed obligation maps to an implementation file, every changed Experience Case maps to a test file, and each file declares `action: modify|create`. Modify paths must exist; create paths must not exist until implementation. WorkStarted binds the entire immutable map. Validation exposes three distinct lifecycle signals: - `structural_valid`: graph shape and transactional rules hold; - `implementation_ready`: the selected contract is detailed enough to code; - `verified`: required current evidence exists and no readiness gap remains. Runtime proof comes only from published Mission events. A passing case oracle contains its case id, structured expected/observed result, and a reproducible artifact; no second Experience Evidence manifest or mutable WorkMap evidence copy exists. For UI Runs, `verified` requires independent functional, visual, responsive, and accessibility audit artifacts. An oracle alone or one reused screenshot cannot satisfy that gate. ## Source observations `lamina graph observe` runs the managed, platform-native CocoIndex worker from the standalone release's private cache. Each file produces an explicit Observation envelope with snapshot, content hash, locator, extractor identity/version, and normalized payload. The payload includes deterministic brownfield signals for entry points, commands, routes, handlers, schemas/entities, state transitions, permissions, events, tests, documentation/personas, feature flags, and dependencies. `.lamina/business-context.md` and `.lamina/personas.json` are source evidence; legacy `.lamina/runs/` remains excluded and has no runtime meaning. The worker sends authenticated idempotent upsert/delete batches over the local transport and never opens Ladybug. The client reuses graphd only when protocol and required capabilities match. An incompatible daemon is replaced automatically without rewriting `.git/lamina/graph.lbdb`. `rebuild-observations` is for a genuinely incomplete or corrupted observation generation; repeating it cannot repair a daemon/client contract mismatch. `lamina graph discover --brownfield` performs the same incremental observation update and returns a coverage report, unsupported-source counts, stale snapshots, and explicit static-analysis limitations. Absence of an Observation is never treated as evidence that behavior does not exist. ## Missions ```bash lamina mission compile --workflow lamina mission run --events events.json lamina session query lamina session publish ``` Compilation creates an independent Mission for every active Persona. `mission run` stages its Run and HarnessResult in an isolated session; it does not publish implicitly. Adapters are selected through capability manifests; modalities remain open strings. Only normalized adapter events produce runtime evidence. ## Epistemic classes Ingress derives intended, observed, inferred, simulated, human_evidence, or runtime_evidence. Callers cannot set epistemic class or approval. Every public agent proposal, including `claim.add`, is inferred. The socket does not expose `intent.*` methods. Intended knowledge requires a trusted engine-owned intent adapter, so method-name selection cannot be used to spoof epistemic class. The rationale, rejected alternatives, and v1 consequences are recorded in [ADR-001](https://github.com/aryaniyaps/lamina/blob/main/docs/decisions/001-transactional-product-graph.md). The executable requirement matrix is in [Transactional plan acceptance](https://lamina.dev/docs/reference/transactional-plan-acceptance). --- ## reference/transactional-plan-acceptance URL: https://lamina.dev/docs/reference/transactional-plan-acceptance # Transactional plan acceptance This page maps the original transactional product-graph plan to executable repository evidence. A row is complete only when its implementation and its named validation are both present. | Requirement | Implementation evidence | Executable evidence | |---|---|---| | Ladybug is canonical and graphd is the sole writer | `packages/cli/lib/graph-runtime/engine.mjs`, `server.mjs`, `client.mjs` | `transactional_graph_test.mjs`, `graphd_protocol_test.mjs` | | Generic Resources, Statements, versions, and views | graph runtime engine and query protocol | `transactional_graph_test.mjs` | | Atomic typed sessions with compare-and-swap and rebase | session start, stage, validate, publish, rebase, abort | `transactional_graph_test.mjs`, `graphd_worktree_test.mjs` | | Deterministic policy validation and Contradictions | affected-closure validation and canonical contradiction reconciliation | `transactional_graph_test.mjs` | | Git branch, worktree, and multi-parent merge semantics | source-revision ancestry and branch GraphViews | `graphd_worktree_test.mjs`, `transactional_graph_test.mjs` | | CocoIndex observations are rebuildable and never canonical | `observe.mjs`, observation ingress, generation tombstones | `observation_cli_test.mjs`, `transactional_graph_test.mjs` | | Brownfield discovery reports coverage and limitations | `graph observe` and `graph discover --brownfield` | `observation_cli_test.mjs` | | Every active Persona independently covers every Workflow node before implementation | coverage-bound `persona_walk` Resources and direct case compilation | `passive_context_test.mjs`, `transactional_graph_test.mjs` | | WorkMap rows are mechanically derived, then resolved into an immutable requirement-to-file commitment | v4 scaffold plus modify/create and implementation/test file mappings | `passive_context_test.mjs`, `grade_transactional_graph_evals_test.mjs` | | Every active Persona receives an independent Mission | mission compile/run and capability manifests | `transactional_graph_test.mjs`, `eval_graph_runtime_install_test.mjs` | | Runtime evidence is normalized, isolated, and content-addressed | Mission Run/HarnessResult publication and evidence CAS | `transactional_graph_test.mjs` | | Modalities and product taxonomies remain open | generic Resource kinds, predicates, and string capability requirements | `transactional_graph_test.mjs` | | Stale, missing, corrupt, and capability-limited evidence fails closed | validation receipts and Mission capability checks | `transactional_graph_test.mjs` | | Deterministic backup/restore is the disaster-recovery boundary | `graph backup` and `graph restore` | `transactional_graph_test.mjs` | | The legacy canonical file has no live consumer or dual-write path | graph-backed skills, eval grader, and current benchmark verifier | `no_legacy_runtime_test.mjs`, `grade_transactional_graph_evals_test.mjs`, `behavior_benchmark_test.mjs` | | Markdown is a version-pinned query projection only | design/verify workflow contracts | graph eval assertions and benchmark treatment gate | | Public discovery stays compact without losing focused guidance | 10 public skills plus on-demand capability references and a complete 59-name migration map | `verify_lamina_bundle.mjs`, `eval_install_all_skills_test.mjs` | | Every eval run loads the complete cross-referenced skill set | ASE and multi-turn install hooks copy all 10 public skills and nested references before invocation | `ase_run.py`, `eval_install_all_skills_test.mjs` | | CLI and skills are independently installable | checksum-verified standalone CLI release assets and root GitHub skill | `cli_binary_smoke_test.mjs`, `release_artifact_smoke_test.mjs`, `eval_graph_runtime_install_test.mjs` | | Current evals exercise graph state rather than legacy artifacts | live graph assertions in `evals/hooks/grade-lamina.mjs` | generated-suite validation and graph grader tests | | Current Lamina benchmark cells install and enforce the graph runtime | standalone CLI release contract, graph backups, fail-closed treatment gate | `validate-transactional-pilot.mjs`, `behavior_benchmark_test.mjs` | Intentionally deferred v1 work remains outside the accepted plan: cross-clone graph synchronization, distributed consensus, arbitrary project-supplied validators, raw Cypher access, multiple graph backends, and semantic-search infrastructure. The architectural rationale is recorded in [ADR-001](https://github.com/aryaniyaps/lamina/blob/main/docs/decisions/001-transactional-product-graph.md) and the current distribution decision in [ADR-013](https://github.com/aryaniyaps/lamina/blob/main/docs/decisions/013-compact-public-skill-catalog.md). The current Persona/WorkMap simplification is recorded in [ADR-011](https://github.com/aryaniyaps/lamina/blob/main/docs/decisions/011-compile-cases-from-persona-walks.md). --- ## reference/validation URL: https://lamina.dev/docs/reference/validation # Validation ```bash lamina graph validate --at HEAD lamina graph validate --at lamina graph validate --at HEAD --scope workflow.cancel-booking ``` The installed engine checks Statement shape/references, aliases, workflow ordering/reachability, lifecycle transitions, actor authority, dependencies, proof/evidence coverage, Mission capability compatibility, epistemic ingress, Contradictions, uniqueness, and cycles. `ok` reports structural validity; `approved` additionally requires an empty `readiness_gaps`, `stale_evidence`, and `contradictions` set. Scoped validation walks the connected affected closure; whole-view validation remains available with `--at`. Approval additionally requires current reproducible evidence and no relevant Contradiction. Agents cannot add executable validators or approve their own output. --- ## LaminaBench URL: https://lamina.dev/docs/advanced/lamina-bench Summary: Harbor v4 behavior benchmark that proves Lamina works under matched arms # LaminaBench LaminaBench v4 tests whether agents that complete the **design → implement → verify → fix** loop ship thin products that pass more held-out behavior checks than matched non-Lamina baselines. No publication result exists yet. Run the pilot matrix locally, confirm treatment gates and behavior lift, then expand before marketing claims. ## What this suite proves **Claim (when gates + outcome both pass):** Agents that complete a full Lamina loop (`spark`/`shape` with in-scope harden rigor, UI walkthrough + persona-panel subagents) pass more authority / lifecycle / recovery behavior checks than `direct` / `checklist` on the same fuzzy brief. **Not claimed from this suite:** - Human “iterate faster” (deferred crossover study) - Full `harden` release rigor beyond the thin-slice prototype posture - Skill slash-command compliance alone (see `evals/`) ## How it works | Piece | Detail | |---|---| | Construct | Behavior integrity from a fuzzy founder brief | | Primary metric | `behavior_pass_rate` on `app.mjs` (`createInitialState` / `reduce` / `project`) | | Steps | Matched **4,200s** agent budget per arm. Baselines: `shape_build` + `verify_fix` (2,100s each). Lamina: `lamina_init` → `lamina_design` → `implement` → `lamina_verify` → `fix`; final step scores | | Oracle | `reduce`/`project` must change with actions; action ids must appear in reduced state (anti-gaming) | | Agent aid | Structural `selfcheck.mjs` on coding steps — public actions only, no graded expect substrings | | Anti-leak | `grade.mjs` keeps expects opaque (base64); agents must not decode/stuff oracle strings | | Lamina arm | Real skills (`/lamina-init`, `/lamina-design`, implement, `/lamina-verify`, fix) with bench profile | | Treatment gates | Lamina attempts without `.lamina/` charter + run + verify outputs + UI walkthrough + ≥2 `persona_findings` are disqualified (reward 0) | | Baselines | `direct`, `plan`, `checklist` — no Lamina skills injected | | Model (pilot) | Claude Sonnet (`sonnet`) | ### Bench profile (lamina arm only) - Stage starts at `shape` / `spark` per task; harden-level rigor still applies at in-scope authority/lifecycle boundaries - Delivery is an in-memory reducer + HTML UI (no OAuth/CSRF theater) — authority and lifecycle remain first-class in `reduce`/`project` - Normal design proof ceilings; budget must cover every published action type - Full skill risk loads from `audit-profiles.yaml` (accessibility, trust, concurrency, etc. injected) - Verify requires live UI walkthrough + ≥2 agent-spawned persona-panel findings - Harbor image includes Chromium at `/usr/bin/chromium` ## Arms | Arm | Method | |---|---| | `direct` | Normal coding agent | | `plan` | Plan-first coding agent | | `checklist` | Generic product checklist before build | | `lamina` | Lamina loop with full risk-capability skill injection | Lamina vs `checklist` estimates method value. `control-simple-list` is the negative control — Lamina should not dominate a trivial todo app. ## Commands ```bash npm run bench:build npm run bench:validate npm run bench:run:publish # full 6-cell pilot matrix + harvest npm run bench:run:publish:dry # print matrix without running npm run bench:run:pilot:lamina # care-circle, lamina arm, 2 attempts npm run bench:run:pilot # build + validate + full pilot matrix npm run bench:harvest # copy .lamina trees from results if present ``` Pilot matrix: `pilot-care-circle` + `control-simple-list` × `{direct, checklist, lamina}` × 2 attempts on Sonnet. Set `ANTHROPIC_API_KEY` in the **repo root** `.env`. The runner loads that file and passes it to Harbor via `--env-file`. ## Claim discipline - Reward is **behavior only** — no keyword, brief length, or `.lamina/` ceremony points - Report paired task-level pass rates and loop delta (final − mid behavior) - Do not cite legacy Harbor v1 file-marker results or v2 studies until those harnesses ship - Confirmatory cohort on `opus` only after Sonnet pilot shows valid treatment + directional lift ## Deferred studies LaminaBench v2 (contract quality, fresh-builder transfer, human iteration crossover) remains documented for future publication but is **not** the runnable harness in this repo today. --- ## advanced/orchestrator URL: https://lamina.dev/docs/advanced/orchestrator # Orchestrator The orchestrator routes init, design, and verify work through graphd. Multi-fact work uses explicit sessions. Persona verification compiles all relevant Missions and isolates every Run. Craft skills contribute schema-aware judgment, but cannot submit executable validators, epistemic class, approval, or raw Cypher. --- ## Crash-safe runner URL: https://lamina.dev/docs/advanced/safe-runner Summary: Mandatory process-tree safety boundary for resource-intensive Lamina development and qualification # Crash-safe runner The crash-safe runner is the mandatory host-safety boundary for resource-intensive benchmark, experiment, fixture, and Lamina commands in the practical-runtime program. It controls and measures the complete descendant tree on supported Linux hosts. A safety-limit hit is a failed scenario. Never report it as a product measurement, rerun it without limits, add swap, or alter host/kernel memory behavior. ## 1. Inspect the effective envelope ```bash npm run safe:envelope ``` This command is read-only. It reports host memory and disk, derived limits, cgroup-v2 controller availability, the selected adapter, current self-test attestation, and completed tier promotions. It does not create a scope or launch a payload. The default hard memory ceiling is `min(3 GiB, 25% of physical RAM)`. The 8 GB profile cannot exceed 2 GiB, and launch must preserve at least 2 GiB for the OS/desktop. The default process ceiling is 64 and production concurrency is one. ## 2. Qualify the current host and runner build ```bash npm run safe:self-test ``` The self-test uses only tiny fixtures and low artificial limits, including a maximum of 32 aggregate tasks (24 for the process-storm case). It covers: - direct and aggregate child memory; - ignored graceful termination and timeout; - rapid process spawning; - stdout/stderr flooding; - runner-owned temporary-file growth; - handled parent interruption plus uncatchable supervisor `SIGKILL` recovery; - stale PID identity; and - a parent that exits with a detached descendant. Every case writes a versioned report, proves cleanup, and contributes a digest to the host attestation. The attestation is invalidated when the host, architecture, controllers, adapter, runner source, gate, or schema changes. If user-systemd or cgroup-v2 aggregate enforcement is unavailable, the portable adapter can run only the exact built-in low-limit self-test allowlist. The host-qualification command itself refuses before launching the adversarial matrix, because a portable process group cannot prove cleanup of the detached descendant case. Portable focused contract tests never qualify medium or large execution. macOS and Windows CI run that dedicated adapter/refusal contract; they do not execute the Linux/POSIX unit harness. Portable preflight reports attestation as explicitly unavailable and unqualified without probing Linux infrastructure binaries or computing a host fingerprint. The low-limit Linux CI job is pinned to Ubuntu 22.04 and provisions Bubblewrap without privilege. It downloads the official Debian Bookworm 0.8.0 package by an immutable URL, verifies the pinned SHA-256 digest, records package and ABI dependency evidence, and extracts only the binary into the ephemeral runner directory. Bookworm's declared glibc, libcap, and libselinux minima are satisfied by Jammy. The job then runs the real hard-quota probe before the adversarial matrix; it does not use `sudo` or modify the host package database. The job also copies setup-node's complete runtime root—including its relative npm/npx links and npm package—into a mode-0700 current-user directory, removes group/world write permission, records source/staged Node and physical npx-target SHA-256 plus ancestor evidence, and puts its physical `bin` first on subsequent PATHs. This satisfies the existing trusted-ancestor and exact-npx policies without weakening either for the hosted tool-cache layout. Ubuntu 24.04's hosted AppArmor policy blocks this rootless namespace path unless a privileged package profile is installed, so it is not used as the qualification host. The native release workflow runs source-quality checks on every target before an adapter qualification gate. Until issue #57 supplies production enforcement for macOS and Windows, those targets refuse qualification and the workflow does not enter packaging or artifact-upload steps. ## 3. Run one scenario ```bash npm run safe:run -- \ --tier small \ --workload retrieval-v1 \ --report /absolute/path/to/small-result.json \ --promote \ -- [args] ``` Use `--promote` only for an intended tier-qualification scenario. The stable `--workload` identifier binds smaller-tier evidence to the same workload; success from a trivial or unrelated command cannot unlock another workload. Promotion is recorded only after a successful command, schema-valid report, empty descendant set, removed scope, removed runner temporary directory, and error-free cleanup. Medium requires current small promotion. Large requires current small and medium promotion. Both also require a valid production attestation, aggregate enforcement, and the global concurrency lock. Every tier refuses while an existing Lamina runtime is already active, because a pre-existing process is outside the new scope. Immediately before release, the runner revalidates its frozen preflight identity and persists an active-attempt fence. The identity covers the complete normalized argv, ordinary file arguments resolved against the supplied cwd, the dedicated manifest-bound retrieval authority when applicable, content-hashed Git source, and runner build. The exact frozen identity is reused after execution, so a payload that edits its checkout cannot promote the edited source. Limits are deliberately excluded: a limits-only edit cannot retry known unsafe work. The fence is cleared only after a non-limit clean outcome, final report publication, and watchdog disarm; a limit or controller crash retains it. All limit flags are downward-only: ```text --memory-mib --memory-high-mib --pids --timeout-ms --output-mib --temporary-mib --sample-ms --high-samples --grace-ms ``` Diagnostic stdout/stderr tails are 8 KiB by default. The exact `real-repository-oracle-v1:case-discovery` workload has a narrow structured-output profile that retains up to 1 MiB of stdout while stderr remains at 8 KiB. The effective per-stream tail bounds are recorded in `report.limits`; this profile does not change the 32 MiB hard combined-output limit and does not apply to the later evidence-expansion workload. There is no unrestricted fallback or arbitrary child-command surface. Only the repository's explicit audited entrypoint allowlist can launch; Node loader/eval indirection, package-runner indirection, symlink substitution, and unknown wrappers fail closed. Docker, Harbor, or another external daemon cannot be used as the payload because the runner cannot prove ownership of the daemon-created descendants. This refusal also inspects shell, package-script, and local wrapper indirection rather than trusting only argv[0]. On Linux the payload runs in unprivileged bwrap mount, PID, and (for offline entrypoints) network namespaces. The host root and repository snapshot are read-only. Repository-output entrypoints are refused because their live output trees do not have sealed, same-filesystem hard-quota authority. The only mutable repository-adjacent surface is the reviewed Git-common `lamina/work` scratch authority used only by the graphd-client and mutable test fixtures at `small`; medium and large refuse those fixture entrypoints. `/`, `/tmp`, runtime-control directories, and any worktree overlapping runner authority state are refused. User/system D-Bus, user-systemd, and common Docker/Podman/container control sockets and inherited control addresses are masked. Network-required entrypoints are separately and narrowly allowlisted. The runner temporary directory is a size-limited private tmpfs. The prepared report parent is a separate identity-bound authority mount: it is read-only inside the payload namespace. Slot acquisition uses `O_NOFOLLOW` and `O_TRUNC` before lengthy preparation, so a crash can leave an invalid/empty or current-run non-success file, never a previous success. Completed reports use an unpredictable exclusive temporary file plus immutable parent/run identity before atomic replacement. The controller verifies that tmpfs before releasing the payload and reads its allocated blocks and inode usage through `/proc//root`; this accounts for deleted-but-open files without an unbounded directory scan. Symlinks in the temporary tree, inode storms, quota exhaustion, or absence of this enforcement capability fail closed. Managed `graphd` is a fixture-only exception, not an ordinary workload or detached-tree escape hatch. The small graphd-client fixture uses its nested Git repository beneath Git-common `lamina/work`; standalone CLI smoke uses only its child-cwd repository created inside private payload tmpfs and cannot reserve source Git-common paths. Before spawn, the fixture asks the live supervisor broker to prove the socket/lock paths absent and durably reserve them. After spawn it binds that reservation to the authorized host/namespace PIDs, Linux start identity, command, child cwd, and exact runtime path. The reservation nonce is embedded in the graphd lock for the creation-to-seal transition. Once readiness creates both objects, graphd and the client seal their exact `lstat` type, device, inode, owner, mode, and size; the lock PID must match the bound PID set. No child-writable registry is authoritative. After the CLI exits, the runner accepts only that exact registered `server.mjs`/`--graphd` root and its in-scope descendants, sends the complete scope `SIGTERM`, and still requires an empty scope. A mismatched identity, unrelated process, or unregistered detached descendant is a safety failure. Immediately after the current-run non-success report slot is durable, the controller starts a detached identity-bound watchdog child without creating a lock or temporary directory first. The child creates and returns exact device/inode/owner identities for its watchdog, runner, and payload temporary directories, acquires the exact-unit production lock when required, and writes those identities into its initial manifest before declaring ready. A ready timeout or child exit cleans only progress-reported exact identities; there is no stale-prefix sweep. The manifest later records the exact cgroup and graphd reservation/bind/seal state. If the supervisor is killed, the watchdog kills and removes that exact scope, removes only identity-matched temporary/managed paths after an immediate identity recheck, releases the exact lock only after authoritative absence proof, and writes a schema-valid crash report. The existing `parent_signal` qualification case bundles handled-signal and supervisor-`SIGKILL` subproofs, preserving the public eleven-case contract. Focused CI additionally kills the controller at pre-watchdog report preparation, child-owned watchdog and runner-directory bootstrap boundaries, and graphd reserved, bound, objects-created, and sealed boundaries. The requested report slot contains a schema-valid current-run non-success provisional record before adapter probing or payload preparation. Final outcomes atomically replace that run-bound slot. Because watchdog write authority uses the immutable parent and run rather than a changing report inode, controller death after success publication but before disarm overwrites that success with schema-valid crash evidence. Infrastructure binaries are resolved and identity-bound independently of the caller and rechecked at launch. CI supplies bwrap through an absolute physical path plus SHA-256; local runs retain a fixed-system-path fallback, and probe and launch use the same persisted identity. PATH and complete dynamic-loader, Node, exported Bash-function, and analogous shell/runtime hook families are sanitized before `systemd-run`, the gates, bwrap, and the payload launcher start, including for reusable API environment overrides. Retrieval evaluation and calibration have no environment or uv fallback. They require exactly one explicit repository-contained physical `--worker`, `--model`, `--tokenizer`, and lowercase `--model-digest`; the worker must be executable, and no unknown flags or positional tokens are accepted. Model bytes, size, and digest must match the canonical retrieval model manifest. Tokenizer bytes are not separately manifest-pinned, but all three inputs and the manifest are descriptor-copied into the frozen launch and execution-snapshot identities. This dedicated authority admits the canonical model above the generic 64-MiB argv-input ceiling without increasing that ceiling: the manifest is capped at 1 MiB before read, its declared model and the worker at 256 MiB, and the tokenizer at 64 MiB. Snapshot construction must match both its recomputed source identity and copied bytes to the original preflight authority. Inherited `LAMINA_TEST_*` controls are removed for non-self-test payloads, and retrieval semantic environment names are stripped before launch. Only exact descriptor-copied native/smoke values encoded in the snapshot authority survive the final bwrap unset layer. ## Reports and outcomes Each run writes `lamina.safe-runner-report/v1`. It includes: - limits and complete preflight data; - aggregate process RSS and cgroup `memory.current`/`memory.peak` as distinct measures, plus bounded per-process samples and peaks; - bounded output counts/tails and temporary disk usage; - every observed descendant with PID start identity; - cgroup memory/PID events; - exit status, signal, termination reason, and requested signals; and - descendant, scope, temporary-directory, lock, and report cleanup. Host attestation binds the evidence to the boot ID, kernel release, systemd version, user-manager identity, root controller/subtree state, architecture, adapter, schemas, runner sources, graphd integration, and adversarial fixture. The outcome is one of `success`, `command_failed`, `safety_limit_exceeded`, `preflight_refused`, `interrupted`, or `internal_error`. Validate a report independently with: ```bash node scripts/safe-runner/cli.mjs validate-report --file /absolute/path/to/result.json ``` If the requested report path cannot be written, the runner attempts a bounded fallback report in the system temporary directory and marks the run as an internal failure. A missing report is never a measurement. Reports deliberately omit the child environment and recursively redact common credential flags, bearer tokens, URL userinfo, and secret-like output patterns. Redaction applies to disk, the Node API return, and CLI JSON. It is defense in depth, not a data-loss-prevention guarantee: commands can print arbitrary sensitive material. Treat reports as sensitive diagnostics, keep them mode `0600`, review them before sharing, and never publish raw reports or CI artifacts containing real credentials. ## Child-command integration Resource-intensive repository entrypoints can call `assertSafeRunnerContext()` from `scripts/safe-runner/index.mjs`. It obtains the authoritative tier, unit, and limits from a live supervisor-held broker, then independently reads the caller's cgroup and controller values. Context files, tokens, tier variables, and plain environment flags are not proof. Lamina's graph client also reserves, binds, and object-seals any graphd it starts by host/namespace PID and Linux start ticks. After the payload exits, the runner gives that exact registered daemon a short graceful shutdown window and verifies that its socket, lock, process tree, and scope are gone. Any unregistered detached process—or any registered graphd that outlives the deadline—fails the scenario and triggers complete scope termination. See [ADR-014](https://github.com/aryaniyaps/lamina/blob/main/docs/decisions/014-crash-safe-resource-supervision.md) for the ownership and fail-closed rationale. ---