Skip to content

Latest commit

 

History

History
76 lines (60 loc) · 4.13 KB

File metadata and controls

76 lines (60 loc) · 4.13 KB

labkit — turn a lab into a public repo

labkit automates graduating a labs/* project into its own public GitHub repo (Pitot, Boatstack, Value Map today). One declarative publish.config.json per lab drives everything: the projection of curated lab bytes into the public repo, the workflows on both sides of the sync, and a drift gate that keeps them from quietly diverging.

The monorepo (operatorstack/intelligence-flow) is the single source of truth. Public repos are byte-for-byte projections of a curated subset of one lab — strictly one-directional. Nothing flows back.

The model

labs/<lab>/publish.config.json        # single source of truth for one public repo
         │
         ├─ projection engine ────────►  public repo files + UPSTREAM.json (provenance)
         ├─ generator ────────────────►  .github/workflows/<project>-publish.yml   (dispatcher)
         │                               labs/<lab>/.labkit/generated/sync-upstream.yml
         └─ doctor ───────────────────►  fails CI if any generated file drifts from the config

Two manifest styles, mirroring what the labs already do:

  • surface — a {schema_version, files{path: sha256}} manifest committed in the lab as a drift gate over the public surface (Pitot). Such a lab may also opt into a downstream projection provenance manifest (manifest.downstream) so the public repo carries the source commit.
  • projection — a richer {schema_version, generator, source, files} manifest written into the public repo (Value Map, Boatstack).

Genuinely bespoke labs (Boatstack rebrands and recomputes fingerprints) supply a .labkit/hooks.py whose build_files(ctx) returns the complete file map; the engine treats it as the projection.

Commands

python -m labkit <cmd>
Command What it does
project --config <cfg> --repo <dir> --source-commit <sha> --write Project a lab into a public-repo checkout (add --adopt on first import).
project --config <cfg> --check Verify the committed in-lab surface manifest (surface style).
gen [--repo-root <root>] [--check] (Re)generate the dispatcher + staged sync-upstream.yml for every lab; --check fails on drift.
doctor [--repo-root <root>] [--remote] [--remote-governance] Validate every config, fail on generated drift, assert each verify gate exists; --remote diffs live public workflow control planes, while --remote-governance verifies auto-merge and required checks with an Administration-read token.
publish init <lab> Scaffold publish.config.json + workflows + a first release note for a new lab.
release-notes <check-policy|validate|preflight> The shared append-only release-note policy.

Graduate a new lab

  1. python -m labkit publish init labs/NN-yourlab --project your-lab --display-name "Your Lab" --repo your-lab
  2. Edit the generated publish.config.json — declare the real surface rules.
  3. python -m labkit gen then ... doctor — regenerate and validate.
  4. Add the hand-maintained verify gate .github/workflows/your-lab-lab.yml (bespoke per lab; not generated).
  5. Create the public repo, install labs/NN-yourlab/.labkit/generated/sync-upstream.yml into it at .github/workflows/sync-upstream.yml, and set the publisher app vars/secrets on both repos. (The projection token deliberately cannot rewrite .github/**, so the control plane is installed once by hand.)

What is and isn't generated

  • Generated (config-driven, drift-gated): <project>-publish.yml, labs/<lab>/.labkit/generated/sync-upstream.yml.
  • Hand-maintained (bespoke, reviewed): <project>-lab.yml (the per-lab verify gate — Go matrices, wind-tunnel, pnpm evals). doctor only checks it exists.

Standardized defaults

Omitted config fields fall back to defaults.py: the shared Operator Stack publisher app (with the Boatstack app as fallback), a deterministic per-project cron minute derived from the slug (no hand-picked collisions), stale-guard on, and .github/** always excluded from projection.