reconcile drift
Reconcile contract drift
Section titled “Reconcile contract drift”When the 30-min state-sweep reports contract_drift=true for a
registered consumer, the consumer’s .petrova/contract.yaml has
moved ahead of (or behind) the contract_sha recorded in
registry.yaml > repos[<slug>]. The
petrova_act_reconcile_drift verb realigns the registry to match
the consumer’s source of truth, recording the realignment in a dated
ADR. The substantive contract change is the consumer’s responsibility
and is captured in their git history — the verb only records that
the control plane has acknowledged it.
This is a control-plane self-edit. The PR is opened against
petrova-codes/petrova:main with labels registry-edit +
awaiting-human-merge and does not auto-merge (MR-12).
When to use
Section titled “When to use”/console/phasesshows the slug in thecontract_drift=truechip, and- The state-sweep that generated that signal is recent (≤60 min old) — the verb refuses on stale data.
If the sweep is stale, trigger a fresh one first:
gh workflow run state-sweep.yml -R petrova-codes/petrova# or, locally:npx petrova-cli sweep-state --apply1. Confirm the drift signal
Section titled “1. Confirm the drift signal”yq '.contract_drift, .actual_contract_sha, .last_full_sweep' \ state/<slug>.yamlYou want true, a 12-char hex SHA, and a timestamp within the last
hour.
2. Dry-run the verb
Section titled “2. Dry-run the verb”echo '{"slug":"<slug>"}' | \ petrova petrova_act_reconcile_drift petrova-codesReview the dry-run output:
before_contract_sha/after_contract_shamatch whatstate/<slug>.yamlreports.diff_preview.filescontains exactly two entries:registry.yaml(modify) and a dated ADR (create).diff_preview.branchispetrova/registry-edit/petrova_act_reconcile_drift/<slug>.
3. Apply
Section titled “3. Apply”echo '{"slug":"<slug>"}' | \ petrova petrova_act_reconcile_drift petrova-codes --applyReturns the PR URL. The PR will not auto-merge — review it and
gh pr merge --merge by hand.
4. Verify post-merge
Section titled “4. Verify post-merge”After the PR merges:
git -C ~/code/workspace/petrova-codes pullgh workflow run state-sweep.yml -R petrova-codes/petrova# wait ~60s, then:yq '.contract_drift' state/<slug>.yaml # should now be `false`If contract_drift is still true, the consumer pushed another
contract change between the dry-run and the sweep. Repeat from step 1.
Failure modes
Section titled “Failure modes”| Code | Meaning | Fix |
|---|---|---|
SLUG_NOT_IN_REGISTRY | No state/<slug>.yaml — slug isn’t registered or has never been swept | Use petrova_act_register_consumer first |
STALE_SWEEP_REPORT | last_full_sweep > 60 min old | Trigger a fresh sweep, retry |
NO_DRIFT_DETECTED | contract_drift is false/null, or actual_contract_sha is null | Nothing to do; the chip is stale, refresh the dashboard |
REGISTRY_VALIDATION_FAILED | The new SHA fails registry schema (e.g. wrong length) | Inspect state/<slug>.yaml; the sweep wrote a bad value |
Why this verb exists
Section titled “Why this verb exists”Before TASKSET 5b, the drift signal had no actor. The dashboard could
surface drift but the only way to clear it was a hand-edited PR
against registry.yaml. That friction caused several stale entries
in the registry. This verb closes the loop: signal → verb → PR →
human-merge → cleared signal — all without manual YAML editing, and
with a permanent ADR trail per MR-7.
Why no auto-merge
Section titled “Why no auto-merge”The verb targets petrova-codes itself. MR-12 (control-plane
firewall) requires every change to the registry to pass human review.
The awaiting-human-merge label is the firewall — agent fleets and
automation can compose the PR, but a human always merges it.