Validate configs
The Orchestrator for AI Agents — Connect OpenClaw, Hermes Agent, Claude Code, Codex, Cursor, Gemini CLI, OpenCode, Pi, and Qwen Code. Pool their knowledge, delegate tasks, and build your swarm of agents.
npx -y skills add tale-project/tale --skill validate-configsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 17 stars17 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when you touch Tale file-based org config or its guards — builtin-configs/, e2e fixture config trees, CONFIG_DOMAINS, Zod schemas under lib/shared/schemas/, app bundles under builtin-configs/apps/, or a red builtin-configs, builtin-apps, email-parity, fixture-drift, or migrations:check gate. Owns which gate proves what, validator registration, enforcement postures, and the snapshot-vs-migration ritual. Run the matching gate before shipping; never duplicate a shape a shared schema already owns. For tests use test-code; for failing behaviour use fix-bug.
SKILL.md
8.6 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
validate-configs
Per-org configuration is JSON files under $TALE_CONFIG_DIR/<org>/<domain>/, seeded from the
builtin-configs/ catalog and validated by one shared Zod schema per
domain in lib/shared/schemas/. This skill owns
running and extending those guards. Editing a skill bundle's content is
author-skill; writing tests generically is
test-code.
When this applies
- Editing or adding any file under
builtin-configs/or the fixture org treesservices/platform/tests/e2e/fixtures/config/{default,qa-guides-org}/. - Adding a domain to
CONFIG_DOMAINS(lib/shared/config/registry.ts) or editing any schema underlib/shared/schemas/. - Authoring or refreshing an app bundle under
builtin-configs/apps/<slug>/. - A red gate — the universal suite,
builtin_apps,email_bundle_parity,fixture_bundle_drift, ormigrations:check.
The gates — run what you changed
All vitest gates run from services/platform/; migrations:check from the repo root.
| You changed… | Run |
|---|---|
catalog / fixture JSON in any non-apps domain | bunx vitest --run --project server lib/shared/config/builtin_configs_validation.test.ts |
| an app bundle (manifest, views, messages, wf, agents) | bunx vitest --run --project server convex/workflow_engine/helpers/validation/builtin_apps.test.ts convex/apps/email_bundle_parity.test.ts convex/apps/fixture_bundle_drift.test.ts |
any schema under lib/shared/schemas/ | bun run --filter @tale/platform migrations:check |
The universal suite is registry-driven — it walks every CONFIG_DOMAINS domain over
builtin-configs/ plus both fixture org trees with the same schemas the platform load path
uses. Its header doc carries the walker details; read it before touching it.
The same walk also runs as bun run --filter @tale/platform configs:validate (plain Bun, no
vitest) — wired into the platform build script and a CI step in build.yml so a broken builtin
catalog fails the image build, not just the test job — and, non-fatally, post-deploy via the
validateBuiltinCatalog internal action (convex/lib/config_store/validate_builtin_catalog.ts),
which walks the deployed $TALE_CONFIG_BUILTIN_DIR and logs any issue loudly without blocking boot.
The rules
- One schema, every consumer. The loader (
convex/<domain>/file_utils.ts), the write/publish path, and the CI gate all import the domain's schema fromlib/shared/schemas/— a hand-rolled twin drifts silently and validates nothing (reviewer-caught; inside the gates it's structural — they import the shared schemas). - Every domain declares a validator. A
CONFIG_DOMAINSentry with noDOMAIN_VALIDATORSentry fails the suite with "add a validator" — new domains cannot ship an unvalidated catalog. The walkers +DOMAIN_VALIDATORSregistry live incatalog_validator.ts(also driving the build-timeconfigs:validategate and the post-deploy runtime check); the vitest suite (builtin_configs_validation.test.ts) is a thin wrapper over it. - Enforcement posture follows the path. Publish/upload throws
ConvexErrorcodes —INVALID_VIEW,VIEW_BINDING_NOT_ALLOWED,VIEW_ROLE_UNKNOWN,INVALID_MANIFESTinconvex/apps/bundle_parse.ts— so a broken file never reaches an org's disk. Discovery degrades visibly — warn+skip a bad manifest, surface a bad view as an{ id, error }repair stub, never a silent drop and never a failed list (convex/apps/file_actions.ts). Match the posture of the path you're on. - Schema change ⇒ snapshot ritual.
migrations:checkfingerprints every schema againstconvex/migrations/config.snapshot.json. Data-safe growth (new optional field, widened enum, removed field) → refresh withbun run --filter @tale/platform migrations:snapshot. Data-incompatible (new required field, retype, narrowed enum/literal, optional→required, tightened constraint) → ship the versioned migration FIRST — scaffold withbun run gen:migrationand followconvex-migrations(enforced bymigrations:check). - Fixtures track builtins byte-for-byte. A builtin app-bundle refresh re-syncs its pinned
copies in both fixture trees (enforced by
convex/apps/fixture_bundle_drift.test.ts— its header documents the one allowedissue-desk-qarename transform). The three email inbox bundles (outlook/sync-emails,gmail/sync-emails,imap-smtp/sync-emails) are one product per provider — an edit to one must hit all three (enforced byconvex/apps/email_bundle_parity.test.ts). - Unknown-file posture matches the loaders. Flat/tree domains are STRICT — only
*.json(+*.secrets.jsonsidecars); any other file would be invisible at runtime, so the gate rejects it. Bundle items (skills/,integrations/<slug>/,apps/<slug>/) carry arbitrary assets; bundle roots hold only item directories. - Landmine — shipped workflows validate schema-only on the file path. About a dozen builtin
workflows deliberately fail
validateWorkflowDefinition's stricter reference/port lints while parsing fine withworkflowJsonSchema; the lint runs only on the agent-tool create/save (publish) path. Don't "fix" the builtins to pass it and don't add the lint to the file gate. App-bundled workflows DO pass full definition validation in the builtin-apps gate.
Adding a config domain (the drift guard forces all of it)
- Schema in
lib/shared/schemas/<domain>.ts— the loader and the gate must share it. - Registry entry in
CONFIG_DOMAINS— layout, readContext, dataModel, scaffoldKind; the list order is the org-scaffold seed order, keep it stable. The registry is pure (V8-importable); filesystem resolvers live inconvex/lib/config_store/resolvers.ts— the registry header explains the layering. - Validator entry in
DOMAIN_VALIDATORS— reuse the walker matching the layout (walkFlat/walkJsonTree/walkBundles), orexternal-gatewithcoveredBypointing at a dedicated suite (theappspattern; the suite then asserts your gate files keep existing). - Catalog-scaffolded (
scaffoldKindset)? Shipbuiltin-configs/<domain>/with at least one valid file — the catalog root asserts nonzero validated files. - Run
migrations:check— a new schema module changes the fingerprint (see the snapshot ritual).
Before you call it done
Tick every box, or N/A with a reason; an unticked box means not done.
- The gate matching each change ran green (per the table above) — output observed, not assumed.
- No consumer re-declares a shape — every new parse imports from
lib/shared/schemas/. - App-bundle edits — both fixture-tree copies re-synced and all three email siblings updated (drift + parity gates green), or N/A.
- Schema edits — snapshot refreshed (data-safe) or a versioned migration shipped (data-incompatible), or N/A.
- New domain — schema + registry entry + validator + builtin catalog dir all present, or N/A.