demolab-cli 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- demolab_cli-1.0.0/.github/workflows/landing-preview.yml +62 -0
- demolab_cli-1.0.0/.github/workflows/landing.yml +76 -0
- demolab_cli-1.0.0/.github/workflows/publish.yml +33 -0
- demolab_cli-1.0.0/.github/workflows/tests.yml +69 -0
- demolab_cli-1.0.0/.gitignore +35 -0
- demolab_cli-1.0.0/AGENTS.md +59 -0
- demolab_cli-1.0.0/CLAUDE.md +19 -0
- demolab_cli-1.0.0/DEVELOPING.md +76 -0
- demolab_cli-1.0.0/LICENSE +21 -0
- demolab_cli-1.0.0/PKG-INFO +101 -0
- demolab_cli-1.0.0/README.md +70 -0
- demolab_cli-1.0.0/demolab_cli/CHANGELOG.md +445 -0
- demolab_cli-1.0.0/demolab_cli/VERSION +1 -0
- demolab_cli-1.0.0/demolab_cli/__init__.py +10 -0
- demolab_cli-1.0.0/demolab_cli/_paths.py +63 -0
- demolab_cli-1.0.0/demolab_cli/build.py +284 -0
- demolab_cli-1.0.0/demolab_cli/cli.py +414 -0
- demolab_cli-1.0.0/demolab_cli/deploy/deploy.yml +61 -0
- demolab_cli-1.0.0/demolab_cli/deploy/preview.yml +56 -0
- demolab_cli-1.0.0/demolab_cli/devserver.py +380 -0
- demolab_cli-1.0.0/demolab_cli/guides/AUTORESEARCH-RULES.md +149 -0
- demolab_cli-1.0.0/demolab_cli/guides/GLOSSARY.md +55 -0
- demolab_cli-1.0.0/demolab_cli/guides/HOUSESTYLE.md +108 -0
- demolab_cli-1.0.0/demolab_cli/guides/RULES.md +142 -0
- demolab_cli-1.0.0/demolab_cli/guides/SLIDES.md +145 -0
- demolab_cli-1.0.0/demolab_cli/guides/STRUCTURE.md +78 -0
- demolab_cli-1.0.0/demolab_cli/guides/SUPPORT.md +36 -0
- demolab_cli-1.0.0/demolab_cli/overlay.py +47 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/AUTORESEARCH.md +67 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/DOCTOR.md +116 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/EMBED-DOCS.md +39 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/FROM-JUPYTER.md +84 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/FROM-PAPER.md +48 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/GETTING-STARTED.md +281 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/GROUND-CLAIMS.md +166 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/LINT.md +176 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/MIGRATE-CODE.md +49 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/MIGRATE-STACK.md +50 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/NEXT.md +52 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/NIGHT-SHIFT.md +68 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/PLAN.md +64 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/RED-TEAM.md +72 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/STEELMAN.md +44 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/TOUR.md +42 -0
- demolab_cli-1.0.0/demolab_cli/runbooks/UPDATE.md +84 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/ar018/swe-bench.svg +1 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp000/lif.svg +1103 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp000/net.png +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp000/numbers.json +38 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp000/run.sh +3 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp001/eif.svg +1122 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp001/enet.png +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp001/numbers.json +40 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp001/run.sh +3 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp002/cartpole.mp4 +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp002/numbers.json +18 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp002/run.sh +3 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp003/double_pendulum.mp4 +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp003/numbers.json +21 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/data/exp003/run.sh +3 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar000.pdf +546 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar003.pdf +773 -1
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar004.pdf +2846 -2
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar005.pdf +4216 -5
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar006.pdf +1200 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar010.pdf +718 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar011.pdf +530 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar012.pdf +634 -1
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar013.pdf +575 -1
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar014.pdf +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar015.pdf +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar016.pdf +520 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar017.pdf +875 -1
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/ar018.pdf +871 -1
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/book.pdf +10343 -6
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/exp000.pdf +2036 -4
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/exp001.pdf +2226 -2
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/exp002.pdf +683 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/artifacts/pdfs/exp003.pdf +767 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/demolab.yaml +26 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/experiments/exp000.py +106 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/experiments/exp001.py +106 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/experiments/exp002.py +74 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/experiments/exp003.py +73 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/experiments/playground.py +157 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/site/CNAME +1 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/site/landing.typ +38 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/tools/mujoco/test_mujoco.py +42 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/tools/mujoco/tool.py +393 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/tools/neuron/test_neuron.py +106 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/tools/neuron/tool.py +526 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar000.typ +86 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar003.typ +82 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar004.slide.typ +418 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar005.slide.typ +294 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar006.typ +148 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar010.typ +54 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar011.typ +32 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar012.typ +52 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar013.typ +47 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar014.typ +56 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar015.typ +33 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar016.typ +29 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar017.typ +98 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/ar018.typ +128 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/exp000.typ +77 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/exp001.typ +81 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/exp002.typ +47 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo/writings/exp003.typ +61 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/demo-manifest.json +54 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/root/AGENTS.md +54 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/root/CLAUDE.md +18 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/root/README.md +28 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/root/github/workflows/tests.yml +21 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/root/gitignore +30 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/root/pyproject.toml +32 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/HOUSESTYLE.local.md +25 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/artifacts/data/.gitkeep +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/artifacts/pdfs/.gitkeep +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/demolab.yaml +40 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/experiments/helpers/__init__.py +1 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/experiments/helpers/provenance.py +78 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/experiments/helpers/style.py +39 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/experiments/helpers/test_provenance.py +37 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/tools/.gitkeep +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/skeleton/writings/.gitkeep +0 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/starters/monte-carlo-pi/README.md +41 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/starters/monte-carlo-pi/exp000.py +110 -0
- demolab_cli-1.0.0/demolab_cli/scaffold/starters/monte-carlo-pi/exp000.typ +63 -0
- demolab_cli-1.0.0/demolab_cli/slides.py +42 -0
- demolab_cli-1.0.0/demolab_cli/test_build_resilience.py +29 -0
- demolab_cli-1.0.0/demolab_cli/test_cli.py +48 -0
- demolab_cli-1.0.0/demolab_cli/test_command_catalog.py +37 -0
- demolab_cli-1.0.0/demolab_cli/test_devserver.py +84 -0
- demolab_cli-1.0.0/demolab_cli/test_engine_build.py +150 -0
- demolab_cli-1.0.0/demolab_cli/test_init_and_staging.py +133 -0
- demolab_cli-1.0.0/demolab_cli/test_overlay.py +43 -0
- demolab_cli-1.0.0/demolab_cli/test_slide_catalog.py +40 -0
- demolab_cli-1.0.0/demolab_cli/test_slides.py +18 -0
- demolab_cli-1.0.0/demolab_cli/typ/cite-popover.js +38 -0
- demolab_cli-1.0.0/demolab_cli/typ/favicon.svg +8 -0
- demolab_cli-1.0.0/demolab_cli/typ/lib.typ +518 -0
- demolab_cli-1.0.0/demolab_cli/typ/main.typ +92 -0
- demolab_cli-1.0.0/demolab_cli/typ/style.css +263 -0
- demolab_cli-1.0.0/pyproject.toml +69 -0
- demolab_cli-1.0.0/uv.lock +2256 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: PR preview (demo site)
|
|
2
|
+
|
|
3
|
+
# Builds the shipped demo for every pull request and publishes it under pr-preview/pr-<N>/ on the
|
|
4
|
+
# gh-pages branch, posts a sticky comment on the PR with the URL, and tears the preview down when
|
|
5
|
+
# the PR closes or merges. This is what makes a PR's rendered doc set readable in place instead of
|
|
6
|
+
# a raw diff. Pairs with landing.yml (the same gh-pages branch); needs the Pages source set to
|
|
7
|
+
# "Deploy from a branch → gh-pages / (root)".
|
|
8
|
+
#
|
|
9
|
+
# Fork PRs get a read-only token and cannot write gh-pages, so previews are skipped for external
|
|
10
|
+
# contributors. Do NOT switch this to pull_request_target to "fix" that — it runs untrusted PR
|
|
11
|
+
# code with a write token (privilege-escalation footgun).
|
|
12
|
+
on:
|
|
13
|
+
pull_request:
|
|
14
|
+
types: [opened, synchronize, reopened, closed]
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
pull-requests: write
|
|
19
|
+
|
|
20
|
+
# One in-flight run per PR: rapid pushes supersede rather than race commits to gh-pages.
|
|
21
|
+
concurrency:
|
|
22
|
+
group: preview-pr-${{ github.event.pull_request.number }}
|
|
23
|
+
cancel-in-progress: true
|
|
24
|
+
|
|
25
|
+
env:
|
|
26
|
+
TYPST_VERSION: "0.15.0"
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
preview:
|
|
30
|
+
# Upstream only, same as the production deploy — a fork must not publish into demolab's Pages.
|
|
31
|
+
if: github.repository == 'eoinmurray/demolab'
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
# On 'closed' we only tear the preview down (no build needed), so guard the build steps.
|
|
37
|
+
- name: Install Typst ${{ env.TYPST_VERSION }}
|
|
38
|
+
if: github.event.action != 'closed'
|
|
39
|
+
run: |
|
|
40
|
+
url="https://github.com/typst/typst/releases/download/v${TYPST_VERSION}/typst-x86_64-unknown-linux-musl.tar.xz"
|
|
41
|
+
curl -fsSL "$url" | tar -xJ
|
|
42
|
+
echo "$PWD/typst-x86_64-unknown-linux-musl" >> "$GITHUB_PATH"
|
|
43
|
+
|
|
44
|
+
- uses: astral-sh/setup-uv@v5
|
|
45
|
+
if: github.event.action != 'closed'
|
|
46
|
+
|
|
47
|
+
- name: Build the demo with the core engine
|
|
48
|
+
if: github.event.action != 'closed'
|
|
49
|
+
run: |
|
|
50
|
+
rsync -a --exclude 'site/' demolab_cli/scaffold/skeleton/ ./
|
|
51
|
+
rsync -a --exclude 'site/' demolab_cli/scaffold/demo/ ./
|
|
52
|
+
# Same landing-only homepage as production (landing.yml), so the preview matches.
|
|
53
|
+
cp demolab_cli/scaffold/demo/site/landing.typ ./landing.typ
|
|
54
|
+
uv run --no-dev demolab build
|
|
55
|
+
|
|
56
|
+
# Deploy artifacts/site (the raw built demo — no CNAME/installers; those only belong at the
|
|
57
|
+
# production root) to pr-preview/pr-<N>/, maintain the sticky comment, and remove the subdir
|
|
58
|
+
# on 'closed'. The action auto-detects deploy vs remove from the event type.
|
|
59
|
+
- name: Deploy / update / tear down the preview
|
|
60
|
+
uses: rossjrw/pr-preview-action@v1
|
|
61
|
+
with:
|
|
62
|
+
source-dir: artifacts/site
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: Deploy the site (demo at root)
|
|
2
|
+
|
|
3
|
+
# Publishes to GitHub Pages at demolab.eoinmurray.info via the BRANCH-based flow:
|
|
4
|
+
# build the shipped demo → assemble _site (demo at /, CNAME) → commit to the
|
|
5
|
+
# `gh-pages` branch. Branch-based (not the GitHub-Actions Pages flow) so per-PR previews
|
|
6
|
+
# (landing-preview.yml) can live in the same branch under pr-preview/. Requires the Pages source
|
|
7
|
+
# set to "Deploy from a branch → gh-pages / (root)". A user's own lab deploy is separate and
|
|
8
|
+
# opt-in (demolab_cli/deploy/deploy.yml, added by `demolab deploy-setup`).
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
branches: [main]
|
|
12
|
+
paths:
|
|
13
|
+
- "demolab_cli/**"
|
|
14
|
+
- "pyproject.toml"
|
|
15
|
+
- ".github/workflows/landing.yml"
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
# The deploy commits the assembled site to the gh-pages branch, so the token needs write.
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
|
|
22
|
+
# Serialise production deploys against each other and against preview teardowns so two writers
|
|
23
|
+
# never race a commit to gh-pages. Previews use their own per-PR group.
|
|
24
|
+
concurrency:
|
|
25
|
+
group: pages-deploy
|
|
26
|
+
cancel-in-progress: false
|
|
27
|
+
|
|
28
|
+
env:
|
|
29
|
+
TYPST_VERSION: "0.15.0" # match the engine's local toolchain
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
deploy:
|
|
33
|
+
# Upstream only. Forks/templates inherit this file, but must never publish demolab's site to
|
|
34
|
+
# their own Pages — so the job is skipped everywhere but the source repo.
|
|
35
|
+
if: github.repository == 'eoinmurray/demolab'
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- name: Install Typst ${{ env.TYPST_VERSION }}
|
|
41
|
+
run: |
|
|
42
|
+
# Download the pinned release directly (deterministic, no third-party action to track).
|
|
43
|
+
url="https://github.com/typst/typst/releases/download/v${TYPST_VERSION}/typst-x86_64-unknown-linux-musl.tar.xz"
|
|
44
|
+
curl -fsSL "$url" | tar -xJ
|
|
45
|
+
echo "$PWD/typst-x86_64-unknown-linux-musl" >> "$GITHUB_PATH"
|
|
46
|
+
|
|
47
|
+
- uses: astral-sh/setup-uv@v5
|
|
48
|
+
|
|
49
|
+
- name: Build the demo with the core engine
|
|
50
|
+
run: |
|
|
51
|
+
# Materialise the shipped demo at the repo root (skeleton + demo overlay), exactly as
|
|
52
|
+
# `demolab add-demo-content` does, then compile it with the engine. The engine has zero
|
|
53
|
+
# runtime deps and the demo ships its rendered figures/videos, so --no-dev skips the
|
|
54
|
+
# heavy science deps (they're only for *running* experiments and the test suite).
|
|
55
|
+
rsync -a --exclude 'site/' demolab_cli/scaffold/skeleton/ ./
|
|
56
|
+
rsync -a --exclude 'site/' demolab_cli/scaffold/demo/ ./
|
|
57
|
+
# The landing-only homepage (the marketing hero, a custom landing.typ) — kept under
|
|
58
|
+
# site/ so the add-demo-content overlay never puts it in a user's lab.
|
|
59
|
+
cp demolab_cli/scaffold/demo/site/landing.typ ./landing.typ
|
|
60
|
+
uv run --no-dev demolab build
|
|
61
|
+
|
|
62
|
+
- name: Assemble the Pages tree (demo at /, CNAME at root)
|
|
63
|
+
run: |
|
|
64
|
+
rm -rf _site && cp -R artifacts/site/. _site/
|
|
65
|
+
cp demolab_cli/scaffold/demo/site/CNAME _site/
|
|
66
|
+
|
|
67
|
+
# Publish _site to the root of gh-pages. clean-exclude preserves the live PR previews
|
|
68
|
+
# (pr-preview/, owned by landing-preview.yml) — CNAME is re-emitted from _site every run.
|
|
69
|
+
- name: Deploy to gh-pages
|
|
70
|
+
uses: JamesIves/github-pages-deploy-action@v4
|
|
71
|
+
with:
|
|
72
|
+
folder: _site
|
|
73
|
+
branch: gh-pages
|
|
74
|
+
clean: true
|
|
75
|
+
clean-exclude: pr-preview/
|
|
76
|
+
single-commit: true
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Publish demolab-cli to PyPI
|
|
2
|
+
|
|
3
|
+
# Tag-triggered release: `git tag v<VERSION> && git push --tags` builds the wheel from a
|
|
4
|
+
# clean checkout and publishes it via PyPI Trusted Publishing (OIDC — no API token stored).
|
|
5
|
+
# One-time setup on pypi.org: Account → Publishing → add a pending publisher for project
|
|
6
|
+
# `demolab-cli`, owner `eoinmurray`, repo `demolab`, workflow `publish.yml`, environment
|
|
7
|
+
# `pypi` — and create the matching `pypi` environment in this repo's GitHub settings.
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
publish:
|
|
17
|
+
# Upstream only — a fork's tags must never try to publish the package.
|
|
18
|
+
if: github.repository == 'eoinmurray/demolab'
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
environment: pypi
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write # OIDC for Trusted Publishing
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Tag must match the engine VERSION
|
|
27
|
+
run: test "v$(cat demolab_cli/VERSION)" = "$GITHUB_REF_NAME"
|
|
28
|
+
|
|
29
|
+
- uses: astral-sh/setup-uv@v5
|
|
30
|
+
|
|
31
|
+
- run: uv build
|
|
32
|
+
|
|
33
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
# Runs the Python test suite on Linux AND Windows. The Windows leg guards the portability
|
|
4
|
+
# fixes a real Windows user's field report drove: the dev server's dual-stack bind (Windows
|
|
5
|
+
# resolves `localhost` to ::1, so an IPv4-only bind makes the printed URL dead there), the
|
|
6
|
+
# overlay.py copy behind demolab scaffold / add-demo-content (rsync doesn't exist on
|
|
7
|
+
# Windows), and slides.py's deck detection (grep/basename didn't either). macOS/Linux pass
|
|
8
|
+
# these trivially — only a real Windows runner is an honest check.
|
|
9
|
+
#
|
|
10
|
+
# Installing typst on the Linux leg unskips the engine build smoke test there; Windows
|
|
11
|
+
# stays typst-less and fast. The packaging job builds the wheel from this clean checkout
|
|
12
|
+
# and inits a lab from it — the same path `uvx demolab-cli init` takes in the wild.
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
branches: [main]
|
|
16
|
+
paths:
|
|
17
|
+
- "demolab_cli/**"
|
|
18
|
+
- "pyproject.toml"
|
|
19
|
+
- ".github/workflows/tests.yml"
|
|
20
|
+
pull_request:
|
|
21
|
+
paths:
|
|
22
|
+
- "demolab_cli/**"
|
|
23
|
+
- "pyproject.toml"
|
|
24
|
+
- ".github/workflows/tests.yml"
|
|
25
|
+
workflow_dispatch:
|
|
26
|
+
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
pytest:
|
|
32
|
+
strategy:
|
|
33
|
+
fail-fast: false
|
|
34
|
+
matrix:
|
|
35
|
+
os: [ubuntu-latest, windows-latest]
|
|
36
|
+
runs-on: ${{ matrix.os }}
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- uses: astral-sh/setup-uv@v5
|
|
41
|
+
|
|
42
|
+
- name: Install typst (Linux — unskips the engine build tests)
|
|
43
|
+
if: runner.os == 'Linux'
|
|
44
|
+
env:
|
|
45
|
+
TYPST_VERSION: "0.15.0" # match the engine's toolchain (see landing.yml)
|
|
46
|
+
run: |
|
|
47
|
+
curl -sL "https://github.com/typst/typst/releases/download/v${TYPST_VERSION}/typst-x86_64-unknown-linux-musl.tar.xz" \
|
|
48
|
+
| tar -xJf - -C /usr/local/bin --strip-components=1 "typst-x86_64-unknown-linux-musl/typst"
|
|
49
|
+
|
|
50
|
+
- name: Run the test suite
|
|
51
|
+
run: uv run pytest
|
|
52
|
+
|
|
53
|
+
packaging:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- uses: astral-sh/setup-uv@v5
|
|
59
|
+
|
|
60
|
+
- name: Build the wheel and init a lab from it
|
|
61
|
+
run: |
|
|
62
|
+
uv build
|
|
63
|
+
# Noise that must never ship (untracked locally, but belt-and-braces).
|
|
64
|
+
if unzip -l dist/demolab_cli-*.whl | grep -E 'demo/temp/|demo/artifacts/site/|__pycache__|\.demolab/'; then
|
|
65
|
+
echo "wheel carries build noise" && exit 1
|
|
66
|
+
fi
|
|
67
|
+
mkdir /tmp/lab && cd /tmp/lab
|
|
68
|
+
uvx --from "$(ls "$GITHUB_WORKSPACE"/dist/demolab_cli-*.whl)" demolab-cli init
|
|
69
|
+
test -f demolab.yaml && test -f .demolab/lib.typ && test -f AGENTS.md
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.venv/
|
|
6
|
+
.uv/
|
|
7
|
+
|
|
8
|
+
# Tool caches
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
|
|
11
|
+
# macOS
|
|
12
|
+
.DS_Store
|
|
13
|
+
|
|
14
|
+
# Agent / editor local tooling (not part of the repo)
|
|
15
|
+
.claude/
|
|
16
|
+
|
|
17
|
+
# Short-lived run scratch (regenerated by every tool run).
|
|
18
|
+
# Note: artifacts/data/ (figures + numbers.json) and artifacts/pdfs/ (compiled
|
|
19
|
+
# deliverables you host/link) are committed; artifacts/site/ is a regenerable build.
|
|
20
|
+
temp/
|
|
21
|
+
dist/
|
|
22
|
+
artifacts/site/
|
|
23
|
+
demolab_cli/scaffold/demo/temp/
|
|
24
|
+
demolab_cli/scaffold/demo/artifacts/site/
|
|
25
|
+
# Transient preview copy written by `demolab dev --demo --landing` (source of truth is
|
|
26
|
+
# demo/site/landing.typ) — never committed, never part of the user-facing demo overlay.
|
|
27
|
+
demolab_cli/scaffold/demo/landing.typ
|
|
28
|
+
|
|
29
|
+
# Engine staging dir the demolab CLI materialises at the lab root (lib.typ + web assets
|
|
30
|
+
# + version stamp) — regenerated whenever the installed demolab-cli version changes.
|
|
31
|
+
.demolab/
|
|
32
|
+
|
|
33
|
+
# Secrets — never commit
|
|
34
|
+
.env
|
|
35
|
+
.env.local
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Demolab — an agent-operated lab notebook for computational science. This file is the thin
|
|
4
|
+
entry point; the substance (runbooks + guides) ships inside the `demolab-cli` package and
|
|
5
|
+
is reached through the CLI, so it's always in step with the installed engine. **Read the
|
|
6
|
+
rules before working here.**
|
|
7
|
+
|
|
8
|
+
> **This checkout is also the demolab-cli source repo** — the engine lives in
|
|
9
|
+
> `demolab_cli/` (build code, Typst templates, runbooks, guides, scaffold). Editing the
|
|
10
|
+
> engine itself? Read [DEVELOPING.md](DEVELOPING.md) first. Everything below applies to
|
|
11
|
+
> operating a lab, here or anywhere.
|
|
12
|
+
|
|
13
|
+
**Finding the docs:** run `demolab docs` for the menu of runbooks (step-by-step procedures)
|
|
14
|
+
and guides (reference). `demolab docs <NAME>` prints the file's absolute path — read that
|
|
15
|
+
file. Start with `demolab docs RULES` — the single conventions doc: toolchain, what you may
|
|
16
|
+
edit, commits, the tool ↔ experiment contract + schemas, and how to add a tool /
|
|
17
|
+
experiment / writing. Unfamiliar with a term? `demolab docs GLOSSARY`. Authoring a writing?
|
|
18
|
+
`demolab docs HOUSESTYLE` (a root `HOUSESTYLE.local.md`, if present, extends or replaces it
|
|
19
|
+
— read it too). A slide deck? `demolab docs SLIDES`. Lost in the layout? `demolab docs
|
|
20
|
+
STRUCTURE`. Need a human? `demolab docs SUPPORT`.
|
|
21
|
+
|
|
22
|
+
Three rules important enough to state here too:
|
|
23
|
+
|
|
24
|
+
- **Toolchain:** use `uv` (Python) and `typst` (publishing) via the `demolab` CLI. Never
|
|
25
|
+
call `pip` / `python` / `python3` directly.
|
|
26
|
+
- **Commits:** author every commit as the human only — never a `Co-Authored-By:` / agent
|
|
27
|
+
trailer, never an agent in the author/committer fields.
|
|
28
|
+
- **Don't hand-edit machine-managed dirs:** the gitignored `.demolab/` staging dir at a
|
|
29
|
+
lab root belongs to the CLI. In a user's lab the engine isn't even on disk to edit — it
|
|
30
|
+
lives in the installed package; updating it is a dependency bump (`demolab docs UPDATE`).
|
|
31
|
+
|
|
32
|
+
## Commands — type a NAME
|
|
33
|
+
|
|
34
|
+
demolab is driven by typing a **name in CAPS** (SCREAMING-KEBAB). Three commands:
|
|
35
|
+
|
|
36
|
+
- **`HELP`** — run `demolab docs` and present its menu, one line each.
|
|
37
|
+
- **`<RUNBOOK>`** — a runbook name (e.g. `GETTING-STARTED`, `LINT`, `DOCTOR`) → run
|
|
38
|
+
`demolab docs <NAME>`, read the file, then **start it** and drive it step by step: run a
|
|
39
|
+
step, show the result, confirm before the next. Never dump the whole runbook at once.
|
|
40
|
+
- **`<GUIDE>`** — a guide name (e.g. `RULES`, `SLIDES`) → read it the same way, then **walk
|
|
41
|
+
the user through it**: summarise, go section by section, answer questions — don't just
|
|
42
|
+
paste the file.
|
|
43
|
+
|
|
44
|
+
**The NAME is the command.** If the user's message is (or starts with) one of these names,
|
|
45
|
+
that *is* the request: act on it, don't ask what they mean. Natural phrasings route too
|
|
46
|
+
("lint the writings" → `LINT`, "set up my lab" → `GETTING-STARTED`) — the `demolab docs`
|
|
47
|
+
menu's one-liners tell you which doc covers what.
|
|
48
|
+
|
|
49
|
+
**Docs are the source of truth.** When the user is confused, stuck, or asks "how do I…"
|
|
50
|
+
about operating demolab, check the menu *before* improvising an answer. If a runbook or
|
|
51
|
+
guide covers it, ground your answer in it — cite it, or offer to start it — rather than
|
|
52
|
+
explaining from memory.
|
|
53
|
+
|
|
54
|
+
> **`GETTING-STARTED`** ("set up my lab", "how do I get started") means **following the
|
|
55
|
+
> runbook as a conversation** — orient the user, then ask the gated questions *in order*
|
|
56
|
+
> and wait for answers. **Do not autonomously scaffold, install, build an experiment, and
|
|
57
|
+
> report back** — that races past every choice the user is supposed to make (what to
|
|
58
|
+
> compute, branding, publishing). Read the runbook first; run nothing before its step-0
|
|
59
|
+
> orient + ready-check.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Read **[AGENTS.md](AGENTS.md)** before working here — it's the entry point. (This checkout
|
|
4
|
+
is also the demolab-cli source repo; engine work goes through [DEVELOPING.md](DEVELOPING.md).)
|
|
5
|
+
|
|
6
|
+
## Commands — type a NAME
|
|
7
|
+
|
|
8
|
+
demolab is driven by names in CAPS. **If the user's message is just one of these names,
|
|
9
|
+
that IS the command — do it, don't ask what they mean:**
|
|
10
|
+
|
|
11
|
+
- **`HELP`** — run `demolab docs` and present the menu of runbooks and guides.
|
|
12
|
+
- **A runbook name** (e.g. `GETTING-STARTED`, `TOUR`, `LINT`, `DOCTOR`, `RED-TEAM`,
|
|
13
|
+
`STEELMAN`, `NEXT`, `UPDATE`) — run `demolab docs <NAME>`, read the file it points at,
|
|
14
|
+
then **start that runbook** and drive it step by step.
|
|
15
|
+
- **A guide name** (e.g. `RULES`, `HOUSESTYLE`, `SLIDES`, `STRUCTURE`, `GLOSSARY`,
|
|
16
|
+
`SUPPORT`) — read it the same way, then **walk the user through it** interactively.
|
|
17
|
+
|
|
18
|
+
The full, current menu (names + one-liners) comes from `demolab docs` — run it rather than
|
|
19
|
+
relying on a memorised list. Details of the interaction rules are in [AGENTS.md](AGENTS.md).
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Developing demolab
|
|
2
|
+
|
|
3
|
+
This repo is the source of the **`demolab-cli`** package — the engine (`demolab_cli/`:
|
|
4
|
+
build code, Typst templates, runbooks, guides, scaffold + demo) plus the packaging to ship
|
|
5
|
+
it to PyPI. `uv sync` installs the package **editable**, so the `demolab` command here runs
|
|
6
|
+
the working tree's code directly, and the engine-data lookup resolves to these very files —
|
|
7
|
+
edit, run, no reinstall.
|
|
8
|
+
|
|
9
|
+
## Serve the shipped demo — the usual case
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
demolab dev --demo # materialises the demo into temp/demo-preview and serves it
|
|
13
|
+
demolab dev --demo --landing # …and previews the marketing landing page (site/landing.typ)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This copies the demo into `temp/demo-preview/` (a disposable lab; rebuilt fresh on every
|
|
17
|
+
invocation) and serves it. **Engine edits hot-reload** — the dev server watches the package's
|
|
18
|
+
`typ/` assets and `.py` files, which here *are* the working tree. **Demo-content edits don't**
|
|
19
|
+
(the served copy is a snapshot): edit under `demolab_cli/scaffold/demo/`, then rerun the
|
|
20
|
+
command — or serve the demo source directly when iterating on demo content itself:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
DEMOLAB_ROOT=demolab_cli/scaffold/demo uv run python -m demolab_cli.devserver
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
(That writes build scratch into `scaffold/demo/temp/` + `scaffold/demo/artifacts/site/` —
|
|
27
|
+
both gitignored, both excluded from the wheel.)
|
|
28
|
+
|
|
29
|
+
## Full sandbox — when you need to *run* the experiments
|
|
30
|
+
|
|
31
|
+
To **run** the demo's experiments (regenerate figures, tweak a runner), materialise the demo
|
|
32
|
+
at the repo root — this repo's own `demolab.yaml` makes it a valid lab:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
demolab add-demo-content # copy the worked demo (skeleton + demo) to the repo root
|
|
36
|
+
demolab dev # serve whatever content is at the root
|
|
37
|
+
demolab run exp000 # re-run a runner, etc.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This *copies* the demo to the root, so keep it out of git with a **local** exclude — never
|
|
41
|
+
the shipped `.gitignore`. `.git/info/exclude` is per-clone and never committed:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
cat >> .git/info/exclude <<'EOF'
|
|
45
|
+
# local dev sandbox — never committed
|
|
46
|
+
/writings/
|
|
47
|
+
/experiments/
|
|
48
|
+
/tools/
|
|
49
|
+
/artifacts/
|
|
50
|
+
EOF
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Tear it down with `demolab clear-demo-content` (or `rm -rf writings experiments tools artifacts`).
|
|
54
|
+
|
|
55
|
+
## Packaging & release
|
|
56
|
+
|
|
57
|
+
- **Build + inspect the wheel:** `uv build`, then `unzip -l dist/demolab_cli-*.whl` — the
|
|
58
|
+
wheel must carry `typ/`, `runbooks/`, `guides/`, `scaffold/` (demo *without* its
|
|
59
|
+
`temp/`/`artifacts/site/` noise) and no `demolab_cli/test_*.py`. CI builds from a clean
|
|
60
|
+
checkout, so local noise can't ship even if the excludes drift.
|
|
61
|
+
- **Version:** `demolab_cli/VERSION` is the single source of truth (hatchling reads it via
|
|
62
|
+
the regex version source; `demolab version` prints it; lib.typ stamps it into the site's
|
|
63
|
+
generator meta). SemVer per `demolab_cli/CHANGELOG.md`.
|
|
64
|
+
- **Test from the wheel:** `uvx --from dist/demolab_cli-*.whl demolab-cli init` in an empty
|
|
65
|
+
dir, then point the fresh lab's `[tool.uv.sources]` at the wheel to `uv sync` against it.
|
|
66
|
+
- **Release:** update `CHANGELOG.md`, bump `VERSION`, commit, then
|
|
67
|
+
`git tag v<VERSION> && git push --tags` — `.github/workflows/publish.yml` builds and
|
|
68
|
+
publishes to PyPI via trusted publishing (the tag must match `VERSION`).
|
|
69
|
+
|
|
70
|
+
## Why the lab needs `.demolab/` staging at all
|
|
71
|
+
|
|
72
|
+
Writings use root-relative paths (`/.demolab/lib.typ`, `/artifacts/…`) and Typst confines
|
|
73
|
+
every read to `--root` (the lab). The engine lives in site-packages — outside every lab —
|
|
74
|
+
so the CLI materialises the few files Typst must read (`lib.typ` + web assets) into the
|
|
75
|
+
gitignored `.demolab/` and stages `main.typ` into `temp/bundle/` per build. Everything else
|
|
76
|
+
the engine does happens in Python, where site-packages is a perfectly good home.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eoin Murray
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: demolab-cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Lab notebook for computational science: Python tools produce per-run artifacts; Typst publishes them as a web bundle, per-entry PDFs, and a book.
|
|
5
|
+
Project-URL: Homepage, https://github.com/eoinmurray/demolab
|
|
6
|
+
Project-URL: Changelog, https://github.com/eoinmurray/demolab/blob/main/demolab_cli/CHANGELOG.md
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 Eoin Murray
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Python: >=3.10
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# Demolab
|
|
33
|
+
|
|
34
|
+
**A lab notebook for computational science — reproducible results, published and citable, run by a coding agent instead of a build system.**
|
|
35
|
+
|
|
36
|
+
> **Coding agent setting someone up?** Run `uvx demolab-cli docs GETTING-STARTED`, read the file it prints, and follow it strictly, step by step. *(Human, setting up by hand? See [Quickstart](#quickstart).)*
|
|
37
|
+
|
|
38
|
+
You write a model or experiment once as a small program. Demolab runs it, captures everything it produced, stamps it with the exact code version, and publishes a clean page — figures, numbers, and real typeset maths — to both the web and PDF. The numbers on the page are read from the run, so they can't drift. You drive it all by talking to a coding agent; there's no web development or build config to touch.
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
Open your coding agent in an empty folder and paste:
|
|
43
|
+
|
|
44
|
+
> Run `uvx demolab-cli init` here, then follow its GETTING-STARTED runbook strictly.
|
|
45
|
+
|
|
46
|
+
It lays your lab down, walks you through the toolchain (`uv`, `typst`) and your first experiment, one step at a time.
|
|
47
|
+
|
|
48
|
+
<details>
|
|
49
|
+
<summary><b>Set it up by hand instead?</b></summary>
|
|
50
|
+
|
|
51
|
+
Install [`uv`](https://docs.astral.sh/uv/) and [`typst`](https://typst.app) (`brew install uv typst`), then:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
mkdir my-lab && cd my-lab
|
|
55
|
+
uvx demolab-cli init # lab structure + git init — yours from the first commit
|
|
56
|
+
uv sync # installs the deps and the `demolab` command
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Then `demolab add-demo-content && demolab run exp000 && demolab dev` to see the loop. `demolab clear-demo-content` wipes the demo again. The engine lives in the `demolab-cli` package — updating it is `uv lock --upgrade-package demolab-cli && uv sync`.
|
|
60
|
+
|
|
61
|
+
</details>
|
|
62
|
+
|
|
63
|
+
## What to ask your agent
|
|
64
|
+
|
|
65
|
+
Open your lab in your agent and say a runbook's name — it follows that runbook one step at a time. `demolab docs` lists them all (each is a plain file shipped in the package; `demolab docs <NAME>` prints its path). In this repo they live under [`demolab_cli/runbooks/`](demolab_cli/runbooks/).
|
|
66
|
+
|
|
67
|
+
| Say… | …and it will |
|
|
68
|
+
|------|--------------|
|
|
69
|
+
| **GETTING-STARTED** | set you up end to end: scaffold, your first experiment live on a page, brand, publish |
|
|
70
|
+
| **TOUR** | guided walkthrough of the lab — what's here, what it found, where to start |
|
|
71
|
+
| **MIGRATE-CODE** | bring an existing codebase in, one experiment at a time |
|
|
72
|
+
| **FROM-JUPYTER** | launder a Jupyter notebook into a reproducible, seeded experiment |
|
|
73
|
+
| **FROM-PAPER** | scaffold experiments to reproduce a paper's key result in your stack |
|
|
74
|
+
| **MIGRATE-STACK** | write your tools in MATLAB / Julia / R / Octave instead of Python |
|
|
75
|
+
| **EMBED-DOCS** | drop demolab into another project as a `docs/` site |
|
|
76
|
+
| **NEXT** | read your whole arc and propose the next experiments worth running |
|
|
77
|
+
| **GROUND-CLAIMS** | find the source sentences behind each citation |
|
|
78
|
+
| **LINT** | check your writeups against the house style |
|
|
79
|
+
| **DOCTOR** | audit the repo against the conventions |
|
|
80
|
+
| **RED-TEAM** | adversarially check a result holds up before you publish it |
|
|
81
|
+
| **STEELMAN** | build the strongest honest case for a result, so you don't under-sell it |
|
|
82
|
+
| **UPDATE** | update the engine package, leaving your content untouched |
|
|
83
|
+
|
|
84
|
+
## How it works
|
|
85
|
+
|
|
86
|
+
One decoupled loop: **a tool computes → drops data → an experiment writes it up → the site publishes it.** Every run records its exact parameters and the git commit it came from (stamped on the page), and tables read their numbers straight from the run — so prose and results can't disagree. A single Typst pass emits a website, a PDF per entry, and a book, all sharing the same live numbers.
|
|
87
|
+
|
|
88
|
+
The detail lives in the guides (in a lab: `demolab docs <NAME>`; in this repo, the files under `demolab_cli/guides/`):
|
|
89
|
+
|
|
90
|
+
- **[RULES.md](demolab_cli/guides/RULES.md)** — the tool ↔ experiment contract, schemas, provenance, and how to add things.
|
|
91
|
+
- **[STRUCTURE.md](demolab_cli/guides/STRUCTURE.md)** — the annotated file tree.
|
|
92
|
+
- **[HOUSESTYLE.md](demolab_cli/guides/HOUSESTYLE.md)** — prose, maths, and figure style.
|
|
93
|
+
- **[AGENTS.md](AGENTS.md)** — the agent entry point.
|
|
94
|
+
|
|
95
|
+
## Commands
|
|
96
|
+
|
|
97
|
+
`demolab` shows them all. The everyday ones: `init`, `docs`, `install`, `scaffold` · `add-demo-content` · `clear-demo-content`, `run expNNN`, `dev`, `build`, `test`.
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
[MIT](LICENSE) — free to use, fork, and adapt for your own lab.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Demolab
|
|
2
|
+
|
|
3
|
+
**A lab notebook for computational science — reproducible results, published and citable, run by a coding agent instead of a build system.**
|
|
4
|
+
|
|
5
|
+
> **Coding agent setting someone up?** Run `uvx demolab-cli docs GETTING-STARTED`, read the file it prints, and follow it strictly, step by step. *(Human, setting up by hand? See [Quickstart](#quickstart).)*
|
|
6
|
+
|
|
7
|
+
You write a model or experiment once as a small program. Demolab runs it, captures everything it produced, stamps it with the exact code version, and publishes a clean page — figures, numbers, and real typeset maths — to both the web and PDF. The numbers on the page are read from the run, so they can't drift. You drive it all by talking to a coding agent; there's no web development or build config to touch.
|
|
8
|
+
|
|
9
|
+
## Quickstart
|
|
10
|
+
|
|
11
|
+
Open your coding agent in an empty folder and paste:
|
|
12
|
+
|
|
13
|
+
> Run `uvx demolab-cli init` here, then follow its GETTING-STARTED runbook strictly.
|
|
14
|
+
|
|
15
|
+
It lays your lab down, walks you through the toolchain (`uv`, `typst`) and your first experiment, one step at a time.
|
|
16
|
+
|
|
17
|
+
<details>
|
|
18
|
+
<summary><b>Set it up by hand instead?</b></summary>
|
|
19
|
+
|
|
20
|
+
Install [`uv`](https://docs.astral.sh/uv/) and [`typst`](https://typst.app) (`brew install uv typst`), then:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
mkdir my-lab && cd my-lab
|
|
24
|
+
uvx demolab-cli init # lab structure + git init — yours from the first commit
|
|
25
|
+
uv sync # installs the deps and the `demolab` command
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then `demolab add-demo-content && demolab run exp000 && demolab dev` to see the loop. `demolab clear-demo-content` wipes the demo again. The engine lives in the `demolab-cli` package — updating it is `uv lock --upgrade-package demolab-cli && uv sync`.
|
|
29
|
+
|
|
30
|
+
</details>
|
|
31
|
+
|
|
32
|
+
## What to ask your agent
|
|
33
|
+
|
|
34
|
+
Open your lab in your agent and say a runbook's name — it follows that runbook one step at a time. `demolab docs` lists them all (each is a plain file shipped in the package; `demolab docs <NAME>` prints its path). In this repo they live under [`demolab_cli/runbooks/`](demolab_cli/runbooks/).
|
|
35
|
+
|
|
36
|
+
| Say… | …and it will |
|
|
37
|
+
|------|--------------|
|
|
38
|
+
| **GETTING-STARTED** | set you up end to end: scaffold, your first experiment live on a page, brand, publish |
|
|
39
|
+
| **TOUR** | guided walkthrough of the lab — what's here, what it found, where to start |
|
|
40
|
+
| **MIGRATE-CODE** | bring an existing codebase in, one experiment at a time |
|
|
41
|
+
| **FROM-JUPYTER** | launder a Jupyter notebook into a reproducible, seeded experiment |
|
|
42
|
+
| **FROM-PAPER** | scaffold experiments to reproduce a paper's key result in your stack |
|
|
43
|
+
| **MIGRATE-STACK** | write your tools in MATLAB / Julia / R / Octave instead of Python |
|
|
44
|
+
| **EMBED-DOCS** | drop demolab into another project as a `docs/` site |
|
|
45
|
+
| **NEXT** | read your whole arc and propose the next experiments worth running |
|
|
46
|
+
| **GROUND-CLAIMS** | find the source sentences behind each citation |
|
|
47
|
+
| **LINT** | check your writeups against the house style |
|
|
48
|
+
| **DOCTOR** | audit the repo against the conventions |
|
|
49
|
+
| **RED-TEAM** | adversarially check a result holds up before you publish it |
|
|
50
|
+
| **STEELMAN** | build the strongest honest case for a result, so you don't under-sell it |
|
|
51
|
+
| **UPDATE** | update the engine package, leaving your content untouched |
|
|
52
|
+
|
|
53
|
+
## How it works
|
|
54
|
+
|
|
55
|
+
One decoupled loop: **a tool computes → drops data → an experiment writes it up → the site publishes it.** Every run records its exact parameters and the git commit it came from (stamped on the page), and tables read their numbers straight from the run — so prose and results can't disagree. A single Typst pass emits a website, a PDF per entry, and a book, all sharing the same live numbers.
|
|
56
|
+
|
|
57
|
+
The detail lives in the guides (in a lab: `demolab docs <NAME>`; in this repo, the files under `demolab_cli/guides/`):
|
|
58
|
+
|
|
59
|
+
- **[RULES.md](demolab_cli/guides/RULES.md)** — the tool ↔ experiment contract, schemas, provenance, and how to add things.
|
|
60
|
+
- **[STRUCTURE.md](demolab_cli/guides/STRUCTURE.md)** — the annotated file tree.
|
|
61
|
+
- **[HOUSESTYLE.md](demolab_cli/guides/HOUSESTYLE.md)** — prose, maths, and figure style.
|
|
62
|
+
- **[AGENTS.md](AGENTS.md)** — the agent entry point.
|
|
63
|
+
|
|
64
|
+
## Commands
|
|
65
|
+
|
|
66
|
+
`demolab` shows them all. The everyday ones: `init`, `docs`, `install`, `scaffold` · `add-demo-content` · `clear-demo-content`, `run expNNN`, `dev`, `build`, `test`.
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
[MIT](LICENSE) — free to use, fork, and adapt for your own lab.
|