Skip to content

Docs rewrite 5/5: reconcile CLAUDE.md and the doc-drift check - #189

Merged
EiffL merged 1 commit into
clean_rebuildfrom
docs-final-pass
Aug 21, 2026
Merged

Docs rewrite 5/5: reconcile CLAUDE.md and the doc-drift check#189
EiffL merged 1 commit into
clean_rebuildfrom
docs-final-pass

Conversation

@EiffL

@EiffL EiffL commented Aug 21, 2026

Copy link
Copy Markdown
Member

Final pass of the documentation rewrite — no doc pages this time, just bringing the two things that govern the docs in line with their new reality.

CLAUDE.md

  • The freeze rule is replaced by its successor: docs are live (PRs Docs rewrite 1/5: README, landing page, install, getting started #185Docs rewrite 4/5: the developer corner #188), two tracks, and a change lands with its docs — a verb change updates its docs/cli/ page, an engine change its docs/api/ module page, user-visible behavior the user guide. The docs inherit the codebase's own discipline: document only what exists, quote refusals from real runs, verify command blocks by executing them.
  • The design-doc pointer now records the decision taken during this rewrite: the design records stay in the sibling checkout and are dropped when the rebuild completes — never imported into docs/ (reverses the paragraph's earlier plan).
  • The workflow inventory catches up: eval runs on dispatch or the run-eval label (re-trigger by re-adding it), check-docs.yml reviews merged PRs, docs-deploy.yml tracks releases; the docs build command is stated.
  • The extending table's "add the next layer" row loses "Docs are deliberately deferred".

Deliberately not done: slimming CLAUDE.md's invariant sections now that the developer corner overlaps them. CLAUDE.md is still the working memory for the remaining rebuild (Perlmutter spike, deferred layers), and gutting it mid-rebuild trades a known-good reference for dedup. Worth revisiting when the rebuild closes and the design docs drop.

check-docs.yml

The post-merge doc-drift check was written before the freeze and knew nothing about the structure. Its prompt now carries:

  • a map from change kind to doc home (verb → docs/cli/, module → docs/api/ + architecture, user-visible → user guide + README, workflow/conventions → contributing);
  • the two failure modes that matter most for these docs: quoted console output drifting from what the CLI prints, and documenting anything the code no longer delivers (the no-foreshadowing rule applied to docs);
  • an updated skip list (CLAUDE.md and evals/ are maintained separately) replacing the stale skills/ rule.

Verification

  • zensical build: zero issues.
  • check-docs.yml validates as YAML.
  • Grep for frozen/stale workflow descriptions in CLAUDE.md comes back clean.

This closes the 5-PR docs rewrite. The site deploys with the next release (or a manual docs-deploy dispatch).

🤖 Generated with Claude Code

https://claude.ai/code/session_01DJzmp2MUhwiNHR94cB91dx

The freeze is over, so the rules that enforced it go: CLAUDE.md now
says docs are live and every change lands with its docs — the verb's
cli/ page, the module's api/ page, the user guide for visible
behavior — with the same document-only-what-exists discipline. The
design-doc pointer records the decision made during the rewrite: the
records stay in the sibling checkout and are dropped when the rebuild
completes, never imported. The workflow inventory catches up too
(run-eval label, check-docs, release-tracking deploys), as does the
extending table's docs column.

check-docs.yml gets a prompt that knows the new structure: a map from
change kind to doc home, and the two failure modes that matter most —
quoted console output drifting from what the CLI prints, and docs
describing anything the code no longer delivers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJzmp2MUhwiNHR94cB91dx
@github-actions

Copy link
Copy Markdown
Contributor

✅ Eval

Metric Value
Outputs check success
Agent run success
Turns 35
Tool calls 33
Cost $0.93
Agent wall time 3m13s
Model claude-sonnet-5
lc status
  mode:    direct
  sandbox: landlock (fs: declared, network: allowed)
  crate:   up to date with the outputs

  · current  baseline/best_fit        156dd21
  · current  baseline/hubble_diagram  156dd21
  · current  baseline/residuals       156dd21

3 current
Confusion & pain points (Claude analysis)

Confusion & pain points

  • numpy not present in the sandboxed venv, causing an initial crash. The agent tried python3 -c "import numpy…" for quick data exploration and hit ModuleNotFoundError, since the scaffolded project has no dependencies yet. Root cause: exploring data before adding dependencies — worked around by hand-rolling the same stats with a pure-Python loop instead of just running uv add numpy scipy matplotlib first, which it did anyway a few steps later. Minor sequencing inefficiency rather than a real product gap.
  • astra-tools invoked via uvx astra-tools@0.2.13 rather than the project's own astra CLI, and with subcommands (info --outputs, spec recipe, spec output) not documented anywhere in the visible trace — the agent appears to have guessed or recalled this surface rather than discovering it from the skill/help output, which is a detour around a CLI surface it should have been able to introspect directly (e.g. astra --help).
  • Manual local testing of recipe scripts bypassed the sandbox entirely (.venv/bin/python scripts/fit.py … run directly, writing to /tmp/testout*), rather than using lc run (the documented probe verb for exactly this purpose). This works but never exercises the Landlock policy or the declared-input/output-directory constraints the real lc materialize run enforces, so a script that passes this ad hoc test could still fail once run for real — the agent got lucky that it didn't.
  • git add staged astra.yaml, pyproject.toml, uv.lock, and scripts/ together in one commit, then a second edit to pyproject.toml (adding the license) landed after the file had already drifted from what the agent last read ("the file had been modified on disk since you last read it") — a Read-then-Edit race caused by the intervening lc materialize run silently rewriting pyproject.toml/committing state between the agent's read and edit, which the harness flagged but could equally have surprised the agent into a bad edit.

Full trace: agent-trace artifact on this run.

@EiffL EiffL left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@EiffL
EiffL merged commit 5d47485 into clean_rebuild Aug 21, 2026
10 of 11 checks passed
@EiffL
EiffL deleted the docs-final-pass branch August 21, 2026 09:01
EiffL added a commit that referenced this pull request Aug 21, 2026
…ibility (#190)

This merges the clean rebuild of lightcone-cli onto main — the full
re-architecture from the Snakemake shim to the model where **the locked
environment is the execution environment**. The pre-rebuild codebase was
deliberately stripped and functionality re-added one layer at a time,
each layer landing with its own tests, dependencies, and (since the
rewrite) docs. 21 PRs, all individually reviewed and merged into
`clean_rebuild`; this PR is the promotion.

## What lightcone-cli is now

A project is `pyproject.toml` + `uv.lock` + `astra.yaml` — uv is the
only environment substrate, and mode is derived, never configured:
direct by default (recipes in the project's `.venv` under
Landlock/Seatbelt), containerized when `[tool.lightcone.image]` is
declared (recipes in a content-addressed image archived in the
repository itself). Five verbs: `init`, `materialize`, `status`, `run`,
`build`.

- **Identity**: `definition_version` (what an output *is*) and
`env_version` (what it ran under) are separate on purpose — a spec
contradiction is `stale` and remade; an environment move is `behind`,
reported and left alone. `--refresh` widens by exactly that one state.
- **Storage**: the DataLad model — git carries history, git-annex
carries bytes, behind ordinary `git add`/`git commit`. Every output is
committed with a manifest and a run record `datalad rerun` can replay;
runs start and end on a clean tree; foreign writes are detected by
history and classify stale.
- **Execution**: one exec boundary (`Policy` → pure argv rewrite →
honest attestation) shared by recipes and the `lc run` probe; a recipe
writes its own output directory and nothing else; denials carry
copy-pasteable remedies. Network is uncontrolled on every mechanism,
symmetrically attested.
- **Venues**: detected, never configured — a SLURM allocation is spanned
with one worker per node; known centers get a login guard whose refusal
prints the center's own `salloc`/`sbatch` spellings; podman-hpc makes
multi-node containerized runs real.
- **Publication**: declaring `[project].license` turns on the RO-Crate
view — `ro-crate-metadata.json` converged by materialize, validated
against Provenance Run Crate 0.5 in CI. Deposit is `git archive`.
- **The engine is the host's uv tool, never a project dependency** — a
project's lock carries only what the analysis imports, and an engine
upgrade rebuilds nothing.

## The layers, as merged

| PR | Layer |
|---|---|
| #173 | Layer 5: the exec boundary and `lc run` (landed first — the
smallest honest consumer of the boundary) |
| #175 | Layers 2 + 4: identity, provenance, `lc materialize` |
| #178 | The engine is the host's uv tool (deletes layer 3 by decision)
|
| #180 | Layer 6: the container hatch |
| #181 | Layer 7: venues — SLURM in-allocation, podman-hpc |
| #182 | Layer 8: the publication view |
| #184 | Hardening: the recorded residues closed (UV_* scrub,
write-scope narrowing, symmetric network attestation, machine-level
uv.toml advisory) |
| #183 | The agentic eval reactivated: `uv tool install` of the branch
under test, empty-environment task, RO-Crate gate — three green runs |
| #185#189 | The documentation rewritten end to end: README, user
guide, CLI reference, developer corner, governance — every command block
executed before shipping, every refusal quoted from a real run |

## Verification

- The suite (tests, lint, mypy strict) is green on `clean_rebuild`,
including the three gated suites CI requires: sandbox enforcement
(Landlock on Linux, Seatbelt on macOS), container smoke (real build →
archive → bytes-free-clone `datalad rerun`), and crate smoke (the
official validator, REQUIRED clean).
- The agentic eval passes end-to-end on this branch: an agent builds a
supernova-cosmology analysis from the spec, manages the environment with
`uv add`, materializes through the real engine, and publishes a crate —
$0.70–$1.22 per run.
- `zensical build` renders the rewritten docs with zero issues; the site
deploys on the next release.

## Known deferred work (tracked, not blocking)

- The one-time **Perlmutter spike** (layer 7's pending items are listed
in CLAUDE.md) — HPC support ships honestly labeled "early days".
- **hub/GKE + Cloud Build** venue and **apptainer/singularity** runtimes
— design headroom recorded, deliberately not stubbed.
- Multi-arch image archives; the design-doc drop and CLAUDE.md slimming
when the rebuild formally closes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01DJzmp2MUhwiNHR94cB91dx

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant