* perf(doctor): keep telegram doctor enumeration off the runtime graph Telegram's built doctor artifact reached execa through dist chunking, so a source-run host (pnpm dev, tsx CLI, vitest) could not require it and silently dropped all 9 telegram legacy config rules plus its state migration. The artifact also pulled telegram's runtime stores, making it a 674-chunk outlier that dominated doctor enumeration. Root cause: `src/token.ts` took the broad `plugin-sdk/provider-auth` barrel for `resolveDefaultSecretProviderAlias`, dragging the auth-profile store, provider runtime, and plugin install graph (execa, kysely, commander) into the closure. The alias now has a narrow `plugin-sdk/secret-provider-alias` leaf, and provider-auth re-exports it so its runtime surface is unchanged. Thread-binding, sent-message, and sticker-cache row shapes, keys, and legacy sidecar readers move to `*.legacy-state.ts` leaves. The doctor closure keeps the rows and drops the ACP, session-binding, send, logger, and plugin-runtime graphs the stores also load. The postbuild control-plane verifier only required each artifact in a plain Node child, the one host where these graphs resolve fine, so it proved nothing about the invariant that broke. It now also walks each built doctor artifact's static import closure and fails when it reaches the process-spawn graph, which is the dist-level analogue of the source closure guard. Guard rules added for provider-auth, acp-runtime, and conversation-runtime; the telegram boundary test became a real closure assertion instead of a string grep. * fix(doctor): drop dead export surface from the telegram legacy-state split Knip and oxlint caught leftovers from the split: the leaves exported helpers only they use, the store modules re-exported constants nobody imports from them anymore, and thread-bindings kept a `testing` barrel whose last production caller was the migration path that now reads the leaf directly. Tests import the constants from the leaf that owns them, and the reset helper directly. The closure gate's failure message still interpolated a `host` field left over from a probe-host approach that was reverted before commit; the existing verifier test caught it. The gate now has its own coverage: a transitive chunk edge to a forbidden dependency is reported, while dynamic imports and non-doctor contract surfaces are not. * fix(doctor): adopt the upstream telegram thread-binding store split `main` landed an equivalent thread-binding leaf as `thread-bindings-store.ts` while this branch was open, so the branch-local `thread-bindings.legacy-state.ts` is dropped rather than kept as a second path for the same rows. `state-migrations.ts` now reaches token.js through the lazy import `main` added, so `token.ts` is no longer in the doctor closure at all. The narrow `secret-provider-alias` leaf still matters: telegram's contract-api closure reaches `provider-auth` through `token.ts` on current `main`, which is the same execa/kysely/commander graph, so the barrel is repaired at its source instead of being deferred a second time. * fix(scripts): type the built doctor closure gate for the TypeScript migration The gate was authored against the `.mjs` script and landed in the `.mts` file `main` migrated to, so its parameters were implicitly `any` and `check:test-types` failed. Adds the explicit signatures plus the violation type. Regenerates the plugin-sdk API baseline: `provider-auth` re-exports the default secret-provider alias from the new leaf, so its module hash moves while its runtime export surface stays identical.
summary, read_when, title
| summary | read_when | title | |||
|---|---|---|---|---|---|
| Repository script entry points and compatibility notes |
|
Scripts Directory |
Scripts Directory
The scripts/ directory contains repository tooling used by local development,
CI, docs publishing, releases, Docker proof, and maintainer operations. Prefer
the package-script entry points in package.json when one exists, then read the
underlying script before running it directly.
Compatibility
Many scripts are stable paths referenced by package.json, GitHub Actions,
docs, and maintainer runbooks. Do not move, rename, or regroup scripts only to
improve taxonomy. A directory migration needs an explicit maintainer-approved
compatibility plan for package scripts, workflows, docs snippets, and any raw
script paths users may have copied.
This index is a discovery aid for the current flat layout. It does not define a new directory taxonomy.
Common Entry Points
| Area | Prefer | Notes |
|---|---|---|
| Build | pnpm build |
Runs scripts/build-all.mts; use specific build scripts only when debugging a build stage. |
| Changed checks | pnpm changed:lanes --json, pnpm check:changed |
Lane classification lives in scripts/changed-lanes.mjs; changed-file checks live in scripts/check-changed.mjs. |
| Docs | pnpm docs:list, pnpm docs:check-mdx, pnpm docs:check-links |
Backed by scripts/docs-list.js, scripts/check-docs-mdx.mjs, and scripts/docs-link-audit.mjs. |
| Formatting docs | pnpm format:docs:check |
Uses scripts/format-docs.mts; use write mode only when intentionally formatting docs. |
| Lint | pnpm lint, pnpm lint:core, pnpm lint:all |
Wrapper scripts keep oxlint behavior aligned with repo config. |
| Targeted tests | pnpm test <path-or-filter> or node scripts/run-vitest.mjs <path-or-filter> |
Avoid bare vitest; it can start watch mode. |
| Changed tests | pnpm test:changed |
Uses the repo's changed-test resolver instead of a broad Vitest run. |
| Docker proof | pnpm test:docker:all, pnpm test:docker:rerun, pnpm test:docker:timings |
Use the planner/rerun helpers before launching broad Docker work. |
| Live proof | pnpm test:live |
Live checks require the matching environment and credentials. |
| Release checks | pnpm release:check, pnpm release:beta, pnpm release:candidate |
Release scripts are maintainer workflows; read release docs before use. |
| GitHub reads | scripts/gh-read |
Uses a GitHub App read token when configured, leaving normal gh login for writes. |
| Commits | git add <files...> then git commit -m "<message>" |
Stage only the intended files for each commit. |
| Remote proof | node scripts/crabbox-wrapper.mjs ... |
Agent default for tests and heavy work; pre-warm by source trust, sync each run, reuse the lease. |
Script Families
check-*.mts/check-*.ts/ retainedcheck-*.mjs: guardrails for architecture, docs, package contents, boundaries, workflows, and generated artifacts.run-*.mjs/run-*.mts: stable wrappers and typed implementations for Node, Vitest, oxlint, tsgo, and environment setup.test-*.mts/ retainedtest-*.mjs/test-*.sh/test-*.ts: test planners, Docker lanes, live checks, and focused validation helpers.docs-*andcheck-docs-*: docs listing, link auditing, MDX checks, spellcheck, sync, and i18n glossary checks.release-*,openclaw-npm-*, andplugin-*-release-*: release preparation, package verification, and publishing helpers.docker-*,test-docker-*, andtest-live-*-docker.sh: Docker E2E planning, rerun, timing, and live/package lane helpers.gh-read*,label-*,sync-labels.ts, and PR helpers: GitHub read, labeling, and maintainer workflow support.generate-*,write-*,copy-*, andsync-*: generated docs, metadata, package surfaces, and build artifact support.lib/: shared helpers imported by script entry points.
Maintenance Rules
- Read
scripts/AGENTS.mdbefore changing scripts. - Keep package scripts, generators, generated-artifact checks, docs references, and workflow references aligned when touching a script path.
- Prefer existing wrappers instead of introducing a raw tool invocation.
- Add or update focused tests under
test/scripts/when changing script behavior.
See also Scripts for public-facing script guidance.