| name | expectations-checklist |
| description | Operator wishlist checklist seeded at /dr-prd or /dr-plan; verified at /dr-qa and /dr-compliance with BLOCKED routing on missed/partial without override. |
| current_aal | 1 |
| target_aal | 2 |
Expectations Checklist
Why this exists. The init-task file (see init-task-persistence.md)
preserves the operator's prompt. The expectations file preserves the
operator's acceptance test — what the operator wants to verify when the
work comes back. Each item is one human-readable wish: "did this aspect of
the task come out the way I asked?" Without it, agents run their own
/dr-qa checks against PRD acceptance criteria, which are an agent's
paraphrase of operator intent and can drift silently.
Expectations are written in plain Russian (or the operator's most recent
message language), one bullet per wish, with a verifiable success
criterion and an advisory cross-link to a PRD acceptance criterion when
one exists. /dr-qa and /dr-compliance assign each item a status
(met / partial / missed / n-a / deleted); partial or missed
without an operator-supplied override blocks the pipeline and routes work
back to /dr-do with the offending wish-ids in focus.
File location and naming
datarim/tasks/{TASK-ID}-expectations.md
One file per task. Same {TASK-ID} as the corresponding
{TASK-ID}-task-description.md and {TASK-ID}-init-task.md. The three
artefacts form a sibling triad:
| File | Author | Purpose |
|---|
{ID}-init-task.md | operator (verbatim) | the original prompt |
{ID}-task-description.md | planner | the agent's interpretation + implementation notes |
{ID}-expectations.md | architect (L3+) / planner (L2 no PRD) | the operator's acceptance test |
When the file is created
| Complexity | Stage | Agent | Trigger |
|---|
| L3, L4 | /dr-prd | architect | after PRD acceptance criteria are finalised |
| L2 (no PRD) | /dr-plan | planner | after plan acceptance is finalised |
| L1 | — | — | not required (optional; soft window applies) |
Expectations are canonical first, append-merge after. The first write
creates the file from PRD/plan AC plus the operator's init-task brief. Later
edits (operator amendments, new AC, scope changes) append new items at the
bottom; existing items are not rewritten — instead a History entry records
the transition.
Artifact schema
Required YAML frontmatter (closed schema):
---
task_id: <TASK-ID>
artifact: expectations
schema_version: 2
captured_at: <YYYY-MM-DD>
captured_by: /dr-init
status: canonical
agent: planner
parent_init_task: <path>
parent_prd: <path>
---
Schema v3 (opt-in): adds optional per-wish verification_mode and
evidence_artifact fields distinguishing a one-off manual check from a
reproducible/wired check. See § verification_mode axis. Only active when the
file declares schema_version: 3; all sub-v3 files are UNCHANGED.
Schema v2 (current default): adds required evidence_type field per wish item
(enum: empirical | static | measurement). Validator
("${DATARIM_RUNTIME:-$HOME/.claude}/dev-tools/check-expectations-checklist.sh") rejects items without
evidence_type in v2 mode.
Schema v1 (legacy): accepted by validator until 2027-05-23 (12 months
from the v1→v2 migration archive). Deprecation warning emitted on every validator
invocation. Migration recipe: add evidence_type: empirical (or
static/measurement) to each wish; bump schema_version: 2.
Migration note — author new files at v2. /dr-prd (and /dr-plan for the
L2-no-PRD path) MUST create new expectations files at schema_version: 2
directly — never author a v1 file and migrate it afterwards. v1 is deprecated
(sunset 2027-05-23) and emits a per-invocation deprecation warning, so
starting at v2 avoids a needless migration and a noisy validator. Schema v3
stays opt-in per the note above; the default first-write target is v2.
Body shape
# {TASK-ID} — Ожидания оператора
## Ожидания
- **<N>. <Plain-language title ending with a period>**
- wish_id: <kebab-slug; cyrillic letters allowed>
- Что хочу проверить: <one or two sentences>
- Как проверить (success criterion): <one concrete signal — file path,
command output, visible behaviour>
- Связанный AC из PRD: V-AC-<N> или «—»
- evidence_type: <empirical | static | measurement> # v2 — required
- override: <optional reason text, only used when status flips to
partial/missed and the deferral is genuinely legitimate>
- override_by: <agent | operator> # who authored the override
- override_class: <time-dependent | external-blocker | operator-authorized | plan-scope-boundary>
- override_artifact: <follow-up ID or blocked_by reference verifiable in the KB>
- #### История статусов
- <ISO 8601> / <local time> · <stage> · <prior> → <new> · reason: <plain ru>
- #### Текущий статус
- <pending | met | partial | missed | n-a | deleted>
## Append-log (operator amendments)
_(empty on first write)_
override indent — concrete syntax
dev-tools/check-expectations-checklist.sh matches the override line with the
exact regex ^ - override: — 2 spaces, same indent level as wish_id /
Что хочу проверить / Связанный AC из PRD. A misplaced override nested at
the 4-space level (the indent used by #### Текущий статус sub-items) is
invisible to the regex: the validator finds no override and silently returns
BLOCKED for a partial/missed wish, with no diagnostic pointing at the indent.
Correct (2-space, matches the regex):
- override: soak period not yet complete, see follow-up TASK-XXXX
Incorrect (4-space, silently ignored by the validator):
- override: soak period not yet complete, see follow-up TASK-XXXX
Item rules
-
wish_id is a kebab-slug derived from the title. Cyrillic letters,
ASCII letters, digits, and hyphens are allowed. Used as the focus key in
FAIL-Routing CTA (/dr-do <ID> --focus-items <wish_id_1,...,N>).
-
Связанный AC из PRD is advisory for L1-L2. For L3-L4 current,
non-overridden wishes it is required when spec-graph hard mode is active:
the value MUST be V-AC-N, not «—». Deleted, superseded, or operator-overridden
wishes retain the advisory form. Renames in the PRD are recorded in the item's
История статусов with stage: append-merge.
-
override is plain prose, optional. When the current status is
partial or missed, an override of fewer than 10 characters is treated
as absent and the verify mode emits BLOCKED.
-
override_by records who authored the override (agent | operator).
This closes the self-certification loophole: an agent cannot wave its own
partial/missed wish through with prose alone.
operator — accepted unconditionally (the operator may authorise any
deferral; the ≥10-char floor still applies).
agent — accepted ONLY when the deferral is genuinely legitimate, proven
by override_class ∈ {time-dependent, external-blocker,
operator-authorized, plan-scope-boundary} AND an override_artifact
that names a follow-up ID or blocked_by reference which the verifier
confirms EXISTS in backlog.md / tasks.md. Prose without a verifiable
artefact → BLOCKED.
- Absent
override_by on a partial/missed item defaults to agent
(most restrictive) for back-compat — i.e. a legacy prose-only override
now BLOCKED. Add override_by: operator (or a verifiable artefact) to
clear it.
-
override_class / override_artifact — only meaningful for an
agent-authored override. A legitimate deferral is time-dependent (result
physically unverifiable now, needs ≥1 day) or hard-external-blocker; the
artefact makes that claim falsifiable rather than self-asserted.
-
Evidence-collector rule for deferred empirical wishes. When an
empirical wish is deferred (operator-deferral or any agent-authored
legitimate-deferral class) because its evidence depends on a future event
(external input arriving, a scheduled window, a real-world trigger), the
override SHOULD cite a ready-to-run evidence-collector command — the
exact invocation plus its PASS criterion — recorded in the artefact the
override_artifact points to (task description section, follow-up task
body). Rationale: a deferral without a collector rots — by the time the
trigger fires, the verification recipe must be re-derived from context that
no longer exists. With a collector, anyone (or any later session) closes
the wish mechanically at the trigger event. Verifiers treat a missing
collector on such an override as an advisory note, not a block.
-
#### История статусов is append-only by convention. One line per
status transition. Canonical line format:
<ISO> / <local> · <stage> · <prior> → <new> · reason: <plain ru>. The
three · separators and the literal reason: token are required.
-
#### Текущий статус carries the current enum value. Allowed values:
pending, met, partial, missed, n-a, deleted.
-
evidence_type (schema v2, required) declares what kind of evidence
/dr-qa must produce for this wish at Layer 3b. Allowed enum:
empirical — runtime check: command invocation, smoke test, E2E
test, integration probe. Per-wish QA report MUST contain actual
command + stdout/exit-code, not only a grep-against-markdown.
static — static check: grep, test -f, line-count, regex match
against the source tree or a documentation file. Cheapest tier; if all
wishes in a task are static, the validator emits an advisory warning
(--all mode) because the task likely lacks runtime evidence.
measurement — numeric measurement: latency p95, throughput,
coverage %, token cost, file count vs target. Per-wish QA report MUST
contain the measured value + comparison to expected (X = 87ms < budget 100ms).
-
verification_mode (schema v3, optional per-wish) closes the
"manual-check ≠ coded verification" error class (the motivating incident:
an oral requirement closed by a one-off curl spot-check, never coded →
regression later). Allowed enum:
one-off — manual or one-time check; no wired test required. This
is the implicit default when the field is absent. A one-off value on
a world-state-class wish (production URL, live HTTP status) SHOULD carry
the existing override triad (override_by, override_class,
override_artifact with a filed follow-up task) — the override creates
a falsifiable obligation that the operator consciously accepts regression
risk. No new validator enforcement for this; the obligation lives in
docs and /dr-archive recap (see § Recap obligation).
reproducible — a wired, repeatable check exists: a committed test
path, a CI job name, or a test-id string findable in the source tree.
When reproducible, the wish block MUST also contain
evidence_artifact: (see below); the validator exits 1 on the
verification-not-wired error if it is missing.
-
evidence_artifact (schema v3, required when verification_mode: reproducible) names the concrete check: a relative file path, an
absolute path, a test-id string, or a CI-job name. Resolution is
deterministic and repo-root anchored (two-tier):
test -f (absolute path, or $repo_root/$value) — file exists → OK.
grep -rqF "$value" across *.bats *.sh *.yml *.yaml under
$repo_root — string found → OK (covers test-id + CI-job-name without
needing to distinguish syntactically).
Missing or unresolvable artifact → ERROR verification-not-wired: <wish_id> (hard at /dr-compliance, advisory at /dr-qa Layer 3b).
Stub-literal guard (advisory, best-effort): when evidence_artifact
resolves to an existing file, the validator scans for stub literals
(it.skip, xit(, .todo, expect(true).toBe(true), test.skip,
@pytest.mark.skip). When every non-blank line is a stub → advisory
finding evidence-artifact-is-stub: <wish_id> to stderr; exit code
unchanged. Residual risk: the guard cannot reliably distinguish a
partially-implemented test file from a stub-only file. A file with mixed
real and stub tests passes the guard even when the relevant assertion is
the stub. Operator must verify stub coverage during /dr-qa review.
Heuristic advisory (sub-v3 and v3, NEVER hard): for schema v3
wishes where verification_mode is ABSENT and evidence_type: empirical, the validator runs a narrow deterministic case-insensitive
regex over the "Как проверить (success criterion)" text for world-state
predicates: https?://, \bHTTP\b, \bcurl\b, redirect, \bprod\b,
production, статус, status, перед тем как, /app/-style endpoint
paths, deploy. On match → advisory warning
verification-mode-suggested-reproducible: <wish_id> to stderr; exit
code unchanged. Sub-v3 files are never checked.
Status semantics
| Status | When | Verify verdict |
|---|
pending | item created, not yet verified | non-blocking (PASS) |
met | success criterion verified | non-blocking (PASS) |
partial | partially verified; missing sub-check or flaky signal | blocking unless override ≥10 chars |
missed | success criterion not met | blocking unless override ≥10 chars |
n-a | item became inapplicable (scope changed, environment drift) | non-blocking |
deleted | operator dropped the wish (history retained) | non-blocking |
Glossary note. closed is NOT an enum value here, although the word often appears in QA/PRD prose to mean "success criterion verified". The correct enum for that semantics is met. The validator ("${DATARIM_RUNTIME:-$HOME/.claude}/dev-tools/check-expectations-checklist.sh" --task <ID>) rejects closed as a structural error; pipelines fail late at /dr-compliance --verify rather than at write time. Source: TUNE-0295 Phase H L2-F-8 wrote closed, surfaced only at /dr-compliance re-validation.
Numeric literals in success criteria
Avoid hardcoded counts in success criteria when the count is derived from
the codebase (skill count, line count, test count, file count). A literal
number locks the AC to plan-time arithmetic and drifts when implementation
revises the scope — for example, when a phase absorbs an unmerged branch
and adds an extra artefact.
Prefer one of two formulations:
- Formula. «Counter X equals the number of files matching pattern Y
plus the agreed delta Z.» Verification is
find ... | wc -l plus an
inline comparison, which stays correct under scope revisions.
- Re-derive at /dr-do time. When the literal is genuinely required
(e.g. user-visible counter on a landing page), record the actual
implementation count in the expectations item's История статусов as a
one-line
stage: implementation-count entry, and treat that line as
the authoritative target. PRD-side AC remains an estimate.
Drift on a literal is recorded as «implemented with documented drift»
rather than missed; the verify verdict still PASSes because operator
intent (counter reflects new artefacts) is satisfied. Repeated occurrences
of the same drift class across tasks indicate the AC was authored as a
literal where a formula would have served.
Live-endpoint AC verification commands must follow redirects
When a success criterion's verification command asserts against a live,
reachable HTTP endpoint (a wish or PRD AC of the form "curl ... returns
X" / "curl ... | grep ..."), the command MUST be run against the real
endpoint before the wish is marked met — never presumed from the page
content alone. In addition, if the target site applies a lang-prefix or
locale-detection redirect (bare /privacy, /cookies, /terms and
similar routes that 302 to /en/... or /ru/...), the curl invocation
MUST include -L (follow redirects) — e.g. curl -fsSL, not
curl -fsS. Without -L, the bare path returns an empty 302 body and the
grep silently fails, producing a false missed verdict even though the
underlying content is correct. Author success criteria for such wishes as:
"curl -fsSL <URL> | grep '<expected text>' matches" and record the actual
executed command + exit code as the evidence, not just the expected text —
this closes the gap between "AC text says curl should return X" and "an
agent actually ran curl against a reachable endpoint and confirmed X".
Mandatory read by pipeline commands
After the file is created, every later pipeline command MUST read it and
reconcile any divergence in its own output document:
| Command | What it reads | Where divergence is recorded |
|---|
/dr-design | wish bodies | design doc § Decisions |
/dr-do | wish bodies; --focus-items ⇒ those wish-ids first | task-description § Implementation Notes |
/dr-qa | wish bodies; writes per-item Текущий статус | QA report § Expectations + History entries |
/dr-compliance | wish bodies; writes per-item Текущий статус | compliance report § Expectations + History entries |
/dr-archive | wish bodies; writes final per-item summary | archive doc § Выполнение ожиданий оператора |
Append-merge contract
When /dr-prd or /dr-plan runs a second time on a task that already has
an expectations file:
- Load existing items by
wish_id.
- For each new wish derived from updated PRD/plan AC, look up by wish_id:
- No match → append as a new item at the bottom; record one History
line
stage: append-merge with reason "added at ".
- Match → leave the item body untouched; record a History line
stage: append-merge only if the linked AC reference changed.
- Do not rewrite, reorder, or delete existing items. Operators control
pruning via explicit
Текущий статус: deleted.
Multi-phase umbrellas (phase-level verify)
When the task being verified is one phase of a multi-phase umbrella whose
expectations file lives at the umbrella task ID (no separate
{PHASE-ID}-expectations.md exists), /dr-qa and /dr-compliance invoked
on the phase ID MAY legitimately:
- Update
#### Текущий статус only for wish-ids that fall in the phase's
scope (e.g. flip from pending to met when the phase delivers the
underlying success criterion).
- Leave umbrella close-gate wish-ids and later-phase wish-ids as
pending. These are not n-a (the wish remains in scope; it is just
not yet verifiable) and not partial/missed (no failure to record at
this point in the pipeline).
- Append one
История статусов line per touched item with reason: text
that names the phase scope explicitly (e.g. "this wish belongs to phase 3
(audit coverage); it is not implemented in phase 1"). The phase mention
in the reason is what lets the umbrella close-gate auditor distinguish
«pending because phase X hasn't run» from «pending because no one looked».
The validator still PASSes when Текущий статус is pending for these
items; the audit clarity comes from the History entry, not the status enum.
On umbrella close (the last phase's /dr-archive or a follow-up umbrella
QA pass), the remaining pending items are reconciled to met /
partial / missed per the actual umbrella-wide outcome.
Verify-routing contract
/dr-qa and /dr-compliance both invoke
"${DATARIM_RUNTIME:-$HOME/.claude}/dev-tools/check-expectations-checklist.sh" --verify <ID> after running
their own structural checks. Three verdicts (single source of truth: the
validator's stdout markers):
PASS — every item is met, n-a, pending, or deleted. The
command proceeds.
CONDITIONAL_PASS — at least one partial/missed item, but every
such item carries a valid override ≥10 characters that is either
operator-authored (override_by: operator) or agent-authored with a
verifiable legitimate-deferral artefact (override_class in the allowed
enum + an override_artifact ID present in the KB). The command proceeds;
the report records the conditional state.
BLOCKED — at least one partial/missed item without a valid
override, OR with an agent-authored prose-only override that names no
verifiable artefact (the self-certification loophole). The validator prints Focus items: <wish_id_1,...,N> and
Next step: /dr-do <ID> --focus-items <wish_id_1,...,N>. The command
refuses to continue and emits a FAIL-Routing CTA (see cta-format.md).
Backwards-compatibility window
- Per-task 30-day rolling soft window. Tasks created before the
expectations contract existed (or in the first 30 days after adoption)
are protected from blocker-level findings.
- Below L3 is optional. L1 and L2 tasks may skip the file entirely;
--all advisory does not flag them.
- Archive immunity. Tasks with
status: archived | completed | cancelled are never flagged.
- Legacy marker. Operators MAY set
legacy: true in the description's
frontmatter to suppress findings indefinitely.
Recap obligation (one-off wishes in /dr-archive)
When /dr-archive writes the ## Как решили section, it MUST list every
wish closed as verification_mode: one-off (or whose verification_mode is
absent on a world-state-class wish identified by the heuristic) so the
operator consciously accepts regression risk. The listing format mirrors the
existing expectations fold contract (see § Body shape → ## Как решили
bullet with (уточнение брифа) marker):
- Append
(проверено вручную) after the wish title when
verification_mode: one-off is explicit.
- Append
(нет воспроизводимой проверки) when verification_mode is absent
on a world-state-class wish.
- No new override enforcement beyond existing
override_class; the
obligation is editorial (human-in-loop boundary).
The rationale: a one-off check closes the pipeline but creates no regression
guard. Surfacing it explicitly in the archive document lets the operator
decide whether to file a follow-up for a wired test, or accept the risk
knowing the decision is recorded.
Validation
"${DATARIM_RUNTIME:-$HOME/.claude}/dev-tools/check-expectations-checklist.sh" is the canonical validator.
--task <ID>: structural validation. Exit 0 / 1 / 2.
verification-not-wired: <wish_id> — reproducible wish whose
evidence_artifact is absent or unresolvable. Severity ladder:
advisory at /dr-qa Layer 3b (PASS_WITH_NOTES), HARD at
/dr-compliance (validator structural exit 1 enforces it).
evidence-artifact-is-stub: <wish_id> — advisory only, never hard.
verification-mode-suggested-reproducible: <wish_id> — heuristic
advisory, stderr only, never affects exit code.
--verify <ID>: verdict mode. Exit 0 (PASS / CONDITIONAL_PASS) /
1 (BLOCKED or malformed) / 2 (usage).
--all: advisory scan for L3+ tasks without expectations. Always exit 0;
severity ladder info (<30d) → warn (≥30d).
Full verdict requires both passes. --task exit 0 is necessary but
not sufficient for --verify PASS — --task checks schema validity and
status presence; --verify additionally parses verdict routing
(PASS / CONDITIONAL_PASS / BLOCKED) and enumerates focus-items on block.
For complete pre-archive verdict, run both in sequence: first
--task <ID> to confirm schema/status, then --verify <ID> to obtain the
routing verdict.
Dogfooding
The first task to use this contract is the task that defines it. Its own
expectations file lives at datarim/tasks/{TASK-ID}-expectations.md of the
framework workspace; /dr-qa and /dr-compliance invoked on that task
exercise the verify-routing path against the contract itself before the
rest of the framework adopts it.
Related skills
Automatic spec-graph addressing
The pipeline builds the requirement graph without an operator command:
wish_id → V-AC comes from Связанный AC из PRD;
V-AC → D-REQ comes from the PRD Covers: line;
V-AC → plan-step comes from an explicit Verifies: V-AC-N[, ...] marker;
V-AC → evidence comes from Evidence: V-AC-N — <command/test/artifact>.
dev-tools/spec-graph-gate.sh validates these bindings automatically at PRD,
plan, do, QA, compliance, and verify stages. Source-code comments and incidental
V-AC prose are not graph edges.
See also skills/v-ac-axis-split/SKILL.md for V-AC group composition rule
(deterministic vs statistical axis separation). When drafting success
criteria, identify whether each axis is rule-based (deterministic — single
bats assertion or grep evidence) or rate-based (statistical — threshold over
a measurement window with sample size and confidence interval). Mixing the
two in one wish item masks which axis is the actual uncertainty source and
yields false confidence at /dr-qa time. Split early; cite the measurement
window for statistical criteria; cite the assertion evidence for
deterministic criteria.