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>
Replaces the caret-dropdown preset menu with two stacked cards:
Groups (top) — saved bundles of projects; click to open the archive
with that group's project set; per-row edit/delete
buttons.
Projects — filterable table; in default mode no checkboxes,
click any row to open just that project.
"+ New group" or a row's edit button enters select-mode: checkboxes
appear on each project row, an action bar shows above the projects card
with Save group / Open visible-checked / Cancel.
"Open visible-checked" intentionally excludes filter-hidden checked
projects so users can scope to a subset they're currently looking at.
Storage migrates from old zddc_landing_presets to zddc_landing_groups
(simpler shape: {name, projects: [...]}). One-shot migration runs on
first load.
Adds the new favicon SVG to the landing header alongside the title.
Drops the ?projects= URL state since selection is no longer the page's
primary state in click-to-open mode.
Updates Playwright suite: 9 new test cases covering click-to-open, group
crud, edit pre-population, "open selected visible" scoping, and legacy
preset migration. Adds a LandingApp._setNavigate test hook since
window.location.href cannot be reliably patched in modern engines.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rolls back the HTML-tool side of the Codeberg-as-canonical refactor
(commits 2dc9ad2, b28c4ae, bdac8dc) in favor of a simpler model:
per-version HTML files committed under website/releases/ as immutable
real files; partial-version pins (<tool>_v<X.Y>.html, <tool>_v<X>.html)
and channel mirrors (<tool>_<channel>.html) are checked-in symlinks.
Docker-tag pattern: :1.2.3 is pinned, :1.2 floats, :1 floats further,
:stable floats furthest.
URL scheme — every URL resolves to actual HTML via the symlink chain;
no JS indirection, no manifest.json, no Caddy regex-rewrite:
/releases/<tool>_v<X.Y.Z>.html exact version (real file)
/releases/<tool>_v<X.Y>.html latest patch within X.Y.* (symlink)
/releases/<tool>_v<X>.html latest within X.*.* (symlink)
/releases/<tool>_stable.html current stable (symlink)
/releases/<tool>_beta.html current beta (symlink to stable when no
active beta; real file when beta is in flight)
/releases/<tool>_alpha.html current alpha (similar — symlink to beta
or stable when no active alpha)
Cascade rule (in shared/build-lib.sh promote_release):
--release [version] (stable cut) → write per-version file; refresh 5
symlinks (_v<X.Y>, _v<X>, _stable,
_beta, _alpha) → new versioned file;
tag <tool>-v<X.Y.Z>.
--release beta → overwrite <tool>_beta.html with real
bytes; cascade _alpha.html → _beta.html
(symlink). No tag — channel URLs are
stable URLs by design; counters defeat
that.
--release alpha → overwrite <tool>_alpha.html with real
bytes. No tag, no other side-effects.
Plain `sh tool/build.sh` → dist/ only. No website/releases/
side-effect, no commit.
Code changes:
- .gitignore — drop website/releases/*.html and website/releases/zddc-server-*
exclusions; HTML tool files are tracked again. Replace the comment with
the new model description.
- shared/build-lib.sh — drop next_prerelease (no -alpha.N / -beta.N counter
tags). Drop the Codeberg-upload path for HTML tools (no longer sourcing
publish-codeberg-release.sh from build-lib). promote_release rewritten
with two helpers: _promote_stable (per-version file + 5 symlinks + tag)
and _promote_channel (overwrite mirror + cascade alpha→beta on beta cut).
- zddc/release.sh — drop alpha/beta channel path entirely; binaries publish
only on stable cuts. zddc-server's beta/alpha builds-from-source via the
helm charts (next phase) — no binary distribution needed for those channels.
- bootstrap/level2.html.tmpl — drop manifest.json fetch; resolve ?v= to a
static URL via the symlink chain. New suffixFor() handles channel names,
exact versions, and partial-version pins (?v=0.0, ?v=0). Same logic in
level1.html.tmpl already works because the local-staging files (e.g.
../<tool>_v0.0.html) exist via the same symlink scheme.
- build.sh build_releases_index — revert to filesystem scan of
website/releases/ instead of Codeberg API call. Drop manifest.json
generation. Per-tool sections list channel chips + per-version pin links;
zddc-server section links to Codeberg release pages directly.
- tests/build-label.spec.js — fix the channel-label regex to match the
pre-release-semver format introduced in commit 9459139 ("v0.0.3-alpha · ...").
Pre-existing test failure that wasn't caught at the time.
Storage:
- 30 new committed files under website/releases/ — 10 real (per-version) +
20 symlinks (5 tools × 4 partial/channel variants, plus alpha as a real
file by default).
- Initial state: stable v0.0.2 across all 5 tools; alpha/beta/v0.0/v0
symlinks all point at <tool>_v0.0.2.html.
- manifest.json deleted (no longer needed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bundles a stretch of in-progress work across the SPA tools so the
tree returns to a coherent shippable state ahead of cutting a new
zddc-server stable image:
- landing: substantial rework of the project picker (sortable/filterable
table, presets refactor, ?projects= filter, ?v= channel propagation,
loading/error states)
- archive: presets cleanup, source.js refactor, filtering/url-state
alignment with the landing page
- mdedit: file-system module split, resizer, file-tree improvements,
base/toc styling tweaks
- transmittal/classifier: small template touch-ups for shared chrome
- shared: build-lib.sh helpers, new favicon.svg
- bootstrap, build.sh: pick up the channel-aware install/track zip
generation
- tests: new landing.spec.js, expanded archive/mdedit/build-label specs
- docs: CLAUDE.md picks up the zddc-server section and freshens the
alpha-build exception note
- regenerated artifacts: install.zip, track-{alpha,beta,stable}.zip,
*_alpha.html — these are produced by `sh build.sh` and per project
convention are committed alongside the source changes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two small additions to the project-filter / channel-selector flow that
already worked end-to-end for HTTP-mode but were missing in the local
File-System-Access path and across landing→archive navigation:
* archive: scanLocalRecursive now applies window.app.projectFilter at
depth 0, mirroring the HTTP source's existing filter at source.js:316.
Loading archive.html?projects=A,B in local mode (file://) now virtually
merges A and B into one combined view, same as HTTP mode does today.
* landing: openArchive() reads ?v= from its own URL and passes it through
to the archive.html link it generates. This keeps the user on the same
channel (alpha/beta/stable/<version>) when they cross from the project
picker to the archive — without it, alpha-channel users would silently
drop back to whatever the deployment-default channel is at the
archive.html boundary.
Test exercises the local-mode filter via the existing mock-fs-api
fixture: three top-level projects, projectFilter set to {A, B}, scan
produces only A's and B's files. (The url-state.restore() URL parsing
path is well-trodden in the HTTP case — the test sets projectFilter
directly to isolate the new source.js change from a pre-existing init()
fragility in the mock environment.)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ZDDC — Zero Day Document Control. A file-naming convention plus five
single-file HTML tools (archive, transmittal, classifier, mdedit,
landing) and an optional Go HTTP server (zddc-server) with ACL and a
virtual archive index. Self-contained, offline-capable, dependency-free.
See README.md for an overview, AGENTS.md and ARCHITECTURE.md for the
build/release/architecture detail, bootstrap/README.md for the
two-level deployment install pattern, and zddc/README.md for the
HTTP server.