cyberine
UsageRun recipes

Promotion check — npm run promote:check (2026-10-02)

Operator decision 2026-10-02: no customers yet and still in the dev phase, so there is no automatic CI. .github/workflows/ci.yml and .githooks/pre-push were deleted, the homelab self-hosted runner was stopped, and nothing runs after a change, a commit or a push. What the CI ran is now a local promotion check that the operator triggers when a promotion to main is near, through the /ci-policy skill:

npm run promote:check                                  # all three jobs against HEAD
npm run promote:check -- --ref <sha>                   # another commit
npm run promote:check -- --jobs gate,docs              # skip the site job
npm run promote:check -- --sweep                       # then the full selftest sweep (clean tree at that commit)
npm run promote:check -- --cleanup                     # remove the generated workspace right after
node scripts/promote-check.mjs list                    # this host's runs, result, workspace present or cleaned
node scripts/promote-check.mjs cleanup <runId>         # remove ONLY what that run generated

It checks the commit out into .claude/worktrees/promote-<runId>/ (branch worktree/promote-<runId>), runs npm ci, then the gate job (typecheck, lint:gate, selftest:gate-list-drift, selftest:claude-md-drift, scripts/plugin-check.sh, selftest:dep-audit), the docs job (docs:catalog:check, docs:plugin-cheatsheet:check) and the site job (its own npm ci, both doc syncs, site typecheck and lint, the eslint-config-next guard, the site dependency audit, the design QA gate that builds the static export). Each job stops at its first failure inside a 10 / 15 / 20 minute budget; the environment carries CI=true, CYBERINE_TASK_TRUSTED=false, CYBERINE_CC_MEMORY=0 and a fresh temp CYBERINE_HOME. Exit 0 means every requested step passed.

Every run writes, once, to .local/promote-check/<host>/<runId>/ (runId <YYYYMMDD-HHMMSS>-<sha8>): run.json (commit, ref, main-checkout HEAD and dirty paths, node/npm/OS versions, the generated paths and sizes, each step's command, cwd, exit code, signal, timeout flag, timings and log file), NN-<job>-<step>.log with each step's full output, and summary.txt. cleanup deletes only the run's worktree, its branch (git branch -d, so only when merged) and its temp CYBERINE_HOME, after checking them against the run id and run.json; it refuses a worktree with a modified tracked file and a run still marked running, records what it did in cleanup-<stamp>.json, and never touches the logs, run.json, configs, stamps or other runs.

Known limitations and deferred work. It checks the committed tree, never uncommitted edits. It runs whatever node is on PATH (the runner used node 22; a different major is flagged in the output and in run.json, not refused). The dependency audits need the npm registry. Nothing runs it automatically, by design; a broken main surfaces at the next promotion check the operator asks for. The browser-dependent design checks (layout audit, 60fps, reduced-motion) stay UNVERIFIED, as they were on the runner.