Skip to content

One grammar for the profile language

  • Context: reserved words spread over decoders, per-key checks, hand-written JSON schemas and reference pages let one word mean different things in different places, let a key be documented and not read or read and not documented, and let a typo load silently.
  • Decision: one Go table, builtin.Grammar (internal/intent/builtin/grammar*.go), is the only source of every reserved key of an intent and a workflow manifest, a step’s arguments, actions.toml, tasks.toml, views.toml, gates.toml, keys.toml, defaults.toml, labels.toml and config.toml: its path, kind, values, default and one-line doc. builtin.Check, run by every loader, judgment blocks’ front matter included, validates kinds, enums and defaults against it; a decoder that checks a value itself takes the value set from the table (builtin.ValuesOf) and words the refusal as the table does. An unknown key or value is refused with a suggestion only when a close one exists (expr.Closest, the one similarity every surface uses), and never with a mode that sends or runs with no person approving. There are no aliases: a removed name is unknown like any other. profile schema writes the JSON schemas from it, and make docs-ref writes the reference pages, the profile language among them, one line per reserved word. Core words are neutral and name no provider; a plugin’s own words carry its slot’s prefix (pr.review, pr.reviewed) and its configuration lives under its id (github.*, slack.*). Every intent, workflow and built-in action says what it does in a required summary, and the words of the built-in actions, the verbs, the views and the core keys’ help are the profile’s actions.toml, tasks.toml, views.toml and keys.toml.
  • Consequence: a word means one thing wherever it appears (mode only in an approval table, observe for a workflow that plans only, dry_run for a draft that is never sent, runner for how a turn runs, stage for the pass over a unit); a pull request fact has one name and one spelling in every slot (pr.repo is owner/repo, pr.repo_name the bare name, pr.state GitHub’s OPEN, CLOSED or MERGED); a new key is a row with its doc, and its schema and reference follow from make docs-ref; an old configuration or manifest fails at load, naming each unknown key.
  • Enforced by: TestCheckRefusesAnUnknownKey, TestCheckRefusesAnUnknownValue, TestCheckReadsKinds, TestGrammarDefaultsAreValid, TestEveryConfigKeyIsInTheGrammar, TestTheGrammarRefusesTheOldUserConfig, TestBundledProfileLoadsClean, TestManifestKeysAreInTheGrammar, TestGrammarDocIsCurrent, TestTheDecodersCheckValuesInTheTablesWords, TestNoGuessReleasesADraftOrARun, TestClosestGuessesNothingForAnOldName, TestPRFactsAreSpelledAlikeInEverySlot. See Profile first.