> ## Documentation Index
> Fetch the complete documentation index at: https://hubify.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Lab Manifest (lab.yaml)

> The Hubify Lab Manifest spec v0.1 — the portable YAML file behind every lab's Reproduce This Lab button.

# Lab Manifest (`lab.yaml`)

A **lab manifest** (`lab.yaml`) is the portable description of a reproducible research lab: everything a human or agent needs to inherit the research. It is the contract behind the **Reproduce This Lab** button — see [Reproduce a Lab](/docs/concepts/reproduce).

<Note>
  `lab.yaml` (Hubify Lab Manifest spec v0.1) is a different file from `hubify.json` (the per-lab-repo manifest that wires a lab repo to Convex sync, GitHub, and compute). This page covers `lab.yaml` only.
</Note>

## Where it lives

Every registered lab has a copy at `labs-registry/<slug>/lab.yaml` in the `hubify` repo:

```
labs-registry/
  bigbounce/lab.yaml
  eti/lab.yaml
  hubify-self-improving/lab.yaml
```

`src/lib/lab-manifest.ts` is the **only** place that parses `lab.yaml` — every page and component consumes typed `LabManifest` objects through it, never the raw file:

* `loadLabManifest(slug)` — reads, parses, and validates `labs-registry/<slug>/lab.yaml`. Throws `LabManifestNotFoundError` if the file is missing, or `LabManifestValidationError` (with a list of specific issues) if required fields are absent.
* `listRegisteredLabs()` — enumerates every slug under `labs-registry/` that has a valid `lab.yaml`, sorted.

Both are **server-side only** (they use `node:fs`) and back the `/labs` directory page and `/labs/[slug]` static params — there is no client-side or API accessor for manifest content today. See [access patterns](/docs/concepts/reproduce#mcp-and-api-access-patterns) for what that means in practice.

## Schema

### Top level

| Field             | Type                     | Required | Notes                                                                                              |
| ----------------- | ------------------------ | -------- | -------------------------------------------------------------------------------------------------- |
| `hubify_lab`      | number                   | Yes      | Spec version. Current value: `0.1`.                                                                |
| `lab`             | object                   | Yes      | Identity block, see below.                                                                         |
| `source`          | object                   | Yes      | Upstream repo the manifest describes.                                                              |
| `reproducibility` | object                   | Yes      | Headline level + per-level detail. See [Reproducibility Levels](/docs/concepts/reproducibility-levels). |
| `programs`        | array                    | Yes      | The lab's research programs (may be empty).                                                        |
| `surfaces`        | object                   | Yes      | Which agentic surfaces (API, MCP, skills, site) the lab exposes.                                   |
| `manifests`       | `Record<string, string>` | No       | Named pointers to machine-verifiable manifests, e.g. a Level 0 file-hash manifest.                 |
| `sanitization`    | object                   | No       | Export policy for a lab whose source repo isn't yet fully public.                                  |

### `lab`

| Field             | Type        | Required | Notes                                                                                         |
| ----------------- | ----------- | -------- | --------------------------------------------------------------------------------------------- |
| `slug`            | string      | Yes      | Must match the `labs-registry/<slug>/` directory name — the loader's validator enforces this. |
| `title`           | string      | Yes      | Display title.                                                                                |
| `tagline`         | string      | Yes      | One or two sentences.                                                                         |
| `homepage`        | string      | Yes      | The lab's public site URL.                                                                    |
| `homepage_status` | `"planned"` | No       | Hubify extension — marks `homepage` as aspirational (not resolving yet).                      |
| `author`          | string      | —        | Part of the TypeScript shape; not currently enforced by the loader's validator.               |
| `license`         | string      | —        | Part of the TypeScript shape; not currently enforced by the loader's validator.               |

### `source`

| Field                 | Type        | Required          | Notes                                                                                                                                     |
| --------------------- | ----------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `authoritative_repo`  | string      | Conditional       | Required **unless** `status: planned`. The scientific source of truth — the lab package is a sanitized reproduction and never mutates it. |
| `safety_baseline_tag` | string      | No                | Git tag marking the safety-reviewed baseline.                                                                                             |
| `baseline_commit`     | string      | No (by validator) | Commit SHA the manifest was built against.                                                                                                |
| `status`              | `"planned"` | No                | Hubify extension — no repo exists yet; `authoritative_repo` may be omitted.                                                               |
| `notes`               | string      | No                | Free-text explanation, typically used alongside `status: planned`.                                                                        |

### `reproducibility`

| Field    | Type                         | Required | Notes                                                                                        |
| -------- | ---------------------------- | -------- | -------------------------------------------------------------------------------------------- |
| `level`  | number                       | Yes      | Headline reproducibility level (0–5). Hand-authored in the YAML, not computed from `levels`. |
| `levels` | `Record<string, LevelEntry>` | Yes      | Keyed `"0"`–`"5"`. See below.                                                                |

A `LevelEntry` is:

| Field    | Type                                           | Required | Notes                                                                                                          |
| -------- | ---------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `name`   | string                                         | Yes      | e.g. `archived`, `artifacts_verified`.                                                                         |
| `status` | `"complete" \| "in_progress" \| "not_started"` | Yes      |                                                                                                                |
| `note`   | string                                         | No       | Hubify extension — human-readable status detail, drives the site's reproducibility board copy. Safe to ignore. |

Full level semantics: [Reproducibility Levels](/docs/concepts/reproducibility-levels).

### `programs[]`

| Field       | Type        | Required    | Notes                                                                               |
| ----------- | ----------- | ----------- | ----------------------------------------------------------------------------------- |
| `id`        | string      | Yes         | Always required.                                                                    |
| `title`     | string      | Yes         | Always required.                                                                    |
| `version`   | string      | Conditional | Required **unless** `status: planned`.                                              |
| `paper_pdf` | string      | Conditional | Required **unless** `status: planned`. Path to the canonical live PDF artifact.     |
| `status`    | `"planned"` | No          | Hubify extension — marks a program that hasn't shipped a versioned artifact yet.    |
| `notes`     | string      | No          | Free-text grounding note, e.g. what already exists elsewhere for a planned program. |

### `surfaces`

| Field    | Type                                 | Notes                          |
| -------- | ------------------------------------ | ------------------------------ |
| `api`    | `{ status: string, notes?: string }` |                                |
| `mcp`    | `{ status: string, notes?: string }` |                                |
| `skills` | `{ status: string, notes?: string }` |                                |
| `site`   | `{ status: string, url: string }`    | `url` is required on this one. |

`status` is a free-text string in the type (not a closed enum) — manifests in the registry today use values like `exists_in_source`, `live`, `planned`, `in_progress`, and (on freshly reproduced labs) `not_configured` / `not_deployed`.

### `manifests`

An optional map of named paths to machine-verifiable manifest files. Today's only user is `manifests.level0`, pointing at the JSON file a Level 0 archive was hashed against, e.g.:

```yaml theme={null}
manifests:
  level0: manifests/level0.manifest.json
```

### `sanitization`

| Field             | Type      | Required               | Notes                                                                                                                                            |
| ----------------- | --------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `policy`          | string    | Yes (if block present) | Path to the asset-classification policy doc governing what may be exported.                                                                      |
| `excluded_always` | string\[] | Yes (if block present) | Glob patterns that are never exported, regardless of sanitization status — secrets, credentials, raw prompt history, private ops narrative, etc. |

## The `planned` extension

`status: "planned"` is a Hubify-side, additive extension to spec v0.1 — an honesty marker distinct from `reproducibility`. `reproducibility` says how far a lab's **results** have been verified; `status: "planned"` says the referenced **thing** (a homepage, a source repo, a research program) doesn't exist or hasn't started yet, so the manifest doesn't have to fabricate a URL, a repo, or a version to satisfy the shape.

It appears in exactly three places, all optional, all backward compatible (absence means the old implicit default of live/exists):

* `lab.homepage_status` — the homepage URL is aspirational.
* `source.status` (+ optional `source.notes`) — no source repo exists yet; `source.authoritative_repo` may be omitted.
* `programs[].status` (+ optional `programs[].notes`) — the program hasn't shipped a versioned artifact; `version`/`paper_pdf` may be omitted.

The `eti` and `hubify-self-improving` registry entries are fully spec-only labs built entirely from this extension — every program is `status: planned`, `source.status: planned`, and `reproducibility.level: 0` with every level `not_started`.

## Validation rules

`loadLabManifest` runs `validateManifest` before returning anything. It checks, in order:

1. The parsed YAML is an object.
2. `hubify_lab` is a number.
3. `lab` is present, and `slug`, `title`, `tagline`, `homepage` are all non-empty strings.
4. `lab.slug` matches the registry directory name.
5. `source` is present; if `source.status !== "planned"`, `source.authoritative_repo` must be a non-empty string.
6. `reproducibility` is present with a numeric `level` and an object `levels`.
7. `programs` is an array; for each entry, `id` and `title` are always required, and `version` + `paper_pdf` are additionally required unless that entry's `status` is `"planned"`.

Any failure collects into a single `LabManifestValidationError` listing every issue found — not just the first.

## Worked example

The registry copy of `bigbounce/lab.yaml` (trimmed comment header), showing a Level 2 lab with real programs and no `planned` fields:

```yaml theme={null}
hubify_lab: 0.1

lab:
  slug: bigbounce
  title: Big Bounce Cosmology
  tagline: >-
    Observational tests of bounce cosmology across galaxy chirality,
    dark-energy closure, non-Gaussianity forecasts, and multi-survey anomalies.
  homepage: https://bigbounce.hubify.app
  author: Houston Golden
  license: TBD

source:
  authoritative_repo: https://github.com/Hubify-Projects/bigbounce
  safety_baseline_tag: safety/pre-hubify-lab-2026-07-23
  baseline_commit: 130cc061

reproducibility:
  level: 2
  levels:
    0: { name: archived,                status: complete,    note: "Complete — 740 publication-critical files SHA-256 hashed at source commit 130cc061." }
    1: { name: environment_reconstructed, status: not_started, note: "Not started as an independently verified step." }
    2: { name: artifacts_verified,      status: in_progress, note: "Tooling proven — 740/740 files verified OK against the manifest, checked against source." }
    3: { name: lightweight_reproduction, status: not_started, note: "Staged next." }
    4: { name: partial_computational,   status: not_started, note: "Staged next." }
    5: { name: full_reproduction,       status: not_started, note: "Staged next — requires explicit cost authorization before any compute runs." }

programs:
  - id: p1a
    title: ECH No-Go Theorem
    version: v1A.0.126
    paper_pdf: site/public/papers/paper1a_ech_nogo_v1A.0.126.pdf
  # ... 5 more programs (p1b, p2, p3, p4, p5)

surfaces:
  api: { status: exists_in_source, notes: "custom lab API built during the research campaign" }
  mcp: { status: exists_in_source, notes: "bigbounce MCP (Convex-backed paper state, findings, closures)" }
  skills: { status: exists_in_source, notes: "bigbounce-* skill stack under scistack/astrostack" }
  site: { status: live, url: https://bigbounce.hubify.app }

manifests:
  level0: manifests/level0.manifest.json

sanitization:
  policy: hubify/project-context/bigbounce-flagship/audit-assets-classification.md
  excluded_always:
    - "**/.env*"
    - "**/*secret*"
    - "**/*credential*"
    # ... see labs-registry/bigbounce/lab.yaml for the full list
```

Notice that this manifest reports headline `reproducibility.level: 2` while `levels.1.status` is still `not_started` — reporting is per-level and honest, not a cumulative ladder. See [Reproducibility Levels](/docs/concepts/reproducibility-levels) for why that's expected, not a bug.

For a fully `planned`-status manifest (no repo, no programs shipped), see `labs-registry/eti/lab.yaml` or `labs-registry/hubify-self-improving/lab.yaml` in the repo.
