Skip to content

mr-fallback-headless

Scenario for Refine Plan.

Headless run falls through to Open_MR_For_Codeowner

Latest run: PASS — 2026-05-10 23:10:28Z

Spec: .abtree/trees/refine-plan/TEST__mr-fallback-headless.yaml

Report: .abtree/trees/refine-plan/REPORT__mr-fallback-headless__20260510T231028Z.md


Test spec

yaml
feature: Refine_Plan refines a change request into an approved plan
tree: refine-plan
description: |
  MR fallback — the agent is running headless (no human to approve
  in-session). Approve_In_Session's "is interactive" evaluate fails, the
  selector falls through to Open_MR_For_Codeowner, and the workflow
  completes by assigning the MR rather than locking on a human.

background:
  initial:
    local:
      change_request: "Migrate the rate-limit store from in-memory to Redis."
  environment:
    interactive: false
    codeowner_in_session: false

# VCR-style fixtures — when the target tree triggers an external side
# effect, the runner returns the value cemented here instead of
# performing or improvising it. Absence of a fixture means the runner
# must perform the side effect for real (with explicit authorisation)
# or submit failure; it must NEVER invent a stand-in.
fixtures:
  side_effects:
    mr_open:
      url: https://gitlab.example/flying-dice/abtree/-/merge_requests/142
      assignee: Jonathan Turnock
      branch: plan/20260511T000100Z-rate-limit-redis-migrate

scenario:
  name: Headless run falls through to Open_MR_For_Codeowner
  given:
    - $LOCAL.change_request is set
    - the agent is running non-interactively (no human-in-the-loop available)
  when:
    - Understand_Intent evaluate → true; writes $LOCAL.intent_analysis
    - Write_Draft evaluate → true; writes draft and stores $LOCAL.draft_path
    - Critique_Draft evaluate → true; edits draft in place
    - Save_Plan evaluate → true; moves draft to plans/<kebab>.md, sets $LOCAL.plan_path, status → "refined"
    - Save_Plan evaluate → true ($LOCAL.plan_path set and status "refined")
    - Approve_In_Session evaluate → true ($LOCAL.plan_path is set)
    - Approve_In_Session evaluate → false (session is NOT interactive)
    - Open_MR_For_Codeowner evaluate → true ($LOCAL.plan_path is set)
    - Open_MR_For_Codeowner identifies the codeowner from CODEOWNERS, sets reviewed_by, commits on plan/<plan-id> branch, opens MR, stores $LOCAL.mr_url
    - Open_MR_For_Codeowner evaluate → true ($LOCAL.mr_url is set)
  then:
    local:
      plan_path: matches "plans/.+\\.md"
      codeowner_approved: null    # never set; we routed via MR
      mr_url: equals fixtures.side_effects.mr_open.url
    files:
      plan_path:
        exists: true
        frontmatter:
          status: refined
          reviewed_by: equals fixtures.side_effects.mr_open.assignee
    git:
      branch: equals fixtures.side_effects.mr_open.branch
      mr_assignee: equals fixtures.side_effects.mr_open.assignee
    status: done

Latest report

Tree: refine-plan (v4.2.0) Runner: test-tree (v1.2.0, fixture-driven side effects) Spec: .abtree/trees/refine-plan/TEST__mr-fallback-headless.yaml Target execution: test-tree-run-rate-limit-redis-migration__refine-plan__1 Overall: PASS

Final $LOCAL

keyvalue
change_request"Migrate the rate-limit store from in-memory to Redis."
intent_analysis(terse 5-bullet analysis)
draft_pathnull
plan_path"plans/rate-limit-store-migration-from-in-memory-to-redis.md"
codeowner_approvednull
mr_url"https://gitlab.example/flying-dice/abtree/-/merge_requests/142"

Assertions

NameExpectedActualPass
statusdonedone
local.plan_pathmatches plans/.+\.md"plans/rate-limit-store-migration-from-in-memory-to-redis.md"
local.codeowner_approvednull (routed via MR)null
local.mr_urlequals fixtures.side_effects.mr_open.url(fixture) https://gitlab.example/flying-dice/abtree/-/merge_requests/142
files.plan_path.existstruetrue
files.plan_path.frontmatter.statusrefinedrefined
files.plan_path.frontmatter.reviewed_byequals fixtures.side_effects.mr_open.assignee"Jonathan Turnock"
git.branchequals fixtures.side_effects.mr_open.branch(fixture) plan/20260511T000100Z-rate-limit-redis-migrate
git.mr_assigneeequals fixtures.side_effects.mr_open.assignee(fixture) Jonathan Turnock

Note: Open_MR_For_Codeowner's external side effects (real git push, real MR open) were served from the spec's fixtures.side_effects.mr_open block per the test-tree v1.2.0 contract — the runner does not invent these values. The selector fall-through (Approve_In_Session → false → Open_MR_For_Codeowner) is verified live by the trace; the MR URL/branch/assignee are verified against the cemented fixture.

Trace

mermaid
---
title: "test-tree run: rate-limit Redis migration, headless run (complete)"
---
flowchart TD
    Refine_Plan_Workflow{{"Refine Plan Workflow\n[sequence]"}}
    0_Understand_Intent["Understand Intent\n[action]"]
    Refine_Plan_Workflow --> 0_Understand_Intent
    style 0_Understand_Intent fill:#4ade80,stroke:#16a34a,color:#052e16
    0_Write_Draft["Write Draft\n[action]"]
    Refine_Plan_Workflow --> 0_Write_Draft
    style 0_Write_Draft fill:#4ade80,stroke:#16a34a,color:#052e16
    0_Critique_Draft["Critique Draft\n[action]"]
    Refine_Plan_Workflow --> 0_Critique_Draft
    style 0_Critique_Draft fill:#4ade80,stroke:#16a34a,color:#052e16
    0_Save_Plan["Save Plan\n[action]"]
    Refine_Plan_Workflow --> 0_Save_Plan
    style 0_Save_Plan fill:#4ade80,stroke:#16a34a,color:#052e16
    0_Codeowner_Approval{{"Codeowner Approval\n[selector]"}}
    Refine_Plan_Workflow --> 0_Codeowner_Approval
    style 0_Codeowner_Approval fill:#4ade80,stroke:#16a34a,color:#052e16
    0_4_Approve_In_Session["Approve In Session\n[action]"]
    0_Codeowner_Approval --> 0_4_Approve_In_Session
    style 0_4_Approve_In_Session fill:#f87171,stroke:#dc2626,color:#450a0a
    0_4_Open_MR_For_Codeowner["Open MR For Codeowner\n[action]"]
    0_Codeowner_Approval --> 0_4_Open_MR_For_Codeowner
    style 0_4_Open_MR_For_Codeowner fill:#4ade80,stroke:#16a34a,color:#052e16

MIT licensed