T-0PIB-site-build-scaffold-asset
Status: closed/done · Impact: medium · Complexity: large
D-0014 wants downstream consumers to build the planning-docs site with
one command. The pieces mostly exist — the Astro scaffold already ships
inside the plugin (plugin/site-template/) and sdlc docs generate site
materializes and fills it — but the build half (install site deps, run
Astro) lives only in the dev repo’s Bun-specific build:doc-site root
script. This task ships sdlc site build: scaffold → generate → deps →
astro build, runnable in any consumer, and points the dev repo’s own
deploy path at it.
| Location | Role today |
|---|---|
plugin/site-template/ | the Astro/Starlight scaffold, shipped as a plugin asset (excluded from tsconfig; copy-not-compile) |
plugin/lib/services/docs/site.ts | docs generate site: materializeScaffold copies the template into <projectRoot>/<docsSiteDir>, then generates content; locates the template module-relative |
plugin/lib/config/load.ts#docsSiteDir | site output dir from sdlc.yaml docs_site (default site) — already project-root-relative |
sites/df-docs/ | the dev repo’s own consumer-side site instance (site.yaml, supplemental/); scaffold materialized in, content gitignored, Cloudflare-rebuilt |
package.json | build:doc-site script: bun install && bun run plugin/cli/sdlc.ts docs generate site && (cd sites/df-docs && bun install && bunx astro build) — Bun-specific, dev-repo-only shape of exactly what the verb must do |
plugin/site-template/package.json | scaffold scripts (fixed by T-T0O9 to call the installed sdlc bin) |
sdlc.yaml | quality_checks / lefthook reference docs generate site — generation only, no build |
Proposed
Section titled “Proposed”sdlc site build [--project-root …] [--out <dir>] is the one-command
consumer surface: ensures the scaffold is materialized (delegating to
the existing docs generate site path), installs site dependencies with
whichever package manager the host has (bun, else npm), runs
astro build, reports the dist path (copying it to --out when given)
with a stable stdout marker. The dev repo’s build:doc-site script
becomes a thin call to the verb, so Cloudflare and consumers exercise
the identical path. Consumers own only site.yaml and supplemental/.
Approach
Section titled “Approach”- Add op
plugin/lib/services/docs/ops/site-build.ts(path: ['site','build']; thedocsservice dir already hosts the generation machinery it composes): a. Run the existing generate-site pipeline (materialize scaffold if absent, regenerate content) against the resolved project root. b. Detect the package manager:bunif on PATH, elsenpm; run<pm> installin the site dir (skippable via--no-installfor CI that pre-installs). c. Runastro buildvia the detected runner (bunx/npx), cwd the site dir. d. EmitSITE: built <abs dist path>; with--out, copy dist there and emit that path instead. Non-zero astro exit propagates with astro’s own diagnostic. - Route the dev repo through it:
build:doc-sitebecomesbun install && bun run plugin/cli/sdlc.ts site build— one place owns the sequence; Cloudflare config needs no change beyond the script it already calls. - Wire a moon task (
root:build-siteor on thedf-docsproject) so the graph knows the site build; keep lefthook/sdlc.yaml generation gates untouched (they check drift, not builds). - Tests: op test with a fixture project (tiny
docs/planning/corpus +sdlc.yaml) asserting scaffold materialization, generation, and the marker line — stubbing the<pm> install/astro buildspawns via the runner seam; one integration smoke in the dev repo running the real thing againstsites/df-docs. - Document the consumer flow in the README distribution section
(install →
sdlc site build→ deploydist/anywhere static).
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
plugin/lib/services/docs/ops/site-build.ts | new | the site build op: generate → pm install → astro build → marker/--out |
plugin/lib/services/docs/tests/ | modify | op test with fixture project + stubbed spawns |
plugin/lib/services/docs/site.ts | modify | export the generate/materialize entry the op composes (if not already callable in-process) |
package.json | modify | build:doc-site delegates to site build |
moon.yml | modify | site-build task wiring |
README.md | modify | consumer site-build flow |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: in the dev repo,
sdlc site buildexits 0 and producessites/df-docs/dist/with the built Starlight site;bun run build:doc-sitegoes through the verb and produces the identical result. - AC-2: in a fixture consumer project (scratch dir with
docs/planning/+sdlc.yaml, plugin installed),sdlc site buildmaterializes the scaffold, builds, and prints theSITE: built <path>marker. - AC-3: with Bun absent from PATH (Node+npm only),
sdlc site buildcompletes in the fixture project. - AC-4:
--out <dir>places the built site at<dir>and the marker names it;--no-installskips dependency installation. - AC-5:
sdlc --helplists thesitenoun; existingdocs generate sitebehavior and its lefthook/quality gates are unchanged.
Out of scope
Section titled “Out of scope”- Scaffold content redesign or Starlight upgrades — the template ships as-is; this is plumbing.
- Deploy integration (Cloudflare config, CI deploy jobs) — consumers
deploy
dist/however they like; the dev repo’s Cloudflare setup already callsbuild:doc-site. - Supplemental-prose drift checking (
/dev-update-docsterritory). - Publishing the scaffold separately — it stays an asset inside the one
artifact (
T-XTGTcopies it into the staged tree).
Dependencies
Section titled “Dependencies”- none hard to build in the dev repo.
T-T0O9fixes the scaffold’s own scripts (complementary); Bun-free AC-3 requiresT-WGV4; running from an installed artifact requiresT-XTGT. Last in the wave alongsideT-521G.
Discovery context
Section titled “Discovery context”- D-0014 Migration step 8 (the D-0010 follow-up). The scaffold-as-asset
half shipped earlier than D-0014 assumed (
plugin/site-template/+materializeScaffoldalready exist); the remaining gap is the build half and its consumer/runtime-agnostic packaging.