Files
X-Financial/docs/superpowers/plans/2026-06-15-steward-application-reimbursement-state.md
caoxiaozhu 9f7b8b46a3 Refine travel reimbursement steward flow
Align planner, runtime rules, and policy assets so travel guidance
matches the updated reimbursement workflow.
2026-06-15 22:55:18 +08:00

5.9 KiB

Steward Application Reimbursement State Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Build a persistent ontology-bound steward state for travel application and travel reimbursement flows.

Architecture: Keep the existing steward planning UI and assistant delegation flow. Add a backend state layer that stores steward_state in AgentConversation.state_json, merges LLM/rule output as patches, and rejects fields outside the ontology registry before downstream services consume them.

Tech Stack: FastAPI, SQLAlchemy JSON state, Pydantic schemas, pytest in Docker x-financial-main:/app, Vue/Vite frontend.


Task 1: Backend State Contract

Files:

  • Modify: server/src/app/schemas/steward.py

  • Create: server/src/app/services/steward_flow_state.py

  • Test: server/tests/test_steward_flow_state.py

  • Step 1: Write failing tests

def test_state_merge_keeps_application_and_reimbursement_flows():
    service = StewardFlowStateService()
    state = service.merge_state(
        {},
        StewardFlowStatePatch(
            active_flow="travel_application",
            flow_id="travel_application",
            intent="travel_application_create",
            fields={"expense_type": "travel", "location": "上海"},
        ),
    )
    state = service.merge_state(
        state,
        StewardFlowStatePatch(
            active_flow="travel_reimbursement",
            flow_id="travel_reimbursement",
            intent="travel_reimbursement_draft",
            fields={"amount": "708", "invoice_no": "NO-1"},
        ),
    )

    assert state["flows"]["travel_application"]["fields"]["location"] == "上海"
    assert state["flows"]["travel_reimbursement"]["fields"]["amount"] == "708"
def test_state_merge_filters_non_ontology_fields():
    service = StewardFlowStateService()
    state = service.merge_state(
        {},
        StewardFlowStatePatch(
            active_flow="travel_application",
            flow_id="travel_application",
            intent="travel_application_create",
            fields={"location": "上海", "invented_field": "x"},
        ),
    )

    assert state["flows"]["travel_application"]["fields"] == {"location": "上海"}
  • Step 2: Run red tests

Run:

docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_flow_state.py

Expected: fail because steward_flow_state.py does not exist.

  • Step 3: Implement minimal state service

Create StewardFlowStatePatch, StewardFlowStateService.merge_state, ontology field filtering, and event append logic.

  • Step 4: Run green tests

Run the same pytest command and expect pass.

Task 2: Steward Plan Persistence

Files:

  • Modify: server/src/app/schemas/steward.py

  • Modify: server/src/app/api/v1/endpoints/steward.py

  • Modify: server/src/app/services/agent_conversations.py

  • Test: server/tests/test_steward_planner.py

  • Step 1: Write failing API/service test

Add a test proving /steward/plans response contains conversation_id and steward_state when context_json.session_type = steward, and the state contains two flows when the input contains one application and one reimbursement task.

  • Step 2: Run red test

Run:

docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_planner.py
  • Step 3: Implement conversation state persistence

Add conversation_id and steward_state fields to response schemas, persist state through AgentConversationService, and merge planner tasks into steward_state.

  • Step 4: Run green test

Run the same pytest command and expect pass.

Task 3: Runtime Decision Reads Persistent State

Files:

  • Modify: server/src/app/services/steward_runtime_decision_agent.py

  • Test: server/tests/test_steward_runtime_decision_agent.py

  • Step 1: Write failing test

Add a test proving runtime decision uses context_json.conversation_state.steward_state when runtime_state is empty.

  • Step 2: Implement minimal fallback hydration

Normalize runtime state by merging request runtime state with persisted steward state.

  • Step 3: Run green test

Run:

docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_runtime_decision_agent.py

Task 4: Frontend State Carry

Files:

  • Modify: web/src/views/scripts/stewardPlanModel.js

  • Modify: web/src/views/scripts/TravelReimbursementCreateView.js

  • Modify: web/src/views/scripts/useTravelReimbursementSessionState.js

  • Step 1: Preserve steward state from backend responses

Normalize conversation_id and steward_state from plan/runtime responses into the local session model.

  • Step 2: Send steward state in later requests

Include the current steward_state under context_json for plan and runtime decision calls.

  • Step 3: Build frontend

Run:

docker exec -w /app/web x-financial-main npm run build

Expected: build succeeds.

Task 5: Final Verification

  • Step 1: Run backend steward tests
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_flow_state.py server/tests/test_steward_planner.py server/tests/test_steward_runtime_decision_agent.py server/tests/test_steward_slot_decision_agent.py
  • Step 2: Run frontend build
docker exec -w /app/web x-financial-main npm run build
  • Step 3: Report workspace status

Run:

git status --short