Skip to content

Scenarios

VAC34 edited this page Jul 27, 2026 · 14 revisions

Scenarios

Common workflow walkthroughs with STATE.md + BOARD.md snapshots.


Scenario 1: New feature request

User: "Add dark mode toggle"

Initial STATE:

phase: DONE
next_action: "Wait for user command"

Flow:

  1. Agent reads STATE (DONE) → BOARD (empty) → no active work
  2. PLAN: reads existing UI code — light theme only, CSS variables in theme.css, no dark palette
  3. BOARD tickets:
    ## TODO
    - [ ] T-1 [P2] add dark mode CSS vars | verify: toggle switches CSS class on <body>
    - [ ] T-2 [P2] add theme toggle button | needs: T-1 | verify: button visible, clickable
    - [ ] T-3 [P1] persist preference in localStorage | needs: T-2 | verify: refresh preserves choice
    
  4. Claim T-1, SCOUT→BUILD. SCOUT: reads theme.css (180 lines), 12 color variables. Creates :root.dark block. BUILD: adds 12 dark-mode vars, wires toggle
  5. VERIFY: toggle switches body class, colors invert, contrast OK
  6. REVIEW: 30-line diff, no creep, no dead code, tests pass
  7. SHIP: commit, tag, push

Final STATE:

phase: DONE
next_action: "Wait for user command"

Time: ~8 min agent working time


Scenario 2: Bug report

User: "Export button crashes on empty state"

Initial STATE:

phase: BUILD
task: T-14 implement CSV export
next_action: "BUILD T-14: wire export endpoint"

Flow:

  1. Pause T-14. Create ticket:
    - [/] T-15 [P1] fix export crash empty state | verify: export([]) returns valid empty CSV
    
    - [ ] T-14 [P2] CSV export (paused for T-15)
    
  2. SCOUT: reads export.py (210 lines). [row for row in data] assumed non-empty. Empty → data[0].keys() raises IndexError. No test. No guard.
  3. BUILD: guard at function entry:
    def export_csv(data):
        if not data:
            return "header1,header2,header3\n"
        headers = data[0].keys()
  4. VERIFY: export_csv([]) returns headers. export_csv([{...}]) still works. pytest green.
  5. REVIEW: 3-line diff, no side effects, tests cover empty case
  6. SHIP: commit "fix: export crash on empty data (T-15)"

After fix: T-14 unaffected. Resume T-14.


Scenario 3: Context handoff (cross-agent)

Agent A (Claude Code) worked 2h, reached SHIP on T-42. User opens Agent B (Gemini) → "saipen continue"

Agent B reads:

.saipen/STATE.md:

phase: SHIP
task: T-42 implement user preferences panel
next_action: "SHIP T-42: verify tests pass, commit v1.3.0, tag, push"
agent: claude-code

.saipen/BOARD.md:

## DOING
- [/] T-42 [P2] implement user prefs panel | owner: claude-code | claim_time: ... | verify: pytest tests/test_prefs.py

.saipen/LOG.md (tail):

[E-88] SCOUT — read prefs API, found PATCH /preferences endpoint, frontend missing
[E-89] BUILD — panel rendered, 5 toggles wired, save calls PATCH
[E-90] VERIFY — all tests pass, toggles persist after refresh

Agent B:

  1. Reads BOOT → STATE (SHIP) → BOARD (T-42 DOING) → LOG tail
  2. Executes SHIP T-42
  3. Runs pytest tests/test_prefs.py — all green
  4. Bumps VERSION, CHANGELOG, commits, tags v1.3.0, pushes
  5. Checkpoints

Result: Agent B shipped Agent A's work in 2 minutes. Zero briefing.


Scenario 4: Collaborative subSaipen

Core agent building feature. User says "saihunt" then "saitranslate". Both run parallel.

  1. saihunt auto-spawns at .saipen/extensions/subs/saihunt/:
    phase: HUNT, task: 6-category sweep, mode: read-only
    
  2. saihunt reads project (read-only), runs 6 categories:
    • Tests: 9/9 PASS
    • Commits: all verified
    • TODOs: clean
    • Silent failures: none
    • Symmetry: bootstrap sh+ps1 pairs ✓
    • Dead code: 2 stale kitchen files (tickets DONE)
  3. saihunt OUTBOX:
    HUNT-001: clean sweep, 1 finding — 2 stale files, owning tickets DONE
    
  4. saitranslate auto-spawns, runs structure validation:
    • 32/32 locales complete
    • 3 Core up to date
    • 29 non-Core stale (ticketed T-186)
  5. collect → main agent reads both OUTBOXes. Deletes 2 stale files. Notes T-186.
  6. Main agent continues BUILD — never interrupted.

Scenario 5: Goal mode sprint

User: "saipen goal make UI responsive"

  1. PLAN generates wave 1:

    T-1: viewport meta tag | verify: <meta name="viewport"> in <head>
    T-2: convert hardcoded widths to %/rem | needs: T-1
    T-3: mobile breakpoint 768px | needs: T-2
    T-4: hamburger nav on mobile | needs: T-3
    
  2. goal_waves=1, goal_tickets=4

  3. Execute T-1→T-4: each SCOUT→BUILD→VERIFY→REVIEW→SHIP→DONE

  4. After each DONE:

    phase: DONE | goal_waves: 1 | goal_tickets: 4/20
    
  5. All wave 1 done. More improvements possible? Yes → wave 2 (T-5..T-8: tablet breakpoint, font scaling, touch targets, reduce motion).

  6. goal_waves=2, goal_tickets=8

  7. Wave 2 done. Product meets responsive bar. Mature exit.

  8. Report:

    Goal complete: UI responsive
    8 tickets shipped across 2 waves
    

Scenario 6: Post-crash recovery

Agent crashed mid-BUILD. New agent opens project.

Sees:

STATE: phase: BUILD, task: T-18 implement search
       next_action: "BUILD T-18: wire search input to backend"
       agent: dead-agent, updated: 3h ago
BOARD: [/] T-18 | owner: dead-agent | claim_time: 3h ago

Recovery (RFC 1.5):

  1. Detects stale claim_time (>15 min)
  2. LOG: [E-91] RECOVERY: T-18 claim by dead-agent stale, resetting
  3. Resets claim: remove owner, claim_time. BOARD line unchanged.
  4. Reads LOG tail for progress:
    [E-85] SCOUT — /search?q= endpoint exists
    [E-86] BUILD — input rendered, onChange wired, 300ms debounce
    
  5. Checks git diff: search.jsx partially written (input + onChange done, results not started)
  6. Reclaims T-18: new owner, new claim_time
  7. Continues BUILD from where dead agent left off

Result: <1 min recovery. No work lost (git preserved partial).


Scenario 7: Translation round

User: "saipen translate"

  1. TRANSLATE loads rules
  2. Agent reads EN root docs: README.md (v7.80.0), SECURITY.md, CONTRIBUTING.md, SPEC.md
  3. Reads .saipen/saitranslate/kitchen/: 32 locales, 5 files each
  4. git diff 40242f3..e2ded74 -- README.md SECURITY.md CONTRIBUTING.md SPEC.md → empty (content unchanged)
  5. Badge drift: EN v7.80.0, locales at v7.64.0
  6. Core: bumps RU/ET/DED badges to v7.80.0
  7. Non-Core: tickets 29 stale as T-186 for subSaipen
  8. LOG: translate → done @e2ded74

After:

python tools/validate.py
PASS: all 32 locale README badges match VERSION (7.80.0)

Scenario 8: Clean sweep

User: "saipen clean"

  1. CLEAN phase loads
  2. Board Scrub: moves old DONE tickets off (preserved in LOG.md). Blocker resolved? Move to TODO. Merge duplicate sections. Fix malformed lines.
  3. Orphan Hunt: old_script.py — no refs, 3mo old. Deleted. notes/ — unclear ownership. Ticketed.
  4. Link Audit: GUIDE.md link to ./old_path.md 404s → fixed.
  5. Trash Removal: __pycache__/ in 3 dirs → cleaned. .tmp in kitchen → deleted. LOG.md 312 lines → seals to LOG-002.md. Fresh LOG starts from continuing E-###.
  6. Freshness Check: VERSION matches badge. git clean. validate.py PASS.
  7. LOG: clean → done @a1b2c3d
  8. STATE → DONE

Result: 3 stale files removed, 1 link fixed, LOG sealed, board decluttered.

Clone this wiki locally