100%

Work-item vertical slice — validate-first SM + REAL proof

Goal

Migrate the work-item SM end-to-end with real proof and the first complete ContextAssembly. The plan API owns workflow state, root/frame facts fix exact scope, and reconcile/validate/do_work/invoke-child/fold/revalidate/complete is script-selected; the LLM receives only bounded coding context.

Self-hosting constraint

Still off-path: the slice runs on a sandbox plan via the engine; the live per-item path (complete_work_item_v7) is unchanged. This is migration step 3 (the cleanest slice).

Implementation sketch

  • Author workflows/work_item.json per the canonical SM: state_authority=domain_artifact; fixed plan-derived reconcile entry; journaled initial proof Action; read-only validate gate; bounded do-work; journaled post-work proof Action; read-only revalidate; reconcile-selected proof persistence and completion flip. Every settled Action/invoke/finalizer returns through reconcile. Persist no semantic node in the frame; only unresolved effect/wait cursors survive.
  • Author proof/action components and consume the engine-core ContextAssembler; the script derives the exact coding prompt and result contract from the current plan-API projection, while the LLM chooses only implementation/discovery details inside that capability.
  • Emit one always, one while_state, and one when_condition Reminder with the active root/frame capability anchor.
  • Dispatch bounded work with an engine task token; only an authorized ResultSubmission may enter revalidation.
  • Reject targets outside the root frame; permit another plan only through an engine-issued child capability and typed return.
  • Close the proof gap: run_proof_probes executes/journals probe_ref; proof_satisfied reads current receipts and applies criterion_verdict; refuse hand-supplied non-probe readings.
  • Route post-work proof failure through stable evidence fingerprinting and a bounded classifier; its opaque ResultSubmission reference may select only record_failure_disposition, which persists the closed FailureDisposition through the plan API before another coding attempt, blocker detour, transient recovery, or human decision.
  • Add retry/catch to proof and classification Actions; persist authenticated human disposition before routing; fail closed through a default arm.
  • Invoke blocker children through the generic child protocol with atomic shelve-on-push, fold-once return, exact-origin resume, and proof rerun.
  • Use structured GateCall/ActionCall args for every parameterized component; restore shelved origin on all stopped-child paths and append DEAD evidence only after active-regression classification.
  • Persist failure origin phase and exact symbolic resume target before classification; recover initial proof, work dispatch, or post-work proof without crossing accounting phases.
  • Bind add-bug and attempt-livelock returns to opaque protocol references, then consume them through record_registered_blocker / record_attempt_reground plan-writer Actions before their values can route; bind HumanDecisionReceipt the same way through record_human_decision. Catch classifier business failure, use canonical status/cycle vocabulary, and route proof-persistence/completion-write failure through reconciled typed engine error.
  • Normalize tracked and human dispositions into the same FailureContext blocker field; gate active regression on work/post-work origin and bounded attempt budget.
  • Invoke generic attempt-livelock on exhaustion; only folded accepted reground evidence resets the budget. Commit blocked/error receipts through terminal on_commit.
  • Request add-bug, fix-bug, and reground capabilities declaratively; generic push derives scoped child tokens from root authority.
  • Require work-item proof, subtree quiescence, and all child results folded before proof persistence; reach completed only after a second plan-derived reconcile observes the committed complete status and current proof. Keep irreducible block separate from runnable livelock recovery.
  • Prove vs ./test-all.sh; consume the canonical python -m scripts.test_all_runtime status/verdict envelope, never a singleton build summary file.

Spec references

  • plans/workflow-engine-rework/spec/workflow-state-machines.md sec 2 (work-item SM), sec 10.2 (canonical work_item.json), sec 11 (hardening). Research: review_phase.complete_work_item_v7; write.record_criterion_evidence (proof gap).

Test strategy / acceptance

Matrix: validate/pass/fail x retry/catch/disposition x child open/folded x blocker register/fix/return x human receipt x token. Pins: every ordinary entry starts at plan-derived reconcile; a present-but-bypassed reconcile node rejects; every settled effect clears its cursor and returns to reconcile; route-affecting results without sanctioned plan/tracker writers reject; unbound/stale frame cursors reject; incomplete composite cannot flip; errors route typed; irreducible block has no cure; wrong/stale result cannot advance; model-authored state/control text cannot replace a plan API read or select a transition.

Work Items

  • Author workflows/work_item.json with domain-artifact authority, initial/reachable plan-derived reconcile, all settled effects returning through it, exactly-one derived route, plan-writer-backed semantic result paths, consume-only classifier/bug-registration/reground/human-decision references plus their named persist Actions, proof/completion composite, receipt-bound in-flight cursors, retry/catch/disposition routing, blocker invoke/fold/resume, and irreducible block separation
  • Author proof/action components and bind bounded work dispatch/result ingestion to the engine-core ContextAssembler; generate the exact prompt from plan/root state and leave only bounded coding/discovery judgment to the LLM
  • Implement run_proof_probes as a journaled sandboxed Action; keep proof_satisfied read-only over current receipts
  • Refuse a non-probe-sourced reading on the new path (harden record_criterion_evidence)
  • Prove the slice vs ./test-all.sh (no new failures) in isolation
  • Extend the vertical slice to emit one always-on, one while-state, and one conditional reminder in payload.reminders without changing route selection; pin mandatory reminder acknowledgment and evidence
  • Pin ContextAssembly to root + active frame; reject unauthorized targets and prove one capability-scoped cross-plan child return

Fresh intel (regenerated)

This slice is the first vertical proof that the whole workflow-engine mission works — it lifts ONE real state machine (work-item complete/abandon/push-forward/revalidate) out of the plan_orchestrator god-object tangle and re-expresses it as one declarative workflows/work_item.json driven by a generic engine, running off-path on a sandbox plan so the live per-item path never moves. Three graph facts frame every decision:

  1. The engine does not exist yet. No EngineTurn / RootClosure / InvocationFrame / ContextAssembler / ReminderScheduler / ResultSubmission / workflows/*.json anywhere in scripts/ (grep-empty). This slice CONSUMES the sibling engine-core (s-e585be74) + root-closure (s-be712e10) deliverables — it is BLOCKED on them landing first (both not-started).
  2. The “before” picture is a low-cohesion god-object cluster. design-opportunities ranks roadmap._route_dispatch (321070), roadmap.orchestrate (265273), and review_phase.verify_and_complete_v7 (callable-risk 75456, span 537, fanout 38) as the top DESIGN:low-cohesion hazards, all mission-cited to the SRP conflict rule. The scattered *_v7 work-item operations (complete/abandon/push_forward/mark_reviewed) embedding-cluster at 0.81-0.86 — they ARE the one SM the JSON must unify. This slice is the mission’s proof-of-concept that the tangle collapses.
  3. The live per-item path is a DO-NOT-TOUCH surface. complete_work_item_v7 (span 289, betweenness 2302, 11 behavioral pins in test_complete_work_item_v7.py) and verify_and_complete_v7 (span 537, fanout 38, betweenness 13924 — the single highest-risk callable) are the strangler-fig’s untouched trunk. The section body states the live path is “unchanged”; the mission bans switching an active root mid-migration.

Decisions this package forces before any code is written:

  1. Confirm the engine-core (s-e585be74) ContextAssembler + root-closure (s-be712e10) capability primitives have landed — this slice is a CONSUMER, not a builder, of them (w-35887a59, w-f3b0946e). It cannot start cold.
  2. Build the SM as workflows/work_item.json + pluggable LogicGate/Action components, NEVER by editing review_phase.py/roadmap.py — the god-object is the anti-pattern the engine replaces, and editing the live path violates the strangler-fig constraint (SCHEMA:unvalidated-config + STRUCTURE:plan-specific-tooling-leak guard the JSON).
  3. The proof gate is a validator terrain — pin it with teeth. run_proof_probes (journaled sandbox exec) and proof_satisfied (read-only receipt read) are NEW; the harden of record_criterion_evidence (w-7151d418, “refuse a non-probe-sourced reading”) is an INVERTED-TDD risk surface — the negative pins (bypassed reconcile rejects, non-probe reading rejects, stale result cannot advance) MUST fail pre-fix.
  4. Prove vs ./test-all.sh through the canonical test_all_runtime status/verdict envelope (w-f6ff0bc6) — the section body + test-all-runtime.md ban singleton-summary reads.
["complete_work_item_v7", "verify_and_complete_v7", "orchestrate", "_route_dispatch"]

DIG DEEPER

# confirm the engine core still absent (this slice's dependency):
grep -rln "EngineTurn\|RootClosure\|InvocationFrame\|ContextAssembl\|ReminderScheduler\|ResultSubmission" scripts/
python -m scripts.plan_corpus.read --summary plans/workflow-engine-rework   # section roster + statuses

(full dossier: work-item-slice—s-051a0f91.intel.md)