Skip to content
This repository was archived by the owner on May 9, 2026. It is now read-only.

release: v1.0.0 — site mode, surface registry, migration runner, hosted SSO#148

Draft
slavasolutions wants to merge 64 commits into
mainfrom
release/v1.0
Draft

release: v1.0.0 — site mode, surface registry, migration runner, hosted SSO#148
slavasolutions wants to merge 64 commits into
mainfrom
release/v1.0

Conversation

@slavasolutions

Copy link
Copy Markdown
Contributor

Summary

This is the v1.0.0 release PR — `release/v1.0` → `main`. Once merged, the changesets bot opens a "Version Packages" PR; merging that triggers the publish train across every `@clearcms/*` package.

Phases shipped

Phase Stream Status
3 wrap-up spec foundation, storage stamp, migration runner stub, renderer scaffold, doctor checks, content-protocol v1
4 editor surface registry (ADR-0023, closes #52) #119
5A mode-aware admin boot — `getProjectMode` / `isSiteMode` (ADR-0021) #120
5B theme tokens UI — `/settings/site/tokens` + 3 groups + ColorPicker + LivePreview (ADR-0024/0025) #131
5C block-schema designer extension — `/settings/blocks/` + dialect conversion (ADR-0024) #140
5D sections surface MVP — `SectionsSurface` + `SectionCard` + `AddSectionPicker` + siteContext loader (T-5D.5/6/7/8 deferred to v1.x via #143/#144) #142
5E `@clearcms/blocks-marketing` v1 — 10 blocks (Hero, Features, CTA, FAQ, Footer, Testimonials, Pricing, Logos, Contact, RichText) #103
5F `packages/create-clear/template-site-marketing/` + `--theme=marketing` #121
6 full migration runner (declarative ops + greedy-at-read + per-block + per-bucket + Hero v1→v2 demo) #136
7 ADR sweep + block-library author guide + CONTENT-PROTOCOL polish + README site-mode + migration guide + STATE refresh (CLI ref + integration guides + REST docs deferred to v1.0.x via #147) #145 + #146

Off-PLAN ships (also live on main)

Acceptance (T-8.1)

  • `pnpm --filter @clearcms/admin typecheck` → 0 errors after workspace pkg build
  • 53 admin tests pass on the critical surfaces (sections registry, project-mode, schemas, tokens, settings-sections, doctor)
  • 35 changesets queued — Version Packages PR will compute v1.0.0 across the train
  • Local `pnpm --filter @clearcms/admin build` clean
  • All Phase 3-7 baton flips ticked in PLAN.md

Drafted

Marked draft because merging this PR triggers the publish train. Operator authorization required before:

  1. Marking this PR ready / merging to main
  2. Tagging `v1.0.0`
  3. Merging the Version Packages PR (npm publish)
  4. Cutting the GitHub Release
  5. Posting the v1 announcement

Deferred to v1.0.x (filed as issues, not blocking)

🤖 Generated with Claude Code

slavasolutions and others added 30 commits May 6, 2026 14:44
Lock seven new ADRs (and one supersession) from the 2026-05-06
grilling session that reshapes v1 around an opt-in site mode.

- 0021 Headless / Site mode split — per-project flag, UUID + manifest
  block ordering (reframes ADR-0007 from definition to storage strategy)
- 0022 Record schema-version persistence — every record stamps version,
  declarative + imperative migrations chain at read
- 0023 Editor surface registry — closed core (form/article/sections/canvas)
  with internal contract; future-opens to third parties non-breaking
- 0024 Site mode renderer = library + scaffold template
  (supersedes ADR-0008)
- 0025 Per-bucket theme tokens — design-system foundation, schemas
  reference via optionsFromTokens, store token name (not resolved value)
- 0026 Preview tier contract — T0/T1/T2 named tiers (T1 mostly built;
  site mode auto-emits markers; T2 reserved)
- 0027 Markdown as first-class widget alongside richtext —
  two prose widgets, two storages
- 0028 Block library publishing rhythm — strict semver,
  package-shipped migrations

CONTEXT.md updated with the new vocabulary (Mode, Site, Block,
Block-schema, Theme tokens, Preview tier, Schema version, Richtext
extensions; Frontend / Editor mode / Widget extended). STATE.md
records the architectural pivot and links the new ADRs.

ADR-0007 reframed (storage strategy, not block definition).
ADR-0008 superseded by ADR-0024.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0.3.0 in package.json never reached npm (broken publish workflow,
fixed by #21). Rather than catch-up publish, accumulate the queued
changesets + open feature PRs and ship as v0.4.0 in one wave.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All 9 queued packages now on npm. Documents the path that got us
there (six commits + per-package TP config) so future debug saves
that walk.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two compounding causes:

1. Cached libSQL singleton in lib/db.ts opened lazily when a route is
   imported was never closed by tests. Added closeDb() export.
2. Windows occasionally needs a retry window on rm even after close().
   Added safeRm() helper in test/teardown.ts (5 retries, 50ms backoff).

Wired into pages-reindex, schemas/[key], preview/[token], backup, restore
test suites. All 389 admin tests pass on Linux. Windows clone should
clear the EBUSY blocking Eng B's full test runs.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…/0028) (#57)

Squash of 9 commits — contract trail preserved here per the PR body's
"do not squash" intent (forced by repo policy: only squash-merge is
allowed). The per-commit narrative below maps to the changeset entries
under .changeset/ that ship with this PR.

1. f4c6f4d feat(spec): add clear.config.json mode field (ADR-0021)
2. 4e0147c feat(spec): add schemaVersion + version per ADR-0022
3. dabb8e5 feat(spec): add sections + canvas editor modes (ADR-0021/ADR-0023)
4. eb50062 feat(spec): add markdown as a first-class widget (ADR-0027)
5. 2a4c137 feat(spec): per-field extensions allowlist for richtext + markdown
6. f2bdd41 feat(spec): per-field optionsFromTokens for select widgets (ADR-0025)
7. ed0bea0 feat(spec): block-schema dialect + block-instance + blockStorage hint
8. 96a0a3b feat(spec): per-bucket tokens shape + Migration types (ADRs 0025/0022)
9. b6c6294 chore(spec): self-review polish — drop dup config re-export,
   symmetric tokens re-exports

Phase 3 of the v1.0 release plan. Extends @clearcms/spec with the
contract surface site mode and schema-version persistence depend on.

Eng B track per clearcms/planning/decisions/2026-05-06-v1-architecture.md.

Track tests: 219/219 (spec) — typecheck clean, build green.
Self-review: APPROVE — no blockers, three LOW-severity nits addressed in commit 9.

Closes the Phase 3 spec foundation milestone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Squash of 6 commits — Eng B Phase 5/6 storage track. Trail preserved
here per the no-squash intent (forced by repo policy: only squash-merge
allowed). Per-commit narrative maps to .changeset/ entries.

1. 4956c11 feat(storage): write-time schemaVersion stamp (ADR-0022)
2. 40612df feat(storage): named-global writers — identity / nav / tokens
3. e8db616 feat(storage): writeItem + writePage with status routing
4. 971102c feat(storage): writeBlock + resolveBlockStorage + writePageData stamp
5. f31fe83 feat(storage): bucket-path helpers
6. b696176 feat(admin): clear-admin backfill-schema-versions CLI surface (stub)

Adds the load-bearing schema-version write primitives + every named
writer the v1 plan asks for, all routing through `writeStampedJson`:

- `stampSchemaVersion(record, schemaVersion?)` — pure precedence
  chain (explicit arg → record's existing valid semver →
  `DEFAULT_SCHEMA_VERSION`).
- `writeStampedJson(adapter, key, record, schemaVersion?)` — atomic
  temp+rename with stamp.
- Named globals: `writeIdentity` / `writeNav` / `writeTokens` /
  `writeGlobal` (generic dispatch on closed-set name).
- Records: `writeItem` (status-routed via `itemPath()`), `writePage`
  (`content/pages/<slug>/index.json`).
- `writeBlock` for `blockStorage: "files"` per-instance file path.
- `writePageData` augmented to stamp on object payloads.
- `resolveBlockStorage(collectionSchema, collectionSlug)` strategy
  resolver (default `"files"` for `pages`, `"inline"` elsewhere).
- Path helpers `themeBlocksDir` / `pageBlocksDir` / `pageBlockPath`.
- `clear-admin backfill-schema-versions` CLI surface (stub; full
  bucket walk lands in Phase 6 closeout).

Track tests: spec 219/219 + storage 89/89 = 308 ✅. Full implementation
of bucket walk pending Phase 6.

Stacked on PR #57; auto-retarget didn't fire — manually retargeted to
release/v1.0 + rebased --onto to drop the now-merged spec commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Squash of 2 commits — Stream-Migrate. Trail preserved here per
no-squash intent (forced by repo policy).

1. 89441bc feat(spec): migration runner + library discovery (ADR-0022, ADR-0028)
2. ebf44a1 feat(admin): clear-admin migrate-records stub (ADR-0022)

`@clearcms/spec/migrate` runtime: `migrate(record, from, to, migrations)`,
`buildMigrationChain` (greedy shortest-path), `applyOp` for each
declarative op kind (rename / default / remove / tiptap-to-markdown /
markdown-to-tiptap), `discoverMigrations` walking both
`<bucket>/migrations/` and `node_modules/@clearcms/blocks-*/migrations/`
per ADR-0028.

Markdown ↔ TipTap conversions are best-effort with `_migration_warnings`
annotation per ADR-0027. In-package serializers (no `marked` / `remark`
deps).

`apps/admin/src/cli/migrate-records.ts` — argv shape (`--collection
<slug>` | `--all`, `--dry-run`) locked, full bucket walk + persist
deferred to Phase 6 closeout.

Track tests: spec 247/247 (+25 for migration runner). Stacked on PR #57;
manually retargeted + rebased --onto release/v1.0 to drop the spec
commits already squashed via #57.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Squash of 2 commits — Stream-Renderer scaffold.

1. f06d7f8 feat(renderer): library scaffold (ADR-0024)
2. 43c2d70 chore(renderer): clarify FOLLOWUP(#57) marker for spec-types swap

`@clearcms/renderer` library shape (NOT an Astro integration). Types
+ dispatch only — no real blocks yet.

Exports: `renderBlocks(blocks, registry)` (pure dispatch),
`UnknownBlock` (no-op fallback per ADR-0021), `usePreview()` (SSR-safe
`?clear-preview=` detection + `markField` helper for ADR-0026 T1
markers). Framework-neutral — no React/Astro/Vue dep.

`RendererBlockInstance` is a local mirror with a `FOLLOWUP(#57)` marker
for the swap to `@clearcms/spec/blocks` once #57 lands. Now that #57
is merged, the swap is queued — see `grep -r 'FOLLOWUP(#57)' packages/`.

9 tests cover renderBlocks happy path with known + unknown blocks,
`UnknownBlock` fallback, `usePreview` URL detection, `markField`
output shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…1/0022/0025) (#75)

Stream-Doctor — 4 new `clear-admin doctor` checks for the v1
site-mode + ADR-0022 schema-version contract. Each is a pure async
function returning `DoctorIssue[]`; all four return zero issues on a
healthy v0/v1 bucket.

- `checkModeConsistency` (ADR-0021) — `clear.config.json`'s `mode`
  vs the bucket's site-mode artifacts. Headless + `theme/blocks/`
  files present → warning. Site + no `theme/blocks/` → info.
- `checkDanglingBlockTypes` (ADR-0021) — page `data.json` block
  manifests reference unknown block types → warning each.
- `checkStaleSchemaVersions` (ADR-0022) — record `schemaVersion`
  vs the schema's current `version`, per-collection counts.
  Suggests `clear-admin migrate-records` for stale collections.
- `checkDanglingTokenRefs` (ADR-0025) — block-instance fields with
  `widget: "select" + optionsFromTokens: <category>` reference token
  names absent from `theme/tokens.json[<category>]`.

Wired into `doctor.ts`'s main run sequence so `clear-admin doctor`
surfaces the new checks alongside the 10 existing ones.

Tests: 18/18 across 4 new test files. Pure fs fixtures (`mkdtemp` +
JSON file writes); no SQLite DB harness — Windows EBUSY pre-existing
issue (#56) doesn't apply.

Local `assumeSchemaVersion` shim in `doctor-stale-schema-versions.ts`
that should be swapped to `@clearcms/spec`'s now that #57 has merged.
Tracked as a follow-up cleanup PR per the lead's review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Squash of 2 commits — Stream-Docs CONTENT-PROTOCOL v1 rewrite.

1. (initial commit) docs(protocol): CONTENT-PROTOCOL.md v1 rewrite (site mode)
2. (review-nits commit) docs(protocol): address review nits — ADR-0024 scope note + SDK schemaVersion default

Rewrites `docs/CONTENT-PROTOCOL.md` to cover v1 site mode. Archives
the v0 file to `docs/CONTENT-PROTOCOL-v0.md` via `git mv` (history
preserved).

14 sections covering: Overview (mode split) | Bucket layout | Schema
versioning + migrations | Block storage strategy | Theme tokens |
Markdown / richtext widgets | Item document schema | Page document
schema | Block library publishing | REST API | Site mode example |
Headless mode unchanged | Doctor + backfill commands | Summary TOC.

Cross-references ADRs 0021 / 0022 / 0024 / 0025 / 0027 / 0028 inline.

Review nits addressed in commit 2:
- §1 scope note clarifying ADR-0024 (renderer architecture) lives
  outside this protocol doc by design — bucket-level contract only.
- §3 SDK-author note on the absent-`schemaVersion` = `"1.0.0"` rule;
  recommends `assumeSchemaVersion` over `.default()` Zod parse so the
  doctor's "untracked" check stays meaningful.

1015 lines. Status line: v1, descriptive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Establishes the rigid task list + turn-based coordination for the rest
of v1. Both engineers (S1 = lead/Eng A, S2 = Eng B) read these files at
session start and follow them strictly.

PLAN.md is the ordered task queue from now to v1.0.0. Each task is
tagged [S1] or [S2] with prereqs noted. Phase 3 already complete (all
6 PRs merged today). Phase 4-8 still queued.

BATON.md is a single-line file (S1 or S2) marking whose turn it is to
merge to release/v1.0. Initial value: S2 — Eng B has #102/#103 to
process before lead picks up Phase 4.

Hard rules in PLAN.md:
- One in-flight merge at a time per session.
- Strict alternation enforced by BATON.
- No direct push to release/v1.0 except the two-line BATON+PLAN flip
  commit immediately after each merge.
- Surface ownership zones to prevent file-level conflicts.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#102)

Reflects the v1 wave merged on release/v1.0 (PRs #57/#72/#73/#74/#75/#76).

Updates header date + tagline; new "v0.5 conceptual milestone" section listing each merged PR with SHA + scope; bucket protocol section flips to v1 layout; "in flight" section points at next gates (#52, blocks-marketing); ADR status block updated per ADR.

closes T-3.7

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
T-3.9 (lead's #101 migrate-bucket-to-r2 merge) is blocked: the
@clearcms/spec barrel re-exports migrate/run.ts (node:fs/promises +
node:url + node:path), so Vite drags it into both client and server
chunks of admin's astro build. Build fails with __vite-browser-external,
or smoke tests fail with ERR_MODULE_NOT_FOUND at runtime. Confirmed
with a clean lockfile + green typecheck + 426/426 tests + an
astro.config external mark — the issue is fundamentally in the spec
package's exports shape.

Spec is S2 surface (per PLAN ownership zones). Inserting T-3.8.5 [S2]
as a hot unblocker: split @clearcms/spec/migrate so the bucket-walking
runner is a server-only sub-export. Detail in PLAN.md.

Flipping BATON to S2 to enable the fix. T-3.9 stays open and unticked
— S1 will retry it after S2's spec fix lands and lead's #101 rebases
clean. T-3.10 / T-3.11 / T-3.12 reordered for cleaner Phase 3 wrap-up
(pulled #103 blocks-marketing forward as T-3.11 since it's already in
flight).

This commit modifies only BATON.md + PLAN.md per protocol.
…rowing (#106)

Bundled fix unblocking the entire v1 PR queue.

Per-commit trail:
- e9e9b4b fix(spec): split migrate runner — Node-only fs in /migrate/runtime sub-export
- 07b3aa8 fix(deps): regenerate pnpm-lock.yaml after spec exports map change
- 6370200 fix(spec,core,storage,design): publish hygiene — dist-only tarballs + spec/migrate split
- eae5978 fix(admin): narrow editor mode + add markdown widget label (cherry-picked from #109 per S1's Path A)

What this fixes:
1. @clearcms/spec migrate split — run.ts now pure (no node:* imports). Node-only discovery lives in new runtime.ts at @clearcms/spec/migrate/runtime (node condition only). Drops src from files whitelist.
2. Publish hygiene — @clearcms/core, @clearcms/storage, @clearcms/design flipped from raw-TS to dist-only with tsconfig.build.json + conditional exports map.
3. Admin enum narrowing — PageItemEditor + SchemaPreview narrow editorModeFor() via requiresSiteMode guard; PageContentTypeFields uses 'as const'; AddFieldModal adds 'markdown' to WIDGETS + WIDGET_DESCRIPTIONS. Per-callsite narrow until Phase 4 editor surface registry (#52).

Changesets:
- @clearcms/spec: minor (export shape change)
- @clearcms/core: minor
- @clearcms/storage: minor
- @clearcms/design: minor
- @clearcms/admin: patch

Verification:
- pnpm --filter @clearcms/admin typecheck → 0 errors
- pnpm --filter @clearcms/admin build → green (no node:* in browser bundle)
- pnpm pack across the four packages confirms dist-only tarballs

Closes #105
Closes #107
Closes #108
Closes T-3.8.5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(admin): clear-admin migrate-bucket-to-r2 (closes #14)

One-shot fs → R2 data migration. Reads ~/clear/registry.json, creates the
target bucket via the platform R2 token from R2_* env vars, PUTs every
file under bucket/ at the same key, atomically rewrites registry.json
with bucketProvider:'r2', and renames the local bucket dir to
bucket.archived-<ISO>/ so the operator can verify parity before deleting.

Implements ADR-0017 v1 happy path (steps 1, 2, 3, 5, 6, 7, 8). Status
flipped from proposed to accepted.

Deferred (called out in the changeset):
  - Step 4: per-project scoped R2 token mint per ADR-0016.
  - Resume-on-failure via .migration-progress.json (ADR-0017 Risks).
  - Streaming PUTs for large media (v1 reads each file fully into memory;
    fine for text-shaped sites, fails on multi-GB media libraries).

Env contract: reads R2_* (the platform-token shape from
~/.r2-platform.env), distinct from the per-project CLEAR_R2_* the admin
reads at boot. CreateBucket requires admin scope across all buckets, so
the platform token is the right input here; ADR-0016 will replace this
with a per-project token mint.

Tests: vitest fixture suite injects a recording StorageOps double; covers
happy path, content-type map, --bucket-name override, already-on-R2
short-circuit, missing-slug + missing-source-bucket fail-fast, env
validation, and that other registry entries are preserved during rewrite.
8/8 pass.

Dogfooded against ~/clear/clear-marketing/ (37 files, 172K, fs → R2
bucket "clear-marketing"). Post-migration verified: archive dir present,
original bucket renamed, registry shape correct, and astro build with
CLEAR_BACKEND=r2 produces the same 12 pages as the fs baseline (only
diff is the homepage's local _demo/ walker, which is site-code-specific
and unrelated to the migration).

Discovered during testing: doctor.test.ts > "PASS for a present bucket
dir" has a tight 5s timeout on a sqlite3 execSync loop that occasionally
trips when running alongside other parallel test files. Pre-existing
fragility (passes 397/397 with --no-file-parallelism); the new test
file just adds enough load to expose it. Out of scope for this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): remove obsolete vite externals for spec/migrate

Pre-T-3.8.5 astro.config.ts marked @clearcms/spec/migrate as a
ssr.external + rollup external, which baked the BUILD-TIME absolute
path of /home/runner/packages/spec/dist/migrate/run.js into the
items chunk. That path is correct on the dev machine but doesn't
exist on the CI runner (which builds from /home/runner/work/clear/
clear/...), so the smoke test failed with ERR_MODULE_NOT_FOUND.

T-3.8.5 (PR #106) fixed the underlying problem structurally by
splitting @clearcms/spec/migrate into a browser-safe barrel and a
Node-only @clearcms/spec/migrate/runtime subpath. The vite externals
in admin became obsolete and harmful — same posture as release/v1.0
HEAD, which has none.

This commit removes the externals so admin's build matches HEAD's
configuration. Local build passes; CI smoke test should now resolve
the chunk imports through Node's normal package-exports resolution
instead of an absolute file path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First v1 block library shipping with create-clear scaffolds and renderer support.

Per-commit trail:
- 10542dc feat(blocks-marketing): scaffold + Hero (ADRs 0024/0025/0028)
- 3ffca3c feat(blocks-marketing): Features + CTA + FAQ + Footer + Contact (5 blocks)
- 43154d4 feat(blocks-marketing): Testimonials + Pricing + Logos + RichText (final 4 blocks)

10 blocks: Hero, Features, CTA, FAQ, Footer, Contact, Testimonials, Pricing, Logos, RichText.
Each block ships an Astro component + Zod schema with the v1 widget dialect (ADR-0027).
Theme tokens (ADR-0025) referenced via optionsFromTokens binding.
Schema versioning per ADR-0022; lockstep publishing per ADR-0028.

Changeset: @clearcms/blocks-marketing minor.

Closes T-3.11.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements ADR-0023's closed-core surface registry. The schema's
`editor:` keyword resolves through `surfaceFor(schema)` to one of
four surfaces — form, article, sections, canvas — each implementing
the EditorSurface interface (validate + Component). PageItemEditor
and PagePageEditor dispatch through the registry instead of
branching on a narrowed 'form' | 'article' value.

- apps/admin/src/surfaces/types.ts — EditorSurface, SurfaceProps,
  SurfaceContext, SurfaceValidationResult, SiteContext + ok()/failed()
  helpers.
- apps/admin/src/surfaces/{form,article}/index.tsx — delegate to
  SchemaForm for behavior parity. Article validator wraps
  validateArticleSchema (exactly one richtext required).
- apps/admin/src/surfaces/{sections,canvas}/index.tsx — not-implemented
  placeholders. Sections validator refuses outside site mode + when
  no block schemas exist. Canvas validator always refuses (post-v1).
- apps/admin/src/surfaces/index.ts — surfaceFor() dispatcher + the
  closed registry object. Type re-exports for consumers.
- PageItemEditor + PagePageEditor: surface dispatch + inline
  SurfaceValidationFailed render when validate() returns ok: false.

Tests: 10 cases covering dispatch defaults, named-value resolution,
per-surface validators (article richtext-count, sections site-mode
+ block-schema gates, canvas reserved-for-post-v1, form always-ok),
and registry shape integrity.

Per ADR-0023 the registry is internal-only — no public registration
API in v1. Opening it to third-party surfaces is a future ADR keyed
off concrete adopter demand.

Closes T-4.1, T-4.2, T-4.3, T-4.4, T-4.5, T-4.6, T-4.7. Closes #52.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(admin): plumb project mode at boot (T-5A.1, ADR-0021)

Adds the runtime resolution path for ADR-0021's mode flag. Site-mode
surfaces (tokens UI, sections editor, designer extension, blocks
library) consume getProjectMode() / isSiteMode() in T-5B/C/D PRs to
gate sidebar entries and route guards.

- project-config.ts: mode: ProjectMode now resolved from env CLEAR_MODE
  > file.mode > headless. Provenance tracked in sources.mode. Unknown
  values fall back to default rather than throwing — boot must succeed
  even with a slightly off config so the operator can fix the file
  from the running admin.
- project-mode.ts: cached getProjectMode() + isSiteMode() helpers for
  runtime hot paths. Cache resets only via _resetProjectModeCache()
  (tests only).

Existing v0.x installs default to headless and see no behavior change.
The site-mode-only sidebar entries + route guards land in T-5B.1
(/settings/site/tokens) and T-5D.1 (sections route exposure).

Tests: 6 helper cases + 4 resolver cases covering default / file /
env / env-override / unknown-value fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): address #120 review findings — provenance + test cwd hygiene

Self-review pass on T-5A.1 found two in-scope fixes:

1. project-config.ts mode resolution: provenance was reported based on
   which input was *populated*, not which input *resolved*. A bogus env
   like CLEAR_MODE=composer would record sources.mode='env' while
   actually using the default — misleading in doctor output. Fixed to
   use a validity-aware predicate so sources.mode reports the source of
   the *resolved* value.

2. project-mode.test.ts: process.chdir leaked across tests in the same
   worker, and chdir'ing to /tmp picked up stray clear.config.json
   files on dev machines. Fixed by capturing originalCwd in beforeEach
   + restoring in afterEach, and using mkdtemp for the default-case
   tests instead of /tmp.

Follow-up filed separately for the third finding (wire
doctor-mode-consistency.ts to consume the new resolver + warn on typo'd
mode values).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Engineer B and others added 12 commits May 7, 2026 05:56
T-5A.1 follow-up. The mode-consistency check now uses
loadProjectConfig().mode as the resolver — single source of truth
across env / file / default. Critical addition: when the resolver
fell back to default because the raw value didn't validate, the
check WARNs with the operator-supplied bad value. Without this,
mode='sote' silently boots as headless and the operator can't tell
their typo wasn't honored.

Tests: 9 cases (was 5). Added 4: file.mode typo, env.CLEAR_MODE
typo, typo prevails over headless+blocks WARN, valid env value
doesn't trip the typo branch.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(admin): block-schema designer extension (T-5C.1, ADR-0024)

Site-mode-only — extends the visual SchemaDesigner to read+write
theme/blocks/<Name>.schema.json files alongside the existing
collection + layout schemas.

- lib/schemas.ts: 'block' added to SchemaKind; b:<PascalName> key
  encoding with isValidBlockName guard (PascalCase only, ADR-0024);
  listSchemas now scans theme/blocks/*.schema.json; readSchemaByKey
  + writeSchemaByKey convert between BlockSchema (on-disk shape:
  { name, version, fields }) and ClearSchema (designer shape:
  { type: 'object', properties }) so the existing SchemaDesigner
  works without modification. Block meta (name/version/title/
  description/deprecated) round-trips via a clear:block field the
  designer ignores; final-form BlockSchemaSchema validation on
  write.

- SchemaList.tsx: third "Block schemas" section in the left rail,
  shown only when at least one block exists.

- settingsSections.ts: Settings sub-nav adds "Schemas" + "Block
  schemas" entries (gated by schemaEditor).

- pages/settings/blocks/index.astro: site-mode list (302 to /settings
  in headless, /schemas in site).

- pages/settings/blocks/[name].astro: site-mode designer wrapper
  (302 to /schemas/b:<name>; rejects non-PascalCase names with 400).

Tests: 18 cases (was 10). New: block-key encoding (PascalCase
required, path-traversal rejected, empty rejected), dialect
conversion round-trip (fields ↔ properties + meta + deprecated +
default-version fallback).

Closes T-5C.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): address #122-style review on T-5C.1 — site-mode gate + cache + spec parity

Self-review pass on the block-designer extension found 3 in-PR fixes:

1. invalidateCachesForKey: block kind was falling through to the layout-
   cache invalidation branch, calling invalidateLayoutSchema() with a
   block name. Harmless today (no block-schema cache exists yet) but
   wrong shape. Added explicit block branch (no-op + comment).

2. Site-mode leak on /schemas + /api/admin/schemas: the existing schema
   designer routes had no isSiteMode() gate, so a headless operator who
   bookmarked /schemas/b:Hero would land on a working block-designer
   surface. Now: /schemas/[key] returns 404 when key is `b:` and not
   site-mode; /schemas + /schemas/[key] filter blocks out of the rail;
   POST /api/admin/schemas/[key] returns 403 on block writes in headless.

3. PascalCase regex was stricter than @clearcms/spec's BlockNameSchema
   (which allows `[A-Za-z][A-Za-z0-9-]{0,59}` — hyphens + lowercase
   leading). Mismatch meant on-disk hyphenated block schemas would be
   reachable on disk but invisible in the designer. Reconciled by
   matching spec's regex (max 60, leading alpha, alnum+dash). Tests
   updated.

Tests: 19 (was 10 → 18 after T-5C.1 → 19 with the spec-parity case).

Filing follow-ups for: writeSchemaByKey block-path coverage, listSchemas
blocks-present coverage, redirect-route tests, title==name drop edge
case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(admin): sections surface MVP (T-5D.1-4, ADR-0021/0024)

Replaces the Phase 4 SectionsPlaceholder with a real composition UX.
Site-mode admins with at least one block schema can now author a
sections page end-to-end: add block instances, edit each block's
fields via per-type SchemaForm, reorder via up/down buttons, delete.

Files:
- surfaces/sections/types.ts — SectionInstance, SectionsManifest,
  toManifest defensive coercion, newSectionId crypto-random helper.
- surfaces/sections/SectionCard.tsx — header (type label + reorder +
  delete) + body (per-block fields via SchemaForm with block-schema
  converted to ClearSchema). UnknownBlockType renders inline error.
- surfaces/sections/AddSectionPicker.tsx — minimal select + add UI;
  empty state when no block types exist.
- surfaces/sections/SectionsSurface.tsx — manifest stack + dispatcher.
- surfaces/sections/index.tsx — validator now returns ok() when
  siteContext + at least one block schema. Component = SectionsSurface.

Storage strategy: v1 ships inline-in-pageData. Per-instance block
files (writeBlock + blockInstancePath) land as v1.x follow-up. dnd-
kit reorder, visual block picker, click-to-focus from preview also
deferred to v1.x — operator can author end-to-end with the MVP.

Tests: 11 surface-registry cases (added "sections passes when site-
mode + blocks" branch) + 7 manifest helper cases.

Closes T-5D.1 / T-5D.2 / T-5D.3 (basic) / T-5D.4. Defers T-5D.5/6/7/8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): wire siteContext to surface dispatchers (closes block-merge from review)

Self-review on T-5D found a hard blocker: PageItemEditor and
PagePageEditor passed `{}` as the surface validation context, so
sections surface's validator (which requires `ctx.siteContext`)
returned failed() unconditionally — surface never actually mounted.

Fix:
- New `lib/site-context.ts` with `loadSiteContext()` + cache. Reads
  every theme/blocks/*.schema.json and theme/tokens.json into a
  SiteContext shape. Returns null in headless mode.
- PageItemEditor + PagePageEditor accept `siteContext?: SiteContext |
  null` prop, thread it through to surface.validate() + Component.
- .astro callers (item editor + page editor) pass `await
  loadSiteContext()` as the prop.

Plus the memo fix from the same review:
- SectionsSurface uses useMemo for types + schemaForType conversion
  (was rebuilt every render). Removed useCallback that was no-op
  due to props-deps capturing every-render onChange.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): keep storage server-only by converting block schemas in site-context

CI failure on PR #142: SectionsSurface imported blockSchemaToClearSchema
from lib/schemas.ts, which transitively imports @clearcms/storage's
readJson/writeJson — pulled the FS adapter (node:fs/promises, node:path)
into the client bundle and exploded with "join is not exported by
__vite-browser-external".

Fix: move the BlockSchema → ClearSchema dialect conversion into
loadSiteContext() (server-side .astro path). The SiteContext that
arrives at the editor island already carries ClearSchema-shaped block
schemas, so SectionsSurface no longer needs to import any conversion
helper or anything else from lib/schemas.ts. Bundle stays clean.

Local `astro build` now succeeds; CI should match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
T-7.1 — ADR status sweep + block-library author guide + CONTENT-PROTOCOL v1 polish.

ADR sweep:
- 0007 reframed by 0021 (page block storage shifted to v1 dialect)
- 0008 superseded by 0024 (Workers renderer dropped for self-hosted Astro)
- 0021–0028 carry Implementation status (2026-05-07) sections with PR references where shipped

ADR README index:
- 0007 row updated to reframed
- 0019 noted as skipped/reserved
- 0021–0028 annotated with v1 impl status
- New v1 ADR set one-line summaries

New file: docs/guides/block-library-authoring.md (~325 lines)
- Required exports + widget vocabulary (ADR-0027)
- optionsFromTokens binding (ADR-0025)
- Versioning + migrations (ADR-0022)
- Publishing cadence (ADR-0028)
- Worked Pricing block example
- Reference: @clearcms/blocks-marketing

CONTENT-PROTOCOL polish:
- "What's new in v1" section
- Cross-link to author guide
- Renderer name fix: clear-site → @clearcms/renderer

Changeset: empty frontmatter — root docs, no package version bumps.

Closes T-7.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…(T-7.3+T-7.4 partial) (#146)

Pre-stages T-7.3 (README v1 rewrite) + T-7.4 (STATE.md refresh) docs in
parallel with Eng B's T-7.1 docs sweep (separate paths — they touch
docs/adr/ + docs/CONTENT-PROTOCOL.md + docs/guides/, this PR touches
README.md + docs/migration-v0.2-to-v1.0.md + STATE.md).

- README.md — adds prominent "Two modes (v1, ADR-0021)" section near
  the top: explains headless vs site mode + points at the migration
  guide. Existing scaffolder/quick-start sections unchanged.
- docs/migration-v0.2-to-v1.0.md (new) — TL;DR upgrade for headless
  installs (just bump deps + run doctor); spec/storage table of
  changes with backwards-compat notes; site-mode opt-in walkthrough
  (config flag → scaffold → sections layout → renderer); breaking-
  change list (rare; only matters for internal-import consumers);
  rollback notes.
- STATE.md — refreshed package versions to match npm reality (#110)
  + reflect v1 phases shipped: admin 0.4.2 with v1.0.0 queued, create
  0.4.0 with --theme=marketing, blocks-marketing 0.1.0 new, renderer
  0.1.0 scaffold. Header line updated to v1.0 release prep status.

T-7.3 (full): full clear-admin command reference + integration guides
(Astro/React/SDK) + REST docs deferred to v1.0.x — covered by issue
referencing #94.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 103 tests across 7 new files, no production-code changes. Targets
the highest-value gaps in @clearcms/sdk after a public-surface review:

- errors.test.ts (10 tests) — ClearSdkError code/cause contract +
  factory tagging. Adapters branch on err.code; pin the values.
- index.test.ts (13 tests) — isResolvedRef / getResolved edge cases
  (null _resolved, arrays, primitives, missing keys).
- client.test.ts (15 tests) — bucket-direct listPage offset cursors
  (clamp, NaN/negative limits, malformed cursor tolerance, hasMore),
  listAll exhaustion, lazy adapter-load config errors, unknown backend.
- adapters/shared.test.ts (24 tests) — LRU eviction + promotion + delete,
  pMapBounded order/concurrency cap/empty input, all parsers (valid,
  invalid JSON, schema-fail, unicode).
- adapters/rest.test.ts (21 tests) — query-param forwarding (locale,
  status, expand, limit, cursor), Bearer auth, draft-without-token
  guard, 401/403/404/5xx code mapping, fetch network error wrapping,
  malformed JSON parse error, nested page slug encoding,
  metaEffective stripping, favicon URL→bucket-key reverse translation,
  nav 410 subsystem-off fallback, theme-tokens default fallback,
  trailing-slash adminUrl stripping, Z2 cursor pagination shape.
- adapters/config.test.ts (10 tests) — config validation for r2
  (accountId, bucket, credentials.{accessKeyId,secretAccessKey}),
  s3 (endpoint, bucket, region), fs (root). Errors fire on first call
  (lazy load), not factory time — pin that contract.
- adapters/fs.test.ts (13 tests) — empty-bucket defaults
  (DEFAULT_IDENTITY/NAV/THEME_TOKENS), bucket-direct draft invisibility
  on listItems/getItem/pages.list/pages.get, sort-order contract
  (publishedAt desc, slug asc tiebreak), locale filter, missing
  collection prefix, corrupt-JSON tolerance (parse error on get,
  skip-and-continue on list), nested page slug round-trip.

Verification:
- pnpm --filter @clearcms/sdk test → 118 passed (was 15)
- pnpm --filter @clearcms/sdk typecheck → clean
- pnpm pack → no *.test.* files in tarball (verified via tar -tzf)

No new dependencies. No production code touched. No changeset (this is
internal quality work, not a publishable change).

Co-authored-by: Engineer B <engineer-b@clearcms.dev>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 23 tests in a single new file (src/edge-cases.test.ts), no
production-code changes. Targets the corners of the @clearcms/renderer
public surface that the shipped src/index.test.ts doesn't pin:

renderBlocks edge cases (6 tests):
- empty manifest in / empty manifest out
- order preservation across a 50-block manifest
- registry value type-agnosticism (string, number, function, object)
  — locked because the package is framework-neutral
- props reference passthrough (memo-friendly for downstream adapters)
- schemaVersion preserved on descriptor.meta when present
- two unknown blocks of the same type stay independent (no aliasing)

UnknownBlock (3 tests):
- fresh object each call (no shared state)
- props reference passthrough
- kind=\"unknown\" discriminator is stable

usePreview URL parsing (7 tests):
- clear-preview detected when surrounded by other params
- empty value / valueless key still count
- hash-fragment-only \"clear-preview\" does NOT trigger
- relative URL strings work via synthesized base
- query-only string (no path) works
- similar-named params (clear-preview-debug, xclear-preview) excluded
- empty string returns previewing=false

usePreview.markField (7 tests):
- empty fieldPath returns the whole record
- numeric segments resolve through array index lookup
- primitive ancestors (string/number/boolean) return undefined
- null ancestor returns undefined
- non-object input record returns undefined
- __proto__ named keys read literally (own properties only)
- dataClearField only emitted when previewing
  (production markup byte-identical to no-preview path)

Bug found and filed (NOT fixed here):
- #135 — packages/renderer/package.json files array does not exclude
  *.test.ts → tests currently ship in the npm tarball. Mirrors the SDK
  convention. Pure manifest fix; out of scope for this audit branch.

Verification:
- pnpm --filter @clearcms/renderer test → 32 passed (was 9)
- pnpm --filter @clearcms/renderer typecheck → clean

No new dependencies. No production code touched. No changeset.

Co-authored-by: Engineer B <engineer-b@clearcms.dev>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
slavasolutions and others added 17 commits May 8, 2026 14:02
…0005)

Adds canonical action vocabulary (~40 stable string IDs) and matrix shape
contract for role enforcement. Same string IDs feed admin guards,
REST-token-to-action mapping, the permissions panel UI, and the audit
log subsystem when it lands.

@clearcms/spec 0.3.1 -> 0.4.0 (additive).
…SLICE-0021 BUG-3)

`PagePageEditor.handlePublish` ran `await handleSave()` then guarded on
`dataErrors.length > 0 || errMsg !== null`. Those `setState` calls inside
`handleSave` had not flushed to the closure yet, so the guard always saw
the pre-call values and proceeded to call `pages.publish` on a page
whose `pageData.save` had just been rejected — the operator saw a
"Published" pill on data that was never persisted.

`handleSave` now returns `{ ok: boolean }`; `handlePublish` checks the
return value directly. Regression test added in
`PagePageEditor.test.tsx` — fails before the fix, passes after.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…021 BUG-4)

`actions.settings.setLocales` wrote `default_locale`, `enabled_locales`,
and `fallback_strategy` as three separate `settings` upserts in a
non-transactional `for` loop. If the second upsert failed, the first
had already been committed and the third never ran — leaving the
project in a half-saved state with no recovery UX.

Extracted the write to `lib/settings-locales.ts` and wrapped the loop
in `db.transaction(...)`. Two regression tests in
`settings-locales.test.ts`:

- a transaction is opened (asserts the helper does not regress to a
  bare loop)
- a forced failure on row 2 leaves the seeded row 1 untouched

Both fail against the pre-fix bare-loop implementation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…0021 BUG-5)

Eight call sites in `lib/items.ts` and one in `lib/scheduler.ts` used
`void indexItem(...)` / `void unindexItem(...)` to push the FTS write
off the request path. Rejected promises were silently dropped — items
saved successfully but search missed them with no log line and no
doctor signal that anything was wrong, until an operator ran
`clear-admin reindex`.

`indexItemAsync` / `unindexItemAsync` keep the non-blocking shape but
route rejections through a swappable logger that defaults to
`console.error`. Tests can override the logger via
`setFtsLoggerForTests`.

Regression test in `search.test.ts` forces a rejected `execute` and
asserts the logger is invoked. Pre-fix the `void` swallow caused the
rejection to fall through to vitest's unhandledRejection handler and
fail the run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ns (SLICE-0021)

`actions.collections.setEditorMode` invalidates the collection-schema
cache after writing; the four `fields.*` handlers (`create`, `update`,
`delete`, `reorder`) did the bucket dual-write but skipped the
invalidation. `loadCollectionSchema(slug)` could serve a compiled
validator without the new field until the next bucket-watch tick.

Drive-by fix from the save-flow audit's "across-the-board" cache
recommendations. No new test — this is parity with `setEditorMode`,
which already covers the pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Astro's `defineAction` wrappers carry a complex type that doesn't
overlap with `vi.fn`'s `Mock<...>` shape under TS 6 strict-cast
checking, even though the runtime mock from `vi.mock('astro:actions')`
returns plain `vi.fn()`s. Cast through `unknown` to satisfy the
checker. No behavior change.

Follow-on to SLICE-0021 BUG-3 commit; surfaced by `pnpm -w typecheck`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New `widget: "markdown"` option in collection + layout schemas. Renders a
raw-markdown textarea with a live preview pane and a small toolbar
(bold / italic / link / heading / list); Cmd+B / Cmd+I / Cmd+K
shortcuts wrap the selection or insert a link skeleton at the caret.

Stores raw markdown text on save; the renderer parses at read time.
Defaults to full width on the SchemaForm grid, mirroring textarea and
richtext.

Spec changes:
- `'markdown'` added to `CLEAR_WIDGETS` (after `'textarea'`)
- `widthFor` defaults markdown fields to `full`
- minor: 0.3.1 -> 0.4.0

Admin changes:
- new `apps/admin/src/components/widgets/Markdown.tsx`
- `FieldRouter` routes `widget: "markdown"` to it
- `AddFieldModal` exposes Markdown in the picker grid
- preview HTML is sanitised against <script>, <iframe>,
  `javascript:` URIs, and inline event handlers (defence-in-depth;
  not a full DOMPurify pass)
- minor: 0.4.2 -> 0.5.0

Tests:
- `Markdown.test.tsx` — 21 cases: render, commit/save, toolbar,
  keyboard shortcuts, and edge cases (empty / very long / special
  characters / XSS strip)
- `SchemaForm.test.tsx` — router + grid integration cases for the
  new widget; textarea regression guard
- spec `widgetFor` / `widthFor` / `CLEAR_WIDGETS` updated for the
  enum extension

Gates: 431 admin + 128 spec tests green; typecheck clean; CHANGELOGs
updated for both packages; STATE.md bumped in clear/ + plan/.

Acceptance criteria from SLICE.md all checked.
After 005793e retired the PLAN.md+BATON.md coordination protocol, leaving
the file absent created a discoverability hole for any returning collaborator.
This stub replaces it with a 5-line redirect to the new clearcms/plan
orchestration repo so anyone walking into clear/ on release/v1.0 lands on
a clear pointer instead of a missing file.
clearcms/plan is private, so adopters can't reach individual ADR drafts. The
public index is now the single source of truth for the *why* behind every
decision: each ADR gets a 3–6 line plain-language paragraph in
docs/adr/README.md alongside the status table.

The 28 individual ADR files in docs/adr/ are removed; full long-form drafts
continue to live in the private clearcms/plan repo under decisions/.

ADR-0029 (spec v1 type vocabulary), 0031 (storage path resolvers + write-stamp),
and 0032 (content lint engine shape) added to the index.

STATE.md: bumped to 2026-05-08; "In flight — open PRs" replaced with Phase 7
done summary, Phase 7 cherry-picks (SLICE-0005 / 0021 / 0011) and SHAs, Phase 8
Stamp queue, and a note on the 3 open dependabot CVEs to clear before tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pick collision)

The SLICE-0011 markdown widget cherry-pick left two duplicate-key collisions
in apps/admin/src/components/schema-designer/AddFieldModal.tsx that the
companion 7b06585 fix only handled in @clearcms/spec:

- WIDGET_DESCRIPTIONS had two entries for "markdown" (last-write-wins in JS,
  silently overwriting the first description).
- The WIDGETS array listed "markdown" twice, which would render the markdown
  widget card twice in the picker grid.

Both collapsed to a single entry each. Confirmed by clean rebuild — the
"Duplicate key markdown in object literal" vite warning that landed on
release/v1.0 after the cherry-picks is gone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-r build

The "tracked dist" footgun called out in STATE.md ("apps/admin/dist/ is
force-tracked despite .gitignore listing dist/ ... cleanup is its own task")
was wider than the two directories STATE.md mentioned. Five workspace dirs
were force-tracked:

  - apps/admin/dist/
  - packages/astro/dist/
  - packages/index/dist/
  - packages/sdk/dist/
  - packages/spec/dist/

All five untracked via `git rm --cached -r`. The per-package
`packages/spec/.gitignore` that negated the root `dist/` rule
(`!dist/` + `!dist/**`, justified at the time as "consumers without a TS
toolchain can read the artifact") is removed; spec/dist now falls under the
root rule with the rest. Files stay on disk — npm publish builds fresh, so
adopters consuming via `@clearcms/*` packages are unaffected.

Fresh-clone workflow remains as STATE.md already directs:

  pnpm install
  pnpm -r build

Pre-v1.0.0 cleanup. Removes the largest source of "edits to source can land
out of sync with the tracked compiled output" footgun before the tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds pnpm.overrides to root package.json forcing patched versions of three
transitive deps flagged by dependabot on clearcms/clear:

- ip-address >=10.1.1   (was <= 10.1.0)  — GHSA-v2v4-37r5-5v8g
                                            XSS in Address6 HTML methods
- yaml >=2.8.3          (was <  2.8.3)   — GHSA-48c2-rrv3-qjmp
                                            stack overflow on deeply-nested
                                            YAML collections
- esbuild >=0.25.0      (was <= 0.24.2)  — GHSA-67mh-4wv8-2f99
                                            dev server lets any site read
                                            responses

Verified resolved versions: ip-address@10.2.0, yaml@2.8.3, esbuild@0.25.12 +
0.27.7 (multiple esbuild copies in the tree, all on the patched line).

Workspace clean after the bump:
- pnpm typecheck: 278 files, 0 errors, 0 warnings
- pnpm test: 527 tests passed across 49 test files

Pre-tag cleanup. T-8.1 acceptance check item.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ONTEXT

Surveyed 8 peer + agent-aware OSS repos (Payload / Strapi / Sanity / Directus
/ TinaCMS / KeystoneJS / Astro / Next.js). Universal at the root: README,
CONTRIBUTING, LICENSE. Near-universal: AGENTS.md (7/8), SECURITY.md (7/8).
Common: CODE_OF_CONDUCT.md (5/8), CLAUDE.md (4/8). Niche or absent:
ARCHITECTURE.md (1/8 — Sanity). Zero of eight have STATE / ROADMAP / CONTEXT
/ PLAN at the root — those are working-notes filenames, not OSS conventions.

This commit converges clear/ to that standard.

  README.md            ← rewritten. Absorbs ROADMAP "What's next" themes;
                         carries a "Current status" section pointing at
                         GitHub Releases as the canonical timeline. New
                         reading-order section reflects the trimmed surface.
  ARCHITECTURE.md      ← unchanged. Sanity precedent; useful deep-dive.
  AGENTS.md            ← rewritten. New read order (4 files instead of 7).
                         Documents the Issue-driven workflow, agent-ready
                         label convention, repo conventions for commits /
                         PRs / tests / changesets.
  CLAUDE.md            ← new, thin. Mirrors Payload / TinaCMS / Sanity / Next
                         pattern. Points at AGENTS.md as canonical; lists
                         project-specific Claude rules (caveman mode, no new
                         top-level docs, working-notes go to private plan/).
  CONTEXT.md           → moved to docs/glossary.md. Same content, standard
                         path/name. AGENTS.md and README link to the new
                         location.
  STATE.md             → deleted. Adopter-facing "what shipped when" lives
                         on the GitHub Releases page (the OSS standard).
                         Internal daily-touch state moves to plan/STATE.md
                         (private; trimmed in a companion commit there).
  ROADMAP.md           → deleted. Themes folded into README's "What's next"
                         section. Public-roadmap-as-Markdown isn't a
                         standard pattern; GitHub Projects + Issues is.
  PLAN.md (stub)       → deleted. A stub redirect to a private repo serves
                         no adopter purpose.

Net diff: 263 lines removed, 100 lines added. Public surface dropped from
~10 root Markdown files to 6 (README, ARCHITECTURE, AGENTS, CLAUDE,
CONTRIBUTING, LICENSE, SECURITY, CODE_OF_CONDUCT — the standard set).

Companion changes coming:
  - Custom GitHub labels (agent-ready, human-only, priority:p0-p2, area:*).
  - v1.x Project board with the 3-6 candidate work items pulled from the
    private MASTER_PLAN.md before it's archived.
  - plan/ repo shrink to its lean shape (decisions/ + thin STATE + archive).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…8 shape

Future sessions sometimes drift back to invented filenames (STATE.md /
ROADMAP.md / CONTEXT.md / PLAN.md / MASTER_PLAN.md / slices/) when the
working memory of why those were retired isn't surfaced. Adds a "Canonical
structure (locked 2026-05-08) — don't regress" section to CLAUDE.md that:

  - States the fixed root surface (the 8 standard OSS files).
  - Lists the retired patterns explicitly so a session reading CLAUDE.md
    sees them by name and knows not to recreate them.
  - Names where each piece of content actually lives now (Releases, Issues,
    docs/glossary.md, docs/adr/README.md, packages/*/CHANGELOG.md).
  - Tells future sessions to pause + confirm before regressing.

A companion section lands in plan/CLAUDE.md (private repo) for symmetry —
both Claude entry points carry the directive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The cleanup that landed in 6a743ee (drop STATE/ROADMAP/PLAN/CONTEXT) and
90bce43 (consolidate 28 individual ADRs into a single index) left
downstream cross-references unfixed. This commit walks every reference per
the docs-audit checklist and applies the mechanical fixes:

  Class A — ./CONTEXT.md → ./docs/glossary.md
    ARCHITECTURE.md, CONTRIBUTING.md, apps/admin/README.md

  Class B — ./STATE.md → GitHub Releases + CHANGELOGs
    docs/adr/README.md (opening blurb)

  Class C — ./ROADMAP.md → per-package CHANGELOGs
    docs/known-issues.md

  Class D — ./docs/adr/<NNNN>-<topic>.md → ./docs/adr/README.md#<anchor>
    ARCHITECTURE.md (5 refs)
    CONTRIBUTING.md (1 ref)
    docs/glossary.md (10 refs)
    docs/deployment.md (1 ref)
    docs/migration-v0.2-to-v1.0.md (1 ref)
    docs/integrations/r2.md (2 refs)
    .changeset/README.md (1 ref)
    packages/create-clear/template/README.md (1 ref)
    packages/create-clear/template/theme-examples/README.md (1 ref)
    packages/design/README.md (1 ref)

  Class E — clearcms/clear-headless → clearcms/clear (old repo name)
    apps/admin/README.md (4 refs, npm-published)
    packages/core/README.md, packages/db/README.md,
    packages/mcp/README.md, packages/storage/README.md (1 each)

  Orphan — docs/prd/0002-site-tree-phase-2.md
    Single PRD in an otherwise-empty folder; not referenced from any
    active doc. Moved to clearcms/plan repo at
    archive/2026-05-08/imported-prd/. Empty docs/prd/ folder removed.

Audit doc at docs/AUDIT-2026-05-08.md captures the full triage table and
"applied this audit" log for diff against future audits. Two CHANGELOG
historical mentions of STATE.md / ROADMAP.md were intentionally left alone
(immutable changelog history).

Deferred: currency-check pass on docs/CONTENT-PROTOCOL.md +
docs/integrations/*.md + packages/*/README.md prose. Broken references are
now fixed; verifying the prose itself is current is a follow-up before the
v1.0.0 tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v1 hosted blocker: admin needs POST /api/auth/_internal/mint-session bridge endpoint v0.6.0 — editor surface refactor (Phase 4)

1 participant