ZDDC/CLAUDE.md
ZDDC 2dc9ad240c refactor: distribute via Codeberg release assets, drop the upstream image
Removes the codeberg.org/varasys/zddc-server registry image, which had
no remaining consumer outside this shop. The two chart Dockerfiles
(tnd-zddc-chart) now compile zddc-server from source at build time,
fetching the right tag from a Codeberg release. release-image.sh,
zddc/Containerfile, and zddc/podman-compose.yaml are gone.

Build artifacts (HTML tools + zddc-server binaries) move from
website/releases/ in this repo to Codeberg release assets attached to
git tags. The website at zddc.varasys.io serves them by reverse-
proxying /releases/<tag>/<asset> to the corresponding Codeberg URL,
so consumers (zddc-use, level-2 bootstrap stubs, the chart
Dockerfiles) only ever talk to zddc.varasys.io.

Releases page becomes server-rendered static HTML regenerated on each
build via a single Codeberg API call. A small website/releases/manifest.json
maps <tool>-<channel> → tag for runtime channel resolution by zddc-use
and the level-2 stubs.

Files added:
- shared/publish-codeberg-release.sh — POSIX-sh helper that creates a
  Codeberg release for a tag (sets prerelease flag from tag suffix)
  and uploads/replaces release assets idempotently. Sourced by
  build-lib.sh and zddc/release.sh.
- zddc/release.sh — replaces release-image.sh. Tags + cross-compiles
  binaries via native Go (no podman needed; install Go) + uploads to
  Codeberg release assets. No image build, no registry push.

Files modified:
- shared/build-lib.sh — promote_release tags + uploads via the helper
  for stable AND alpha/beta now (alpha/beta were untagged before).
  update_alpha removed; per-tool build.sh files no longer mirror to
  website/releases/<tool>_alpha.html on plain dev builds.
- build.sh — prefers native go build over the old podman-based
  cross-compile (which is gone with Containerfile). build_releases_index
  queries the Codeberg API once and writes static HTML + manifest.json,
  with graceful fallback when the API is unreachable.
- bootstrap/level2.html.tmpl — fetches manifest.json to resolve
  channel → tag, then fetches the asset from /releases/<tag>/<asset>
  (Caddy proxy). Replaces the old /releases/<tool>_<channel>.html flat
  URL pattern. Operators with curl'd level-2 stubs need to re-issue
  them — this is a breaking change.
- AGENTS.md, CLAUDE.md — rewritten to describe the new flow.
- .gitignore — releases/ artifacts now expected to be on Codeberg, not
  committed locally.

NOT in this commit (deferred until $CODEBERG_TOKEN is provisioned):
- Backfilling existing tags as Codeberg releases.
- Cleanup commit: git rm-ing the existing artifacts in website/releases/.
  Until backfill happens, those files are how operators with old
  bootstrap stubs still get content. Once Codeberg has the assets,
  drop them.
- The Caddy reverse-proxy config on zddc.varasys.io.

Operator-side changes (not in this repo):
- tnd-zddc-chart Dockerfile.prod and Dockerfile (dev) need updating
  to compile from source rather than `FROM codeberg.org/...:stable`.
  Done in a separate commit on that repo.
- Caddyfile rule for the /releases/<tag>/<asset> reverse-proxy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:18:26 -05:00

55 lines
6.2 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Authoritative docs — read these first
This repo already has two thorough agent-facing references. **Always consult them before working** — they cover details intentionally omitted here:
- **`AGENTS.md`** — commands, build-system rules, per-tool parser quirks, testing gotchas, git/worktree workflow, release process, zddc-server notes
- **`ARCHITECTURE.md`** — single-file HTML pattern rationale, JS module/state patterns, per-tool architecture, security model
If something in this CLAUDE.md conflicts with those, those win — and please update them rather than letting drift accumulate.
## Repo shape
This is a **monorepo of independent tools**, not one application:
- `archive/`, `transmittal/`, `classifier/`, `mdedit/`, `landing/` — five self-contained HTML tools, each compiled to a single inlined HTML file in its own `dist/`. Naming: the first four output `dist/tool.html`; **`landing/` outputs `dist/index.html`** (it's the project picker served at the root of `zddc-server`).
- `zddc/` — Go HTTP server (separate sub-project, podman/podman-compose; Go 1.24+). Serves `ZDDC_ROOT/index.html` at `GET /` as the landing page; `Accept: application/json` on `/` returns the ACL-filtered project list.
- `shared/``base.css` plus shared JS modules (`zddc.js`, `hash.js`, `zddc-filter.js`, `theme.js`, `help.js`) included by every tool's build, and `build-lib.sh` (POSIX sh helpers sourced by every tool's `build.sh`)
- `website/` — published artifacts: `index.html` (root URL), `releases/<tool>_v<X.Y.Z>.html` (immutable stable archives), `releases/<tool>_stable.html` (symlink to current stable), `releases/<tool>_{alpha,beta}.html` (mutable channel files), and `bootstrap/{level1,track-stable,track-beta,track-alpha}/<tool>.html` (per-channel level-2 stubs + same-origin level-1 stubs that the home-page install snippets curl into the operator's deployment dir). `--release` is the only path to publishing `releases/`; `bootstrap/` is regenerated by every plain `sh build.sh`. There is no `website/dev/`.
- `tests/` — Playwright specs (Chromium only, requires File System Access API). `tests/schema.spec.js` validates `transmittal.schema.json` against canonical fixtures via `ajv` (only dev dep besides Playwright)
## Most-used commands
```bash
sh build.sh # build all five HTML tools (dist/ only)
sh tool/build.sh # build one (archive|transmittal|classifier|mdedit|landing)
sh tool/build.sh --release [version] # cut stable; tag, write website/releases/<tool>_v<ver>.html, refresh _stable symlink
sh tool/build.sh --release alpha|beta # cut channel build; overwrites website/releases/<tool>_<channel>.html (mutable, no tag)
./freshen-channel <tool> <channel> # rebuild alpha/beta from current stable tag (run after every stable release)
npm test # all Playwright specs (build first!)
npx playwright test <tool> # one spec
./dev-server start # ./dev-server stop # cache-busting HTTP on :8000
# zddc/ Go server (separate sub-project, not part of sh build.sh)
(cd zddc && go test ./...) # unit tests (Go 1.24+)
podman build -t zddc-server zddc/ # build container image
sh zddc/release.sh [alpha|beta|stable] [<version>] # cut + publish zddc-server binaries to Codeberg release assets (default: alpha; auto-derives version)
```
No lint/typecheck/format commands exist for the HTML tools — vanilla JS + POSIX sh by design.
## Things that bite if you forget
- **`dist/` is gitignored but force-committed** (`git add -f tool/dist/tool.html`). Never hand-edit a `dist/` file.
- **Never write to `website/index.html`, `website/releases/<tool>_v*.html`, `website/releases/<tool>_stable.html`, or `website/releases/<tool>_beta.html` directly** — promote via `sh tool/build.sh --release [version|alpha|beta]`. Stable releases write `website/releases/<tool>_v<ver>.html` (immutable) and refresh `<tool>_stable.html`; alpha/beta overwrite `<tool>_<channel>.html` in place.
- **Pre-release semver for alpha/beta.** On-page label embeds `vX.Y.Z-{alpha,beta}` where X.Y.Z is the next-stable target (patch+1 from latest clean `<tool>-vX.Y.Z` tag). zddc-server image tags additionally carry a `.N` counter (`v0.0.8-alpha.1`, `.2`, …) since every release is tagged; HTML tools omit the counter (alpha/beta cuts aren't tagged). Stable tags are clean `vX.Y.Z`.
- **Alpha exception — every plain build dirties `website/releases/<tool>_alpha.html`.** Every `tool/build.sh` (no flags) mirrors the just-built dist file into `<tool>_alpha.html` as a real copy (not symlink — the canonical Caddy serves only `website/` and can't follow `../` paths). Side-effect: dev builds dirty those files; commit alongside the source change or `git checkout` to discard.
- **Always build before running tests** — Playwright opens `dist/tool.html` via `file://`.
- **`</` in JS string/template literals breaks inline `<script>`** embedding. `shared/build-lib.sh` provides `escape_js_close_tags`; every tool's `build.sh` runs JS through it before inlining.
- **All ZDDC parsing/formatting/hashing goes through `window.zddc`** (from `shared/zddc.js` + `shared/hash.js` + `shared/zddc-filter.js`). API: `parseFilename`, `parseFolder`, `parseRevision`, `formatFilename`, `formatFolder`, `compareRevisions`, `isValidStatus`, `splitExtension`, `joinExtension`, `crypto.{sha256Hex, sha256String, sha256File, bytesToHex}`, `filter.{parse, matches}`. File objects across tools use `trackingNumber` (string) and `extension` (string, **no leading dot** — use `zddc.joinExtension(name, ext)` to build a filename). Add edge cases to `tests/zddc.spec.js`, not per-tool tests.
- **Two globals only**: `window.app` (per-tool app state + modules) and `window.zddc` (shared library). No others — anything that crosses tool boundaries goes through one of these.
- **Worktrees live at `~/src/zddc-<branch>`.** Check `git worktree list` before starting a feature branch; never `git checkout`/`switch` inside a worktree another agent might be using.
- **Build scripts are POSIX `sh` with `set -eu`**, not bash. `concat_files` takes positional args only.