Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions docs/superpowers/specs/2026-07-26-domain-workflow-policy-decision.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Domain workflow policy — decision record (not building it now)

Date: 2026-07-26
Status: **Decided — do not build in this form now.** Revisit only under the trigger below.

## The question

ORRO compiles a workflow from one of six fixed profiles (`code-change`, `critic-only`,
`review-only`, `verification-only`, `docs-change`, `release-readiness`). The phase order inside a
profile is a hardcoded table in `witnessd/orro_workflow.py` (`_profile_spec`), profile selection is
either explicit or recommended by regex rules in `witnessd/cli/advisory.py`, and lane contents
(`--write-scope`, `--check`, `--command`, `--adapter`) are always declared by a human and never
inferred.

The proposal was to add a layer above that: a *change class* (schema migration, dependency change,
auth surface, public API contract change, release) mapping to *required steps*, so that the workflow
reflects what the domain actually demands rather than one generic shape.

## What we found

Four parallel investigations (standards, prior art, verifiability, adversarial) reached a consistent
picture.

**No authoritative framework prescribes change-class-specific required steps.** NIST SSDF
differentiates by activity type, SLSA by artifact trust level, OWASP ASVS by application risk
profile, ITIL by urgency and repeatability. The closest thing to a real legal instance is EU AI Act
Article 12, which adds specific record-keeping obligations for one *system* category, not for change
classes. What can be cited honestly is narrow: releases (SLSA levels, OpenSSF Scorecard checks),
dependency changes (SSDF PW.4, Scorecard, and NIST publishes SSDF as an OSCAL catalog so task IDs can
be referenced rather than invented), and API contract changes (SemVer 2.0.0 for the
breaking-change-means-major rule). Nothing standard requires a "dry run against production-like data"
or a "rollback plan" as a named control, and the auth/authz class had no citable basis beyond generic
threat modelling.

**The empirical evidence argues against gating.** DORA's finding is direct: external approvals were
negatively correlated with lead time, deployment frequency, and restore time, and had *no* correlation
with change fail rate. A required-steps layer implemented as a pre-merge gate reproduces the change
advisory board, which the same research associates with lower performance. Notably, no standards body
warns against over-proceduralisation — they are structurally biased toward prescribing more process —
so the brake comes only from empirical work.

**The classification step is the historical weak point.** Policy-as-code deployments document
misclassification as a core pitfall; approval boards degrade into rubber-stamping; command denylists
are widely bypassable. If a change class is self-declared, the cheapest path under time pressure is to
declare the least demanding class, and the layer becomes voluntary in practice.

**Almost nothing in the candidate set is verifiable from sealed bytes.** Of seven candidate required
steps, exactly one supports a falsifiable verdict without appealing to an external norm: *if a
dependency manifest is in the bound touched-set, the lockfile must be too.* That one is defensible
because it is repository self-consistency, not a borrowed prescription. "A rollback exists" reduces to
"a file was written". "A dry run ran against a copy" is an argv claim, not a byte fact. "A threat
review happened" is unverifiable. "A human approved" is both unverifiable *and*, per DORA, of negative
value. The rest reduce to what declared checks already do.

## Why not now

The implementable core is a single predicate, and that predicate is already reachable today:
`orro flow --verification-only --check 'uv lock --check'` runs a declared check under observation and
seals its output. In most repositories a missing lockfile update already fails CI. The marginal value
of a new conformance axis for that one predicate does not justify its cost (a comparable axis measured
roughly 650 lines in Depone plus 800 in the witnessd producer).

The differentiating capability would be verifying that *a declared verification actually executed* —
not merely that a path exists. That was blocked by the evidence substrate: health gate exit files were
producer transcriptions rather than bundle-bound artifacts, so command-based claims had a structural
advisory ceiling. That gap is now closed (witnessd #204, shipped in 2.31.0 with Depone 0.2.11), which
means the sequencing was backwards, not the idea.

## If it is built later, this is the shape

These constraints are the durable output of the investigation and should not be re-derived.

- **Refutable claims, not required steps.** Absence of evidence is advisory; only contradiction between
sealed bytes and the declared class blocks. This keeps the layer out of the deployment gate and
therefore out of the failure mode DORA documents.
- **Repository self-consistency, not borrowed prescription.** The only justification that survives
without a citation is "this repository's own bytes contradict each other". Anything framed as
industry requirement needs a real citation or it is the overclaiming this project exists to prevent.
- **Monotone classification.** Do not accept a freely chosen class. The verifier re-derives the
policy's triggers against the bound observed touched-set; if a stricter class fired and was not
declared, that is a failure. Declaring a stricter class is always allowed. The effect is that an
AI-proposed classification can only *add* obligations, never remove them — the same falsifiable
declaration pattern used in ORRO #70.
- **No shipped default policy.** Policy provenance should admit only `detected` (derived from tooling
the repository already adopted, the way health gates are detected) and `operator-authored`. There
must be no third value representing an ORRO-supplied best-practice pack; making that unrepresentable
in the schema is what prevents the prescription problem structurally.
- **A repository can always weaken its own policy.** That is not a defect to hide. The verdict can be
honest about how weak a policy is; taking enforcement away from the repository would make this an
external approval gate, which is the thing to avoid.

## Revisit trigger

Build it when real use — including our own dogfooding — produces at least one case that a declared
check cannot catch but a class-bound claim would. Until such a case exists, the evidence says the
layer would restate what the product already does.

## References

- OVERT 1.1 conformance statement: `witnessd/docs/conformance/OVERT.md`
- Evidence substrate binding: witnessd #204, witnessd 2.31.0, Depone 0.2.11
- Falsifiable declaration precedent: ORRO #70
- Consensus-citation precedent: `docs/superpowers/specs/2026-07-22-orro-code-health-axis-design.md`
Loading