Petrova Skills Set
petrova intermediate 8 min read
ELI5
Eleven small toolboxes, each labelled with one job. Some toolboxes only have measuring tape (look but don’t touch). The ones that touch always go through the same chain: open a PR, never push, refuse if rules would break.
Technical Deep Dive
The eleven skills, by mode
classDiagram class ReadOnlySkills { +petrova-status +petrova-drift-check +petrova-mr-audit +petrova-boundary-check +petrova-recover «trait» never opens PRs } class WriteThroughActSkills { +petrova-act +petrova-decide +petrova-onboard +petrova-phase-cycle +petrova-plan +petrova-realign «trait» compose JSON, dry-run, --apply gated } class petrova-act { +open_decision() +update_milestone() +start_phase() +close_phase() +verify_round() +request_review() +request_merge_when_green() +propose_fix() } WriteThroughActSkills --> petrova-act : compose verb input petrova-act --> registry : reads petrova-hq/registry.yaml petrova-act --> PR : emits PR with idempotency_key ReadOnlySkills ..> registry : reads ReadOnlySkills ..> diagnoses : ~/.petrova/diagnoses.jsonlRead-only skills
| Skill | Purpose | Output |
|---|---|---|
petrova-status | Cross-repo + single-repo + MR-validation inspection. Three CLI commands: petrova status / diagnose <slug> / validate <slug>. | Stdout summary + diagnosis_id (cached at ~/.petrova/diagnoses.jsonl). |
petrova-drift-check | Three drift axes — methodology drift, projection drift (MR-12), intent drift (recent commits vs north-star). | Numbered drift report sorted by likely-accidental drift. |
petrova-mr-audit | Per-rule MR-1..MR-12 verdict with one file:line citation each. | PASS / WARN / FAIL table. Works on non-governed repos too. |
petrova-boundary-check | Audit implicit write paths to privileged surfaces (.github/workflows/, *.env, secrets/, deploy/credentials/). | Remediation table mapping current write paths → bounded verb calls. |
petrova-recover | Map a verb’s failure envelope (errors[].code) to the canonical recovery playbook. | Triage doc; only writes a finding if the human asks. |
Write-through skills (compose petrova-act under the hood)
| Skill | Verb composed | Refusal conditions |
|---|---|---|
petrova-act | All verbs (low-level wrapper). | REPO_NOT_IN_REGISTRY, FLEETS_ALLOWED, missing privileged-path guard, dry-run-only without explicit human go-ahead. |
petrova-decide | open_decision | <2 alternatives considered, backdated date, edits to closed-status decision doc. |
petrova-onboard | request_review against petrova-hq:registry.yaml | slug already registered (route to update flow), missing local clone, unset PETROVA_GITHUB_TOKEN on --apply. |
petrova-phase-cycle | verify_round → close_phase → optional start_phase | empty verification round, deferred items without target milestone (MR-2), close without sign_off.human (MR-10). |
petrova-plan | none directly (planning skill) | Refuses to start coding before plan is signed off; halts on missing north-star ground. |
petrova-realign | open_decision (realignment shape) | Refuses if docs/north-star/ absent — recommends petrova-onboard first to establish intent. |
How a write skill flows into petrova-act
flowchart LR user["operator question"] --> pick["pick skill<br/>(by description match)"] pick --> compose["skill composes typed JSON"] compose --> validate["validate against<br/>spec/verbs/<verb>.schema.json"] validate --> dry["petrova <verb> --input X<br/>(dry-run)"] dry --> review["operator reviews<br/>slug, key, branch, file changes"] review -->|go| apply["petrova <verb> --input X --apply"] apply --> pr["PR opened on target repo<br/>idempotency_key in body"] review -->|stop| edit["fix JSON, re-dry-run"] edit --> dryRefusal semantics are first-class
Every write skill enumerates explicit refusal conditions in its SKILL.md frontmatter description. These become the discipline anchor: petrova-decide refuses fewer than 2 alternatives, petrova-phase-cycle refuses empty rounds (MR-10), petrova-act refuses any privileged path (.github/workflows/, *.env, secrets/, deploy/credentials/) unconditionally — humans edit those. This pattern mirrors AGENTS.xml’s <refusal_conditions> block and is what keeps the skills layer from evolving into improvised delegation (MR-6).
The phase-cycle skill is the discipline crown jewel
petrova-phase-cycle packages verify_round → close_phase → optionally start_phase as one skill because skipping any step is the most common discipline failure. Empty rounds are forbidden (returns a ROUND-CLEAN sentinel naming what was checked); deferred friction items must carry a target milestone before close; the close PR must include sign_off.human before the verb completes. The skill is the runtime enforcement of MR-2 + MR-10.
Recovery is its own skill
When any write verb returns a non-zero envelope, petrova-recover matches errors[].code to a canonical recovery playbook: AUTH_MISSING → set credentials; REPO_NOT_IN_REGISTRY → route to petrova-onboard; FLEETS_ALLOWED → registry update PR; PROFILE_PERMITS_AUTOMERGE → switch from request_merge_when_green to request_review; DIAGNOSIS_EXISTS → run petrova diagnose (cached at ~/.petrova/diagnoses.jsonl) within the 24h freshness window before re-trying propose_fix.
Key Terms
- Skill — Anthropic-style auto-loaded capability with a frontmatter
descriptionwhose triggering language matches operator queries; the body is the workflow. - Verb — a typed action exposed by
petrova-act(e.g.open_decision,update_milestone); each verb has a schema inspec/verbs/and an MR-groundedupholds=declaration inAGENTS.xml. - Idempotency key — token in the PR body; re-running the same verb input detects the existing PR and becomes a no-op.
- Diagnosis cache —
~/.petrova/diagnoses.jsonl;propose_fixrequires a diagnosis ≤24h old.
Q&A
Q: Which skills are read-only and which can mutate repo state, and how is that boundary enforced?
A: Read-only: petrova-status, petrova-drift-check, petrova-mr-audit, petrova-boundary-check, petrova-recover (the last writes a finding only when the human asks). Mutating: petrova-act (and the wrappers petrova-decide, petrova-onboard, petrova-phase-cycle, petrova-plan, petrova-realign). Mutation always emits a PR with an idempotency key, never a direct push; the boundary is enforced both by the skill’s frontmatter description (which advertises its mode) and by petrova-act’s preconditions, including an unconditional refusal of privileged paths (.github/workflows/, *.env, secrets/, deploy/credentials/).
Q: Which skill wraps the phase-boundary trilogy (verify → close → optionally open) into a single discipline-preserving flow?
A: petrova-phase-cycle. It runs MR-10’s mandatory verification round, refuses empty rounds (emits ROUND-CLEAN with what was checked), classifies friction (MR-2), refuses deferred items without a target milestone, refuses close without sign_off.human, then optionally opens phase N+1 carrying the deferred items.
Q: When a write verb returns a non-zero envelope, which skill diagnoses the failure and which skills does it route to next?
A: petrova-recover. It maps errors[].code to a recovery: REPO_NOT_IN_REGISTRY → petrova-onboard; FLEETS_ALLOWED → composing a registry-update request_review (also via petrova-onboard/petrova-act); DIAGNOSIS_EXISTS → petrova-status diagnose; AUTH_MISSING → operator-side fix then retry. It is read-only by default, only writing a finding doc when the human explicitly asks for it.
Examples
An operator asks “can I close phase 7?”. Skill auto-load matches petrova-phase-cycle. Stage 1 enumerates friction across MILESTONES.md § Phase 7 — three items surface. Stage 2 composes verify_round JSON, applies via petrova-act (PR opens with idempotency_key=verify-round-p7-<sha>). Stage 3 classifies: one closed (typo in a runbook), one in-budget (acceptable carry, justified inline), one deferred to M8.2.1. Stage 4 composes close_phase JSON; the verb refuses with DEFERRED_HAS_TARGET because M8.2.1 doesn’t yet exist in MILESTONES.md. petrova-recover matches the code, recommends opening an update_milestone PR adding M8.2.1 first; once merged, close_phase re-runs successfully and emits the 2026-05-06-phase-7-close.md decision doc with countersign.
neighbors on the map
- Skill Export Pipeline exporting a ready prompt as an Anthropic skill
- Skill Export Shape Gates fixing an 'id contains reserved skill token' failure
- eva doctor Validation Rules diagnosing a doctor FAIL line
- AuditTrail & Selective Disclosure implementing a compliance export that must only reveal disclosed audit entries