molecule-core/docs
Hongming Wang 9375e3d4ee
feat(workspace-server): GHCR digest watcher closes runtime CD chain (#2114)
Adds an opt-in goroutine that polls GHCR every 5 minutes for digest
changes on each workspace-template-*:latest tag and invokes the same
refresh logic /admin/workspace-images/refresh exposes. With this, the
chain from "merge runtime PR" to "containers running new code" is fully
hands-off — no operator step between auto-tag → publish-runtime →
cascade → template image rebuild → host pull + recreate.

Opt-in via IMAGE_AUTO_REFRESH=true. SaaS deploys whose pipeline already
pulls every release should leave it off (would be redundant work);
self-hosters get true zero-touch.

Why a refactor of admin_workspace_images.go is in this PR:
The HTTP handler held all the refresh logic inline. To share it with
the new watcher without HTTP loopback, extracted WorkspaceImageService
with a Refresh(ctx, runtimes, recreate) (RefreshResult, error) shape.
HTTP handler is now a thin wrapper; behavior is preserved (same JSON
response, same 500-on-list-failure, same per-runtime soft-fail).

Watcher design notes:
- Last-observed digest tracked in memory (not persisted). On boot the
  first observation per runtime is seed-only — no spurious refresh
  fires on every restart.
- On Refresh error, the seen digest rolls back so the next tick retries.
  Without this rollback a transient Docker glitch would convince the
  watcher the work was done.
- Per-runtime fetch errors don't block other runtimes (one template's
  brief 500 doesn't pause the others).
- digestFetcher injection seam in tick() lets unit tests cover all
  bookkeeping branches without standing up an httptest GHCR server.

Verified live: probed GHCR's /token + manifest HEAD against
workspace-template-claude-code; got HTTP 200 + a real
Docker-Content-Digest. Same calls the watcher makes.

Co-authored-by: Hongming Wang <hongmingwangalt@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 13:36:26 -07:00
..
adapters chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
adr chore: move platform/docs/adr/ to root docs/adr/ — single docs location 2026-04-18 00:12:47 -07:00
agent-runtime fix: CWE-78 rm scope, go vet failures, delegation idempotency 2026-04-21 18:22:30 +00:00
api-protocol chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
architecture docs(security): document the KMS-rooted custody chain for SECRETS_ENCRYPTION_KEY 2026-04-26 11:29:16 -07:00
assets docs(blog + assets): MCP Server List blog post + OG image — v2 from staging 2026-04-23 22:48:15 +00:00
blog Merge pull request #1923 from Molecule-AI/docs/mcp-server-list-og-v2 2026-04-24 07:05:54 +00:00
development docs(security): document the KMS-rooted custody chain for SECRETS_ENCRYPTION_KEY 2026-04-26 11:29:16 -07:00
devrel/demos/tool-trace-platform-instructions docs(devrel): add Tool Trace + Platform Instructions demo (#1844) 2026-04-23 19:16:27 +00:00
engineering docs: testing strategy + PR hygiene + backend parity matrix + boot-event postmortem (#1824) 2026-04-23 19:59:38 +00:00
frontend initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
guides docs(guides): add 5-minute external-workspace quickstart for DevRel 2026-04-23 06:13:16 +00:00
incidents docs(security): move sensitive runbooks to private internal repo 2026-04-22 22:39:23 +00:00
infra docs(security): move sensitive runbooks to private internal repo 2026-04-22 22:39:23 +00:00
integrations docs(opencode): RFC 2119 — 'should not' → 'must not' for SAFE-T1201 warning (closes #861) 2026-04-18 12:04:49 -07:00
pages/api docs(api-ref): add workspace file copy API reference (#1281) 2026-04-21 05:37:55 +00:00
plugins chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
tutorials docs(tutorial): SaaS federation — multi-tenant control plane setup 2026-04-23 11:16:20 -07:00
.gitignore initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
api-reference.md fix(docs): update architecture + API reference paths for workspace-server rename 2026-04-18 01:25:21 -07:00
ecosystem-watch.md PMM: Phase 34 deliverables — positioning, ecosystem-watch, battlecard (#1867) 2026-04-23 20:34:34 +00:00
glossary.md docs(glossary): add GitHub Awesome Copilot disambiguation section 2026-04-17 16:27:41 +00:00
index.md docs: add Remote Agents feature + Phase 30 blog links to docs index 2026-04-21 03:51:52 +00:00
internal-content-policy.md chore: remove internal content + add hard CI gate (CEO directive 2026-04-23) 2026-04-23 16:58:28 -07:00
quickstart.md fix: CWE-78 rm scope, go vet failures, delegation idempotency 2026-04-21 18:22:30 +00:00
README.md chore: structural cleanup — dead dirs, moves, gitignore 2026-04-13 14:06:52 -07:00
workspace-runtime-package.md feat(workspace-server): GHCR digest watcher closes runtime CD chain (#2114) 2026-04-26 13:36:26 -07:00

docs/

This directory serves two purposes:

  1. Markdown content — everything under architecture/, agent-runtime/, api-protocol/, development/, frontend/, plugins/, product/, etc. This is what agents and humans read.
  2. VitePress site.vitepress/config.ts, package.json, package-lock.json. These drive the rendered documentation site.

Local preview

cd docs
npm install
npm run dev      # preview on http://localhost:5173
npm run build    # static build to docs/.vitepress/dist/

Conventions

  • New top-level docs must be linked from PLAN.md, README.md, and CLAUDE.md — otherwise agents can't find them (see .claude/ memory feedback_cross_reference_docs.md).
  • edit-history/YYYY-MM-DD.md is append-only log of significant changes; don't rewrite history.
  • archive/ holds one-shot analyses and retired docs — kept for context but not maintained.

Why site tooling lives here (not in docs-site/)

VitePress expects its config at <root>/.vitepress/config.ts where <root> is also the content directory. Splitting tooling into a sibling docs-site/ would require a non-trivial srcDir shim and break relative links in .vitepress/config.ts. Keeping both together is the pragmatic choice; this README is the tradeoff ledger.