1# The test surface and the guardrails.2#3# These targets are the enforcement surface; the existing build recipes are4# untouched and still live where they always did.5678# The one entrypoint: every required gate, and nothing that can silently9# decline to judge. Go tests run through tools/testgate, which fails the run10# if any test skipped; the lanes run their own boundary rules, type checks and11# suites; depcheck holds the import matrix. What CI runs is this, spelled out12# step by step in .github/workflows/ci.yml because the Windows runner has no13# make.14test:15 go vet ./...16 go run ./tools/testgate ./...17 npm run --silent lane18 npm run --silent seam-lane19 go run ./tools/depcheck2021# The application in a real browser, over a registry packed from the committed22# corpus. Needs a Playwright Chromium (npx playwright install chromium); every23# other prerequisite is built by the target itself.24test-e2e: static25 go run ./tests/e2e/prep26 npx playwright test --config tests/e2e/playwright.config.ts2728# The maintainer's deep check, and deliberately not a CI gate: walk a real29# installed library and hold every current-format bundle to the reader's30# invariants. Compares no stamps, no hashes, no content.31corpus-smoke:32 go run ./tools/corpussmoke3334# The semantic conventions, from their one machine-readable source: the Go35# registry, the TypeScript lanes' key constants, and the document a reader36# learns the vocabulary from. `go generate ./format/semconv` is the same run.37# spec/gen's own test checks that what is committed is what this would write.38spec:39 go run ./spec/gen4041# The guardrails alone: the lane import matrix, hostenv purity, network42# confinement, semconv discipline.43depcheck:44 go run ./tools/depcheck4546# The TypeScript half of the same boundaries, over both lanes.47lint-lanes:48 npx eslint --config eslint.config.mjs analysis render4950# The analysis lane's own gate: the boundary rules, the type checker at its51# strictest, and the conformance suite over every registered system. `make52# test` runs the same thing; this target is the one lane on its own.53analysis-lane:54 npm run --silent lane5556# The seam's own gate: the same boundary rules, the type checker, the seam's57# unit tests against the corpus and its stated models, and the authored-line58# budget as a warning. `make test` runs the same thing.59render-lane:60 npm run --silent seam-lane6162# The seam's built output: one JavaScript file, from one entry point.63seam:64 npm run --silent seam-build6566# The same, rebuilt on every save. `atlas dev -seam-watch` runs this.67seam-watch:68 npm run --silent watch --workspace @atlas/render6970# The tree a host mounts at /static: the seam's bundle as `app.js`, which is71# the one file the shell's script tag asks for. The stylesheet system is NOT72# here -- it is the application's own asset, served from /assets by the73# application itself, which is what makes deleting this lane cost a page one74# script tag rather than its chrome.75#76# It is installed in two places because two hosts want it in two shapes.77# dist/static is the build output a `-static` mount is pointed at, and is what78# the e2e run serves (tests/e2e/playwright.config.ts). static/ is79# the tree the desktop shell embeds (`//go:embed static` in main.go), so that80# the shipped application is one file; see static/README.md. Same bytes, one81# build.82static: seam83 mkdir -p dist/static84 cp render/dist/app.js dist/static/app.js85 cp render/dist/app.js static/app.js8687# The smoke run: the real application, the real registry, and the seam mounted88# where the page looks for it. Read-only against the library.89serve-static: static90 go run ./cmd/atlas serve -static dist/static9192# The included Earth volume: the pinned Blue Marble base map captured, derived93# and composed into the committed bundle the desktop shell embeds94# (included/README.md is the recipe). The crawl step is the one networked part95# and fetches nothing when the pinned source is already in the staged archive;96# everything after it is offline. The registry index compose derives beside the97# bundle is deleted because included/ is an embedded asset, not a library.98included-earth:99 go run ./cmd/atlas crawl -archive crawl/blue-marble/fmg-archive -source nasa-blue-marble earth100 go run ./cmd/atlas tiles -archive crawl/blue-marble/fmg-archive -output tiles/blue-marble101 go run ./cmd/atlas compose -archive crawl/blue-marble/fmg-archive -tiles tiles/blue-marble/index.json -bundles included earth102 rm -f included/index.json103104# The desktop shell (issue #5 ยง3.4): the application in a window, one file,105# seam embedded. This is the macOS recipe -- the same `go build` .github/106# workflows/release.yml runs, plus the bundle directory macOS wants before it107# will treat a binary as an application. Linux and Windows need no bundle and108# only the `go build` line, with the tags the release workflow spells.109#110# It is `go build`, not `wails build`: the Wails CLI scaffolds and drives a111# Vite frontend, and this tree serves its own pages. There is no wails.json112# for the same reason.113desktop: static114 go build -tags "desktop,production" -ldflags "-s -w" -o Atlas .115 mkdir -p Atlas.app/Contents/MacOS116 cp Atlas Atlas.app/Contents/MacOS/Atlas117 printf '%s\n' \118 '<?xml version="1.0" encoding="UTF-8"?>' \119 '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' \120 '<plist version="1.0">' \121 '<dict>' \122 ' <key>CFBundleExecutable</key><string>Atlas</string>' \123 ' <key>CFBundleIdentifier</key><string>dev.felinestatemachine.atlas</string>' \124 ' <key>CFBundleName</key><string>Atlas</string>' \125 ' <key>CFBundlePackageType</key><string>APPL</string>' \126 ' <key>CFBundleInfoDictionaryVersion</key><string>6.0</string>' \127 ' <key>LSMinimumSystemVersion</key><string>12.0</string>' \128 ' <key>NSHighResolutionCapable</key><true/>' \129 '</dict>' \130 '</plist>' > Atlas.app/Contents/Info.plist