policy-author · git:20260609.7560e07 · 2026-06-09 · sha256 b3bbcbda2711d78c
policy-author git:20260609.7560e07A
Immutable. This exact content is served forever at /api/v1/blob/b3bbcbda2711d78c.
---
name: policy-author
description: Turn a plain-English governance brief into one validated runx operational policy, or tighten an existing one, with a fail-closed lint pass before it ships.
runx:
category: ops
---
# Policy Author
Author one governed runx operational policy from intent, and prove it lints.
Adopting governed runx means writing an operational policy: which repos may be
touched, who owns which surface, which sources are trusted, what confidence is
required before action, and which outcomes need a human. Written by hand that is
a long, error-prone document. This skill turns a plain-English governance brief
into one `runx.operational_policy.v1` proposal, or tightens an existing policy,
and runs a fail-closed lint over it before it ships. It proposes; a human
approves.
## What this skill does
1. **Read the intent.** Take the governance brief (and an existing policy when
tightening) and identify the target surfaces, sources, owners, and the risk
posture.
2. **Draft the policy.** Produce a complete `runx.operational_policy.v1`: target
repos, runner binding, allowed actions, trusted sources with confidence
floors, owner routes, and outcome rules.
3. **Lint fail-closed.** Run the policy checks below. Any failing check blocks
the proposal with the exact fix, rather than shipping a permissive policy.
4. **Tighten, never loosen.** When given an existing policy, only propose
changes that narrow authority (auto-merge off, human gate on, confidence up).
Widening is a separate, explicit human decision.
## Core principles
- **Fail closed.** Unspecified means denied. A missing owner route, source rule,
or confidence floor is a lint error, not a permissive default.
- **Human gate on mutation.** Any policy that allows repository mutation must set
`require_human_merge_gate: true` and `auto_merge: false`.
- **Named owners.** Every target surface routes to a named owner; no orphan
surfaces.
- **Bounded sources.** Each trusted source declares a minimum confidence; no
source admits work below its floor.
- **Verification before close.** A source issue closes only when the outcome is
verified.
## When to use this skill
- Bootstrapping a new runx deployment that needs an operational policy.
- Tightening an existing policy after a near-miss or an audit.
- Onboarding a new target repo, source, or owner into an existing policy.
## When not to use this skill
- To widen authority (add auto-merge, drop a human gate, lower confidence). That
is an explicit human decision, not a generated proposal.
- To write skill logic or graphs. This authors the governance envelope, not the
skills it governs.
## The operational policy model
The proposal fills `runx.operational_policy.v1`:
- `target_repos`: the repositories the policy may act on.
- `runner`: the runner binding (id, kind, and required substrate, e.g. GitHub
Actions + scafld).
- `allowed_actions`: the lanes permitted (e.g. `issue-intake`, `issue-to-pr`,
`pr-review`).
- `sources`: trusted inbound sources, each with a `min_confidence` floor.
- `owner_routes`: surface-to-owner routing; every surface has a named owner.
- `outcomes`: `verification_required`, `close_source_issue`,
`require_human_merge_gate`, `auto_merge`.
## Lint diagnostics
The fail-closed lint emits these; any error blocks the proposal:
- `policy.owner.unrouted` (error): a target surface has no owner route.
- `policy.mutation.no_human_gate` (error): mutation allowed without
`require_human_merge_gate: true`.
- `policy.mutation.auto_merge_on` (error): `auto_merge` is true on a mutating
policy.
- `policy.source.no_confidence_floor` (error): a source has no `min_confidence`.
- `policy.source.floor_too_low` (warning): a confidence floor below 0.7.
- `policy.close.before_verify` (error): `close_source_issue` set without
`verification_required`.
- `policy.action.unknown` (error): an allowed action is not a known lane.
## Procedure
1. Validate that the brief names the governed work, the target repo or surface,
and the intended owner or escalation route.
2. Extract all repos, sources, actions, owners, confidence floors, and outcome
rules from the brief and any existing policy.
3. If tightening an existing policy, diff proposed changes against the current
grant. Flag any widened action, lower confidence floor, removed owner, or
removed human gate as a separate human decision.
4. Draft the smallest complete `runx.operational_policy.v1` that allows the
stated work and denies everything else.
5. Run the lint diagnostics. Any `error` finding prevents `decision: ready`.
6. Emit the policy, lint result, rationale, blockers, and success checkpoint.
## Edge cases and stop conditions
- **No owner route:** return `needs_input`; an ownerless surface is never
governed by default.
- **Mutation without a human gate:** return `reject` or `needs_input`; do not
emit a ready mutating policy without `require_human_merge_gate: true`.
- **Auto-merge requested:** block the proposal unless the user explicitly
performs a separate authority-widening decision outside this skill.
- **Unknown action lane:** return `needs_input` with the unknown action names.
- **Source without confidence floor:** return `needs_input`; implicit trust is
not a policy.
- **Conflicting owner routes:** return `needs_input` and cite the conflicting
surfaces and owners.
## Output schema (`policy_proposal`)
```yaml
decision: ready | needs_input | reject
policy:
schema: runx.operational_policy.v1
target_repos: [string]
runner:
id: string
kind: string
requires: [string]
allowed_actions: [string]
sources:
- provider: string
min_confidence: number
owner_routes:
- surface: string
owner: string
outcomes:
verification_required: boolean
close_source_issue: never | when_verified | always
require_human_merge_gate: boolean
auto_merge: boolean
lint:
status: pass | fail
findings:
- id: string
severity: error | warning
message: string
rationale: string
blockers: [string]
needs_input: [string]
success_checkpoint:
milestone: string
description: string
```
A proposal with any `error` finding must have `decision: needs_input` or
`reject`, never `ready`.
## Worked example
Brief: "Govern issue intake across our three repos. GitHub issues and Sentry
alerts. Kam owns the platform, Chong owns product. Never auto-merge; a human
approves every merge; close the source issue only once the fix is verified."
The proposal binds the three repos to a GitHub-Actions + scafld runner, allows
`issue-intake`/`issue-to-pr`/`pr-review`, trusts GitHub at 0.72 and Sentry at
0.82, routes platform to Kam and product to Chong, and sets
`require_human_merge_gate: true`, `auto_merge: false`,
`verification_required: true`, `close_source_issue: when_verified`. The lint
passes, so `decision: ready`.
## Inputs
- `governance_brief` (required): the governance intent in prose.
- `existing_policy` (optional): a current `runx.operational_policy.v1` to tighten.
- `target_repos` (optional): explicit repo list when not in the brief.
- `objective` (optional): operator intent that focuses the pass.