Skip to content

The execution seam and deviate (0.18.0) - #72

Merged
OriNachum merged 33 commits into
mainfrom
spec/execution-seam-and-deviate
Jul 14, 2026
Merged

The execution seam and deviate (0.18.0)#72
OriNachum merged 33 commits into
mainfrom
spec/execution-seam-and-deviate

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

devague closes the execution seam: a deliverables view answers what we have in the end at the go or no-go, the split plan renders the table humans actually approve, dependency edges can be removed without task recreation, and human-approved deviations become first-class records that connect the plan to the delivery summary

Full devague arc, end to end: /scope/think (spec, 27 claims / 17 honesty conditions) → /spec-to-plan (11 tasks, 4 waves, 34 coverage targets) → /assign-to-workforce (one agent per task, isolated worktrees, TDD-gated merges) → /deviate (dogfooded live: record d1) → /summarize-delivery (committed artifact). Spec: docs/specs/2026-07-14-execution-seam-and-deviate.md · Plan: docs/plans/2026-07-14-execution-seam-and-deviate.md · Review map: docs/deliveries/2026-07-14-execution-seam-and-deviate.md.

What ships (0.18.0)

Wave / Task Map

  • wave 1: t1 (escape hatches + flip echo) · t3 (delivery store + deviate) · t5 (4-column table) · t9 (culture.yaml) · t10 (issue closures)
  • wave 2: t2 (deliverables view) · t4 (summary verb) · t7 (/deviate skill)
  • wave 3: t6 (End state section) · t8 (summarize-delivery update)
  • wave 4: t11 (release closure 0.18.0)

Verification

  • uv run pytest -n auto577 passed; coverage 97.85 % (gate ≥ 95 %)
  • flake8 / black / isort clean per task and post-merge; markdownlint-cli2 clean on all touched docs
  • Boundary audit (Expose plan dependency waves as deterministic metadata, not orchestration #20): zero subprocess / network / LLM usages in the deliverables, deviate, and summary code paths
  • One deviation recorded, pending user decision: d1 — no PLAN_SCHEMA_VERSION bump was needed for depend --remove/amend (frame assumption c14's antecedent didn't hold). Confirm or reject with devague deviate --confirm d1 / --reject d1.

Closes #66. Closes #68. Closes #69. Closes #70.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V

  • devague (Claude)

OriNachum and others added 23 commits July 14, 2026 23:57
Frame execution-seam-and-deviate: bundles issues #70 #69 #68 #67 #66 #62,
the new deviate leg (plan-to-summary connective tissue), and the render-only
devague summary verb (wrap-up skeleton + --pr mode). 27 claims, 17 honesty
conditions, 7 scope entries with provenance, 6 resolved user decisions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
11 confirmed tasks over 4 waves (5/3/2/1), covering all 34 targets of the
execution-seam-and-deviate frame; 2 non-blocking risks. Same-wave tasks own
disjoint files; every task carries acceptance criteria + a verbatim
instruction for the workforce fan-out.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
Add the delivery-side execution-seam companion to the plan engine: a
Delivery/DeviationRecord domain model (devague/delivery.py), its
persistence peer (devague/delivery_store.py, mirroring plan_store
including the 0.17.0 upgrade-on-write schema-version fix), and the
`devague deviate` CLI move (record / --confirm / --reject / --list).
The plan JSON is never touched by any deviate operation (test-asserted
byte-identical before/after).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
…le (#69) [esd t5]

A human reviewing a 13-task fan-out rewrote the split-plan table by hand as
Wave, Task, Model, Task summary, and that rewrite is what got approved. Reshape
the per-task table to exactly that 4-column shape (Model defaults to `sonnet`,
presentation-only per issue #20; summaries truncate past 72 chars with an
ellipsis, never a placeholder). Move the has-instruction/acceptance-count
markers off the table and onto the wave-listing lines, and add a one-line note
telling the operator to edit the Model cell to a real model token (haiku,
sonnet, opus, fable), optionally qualified with the harness (colleague, codex)
when it matters. Go/no-go prompt and fan-out steps are unchanged.

tests/test_assign_to_workforce_script.py drives a fixture plan through the real
devague CLI, then runs the script end to end via subprocess (through a PATH
shim pinned to this worktree, so the test exercises this branch's code rather
than whatever devague happens to be installed globally) and asserts the exact
table shape, wave-then-task ordering, real summaries, ellipsis truncation, the
sonnet default, the wave-listing markers, and the go/no-go text.
Adds two escape hatches to the plan engine so a wrong dependency edge or a
stale task summary/acceptance criterion no longer costs a task-recreation
cascade (issue #68): `Plan.remove_dep` backs `plan depend <tN> --on <tM>
--remove`, and a new `Plan.amend_task` transition backs `plan amend <tN>
[--summary] [--accept-replace <n> <text>] [--accept-remove <n>]` (1-indexed,
validated atomically before any mutation so a bad index never leaves a
partial edit). amend refuses outright on a rejected task rather than
silently letting its declared work keep changing.

Every demoting move on a confirmed task (instruct, amend, depend --remove)
now names the confirmed -> proposed flip on the stdout result line itself,
not just stderr and --json — hardening for harnesses that only read stdout
(issue #67).

No PLAN_SCHEMA_VERSION bump: neither move adds a persisted field, so the
spec's speculative v2->v3 assumption for this slice doesn't apply.
Answers "what do we have in the end?" at the assign-to-workforce
go/no-go: devague plan deliverables [--json] synthesizes, from live
frame/plan state only, the frame's confirmed announcement/after_state/
success_signal claims verbatim, the plan's terminal tasks (new
plan.terminal_tasks helper: active tasks no other active task depends
on) with their acceptance criteria, and surviving open items (the
frame's non-blocking parked vagueness plus the plan's non-blocking
risks). Never mutates .devague/ and never gates on convergence -- an
unconverged plan (or a plan whose source frame has regressed below its
own convergence) still renders, with an explicit not-converged banner
and converged: false in --json (issue #20).
Adds a read-only `devague summary [--pr] [--json] [--plan]` verb that
renders the eight-section delivery-summary skeleton from plan/frame/
delivery state alone: Intent and Planned Work pre-fill verbatim from the
frame and plan, Actual Delivery lists every task with explicit `<fill:
...>` placeholders, and Mid-work Decisions / Drift From Plan quote
approved deviation records by id (a proposed deviation is never rendered
as approved). Run status stays a `<complete | partial | failed>`
placeholder — no section ever claims work as done. `--pr` emits a
condensed PR-body skeleton (title, announcement, wave/task map, approved
deviations, docs/deliveries pointer). No writes anywhere; degrades
gracefully when the source frame is missing.
… skeleton [esd t8]

Method step 1 now starts from the devague summary skeleton (falling back to
hand-assembly via plan show / plan waves --json when the verb or store is
absent, saying so in the baseline: line); Drift From Plan and Mid-work
Decisions quote approved devague deviate records by dN id when a delivery
store exists; the read-only moves table gains devague summary and devague
deviate --list; the intro now names the six-leg flow with /deviate slotting
between /assign-to-workforce and this skill.
Version bump (0.17.2 -> 0.18.0, minor) closing out the execution-seam-and-deviate
plan (#53 esd t1-t11): the deliverables end-state view, the four-column
assign-to-workforce split plan plus End state section, depend --remove plus
amend plus stdout flip echo, the new deviate move/skill/delivery store, the
summary verb plus --pr mode, the culture.yaml backend revert, and the two
evidence-based issue closures. CLAUDE.md, README.md, and docs/skills.md now
name the six-leg flow (scope, think, spec-to-plan, assign-to-workforce,
deviate, summarize-delivery) and the two audiences it serves — operators
driving the CLI and the humans who own the go/no-go and final-PR gates — and a
couple of pre-existing stale spots (the "nothing consumes waves" gap note, the
plan move list missing instruct/amend/deliverables) are corrected along the
way. uv.lock re-locked to record 0.18.0 consistently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
…store

Dogfoods the release itself: baseline rendered by the new devague summary,
deviation d1 recorded via devague deviate (proposed, awaiting user
confirm), t9 honestly partial until the live agex verification at PR-open.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
@OriNachum

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

qodo-code-review Bot commented Jul 14, 2026

Copy link
Copy Markdown

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

Qodo Logo

Backend claude accepted end to end; unrelated agex warning-handling bug
found and filed upstream (devex#92), stash workaround recorded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Close execution seam: deliverables, deviate ledger, summary skeleton (0.18.0)

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add read-only deliverables and summary views to show end-state and wrap-up skeletons.
• Introduce an append-only deviation ledger to record human-approved mid-run plan drift.
• Harden plan escape hatches and update split-plan output to match human review.
Diagram

graph TD
  H(["Human gate owner"]) --> ATS["assign-to-workforce split-plan"] --> CLI["devague CLI"] --> R["Renderers"] --> H
  CLI --> Plans[("Plan store")] --> CLI
  CLI --> Frames[("Frame store")] --> CLI
  CLI --> Delivery[("Delivery store")] --> CLI
  subgraph Legend
    direction LR
    _human(["Actor"]) ~~~ _svc["CLI/Script"] ~~~ _db[("Store")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Store deviations inside plan JSON
  • ➕ Single persistence surface; fewer stores to reason about
  • ➕ Deviations travel with the plan artifact
  • ➖ Weakens the ‘plan is the confirmed contract’ boundary by mutating plan state
  • ➖ Forces plan schema bumps/backward-compat work for runtime ledger behavior
  • ➖ Higher coupling risk between planning and execution-time concerns
2. Record deviations only as docs (e.g., docs/deliveries markdown)
  • ➕ No new schema/store; fully document-driven
  • ➕ Avoids schema incompatibility failure modes entirely
  • ➖ Harder to enforce approval state transitions mechanically
  • ➖ Tooling can’t reliably separate approved vs proposed drift
  • ➖ Less machine-readable for summary prefill and downstream automation

Recommendation: Prefer the PR’s dedicated delivery store. It preserves plan immutability, supports explicit approval semantics (proposed vs approved), and lets summary/summarize-delivery quote recorded ground truth deterministically without forcing plan/frame schema changes.

Files changed (32) +5090 / -138

Enhancement (10) +1283 / -42
assign-to-workforce.shReshape split-plan output and append end-state deliverables +79/-29

Reshape split-plan output and append end-state deliverables

• Replaces the prior per-task table with a single four-column table (Wave/Task/Model/Task summary) including a default model token and 72-char truncation. Adds per-wave instruction/acceptance markers and appends an End state section by invoking 'devague plan deliverables' (non-fatal fallback when missing).

.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh

__init__.pyRegister new 'deviate' and 'summary' commands +4/-0

Register new 'deviate' and 'summary' commands

• Wires new CLI command modules into parser construction so 'devague deviate' and 'devague summary' are available.

devague/cli/init.py

deviate.pyImplement 'devague deviate' CLI move +148/-0

Implement 'devague deviate' CLI move

• Adds a deterministic CLI move for recording, listing, confirming, and rejecting deviation records stored per plan slug. Enforces required '--task' and '--reason', origin-based initial status, and supports '--json' output.

devague/cli/_commands/deviate.py

plan.pyAdd deliverables preview and escape-hatch moves (amend, depend --remove) +253/-13

Add deliverables preview and escape-hatch moves (amend, depend --remove)

• Introduces 'plan deliverables' (markdown/JSON) that renders even when not converged, with an explicit banner. Adds 'plan amend' and 'depend --remove', plus shared demotion helpers to ensure confirmed→proposed flips are visible on stdout (and preserved in JSON).

devague/cli/_commands/plan.py

summary.pyAdd 'devague summary [--pr] [--json]' render-only view +63/-0

Add 'devague summary [--pr] [--json]' render-only view

• Implements a render-only skeleton for delivery summaries derived from plan + best-effort frame load + delivery store. Supports a condensed PR-body mode ('--pr') and structured JSON output.

devague/cli/_commands/summary.py

delivery.pyIntroduce Delivery/DeviationRecord domain model +135/-0

Introduce Delivery/DeviationRecord domain model

• Adds schema-versioned domain model for delivery deviations, including id allocation, status/origin rules, optional classification, and (de)serialization helpers.

devague/delivery.py

delivery_store.pyAdd '.devague/deliveries' persistence with schema gating +83/-0

Add '.devague/deliveries' persistence with schema gating

• Implements JSON persistence for delivery ledgers keyed by plan slug, including upgrade-on-write version stamping and fail-closed load when encountering newer schema versions.

devague/delivery_store.py

plan.pyAdd remove_dep, amend_task, and terminal_tasks helpers +78/-0

Add remove_dep, amend_task, and terminal_tasks helpers

• Adds dependency-edge removal and in-place task amendment (summary + acceptance criteria by index). Introduces 'terminal_tasks' used by deliverables to summarize plan leaves among active tasks.

devague/plan.py

deliverables_md.pyRender end-state deliverables markdown +106/-0

Render end-state deliverables markdown

• Adds markdown renderer for deliverables: confirmed announcement/after-state/success-signal claims, terminal tasks with acceptance criteria, and surviving open items, with a not-converged banner option.

devague/render/deliverables_md.py

summary_md.pyRender delivery-summary skeleton and PR-body skeleton +334/-0

Render delivery-summary skeleton and PR-body skeleton

• Adds deterministic markdown/JSON renderers for an eight-section delivery summary skeleton with strict placeholders. Quotes approved deviations by id, keeps proposed deviations explicitly pending, and provides a condensed '--pr' skeleton.

devague/render/summary_md.py

Tests (5) +1994 / -0
test_assign_to_workforce_script.pyAdd end-to-end test for split-plan table contract +302/-0

Add end-to-end test for split-plan table contract

• Runs the real bash split-plan script against a fixture plan and asserts the four-column table shape, truncation behavior, defaults, and required prompts/markers.

tests/test_assign_to_workforce_script.py

test_deviate.pyAdd tests for delivery store + deviate CLI +503/-0

Add tests for delivery store + deviate CLI

• Covers domain model semantics, persistence (schema gating + upgrade-on-write), CLI behavior (record/list/confirm/reject), and asserts the plan JSON remains unchanged by deviate operations.

tests/test_deviate.py

test_plan_deliverables.pyAdd tests for terminal tasks and deliverables view +357/-0

Add tests for terminal tasks and deliverables view

• Tests terminal task selection, deliverables markdown/JSON content, never-refuse banner behavior, and verifies the deliverables path is read-only via byte-identical state checks.

tests/test_plan_deliverables.py

test_plan_escape_hatches.pyAdd tests for amend/depend--remove and stdout flip echo +390/-0

Add tests for amend/depend--remove and stdout flip echo

• Validates dependency-edge removal and in-place task amendment, including refusal/validation cases. Ensures demoting changes echo confirmed→proposed flips on stdout (not only stderr) and include flip info in JSON.

tests/test_plan_escape_hatches.py

test_summary.pyAdd tests for summary skeleton, determinism, and PR mode +442/-0

Add tests for summary skeleton, determinism, and PR mode

• Verifies eight-section order, placeholder invariants, approved-vs-proposed deviation handling, determinism/read-only behavior, and '--pr' condensed output (including markdownlint expectations).

tests/test_summary.py

Documentation (11) +880 / -93
SKILL.mdDocument split-plan End state section +19/-3

Document split-plan End state section

• Updates the operator skill doc to require appending an End state section sourced from 'devague plan deliverables'. Specifies graceful degradation to a one-line hint on older devague versions.

.claude/skills/assign-to-workforce/SKILL.md

SKILL.mdAdd new /deviate execution-time skill +176/-0

Add new /deviate execution-time skill

• Introduces a sixth origin skill that stops an in-flight run, obtains explicit human approval, records the deviation via 'devague deviate', updates affected briefs, and resumes. Defines hard rules around user approval and LLM-origin proposals.

.claude/skills/deviate/SKILL.md

SKILL.mdMake summarize-delivery start from devague summary and quote deviations +113/-52

Make summarize-delivery start from devague summary and quote deviations

• Updates the method to start from 'devague summary' skeleton output (with a defined fallback ladder). Requires quoting approved 'dN' deviation records as ground truth for Mid-work Decisions and Drift From Plan.

.claude/skills/summarize-delivery/SKILL.md

CHANGELOG.mdAdd 0.18.0 release notes +78/-0

Add 0.18.0 release notes

• Documents new CLI surfaces (deliverables, deviate, summary), plan escape hatches, split-plan output changes, and the six-leg flow. Records compatibility and behavioral guarantees like never-refuse previews and fail-closed schema loads.

CHANGELOG.md

CLAUDE.mdUpdate operator workflow and gates for six-leg flow +80/-18

Update operator workflow and gates for six-leg flow

• Expands workflow documentation to include the new execution-time deviation leg and the new read-only deliverables/summary verbs. Clarifies gate semantics (deviation is an amendment to gate 2, not a new standing gate) and what consumes waves metadata.

CLAUDE.md

README.mdDescribe the six-leg operator flow and audiences +14/-5

Describe the six-leg operator flow and audiences

• Updates the high-level readme to include '/deviate' and to clarify operator vs human gate-owner responsibilities across the flow.

README.md

2026-07-14-execution-seam-and-deviate.mdAdd committed delivery summary artifact for the release run +138/-0

Add committed delivery summary artifact for the release run

• Adds the delivery summary artifact produced from the new skeleton workflow, including task-by-task accounting and a pending deviation callout.

docs/deliveries/2026-07-14-execution-seam-and-deviate.md

2026-07-14-execution-seam-and-deviate.mdAdd exported build plan document +117/-0

Add exported build plan document

• Adds the human-readable build plan artifact defining tasks, dependencies, and acceptance criteria for the release.

docs/plans/2026-07-14-execution-seam-and-deviate.md

skill-sources.mdRegister 'deviate' as an origin skill +13/-11

Register 'deviate' as an origin skill

• Updates origin-skill documentation to include the new 'deviate' skill and associated sourcing/re-vendoring guidance.

docs/skill-sources.md

skills.mdDocument six-leg flow and new deviate leg +39/-4

Document six-leg flow and new deviate leg

• Updates operator skills documentation to include the 'deviate' leg, deliverables consumption in assign-to-workforce, and summary/deviation consumption in summarize-delivery.

docs/skills.md

2026-07-14-execution-seam-and-deviate.mdAdd execution-seam-and-deviate spec document +93/-0

Add execution-seam-and-deviate spec document

• Adds the spec describing requirements, honesty conditions, and success signals for deliverables, deviations, summary skeleton, and split-plan presentation changes.

docs/specs/2026-07-14-execution-seam-and-deviate.md

Other (6) +933 / -3
current_planUpdate current plan pointer to this release plan slug +1/-1

Update current plan pointer to this release plan slug

• Switches the current plan pointer to 'execution-seam-and-deviate' for dogfooding the release artifacts.

.devague/current_plan

execution-seam-and-deviate.jsonAdd delivery ledger with proposed deviation d1 +20/-0

Add delivery ledger with proposed deviation d1

• Adds a schema v1 delivery-store record for the plan slug, including a proposed LLM-origin deviation entry used to validate the execution-time deviation path.

.devague/deliveries/execution-seam-and-deviate.json

execution-seam-and-deviate.jsonAdd generated frame JSON for the spec +491/-0

Add generated frame JSON for the spec

• Adds the captured frame state for the execution-seam-and-deviate spec, including claims and honesty conditions used by the workflow.

.devague/frames/execution-seam-and-deviate.json

execution-seam-and-deviate.jsonAdd generated plan JSON for the build plan +419/-0

Add generated plan JSON for the build plan

• Adds the exported plan state (tasks, deps, acceptance criteria, risks) used by workforce assignment and render-only views.

.devague/plans/execution-seam-and-deviate.json

culture.yamlSwitch backend token to claude +1/-1

Switch backend token to claude

• Changes 'backend: claude-code' to 'backend: claude' to match the mesh standard and unblock tooling expectations.

culture.yaml

pyproject.tomlBump version to 0.18.0 +1/-1

Bump version to 0.18.0

• Updates the project version from 0.17.2 to 0.18.0.

pyproject.toml

@qodo-code-review

qodo-code-review Bot commented Jul 14, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 66 rules
✅ Skills: cicd, communicate

Grey Divider


Action required

1. Delivery model undocumented in spec ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
This PR adds a new persisted Delivery/DeviationRecord model and new CLI surface (devague deviate,
devague summary, devague plan deliverables), but docs/spec-contract.md is not updated to
document the new entity and related contracts. This violates the requirement that the canonical spec
file remains the single source of truth for entity model and move I/O contracts, creating drift risk
for downstream tooling and audits.
Code

devague/delivery.py[R22-106]

+from devague.frame import ORIGINS, parse_schema_version
+
+# Bump when the persisted delivery shape changes incompatibly.
+# `delivery_store.load` fails closed on a delivery whose schema_version is
+# newer/unknown — the delivery-engine peer of frame.SCHEMA_VERSION /
+# plan.PLAN_SCHEMA_VERSION (see #5 / #18 for the frame/plan precedent).
+DELIVERY_SCHEMA_VERSION = 1
+
+DEVIATION_STATUSES = ("proposed", "approved", "rejected")
+# Feeds the drift-entry contract consumed by the summarize-delivery skill.
+CLASSIFICATIONS = ("acceptable", "risky", "needs-follow-up")
+
+
+@dataclass
+class DeviationRecord:
+    id: str
+    what: str
+    task_ref: str
+    reason: str
+    affects: list[str] = field(default_factory=list)
+    origin: str = "user"  # user | llm
+    status: str = "approved"  # proposed | approved | rejected
+    classification: Optional[str] = None  # one of CLASSIFICATIONS, or None
+
+    def __post_init__(self) -> None:
+        if self.origin not in ORIGINS:
+            raise ValueError(f"unknown deviation origin: {self.origin!r}")
+        if self.status not in DEVIATION_STATUSES:
+            raise ValueError(f"unknown deviation status: {self.status!r}")
+        if self.classification is not None and self.classification not in CLASSIFICATIONS:
+            raise ValueError(f"unknown deviation classification: {self.classification!r}")
+
+
+@dataclass
+class Delivery:
+    plan_slug: str
+    schema_version: int = DELIVERY_SCHEMA_VERSION
+    created: str = ""
+    updated: str = ""
+    deviations: list[DeviationRecord] = field(default_factory=list)
+
+    @staticmethod
+    def _next(items: list, prefix: str) -> str:
+        n = 0
+        for it in items:
+            if it.id.startswith(prefix):
+                try:
+                    n = max(n, int(it.id[len(prefix) :]))
+                except ValueError:
+                    pass
+        return f"{prefix}{n + 1}"
+
+    def add_deviation(
+        self,
+        what: str,
+        task_ref: str,
+        reason: str,
+        affects: Optional[list[str]] = None,
+        origin: str = "user",
+        classification: Optional[str] = None,
+    ) -> DeviationRecord:
+        if not reason:
+            raise ValueError("a deviation requires a --reason")
+        status = "proposed" if origin == "llm" else "approved"
+        rec = DeviationRecord(
+            id=self._next(self.deviations, "d"),
+            what=what,
+            task_ref=task_ref,
+            reason=reason,
+            affects=list(affects) if affects else [],
+            origin=origin,
+            status=status,
+            classification=classification,
+        )
+        self.deviations.append(rec)
+        return rec
+
+    def find_deviation(self, did: str) -> Optional[DeviationRecord]:
+        return next((d for d in self.deviations if d.id == did), None)
+
+    def set_status(self, did: str, status: str) -> bool:
+        rec = self.find_deviation(did)
+        if rec is not None:
+            rec.status = status
+            return True
Relevance

⭐⭐ Medium

Spec-contract updates happen (PR #25), but large spec-contract doc-expansion suggestions were
rejected before (PR #16).

PR-#25
PR-#16

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
devague/delivery.py introduces a new persisted entity model with DELIVERY_SCHEMA_VERSION,
DeviationRecord, and Delivery. The canonical contract file docs/spec-contract.md contains no
mention of Delivery or the new deviate move/contract, so the required documentation is missing
for the newly added model and behaviors.

Rule 739224: Document entity model and contracts in single canonical spec file
devague/delivery.py[22-106]
docs/spec-contract.md[18-115]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`docs/spec-contract.md` is required to be the single canonical spec for the entity model and CLI/move contracts, but it does not document the newly introduced Delivery domain model (deviation records, schema versioning) or the new related CLI surfaces.

## Issue Context
This PR introduces a new persisted store under `.devague/deliveries/<plan-slug>.json` with its own `schema_version` gate and a new domain model in `devague/delivery.py`, plus CLI commands that expose this state.

## Fix Focus Areas
- docs/spec-contract.md[18-220]
- devague/delivery.py[22-106]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Delivery load errors misclassified ✓ Resolved 🐞 Bug ☼ Reliability
Description
delivery_store.load() can raise schema-incompatibility and malformed-file errors, but `devague
summary/devague deviate call load_or_new() without translating these into DevagueError`. The
CLI dispatcher will therefore emit a generic “unexpected” error, hiding the real remediation
(upgrade devague or repair the delivery file).
Code

devague/cli/_commands/summary.py[R35-39]

+def cmd_summary(args: argparse.Namespace) -> int:
+    plan: Plan = resolve_plan(args.plan)
+    frame = _load_source_frame(plan.frame_slug)
+    delivery = delivery_store.load_or_new(plan.slug)
+    json_mode = getattr(args, "json", False)
Relevance

⭐⭐⭐ High

Team previously added explicit schema incompatibility errors and clearer CLI surfacing for plan
loads (PR #25).

PR-#25

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
delivery_store.load explicitly raises IncompatibleDeliverySchemaError, and load_or_new only
handles missing files; summary loads via load_or_new without exception translation, and the CLI
dispatcher converts non-DevagueError exceptions into generic “unexpected” errors.

devague/delivery_store.py[51-69]
devague/delivery_store.py[73-83]
devague/cli/_commands/summary.py[35-39]
devague/cli/init.py[100-120]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Delivery-store failures (newer schema, malformed/tampered JSON) surface as generic "unexpected" CLI errors because `summary`/`deviate` do not catch and translate delivery_store exceptions into `DevagueError`.

## Issue Context
The CLI dispatcher wraps any non-`DevagueError` as `unexpected: ...` with a "file a bug" remediation, which is not the right action for schema mismatch or corrupt state.

## Fix Focus Areas
- devague/cli/_commands/summary.py[35-52]
- devague/cli/_commands/deviate.py[58-90]
- devague/delivery_store.py[51-70]
- devague/cli/__init__.py[100-120]

## Implementation notes
- Add a small CLI-layer resolver (e.g. `resolve_delivery(plan_slug)`), analogous to `resolve_plan`, that catches:
 - `IncompatibleDeliverySchemaError` → `DevagueError(EXIT_USER_ERROR, ..., remediation="upgrade devague...")`
 - `ValueError` / JSON decode issues / slug mismatch → `DevagueError(EXIT_USER_ERROR, ..., remediation="repair .devague/deliveries/<slug>.json")`
- Use this resolver in both `summary` and `deviate`.
- Add tests ensuring these error paths produce clean, actionable messages rather than "unexpected".

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Invalid status mutation ✓ Resolved 🐞 Bug ☼ Reliability
Description
Delivery.set_status() assigns any string to DeviationRecord.status without validating against
DEVIATION_STATUSES, bypassing the invariant enforced only during DeviationRecord construction.
If an invalid status is saved, a later load will fail (via from_dictDeviationRecord.__post_init__), effectively bricking that delivery ledger until repaired.
Code

devague/delivery.py[R102-107]

+    def set_status(self, did: str, status: str) -> bool:
+        rec = self.find_deviation(did)
+        if rec is not None:
+            rec.status = status
+            return True
+        return False
Relevance

⭐⭐⭐ High

Repo enforces enum invariants via __post_init__ validations and fail-closed loads; likely to
validate setter mutations too (PR #25).

PR-#25

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The record validates status at construction time, but set_status mutates the field directly,
allowing invalid values to be saved and later rejected during reload when the constructor validation
runs again.

devague/delivery.py[35-52]
devague/delivery.py[102-107]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Delivery.set_status()` can put a `DeviationRecord` into an invalid state by setting `status` to an arbitrary string, creating a persisted ledger that this version cannot reload.

## Issue Context
- `DeviationRecord.__post_init__()` validates `status`, but only at construction.
- `Delivery.set_status()` mutates `rec.status` directly.

## Fix Focus Areas
- devague/delivery.py[35-52]
- devague/delivery.py[102-107]

## Implementation notes
- Validate `status in DEVIATION_STATUSES` before mutating.
- Consider enforcing allowed transitions (e.g. only `proposed -> approved|rejected`) if that matches the intended ledger semantics.
- Add/extend tests to assert invalid statuses are refused and do not persist.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Unvalidated deviation refs ✓ Resolved 🐞 Bug ≡ Correctness
Description
devague deviate persists --task/--affects refs without validating they match real plan
task/target IDs, so typos silently sever traceability to the plan. Those raw refs are later
interpolated into markdown tables (e.g. Drift From Plan), so non-ref strings containing markdown
metacharacters can break the rendered delivery summary.
Code

devague/cli/_commands/deviate.py[R45-67]

+def _record(args: argparse.Namespace) -> int:
+    if not args.reason:
+        raise DevagueError(
+            EXIT_USER_ERROR,
+            "missing --reason",
+            'pass --reason "<text>" explaining why the deviation happened',
+        )
+    if not args.task:
+        raise DevagueError(
+            EXIT_USER_ERROR,
+            "missing --task",
+            "pass --task <tN> naming the plan item this deviation relates to",
+        )
+    slug = _plan_slug(args)
+    delivery = delivery_store.load_or_new(slug)
+    rec = delivery.add_deviation(
+        args.what,
+        args.task,
+        args.reason,
+        affects=args.affects,
+        origin=args.origin,
+        classification=args.classification,
+    )
Relevance

⭐⭐ Medium

Team cares about markdown safety (PR #65), but similar persistence hardening is often
rejected/partial (PR #25/#8).

PR-#65
PR-#25
PR-#8

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The deviate command passes user-provided refs directly into the persisted delivery record, and the
summary renderer later embeds task_ref into a markdown table cell without escaping; without ref
validation this can both break the intended plan linkage and produce malformed markdown output.

devague/cli/_commands/deviate.py[45-67]
devague/render/summary_md.py[144-162]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`devague deviate` accepts arbitrary `--task`/`--affects` strings and persists them without checking that they reference real plan tasks/targets. This leads to silent typos (broken linkage) and can also break markdown rendering downstream when these values are embedded into tables.

## Issue Context
- `cmd_deviate._record()` only checks presence of `--task`, not validity.
- `summary_md._drift_lines()` interpolates `d.task_ref` into a markdown table cell.

## Fix Focus Areas
- devague/cli/_commands/deviate.py[45-67]
- devague/render/summary_md.py[144-162]

## Implementation notes
- Load the resolved plan once (not just its slug) in `deviate`.
- Enforce `--task` references an existing task id in the plan (e.g. `plan.find_task(args.task)` must succeed).
- For `--affects`, validate each ref against `(task ids) ∪ (coverage target ids)` (e.g. `plan.find_task(ref)` or `plan.find_target(ref)`), and refuse unknown refs with a `DevagueError(EXIT_USER_ERROR, ...)`.
- Keep the persisted ledger fail-closed: do not “auto-correct” bad refs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
5. Conflicting deviate flags ✓ Resolved 🐞 Bug ≡ Correctness
Description
deviate accepts --confirm and --reject (and/or positional what) simultaneously and silently
applies precedence (confirm wins). This can approve a deviation when the user intended to reject (or
ignore a provided record payload), producing an incorrect ledger state.
Code

devague/cli/_commands/deviate.py[R115-122]

+def cmd_deviate(args: argparse.Namespace) -> int:
+    if args.confirm:
+        return _resolve_status(args, args.confirm, "approved")
+    if args.reject:
+        return _resolve_status(args, args.reject, "rejected")
+    if args.what:
+        return _record(args)
+    return _list(args)
Relevance

⭐⭐ Medium

No direct history on mutually-exclusive argparse flags; team sometimes rejects CLI UX hardening
changes (PR #3) despite correctness arguments.

PR-#3

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
cmd_deviate checks args.confirm then args.reject then args.what, so multiple flags are
allowed by the parser and lead to silent precedence rather than an error.

devague/cli/_commands/deviate.py[115-148]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`cmd_deviate()` resolves ambiguous combinations of `--confirm`, `--reject`, and positional `what` via precedence rather than refusing the invocation. This can lead to unintended state changes.

## Issue Context
Argparse currently defines `--confirm` and `--reject` as independent flags and `what` as an optional positional.

## Fix Focus Areas
- devague/cli/_commands/deviate.py[115-148]

## Implementation notes
- Use an argparse mutually-exclusive group for `--confirm` and `--reject`.
- Add explicit validation in `cmd_deviate` to refuse combinations like `(confirm|reject) + what`, and `--list` combined with any action.
- On invalid combinations, raise `DevagueError(EXIT_USER_ERROR, ...)` with a concrete hint.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread devague/delivery.py
Comment thread devague/cli/_commands/deviate.py
Comment thread devague/cli/_commands/deviate.py
Comment thread devague/delivery.py
Comment thread devague/cli/_commands/summary.py
OriNachum and others added 5 commits July 15, 2026 01:29
…ables/amend move contracts [PR #72]

Documents the Delivery/DeviationRecord entity model, schema-version/persistence
policy, and status-transition semantics; the deviate/summary move contracts
(input/output/transition/error, matching the doc's existing per-move table
format); and extends the previously undocumented Plan-engine move surface with
deliverables, amend, depend --remove, and the confirmed->proposed re-confirm
rule (including the stdout flip echo). Notes the delivery store as the plan's
execution-side companion — the plan JSON stays byte-identical through every
deviate operation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
…slate delivery-store errors, sonar S3516/S1192 [PR #72]

Six review findings on the execution-seam-and-deviate branch:

- Q2 (bug): `devague deviate` now validates --task against the resolved
  plan's task ids and validates id-shaped --affects refs (^[a-z]\d+$)
  against plan task ids, plan coverage targets, and the plan's live source
  frame's claim/honesty-condition ids -- a frame claim need not be a
  coverage target to be accepted (regression-guarded against the committed
  d1/c14 evidence record). Free-form non-id-shaped --affects text stays
  allowed. summary_md's _drift_lines now escapes '|' and flattens newlines
  in interpolated refs/reasons so they cannot corrupt the markdown table.
- Q3 (bug): --confirm/--reject/--list are now an argparse mutually
  exclusive group; combining --confirm/--reject with a positional record,
  or --list with one, is refused explicitly instead of resolved by
  if/elif precedence.
- Q4 (bug): Delivery.set_status fails closed on an unknown status string
  before mutating anything; the CLI layer refuses to resolve an
  already-approved/rejected deviation, naming its current status in the
  hint.
- Q5 (bug): new devague/cli/_deliveries.py (the delivery_store peer of
  _plans.py) translates a too-new schema_version or a malformed/mismatched
  delivery ledger into an actionable DevagueError instead of falling
  through _dispatch's generic "unexpected: ..." handler; wired into both
  `devague summary` and `devague deviate`.
- S1 (SonarCloud S3516): cmd_summary folded its two `return 0` branches
  into a single return path; the CLI contract (exit 0 on success) is
  unchanged since `_dispatch` treats a `None` return the same way.
- S2 (SonarCloud S1192): "(no tasks recorded on this plan)" is now a
  single NO_TASKS_PLACEHOLDER constant backing all three render paths.

Extended tests/test_deviate.py and tests/test_summary.py with failing
tests first, then fixed; one pre-existing test's fixture
(test_deviate_affects_repeatable) referenced non-existent plan ids, which
was exactly the bug being fixed, so it was updated to use real refs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
…tening landed

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
OriNachum and others added 3 commits July 15, 2026 01:53
…mmarize-delivery join the recipe [d2]

`devague learn skills` (and skills:all / skills:<name>) only ever taught
authoring the original three CLI-driving operator skills. The shipped flow
is now six legs: scope -> think -> spec-to-plan -> assign-to-workforce ->
deviate -> summarize-delivery. OPERATOR_SKILLS gains the three new entries
(roles sourced verbatim from their SKILL.md files) plus a per-skill
method_only marker, since scope/deviate/summarize-delivery ship only a
SKILL.md with no scripts/<name>.sh resolver. _skill_source() omits
script_raw for method-only skills instead of emitting a 404ing URL, and the
rendered text labels them "(method-only)" rather than printing a fake
script path. The layout/resolver sections of the recipe now describe both
shapes explicitly. cmd_plan_learn's closing text in plan.py is updated to
name the six operator skills instead of the stale three.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VexbPuzipZ6SUXtGWHKe3V
@sonarqubecloud

Copy link
Copy Markdown

@OriNachum
OriNachum merged commit 80b4c88 into main Jul 14, 2026
8 checks passed
@OriNachum
OriNachum deleted the spec/execution-seam-and-deviate branch July 14, 2026 22:56
OriNachum added a commit that referenced this pull request Jul 29, 2026
… review)

Qodo found a real silent no-op: cmd_lapse fell through to listing whenever
the positional `what` was absent, so

    devague lapse --code provenance-missing --skipped "<check>" --origin llm

printed "no lapses filed yet" and exited 0 having filed nothing. For a ledger
whose entire premise is that filing is cheap enough to do mid-flight, that is
the worst failure available: the operator believes the degradation is on
record and it is not.

Fails closed now, naming the flags that were given, matching the
flag/positional-ambiguity precedent from #72. --origin's parser default moves
from "user" to None so an explicit --origin is distinguishable from the
default; _record resolves None back to "user", so filing behaviour is
unchanged.

7 new tests, including the confirm/reject and --list combinations and a
regression pinning that bare `lapse` and `lapse --list` still list.

Filed as lapse l4: I called the review clean after reading one comment, three
minutes before the Code Review carrying this bug arrived.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe
OriNachum added a commit that referenced this pull request Jul 29, 2026
* spec+plan: reasoning-degradation ledger (devague#97)

The /scope -> /think -> /challenge -> /spec-to-plan legs for issue #97, plus
the renderer fix the challenge pass itself uncovered.

The frame converged with 16 confirmed claims, 16 honesty conditions, three
resolved hard questions, and 14 scope entries citing what was actually read.
The plan converged into three waves (t1 -> t2/t3/t4 -> t5/t6) with three
targets deliberately deferred to the post-ship dogfood milestone.

The renderer change is dogfood fallout: a scope surface carrying its own
code span was blind-wrapped in another, breaking the export under MD038.
spec_md and frame_md now pass such a surface through untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* t1: Lapse domain model on Frame (LapseRecord, lapse codes, schema v5)

Adds the Reasoning Degradation Ledger's domain model (issue #97): Frame.lapses,
LapseRecord (id, code, what, skipped_check, refs, origin, status), and
Frame.add_lapse / find_lapse / set_lapse_status. Mirrors DeviationRecord's
chassis (devague/delivery.py) -- prefix-generic _next id minting,
origin-driven initial status, fail-closed __post_init__ validation,
append-only with no amend/delete -- but deliberately refines it in one place
(c21): `code` is validated at the filing path (add_lapse), not in
__post_init__, so retiring a code after a dogfood cycle never bricks a frame
that already filed it; `status`/`origin` still validate in __post_init__
since they never retire.

Bumps SCHEMA_VERSION 4 -> 5 and moves the pin in
tests/test_frame_schema_v2.py and tests/test_frame.py (the latter also pins
the version; permitted single-line update per task scope). New tests in
tests/test_frame_lapse.py cover id minting/origin-driven status/round-trip
(AC1), filing-time-only code validation incl. a file-retire-reload regression
test (AC2, h16), the v5 bump incl. fail-closed-before-parsing-malformed-data
and v4-frame-loads-clean-and-resaves-as-v5 (AC3), and no amend/delete API
plus unvalidated free-text refs (AC4, c20).

Covers targets: c2, h2, c17, h12, c20, c21, h16.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* t4: pin gate inertness against the lapse ledger (issue #97)

Both convergence gates (devague/convergence.py, devague/plan_convergence.py)
iterate hand-written allowlists over named fields — frame.claims and
frame.open_vagueness on the frame side, plan.tasks and plan.risks on the plan
side — so Frame.lapses (the Reasoning Degradation Ledger, t1) is invisible to
them by default, the same scope_entries precedent. These are pure test
additions pinning that invisibility as a property: converge output is
byte-identical before/after filing a lapse in every status (proposed,
approved, rejected), and neither gate's blockers/warnings/parked_items/
required_next_moves ever names a lapse id, code, or filed text — checked on
both converged and unconverged frames/plans, and on a plan derived from a
lapse-carrying source frame via targets_from_frame. The property holds today;
no production code changed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* t2: lapse CLI verb — file, list, adjudicate (devague#97)

Clones deviate.py's argument surface and confirm/reject/list shape onto
the Frame-level LapseRecord ledger from t1: `devague lapse "<what>"
--code <code>` files against the current frame (--origin llm lands
proposed; --skipped/--ref stored verbatim, refs never id-validated
since a lapse's refs are deliberately free text); --list [--json]
renders id/code/status; --confirm/--reject transition only proposed
records. Drops --task (no plan link) and id-ref validation relative to
deviate.py, per the plan instruction. Adds the lapse row to learn.py's
MOVES dict so `devague explain lapse` and bare `devague learn` both
surface it.

New tests/test_cli_lapse.py (34 tests) pins the argument surface has no
amend/delete/task/affects flags, the confirm/reject transition rules,
JSON shapes, and deterministic no-subprocess recording.

* t3: render the lapse ledger — show and summary consume, spec stays untouched

frame_md.py gains a "## Lapse ledger" section (id, code, status, what),
omitted entirely when Frame.lapses is empty — the working-state view, so
every lapse renders regardless of status (unlike summary_md's discipline
below). summary_md.py's Delivery Claims section now cites approved lapses
as evidence via a small table (escaped through _escape_table_cell, same as
_drift_lines), proposed lapses render as visibly pending, rejected lapses
are omitted, and a lapse-free (or missing) frame keeps the existing
hardcoded placeholder row untouched — no new failure mode. summary_data's
JSON gains a parallel "lapse_evidence" key. spec_md.py is untouched (no
code change) per the plan's load-bearing design point — a regression test
pins render_spec's byte-identity across every lapse status.

Covers targets c4, h3, c10, c19, h14, h13 (issue #97 t3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* t6: docs, contract, changelog, version (0.22.0, issue #97)

Document the shipped Reasoning Degradation Ledger (Frame.lapses /
LapseRecord, devague lapse, schema v5) in docs/spec-contract.md — a new
LapseRecord entity alongside ScopeEntry, a Moves contract row shaped
identically to the deviate row, a v5 Versioning entry, a convergence-gate
inertness note, and an anti-fabrication-guarantee extension. README.md
names lapse in the flat-verb inventory and the agent-driving flow.
CLAUDE.md's Status section leads with the new release and the stack
expectations verb inventory gains lapse. CHANGELOG gets a 0.22.0 entry
citing issue #97's embodiment evidence verbatim: a 21-task, 7-wave fan-out
whose corrections record was reconstructed from memory, four failed
graders (three inside one task) all found by reading data afterwards and
none by a test failing, one near-miss on a false safety claim, and a
recovery that worked only because raw data happened to be committed.
Version bumped 0.21.0 -> 0.22.0 (minor, new feature) so CI's
version-check passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* t5: skills sweep — producer, consumer, and the subagent boundary (devague#97)

Wire the reasoning-degradation lapse ledger (t2-t4) into the three skills
that touch it, without inventing a new gate or workflow owner:

- challenge/SKILL.md: the routing table gains a seventh row — a reasoning
  degradation the pass itself made while sweeping routes to `devague lapse
  --origin llm`, not the six issue-73 spec-finding categories, since it is
  the agent's self-report about its own reasoning rather than proposed spec
  content. The "nothing else" hard rule now names `devague lapse` alongside
  the existing moves.
- summarize-delivery/SKILL.md: the read-only moves table and hard rule gain
  `devague lapse --list`; the Delivery Claims method step and row-contract
  section now read the ledger (or the `Lapse ledger evidence:` block
  `devague summary` already renders) to ground each confidence level —
  approved lapses cap confidence honestly, proposed ones are not yet
  evidence.
- assign-to-workforce/SKILL.md: the worktree prohibition generalizes from
  "never run `devague plan` inside a task worktree" to "no devague move runs
  inside a task worktree", naming `devague lapse` explicitly — a task agent
  reports a degradation in its transcript, the main agent files the record
  after reconciling the worktree, mirroring the `/scope` subagent boundary
  (#79/#91).
- docs/skills.md: the operator-skills table and the challenge /
  summarize-delivery / assign-to-workforce per-skill sections are swept to
  match every table touched above.

Adjudication is always named as `devague lapse --confirm`/`--reject`,
exercised by the human who already owns the relevant gate — no new gate,
no new role. deviate/SKILL.md is untouched: its only moves table is scoped
to `devague deviate` itself, not a whole-method enumeration, so it needed
no change.

Covers: c5, h4, c6, h5, c9, h7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* deviate(d1): split-plan --write escapes verbatim task text (devague#97)

The committed gate-2 artifact failed the repo's own markdownlint: a task
instruction naming cli/__init__.py rendered as strong-emphasis (MD050 x2,
MD037 x1). The script's safe_body() claimed to mirror render/_md_safety.py
"exactly" but had only ported autolink_urls plus its own angle-bracket
helper — md_safe_text, the half that wraps underscore-bearing identifiers in
code spans, was never carried across.

Ports md_safe_text faithfully (identifier wrapping, stray control chars,
stray backticks, leading hash, code-span and URL carve-outs) and composes it
into safe_body/safe_heading. Verified idempotent: a second --write is
byte-identical.

Recorded as deviation d1 against t5; no plan task covered the split-plan
script, and CI does not lint markdown, so nothing would have caught this
before review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* delivery: reasoning-degradation ledger (devague#97)

The accountability artifact for the six-task, three-wave fan-out: all six
tasks delivered, one approved deviation (d1), two lapses filed against this
run's own reasoning and still awaiting adjudication.

Two delivery claims stay unverified on purpose — h8 (filing costs under a
minute) and c13/h11 (every shipped code has a reachable producer) both need
the embodiment dogfood cycle, and four of the six codes have no filing yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* fix(lapse): refuse record flags given without a positional 'what' (#101 review)

Qodo found a real silent no-op: cmd_lapse fell through to listing whenever
the positional `what` was absent, so

    devague lapse --code provenance-missing --skipped "<check>" --origin llm

printed "no lapses filed yet" and exited 0 having filed nothing. For a ledger
whose entire premise is that filing is cheap enough to do mid-flight, that is
the worst failure available: the operator believes the degradation is on
record and it is not.

Fails closed now, naming the flags that were given, matching the
flag/positional-ambiguity precedent from #72. --origin's parser default moves
from "user" to None so an explicit --origin is distinguishable from the
default; _record resolves None back to "user", so filing behaviour is
unchanged.

7 new tests, including the confirm/reject and --list combinations and a
regression pinning that bare `lapse` and `lapse --list` still list.

Filed as lapse l4: I called the review clean after reading one comment, three
minutes before the Code Review carrying this bug arrived.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

* delivery: record the Qodo fix, l3/l4, and the real SonarCloud result

The artifact claimed a clean review and said nothing about SonarCloud. Both
were wrong: Qodo found a silent no-op in `devague lapse`, and the Sonar gate
had run and passed all along (98.7% coverage on new code) behind a false
negative in `agex pr read`.

Adds the post-review fix under Mid-work Decisions, the two new lapses (l3,
l4) to the ledger-evidence block, #102 and devex#96 to follow-ups, and the
Sonar result to Evidence. Three of the four lapses now share one root cause:
an instrument read once and its output treated as settled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6Zm7QrhKV4bzW2RikPGNe

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment