Four entangled change-sets from one session, committed together because
their file-level overlap (build.sh, docs, embedded/, watcher.go, …) makes
post-hoc separation noisy:
* fix(archive): nested-party + folder-type cascade
transmittalIsUnderVisibleParty short-circuited on the first matched
party segment, only checking the immediately-next segment for a
folder-type marker. Paths like BM/sub/Issued/<txn> bypassed the Issued
toggle entirely. Replaced with isUnderHiddenFolderType (full-path) +
any-segment party match. Eight new Playwright cases pin the contract
in tests/archive-cascade.spec.js.
* refactor(zddc-server): scope .archive index by project
archive.Index now buckets by top-level segment
(.ByProject[<project>].ByTracking[<tracking>]). Resolve and AllEntries
take a project parameter; handler extracts it from contextPath's first
segment. /.archive/ at root returns 404 — stable refs must be
project-rooted. Within-project (tracking, rev) collisions emit a WARN
with both paths. Cross-project tracking-number duplicates no longer
collide.
* perf(zddc-server): lazy-load expensive bits of the profile page
serveProfilePage now ships a minimal shell: Email, EmailHeader,
IsSuperAdmin (root .zddc only). Visible projects + admin subtrees +
editable scaffolds populate client-side via /.profile/access. Subtree-
admin scaffolds live in <template id="tmpl-subtree-admin">; pure
non-admins receive no live admin form. ScanZddcFiles now memoized,
invalidated on .zddc events by the watcher and writer helpers.
* feat: lockstep release + redesigned releases page
sh build.sh --release [version|alpha|beta] is the canonical lockstep
cut: every tool (5 HTML + zddc-server) bumps to the same coordinated
version. zddc-server binaries now committed under website/releases/
with the same cascade chain as HTML tools (no more Codeberg release-
asset publication). zddc/release.sh deprecated (kept as a guard);
shared/publish-codeberg-release.sh removed.
Releases page redesigned as an action-first install guide: hero +
version dropdown that rewires every download link, channel chips for
always-visible alpha/beta access (state-aware labels: "tracks stable"
vs "active dev"), Path A (zddc-server with platform auto-detect from
UA), Path B (5 standalone tool HTMLs), version-pinning empowerment
narrative (drop-a-copy vs .zddc apps: cascade), channels explainer.
Channel-link verifier asserts every <tool>_{stable,beta,alpha}.html
resolves at the end of every build. Bootstrap-friendly: zddc-server
artifact checks skip until the first lockstep cut anchors the chain.
Tests: 167 Playwright + all Go packages green.
Docs: CLAUDE.md, AGENTS.md, ARCHITECTURE.md, zddc/README.md updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
63 lines
8.2 KiB
Markdown
63 lines
8.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; Go 1.24+). Serves `ZDDC_ROOT/index.html` at `GET /` as the landing page; `Accept: application/json` on `/` returns the ACL-filtered project list. Cross-compiled binaries are committed to `website/releases/` and served from `zddc.varasys.io/releases/` (no Codeberg release assets); the `helm/` charts in this repo build from source at deploy time.
|
|
- `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` AND by the top-level `build.sh` for lockstep release helpers).
|
|
- `website/` — committed static site: `index.html` (root URL, hand-edited intro), `releases/<tool>_v<X.Y.Z>.html` (immutable per-version archives), `releases/<tool>_v<X.Y>.html` and `_v<X>.html` (symlinks), `releases/<tool>_{stable,beta,alpha}.html` (channel mirrors), `releases/zddc-server_v<X.Y.Z>_<platform>` (per-version cross-compiled binaries), `releases/zddc-server_<channel>_<platform>` (binary symlinks following the same cascade), `releases/zddc-server_<X>.html` (per-version / per-channel stub pages that fan out the four platform downloads in one matrix-cell link), `releases/index.html` (matrix table regenerated by `build.sh`). **Install model:** local use is a download from `/releases/`. Server use is `zddc-server`, which has the current-stable build of all five tools baked in via `//go:embed` (compile-time default). Tools auto-served at folder-name-driven paths: `archive` everywhere, `classifier` in `Incoming`/`Working`/`Staging` subtrees, `mdedit` in `Working` subtrees, `transmittal` in `Staging` subtrees, `landing` only at root. Override via `.zddc apps:` cascade entry (channel/version/URL/path) — fetched once, cached at `<ZDDC_ROOT>/_app/`. Drop a real `.html` file at any path to override.
|
|
- `helm/` — example Helm charts for zddc-server (`zddc-server-prod/`, `zddc-server-dev/`). Both compile from source via init container. Operators copy `values.yaml.example` and customize. No secrets in repo.
|
|
- `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 # dev build: 5 HTML tools + cross-compile zddc-server binaries + regen releases/index.html
|
|
sh tool/build.sh # build one HTML tool (archive|transmittal|classifier|mdedit|landing)
|
|
|
|
# Lockstep releases — every cut bumps ALL tools (5 HTML + zddc-server) to the same version
|
|
sh build.sh --release # stable, coordinated next-version (max(latest tag) + 1)
|
|
sh build.sh --release X.Y.Z # stable, explicit version
|
|
sh build.sh --release alpha # alpha channel cut for everything
|
|
sh build.sh --release beta # beta channel cut for everything
|
|
|
|
sh tool/build.sh --release [version|alpha|beta] # single-tool release (rare; prefer the lockstep top-level cut)
|
|
./freshen-channel <tool> <channel> # rebuild a single tool's alpha/beta from its current stable tag
|
|
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 (sub-project)
|
|
(cd zddc && go test ./...) # unit tests (Go 1.24+)
|
|
```
|
|
|
|
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.** `tool/dist/<tool>.html` is the canonical built artifact for testing and as the source for `--release` writes. Never hand-edit a `dist/` file.
|
|
- **Lockstep releases.** Every release cut bumps all six artifacts (5 HTML tools + zddc-server) to the same version, even if a tool didn't change. The coordinated next-stable target is `max(latest tag across all tools) + 1`. Per-tool independent versions are no longer the norm — `sh build.sh --release` is the canonical path. Workflow: alpha = active dev, beta = ready for general testing, stable = ready to ship.
|
|
- **`website/releases/` is committed.** HTML tools: per-version `<tool>_v<X.Y.Z>.html` (real immutable files) + partial-version pins + channel mirrors (symlinks). zddc-server: `zddc-server_v<X.Y.Z>_<platform>` per-version binaries (real bytes), `zddc-server_v<X.Y>_<platform>` / `_v<X>_<platform>` / `_<channel>_<platform>` symlinks, plus `zddc-server_<X>.html` stub pages that surface the four platform downloads in one matrix-cell link. Same cascade rule for both: stable cut → beta + alpha both reset to stable; beta cut → alpha cascades to beta.
|
|
- **No tags for alpha/beta.** Channel URLs are stable URLs by design — appending counter tags would defeat the purpose. The on-page label encodes `<date> · <sha>` for traceability. Stable cuts get clean `<tool>-vX.Y.Z` tags for every tool (six tags per cut, all sharing the same X.Y.Z).
|
|
- **Pre-release semver in the on-page label.** Plain dev builds and `--release alpha|beta` cuts embed `vX.Y.Z-{alpha,beta}` in `{{BUILD_LABEL}}` where X.Y.Z is the next-stable target. Plain dev adds a full timestamp + `-dirty` marker; `--release alpha|beta` is date-only.
|
|
- **Channel-link verifier.** Every `sh build.sh` ends with a check that every `<tool>_{stable,beta,alpha}.html` (and zddc-server's per-platform binary mirrors + stub pages) resolves. Bootstrap-friendly: skips zddc-server checks until the first `--release` cut materializes the binaries.
|
|
- **Plain `sh tool/build.sh` is a dev build.** Writes `dist/<tool>.html` only; no `website/releases/` side-effect. To publish, re-run with `sh build.sh --release alpha` to cut all six tools' alpha mirrors together.
|
|
- **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.
|