/autoformalize-policies
Autoformalize a natural-language authorization requirement into a validated Dogwood (.dw) policy. Use when a user describes access rules in prose (\"only allow X if Y\", \"deny after Z\", \"no more than N per hour\") and wants a compilable Dogwood policy. Disambiguates intent
$ npx -y skills add dogwood-policy/dogwood --skill autoformalize-policies --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/autoformalize-policies
Context preview
The summary Claude sees to decide when to auto-load this skill.
Autoformalize a natural-language authorization requirement into a validated Dogwood (.dw) policy. Use when a user describes access rules in prose (\"only allow X if Y\", \"deny after Z\", \"no more than N per hour\") and wants a compilable Dogwood policy. Disambiguates intent
SKILL.md
autoformalize-policies.SKILL.mdname: autoformalize-policies
description: "Autoformalize a natural-language authorization requirement into a validated Dogwood (.dw) policy. Use when a user describes access rules in prose (\"only allow X if Y\", \"deny after Z\", \"no more than N per hour\") and wants a compilable Dogwood policy. Disambiguates intent before formalizing, and always validates the generated policy with the `dogwood` CLI before returning it. This skill CREATES a policy from prose; it is not for running the `dogwood` CLI / validator on an existing `.dw` file (validation here is an internal step, not a standalone command — for CLI usage see the guide's command-line chapter)."
Autoformalizing natural language into Dogwood policies
Your job: turn a natural-language authorization requirement into a **Dogwood `.dw` policy** that parses, validates against a schema, and means what the user actually intended. This is a *formalization* task — the hard part is not the syntax (that is fully documented; see [Ground truth](#the-ground-truth-read-before-authoring)) but **pinning down ambiguous intent** and mapping it onto the right Dogwood construct.
Do **not** guess at intent when a requirement is underspecified, and do **not** return a policy you have not validated. Follow the loop below in order:
1. **Disambiguate** the requirement (resolve every gap that changes the output). 2. **Formalize** it into a `.dw` policy. 3. **Validate** it — run it through the `dogwood` CLI and fix until it is clean. This step is **mandatory** (see [Step 3](#step-3--validate-the-policy-mandatory--never-skip)); a policy that has not been validated is not a finished answer. 4. **Round-trip** the intent and present the result.
The ground truth (read before authoring)
Dogwood's syntax and, crucially, its *legality rules* are precisely documented. Treat these as authoritative; do not invent syntax from memory. These paths are relative to this skill directory (`.claude/skills/autoformalize-policies/`); the guide lives in the `dogwood-docs` crate:
- `../../../dogwood-docs/guide/02-policy-language.md` — core
policy syntax: `permit`/`forbid`, the `(principal, action, resource)` scope, `when`/`unless`, and the complete Cedar expression language (operators, literals, methods, `has`/`like`/`is`, sets/records, entity refs). **100% of the core syntax.**
- `../../../dogwood-docs/guide/04-temporal-expressions.md` — the
`temporal { … }` sublanguage: `formerly`/`previous`/`since`, windows, `exists`/`tp`, `count`/`sum`, predicates, and the **acceptance rules** (range restriction, conjunct ordering, tp-dependence). Read this in full before writing any history-dependent policy.
- `../../../dogwood-docs/guide/02-policy-language.md` (the
"action schema" section) — the action schema and the `context.input`/`context.output` convention.
- `../../../dogwood-docs/guide/03-event-schema.md` — the
event-schema DSL and decision vs history event kinds (needed only when customizing the default).
- `../../../dogwood-docs/guide/05-information-providers.md` —
computed facts via `Provider::Name(args)` calls in an ordinary `when { … }`; see `../../../dogwood-docs/guide/10-provider-schema.md` for declaring providers (`providers.json`, the Rhai contract).
- `../../../dogwood-docs/guide/09-calling-macros.md` — calling
macros; and `../../../dogwood-docs/guide/06-macros.md` — defining `def cedar` / `def temporal` (rarely needed; reach for it only for a genuinely reusable pattern).
If a construct is not in these docs, it does not exist — do not use it.
Step 1 — Disambiguate intent (do this first)
A prose requirement almost always leaves gaps that change the formal policy. Before writing anything, **resolve every gap that affects the output**. If you can infer the answer from a supplied schema or an obvious convention, state your assumption and proceed; otherwise ask the user. Prefer asking a few sharp, batched questions over silently guessing.
Work through this checklist:
1. **Effect and default.** Is this granting access (`permit`) or restricting it (`forbid`)? Remember Dogwood is **default-deny with deny-overrides**: a `forbid` always wins. "Users may X" → a `permit`. "Never allow X" / "block X when Y" → a `forbid` that carves a hole out of the permits. If the user describes an exception to an existing allow, that is a `forbid`, not a narrower `permit`. 2. **Scope: which principal / action / resource?** Which action(s) does this govern (`action == Ns::Action::"X"`, or `action in [ … ]`, or any action)? Is the principal any user, a specific entity, a type (`principal is OAuthUser`), or a group member (`… in Group`)? Same for resource. Map the user's nouns to concrete schema entities/actions — **ask for the schema if you do not have it** (you cannot validate entity/action/field names without it). 3. **Condition data: where does each fact live?** For every fact the rule depends on, decide its source:
- An attribute of the **principal / resource entity** → `principal.<attr>` /
`resource.<attr>` (e.g. `principal.dept`), or the bare `principal` / `resource` for an identity comparison. These are the request scope entities — the *same* names, and the same meaning, in a core `when { … }` clause and inside `temporal { … }`. Do **not** write `context.principal`: as in Cedar, `context` is a separate record, so `context.principal` is a field literally named `principal` in the context record, **not** the scope entity.
- A field of *this* request's **context** → `context.input.<field>` (or
`context.output.<field>`, `context.system.now`). Confirm the field name and type against the schema.
- A *computed* fact (regex match, denylist, risk score, content safety) →
an **information provider** (`when guardrails { … }` / `Provider::Name(args)`). Any action scope works; providers are evaluated unconditionally, so their scripts mu
Read more
name: autoformalize-policies description: "Autoformalize a natural-language authorization requirement into a validated Dogwood (.dw) policy. Use when a user describes access rules in prose (\"only allow X if Y\", \"deny after Z\", \"no more than N per hour\") and wants a compilable Dogwood policy. Disambiguates intent before formalizing, and always validates the generated policy with the `dogwood` CLI before returning it. This skill CREATES a policy from prose; it is not for running the `dogwood` CLI / validator on an existing `.dw` file (validation here is an internal step, not a standalone command — for CLI usage see the guide's command-line chapter)."
Autoformalizing natural language into Dogwood policies
Your job: turn a natural-language authorization requirement into a **Dogwood `.dw` policy** that parses, validates against a schema, and means what the user actually intended. This is a *formalization* task — the hard part is not the syntax (that is fully documented; see [Ground truth](#the-ground-truth-read-before-authoring)) but **pinning down ambiguous intent** and mapping it onto the right Dogwood construct.
Do **not** guess at intent when a requirement is underspecified, and do **not** return a policy you have not validated. Follow the loop below in order:
1. **Disambiguate** the requirement (resolve every gap that changes the output). 2. **Formalize** it into a `.dw` policy. 3. **Validate** it — run it through the `dogwood` CLI and fix until it is clean. This step is **mandatory** (see [Step 3](#step-3--validate-the-policy-mandatory--never-skip)); a policy that has not been validated is not a finished answer. 4. **Round-trip** the intent and present the result.
The ground truth (read before authoring)
Dogwood's syntax and, crucially, its *legality rules* are precisely documented. Treat these as authoritative; do not invent syntax from memory. These paths are relative to this skill directory (`.claude/skills/autoformalize-policies/`); the guide lives in the `dogwood-docs` crate:
- `../../../dogwood-docs/guide/02-policy-language.md` — core
policy syntax: `permit`/`forbid`, the `(principal, action, resource)` scope, `when`/`unless`, and the complete Cedar expression language (operators, literals, methods, `has`/`like`/`is`, sets/records, entity refs). **100% of the core syntax.**
- `../../../dogwood-docs/guide/04-temporal-expressions.md` — the
`temporal { … }` sublanguage: `formerly`/`previous`/`since`, windows, `exists`/`tp`, `count`/`sum`, predicates, and the **acceptance rules** (range restriction, conjunct ordering, tp-dependence). Read this in full before writing any history-dependent policy.
- `../../../dogwood-docs/guide/02-policy-language.md` (the
"action schema" section) — the action schema and the `context.input`/`context.output` convention.
- `../../../dogwood-docs/guide/03-event-schema.md` — the
event-schema DSL and decision vs history event kinds (needed only when customizing the default).
- `../../../dogwood-docs/guide/05-information-providers.md` —
computed facts via `Provider::Name(args)` calls in an ordinary `when { … }`; see `../../../dogwood-docs/guide/10-provider-schema.md` for declaring providers (`providers.json`, the Rhai contract).
- `../../../dogwood-docs/guide/09-calling-macros.md` — calling
macros; and `../../../dogwood-docs/guide/06-macros.md` — defining `def cedar` / `def temporal` (rarely needed; reach for it only for a genuinely reusable pattern).
If a construct is not in these docs, it does not exist — do not use it.
Step 1 — Disambiguate intent (do this first)
A prose requirement almost always leaves gaps that change the formal policy. Before writing anything, **resolve every gap that affects the output**. If you can infer the answer from a supplied schema or an obvious convention, state your assumption and proceed; otherwise ask the user. Prefer asking a few sharp, batched questions over silently guessing.
Work through this checklist:
1. **Effect and default.** Is this granting access (`permit`) or restricting it (`forbid`)? Remember Dogwood is **default-deny with deny-overrides**: a `forbid` always wins. "Users may X" → a `permit`. "Never allow X" / "block X when Y" → a `forbid` that carves a hole out of the permits. If the user describes an exception to an existing allow, that is a `forbid`, not a narrower `permit`. 2. **Scope: which principal / action / resource?** Which action(s) does this govern (`action == Ns::Action::"X"`, or `action in [ … ]`, or any action)? Is the principal any user, a specific entity, a type (`principal is OAuthUser`), or a group member (`… in Group`)? Same for resource. Map the user's nouns to concrete schema entities/actions — **ask for the schema if you do not have it** (you cannot validate entity/action/field names without it). 3. **Condition data: where does each fact live?** For every fact the rule depends on, decide its source:
- An attribute of the **principal / resource entity** → `principal.<attr>` /
`resource.<attr>` (e.g. `principal.dept`), or the bare `principal` / `resource` for an identity comparison. These are the request scope entities — the *same* names, and the same meaning, in a core `when { … }` clause and inside `temporal { … }`. Do **not** write `context.principal`: as in Cedar, `context` is a separate record, so `context.principal` is a field literally named `principal` in the context record, **not** the scope entity.
- A field of *this* request's **context** → `context.input.<field>` (or
`context.output.<field>`, `context.system.now`). Confirm the field name and type against the schema.
- A *computed* fact (regex match, denylist, risk score, content safety) →
an **information provider** (`when guardrails { … }` / `Provider::Name(args)`). Any action scope works; providers are evaluated unconditionally, so their scripts mu
Dogwood is a governance language designed for AI agents and their tools. It supports Cedar policies and adds temporal conditions (since, formerly, once, aggregations) to look back over an agent's recent events.
Other skills on dogwood.
- /authoring-action-schema
Stand up the Cedar ACTION schema (.cedarschema) a Dogwood deployment governs — its entity types (principals/resources), one action per tool/operation, and each action's context.input/output/system layout — either hand-written or generated from an MCP tools/list manifest. Use
Open skill - /authoring-service-schema
Author or edit a Dogwood SERVICE schema — the event schema (.dwschema: event kinds, decision vs history points, renamed/reserved fields, nested records, correlation pins) and/or information providers (providers.json + the Rhai `evaluate` implementation behind a computed
Open skill - /dogwood
Orientation and router for authoring Dogwood authorization policies end to end. Run /dogwood when you are starting from scratch and are not sure which step you are on — it maps the lifecycle (action schema -> service schema, if needed -> policies -> validate/replay) and points
Open skill

