Changelog

Collections declare their own checks

Productv0.10.0Breaking

Collections declare the rules they refuse to publish against, in schema-as-code next to their fields. The built-in check suite drops to publish preconditions: SEO and alt-text are now policy you opt into. myna update upgrades the CLI in place.

Collection policy

A collection declares what it refuses to publish, in the same file as its fields:

import { collection, field, policy } from "@myna-sh/sdk/schema";

export const posts = collection({
  name: "posts",
  guidance: "Second person, present tense.",
  policy: [
    policy.length("title", { max: 60, reason: "Search results truncate past 70 with the site suffix." }),
    policy.length("body", { min: 300, max: 1200, words: true }),
    policy.required(["seoDescription"], { reason: "Snippets are written, not generated." }),
    policy.bannedTerms(["Contentful", "Sanity"], { fields: ["body"] }),
    policy.altText(),
  ],
  fields: { /* … */ },
});

myna schema push deploys it, and the policy check evaluates it on every change set:

$ myna changes checks chs_01...
CHECK       STATUS  STALE  ISSUES
policy      failed  no     2
schema      passed  no     0

  title — title is 78 characters (limit 60). Search results truncate past 70 with the site suffix.
  body — Image ast_01... (hero.png) has no alt text.

Each violation carries the reason you wrote, so the person reading it learns what the limit is for rather than only what it is.

policy.length counts characters, or words with words: true. Prose is measured as the text a reader sees, so a richText body is its words rather than its JSON. policy.required is distinct from required on the field itself: the field version refuses the draft, and this one refuses the publish, because a draft is allowed to be incomplete.

Rules travel with the schema — versioned, reviewed, deployed with the fields — and myna_get_collection_schema returns them next to guidance, so an agent reads them before it writes rather than discovering them in a failed check.

A rule naming a field the collection does not declare is rejected at myna schema push.

Built-in checks

Four remain: schema, references, conflicts, and slugs. Each is a precondition for a coherent publish — content that does not validate, references that do not resolve, a base that has moved, two entries claiming one slug.

seo and alt-text are gone. Alt text is now policy.altText(), declared per collection. There is no built-in SEO rule; policy.length expresses it against your field names.

The policy check reports skipped, not passed, when no collection in the change set declares anything.

myna update

$ myna update
Updating 0.9.0 → 0.10.0 with: pnpm add -g @myna-sh/[email protected]
Updated to 0.10.0. Run `myna doctor` to confirm the API agrees.

It resolves the latest release from npm and installs with the package manager detected from where the binary lives, printing the command first. --check reports without installing and exits 1, so it gates CI.

Fixes

  • myna doctor recognises a source checkout again. It compared 0.0.0-dev against the registry and reported it as "behind", because that string is a valid semantic version and the check asked whether it parsed.

Upgrading

$ myna update
$ myna doctor

If you relied on the built-in alt-text or seo checks, declare them. They no longer run, so a change set they used to block will now publish. Alt text is one line:

policy: [policy.altText()]

The old seo check compared fields named seoTitle, metaTitle, seoDescription, and metaDescription at 60 and 160 characters. If your collection used those names, policy.length("seoTitle", { max: 60 }) restores it against the fields you actually have.

Deploying a policy needs CLI 0.10.0: the CLI bundles the schema DSL, so an older one cannot compile a schema file that imports policy.

API_VERSION is 2026-07-27. Nothing was removed from a request or response shape, but two check names disappeared from the check list, which a client can observe. Detect the new surface with the change-sets.checks.policy capability. The minimum supported client is unchanged at 0.2.0.

Affects api · sdk · cli · mcp · dashboard · docs

Give your agent something to work with.

Free to start, no card required. Sign in with GitHub, enable the products you want, and point your agent at them.