Skip to content

Scenarios

VAC34 edited this page Jul 27, 2026 · 14 revisions

Scenarios

Common workflow walkthroughs with concrete STATE.md and BOARD.md snapshots at each step.


Scenario 1: New feature request

User says: "Add dark mode toggle"

Initial STATE.md:

phase: DONE
next_action: "Wait for user command"

What happens:

  1. Agent reads STATE (phase: DONE) -> BOARD (empty TODO) -> no active work

  2. Enters PLAN phase. Agent reads existing UI code: finds light theme only, CSS variables in theme.css, no dark palette

  3. Produces tickets on BOARD:

    ## TODO
    - [ ] T-1 [P2] add dark mode CSS variables | verify: toggle switches CSS class on <body>
    - [ ] T-2 [P2] add theme toggle button to header | needs: T-1 | verify: button visible, clickable
    - [ ] T-3 [P1] persist theme preference in localStorage | needs: T-2 | verify: refresh preserves choice
    
  4. Agent claims T-1, transitions SCOUT -> BUILD

    During SCOUT: reads theme.css (180 lines), finds 12 color variables. Creates parallel :root.dark block with complementary values. Reads neighbor file header.jsx for import patterns.

    During BUILD: adds 12 dark-mode CSS variables, wires toggle to CSS class switch

  5. VERIFY: toggle switches body class, colors invert, text remains readable (contrast ratio checked)

  6. REVIEW: diff is 30 lines, no scope creep, no dead code, tests pass

  7. SHIP: commit "v1.1.0: add dark mode toggle", tag, push

Updated STATE.md:

phase: DONE
next_action: "Wait for user command"

Total time from user command to shipped: ~8 minutes (agent working time)


Scenario 2: Bug report

User says: "The export button crashes on empty state"

Initial STATE.md:

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

What happens:

  1. Agent pauses T-14 to handle the bug. Creates ticket:

    ## DOING
    - [/] T-15 [P1] fix export crash on empty state | verify: export([]) returns valid empty CSV with headers
    
    ## TODO
    - [ ] T-14 [P2] implement CSV export (paused for T-15)
    
  2. SCOUT: reads export.py (210 lines). Finds [row for row in data] assumed non-empty. When data is empty, next line data[0].keys() raises IndexError. No test for empty input. No guard clause.

  3. BUILD: adds guard at function entry:

    def export_csv(data):
        if not data:
            return "header1,header2,header3\n"  # return headers only
        headers = data[0].keys()
        ...
  4. VERIFY: export_csv([]) returns "header1,header2,header3\n". export_csv([{...}]) still works. pytest tests/test_export.py — all pass.

  5. REVIEW: 3-line diff, no side effects, tests cover empty case now

  6. SHIP: commit "fix: export crash on empty data (T-15)", push

After fix, agent checks if T-14 is impacted by the fix (it's not). Resumes T-14.


Scenario 3: Context handoff (cross-agent)

Scenario: Agent A (Claude Code) worked for 2 hours, reached SHIP on T-42. User opens Agent B (Gemini Code Assist) and says "saipen continue"

What 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 (tail):

## DOING
- [/] T-42 [P2] implement user preferences panel | owner: claude-code | claim_time: 2026-07-27T14:30:00Z | verify: pytest tests/test_prefs.py

## DONE
- [x] T-40 ...
- [x] T-41 ...

.saipen/LOG.md (last 3 lines):

- 27.07.26 14:30 [E-88] [parent: E-87] [T-42] RUN: SCOUT — read prefs API, found PATCH /preferences endpoint exists, frontend panel missing
- 27.07.26 15:45 [E-89] [parent: E-88] [T-42] RUN: BUILD — preferences panel rendered, all 5 toggles wired, save button calls PATCH
- 27.07.26 16:10 [E-90] [parent: E-89] [T-42] RUN: VERIFY — all tests pass, manual check: toggles persist after refresh

Agent B execution:

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

Result: Agent B shipped Agent A's work in 2 minutes. Zero briefing. No chat history shared.


Scenario 4: Collaborative subSaipen

Scenario: Core agent building main feature. User says "saihunt" to delegate a bug sweep. Then "saitranslate" for a translation audit. Both run in parallel.

What happens:

  1. User says "saihunt" -> saihunt subSaipen auto-spawns at .saipen/extensions/subs/saihunt/

    .saipen/extensions/subs/saihunt/STATE.md:
    phase: HUNT
    task: run 6-category sweep against HEAD
    mode: read-only
    
  2. saihunt reads the main project (read-only), runs all 6 HUNT categories:

    • Tests: python tools/run_scenarios.py — 9/9 PASS
    • Commits: all verified against git log
    • TODOs: no stale code markers found
    • Silent failures: no bare except: blocks
    • Symmetry: bootstrap scripts all have sh+ps1 pairs ✓
    • Dead code: 2 stale kitchen files found (markhunt relics, tickets DONE)
  3. saihunt writes OUTBOX:

    ## HUNT-001: clean sweep, 1 finding
    - finding: 2 stale files in .saipen/kitchen/ — owning tickets DONE, content superseded
    - severity: cleanup
    
  4. Meanwhile user says "saitranslate" -> saitranslate subSaipen auto-spawns at .saipen/extensions/subs/saitranslate/, runs translation structure validation:

    • 32/32 locales have all required files
    • All files valid UTF-8
    • 3 Core locales up to date
    • 29 non-Core stale (ticketed as T-186)
    • Writes OUTBOX
  5. User says "collect" -> main agent reads both OUTBOXes:

    • saihunt finding: delete 2 stale files (actioned)
    • saitranslate finding: noted, T-186 covers it
  6. Main agent continues its BUILD work — never interrupted.


Scenario 5: Goal mode sprint

User says: "saipen goal make the UI responsive"

What happens:

  1. PLAN generates ticket wave:

    ## TODO (wave 1)
    - [ ] T-1 [P2] add viewport meta tag | verify: <meta name="viewport"> in <head>
    - [ ] T-2 [P2] convert hardcoded widths to %/rem | needs: T-1 | verify: no px in layout CSS
    - [ ] T-3 [P2] add mobile breakpoint at 768px | needs: T-2 | verify: layout reflows at 767px
    - [ ] T-4 [P1] navigation collapses to hamburger on mobile | needs: T-3
    
  2. goal_waves=1, goal_tickets=4

  3. Agent executes wave 1: T-1 -> SCOUT -> BUILD -> VERIFY -> REVIEW -> SHIP -> DONE. Then T-2, T-3, T-4.

  4. After each DONE, saipen status updates:

    phase: DONE | goal_waves: 1 | goal_tickets: 4/20
    next tickets: T-1 (DONE), T-2 (DONE), T-3 (DONE), T-4 (DONE)
    
  5. All wave 1 tickets done. Agent checks: are more responsive improvements possible? Yes -> PLAN generates wave 2 (T-5..T-8: tablet breakpoint, font scaling, touch targets, reduce motion).

  6. goal_waves=2, goal_tickets=8

  7. Wave 2 executes. After completion, agent checks: product now meets responsive standard. Calls mature exit.

  8. Reports:

    Goal complete: UI responsive
    8 tickets shipped across 2 waves
    All verify criteria pass
    

Scenario 6: Post-crash recovery

Scenario: Agent crashed mid-BUILD. New agent opens project.

What new agent sees:

STATE.md:
phase: BUILD
task: T-18 implement search
next_action: "BUILD T-18: wire search input to backend"
blocker: none
agent: dead-agent
updated: 2026-07-26T12:00:00Z   # <-- 3 hours ago! Stale claim
BOARD.md:
## DOING
- [/] T-18 [P2] implement search | owner: dead-agent | claim_time: 2026-07-26T11:45:00Z

Recovery (RFC 1.5):

  1. Agent detects stale claim_time (>15 min since current time)
  2. Appends LOG: [E-91] RECOVERY: T-18 claim by dead-agent stale, resetting
  3. Resets claim: removes owner: and claim_time: from T-18, moves BOARD line unchanged
  4. Reads LOG tail to understand how much was done:
    [E-85] SCOUT — read search API, found /search?q= endpoint
    [E-86] BUILD — search input rendered, onChange wired, debounce at 300ms
    
  5. Checks git diff for unstaged work — finds search.jsx partially written (input + onChange done, results display not started)
  6. Reclaims T-18: sets owner: to new agent, claim_time: to now
  7. Continues BUILD from where dead agent left off

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


Scenario 7: Translation round

User says: "saipen translate"

What happens:

  1. TRANSLATE phase loads the translation rules
  2. Agent reads EN root docs: README.md (v7.80.0), SECURITY.md (v7.80.0), CONTRIBUTING.md (v7.80.0), SPEC.md (v7.80.0)
  3. Reads existing .saipen/saitranslate/kitchen/:
    • 32 locale directories, 5 files each
    • Check against EN source for drift
    • git diff 40242f3..e2ded74 -- README.md SECURITY.md CONTRIBUTING.md SPEC.md -> empty (no content change, only badge)
  4. Version badge drift detected: EN at v7.80.0, most locales at v7.64.0
  5. Core execution: bumps RU/ET/DED README badges to v7.80.0
  6. Non-Core: tickets 29 stale locales as T-186 for subSaipen instances
  7. Logs completion: translate -> done @e2ded74

After translate:

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

Scenario 8: Clean sweep

User says: "saipen clean"

What happens:

  1. CLEAN phase loads (phases/clean.md)
  2. Board Scrub: scans BOARD.md:
    • Finds 2 DONE tickets from last week: moves them off (preserved in LOG.md)
    • Finds T-12 in BLOCKED where blocker was already resolved last week: moves to TODO
    • Finds duplicate ## DONE sections: merges into one
    • Fixes 1 malformed ticket line (missing space after -)
  3. Orphan Hunt: scans repo for files not referenced anywhere:
    • Finds old_script.py — no imports, no references, last modified 3 months ago. Deleted.
    • Finds notes/ directory — unclear ownership. Ticketed for human review.
  4. Link Audit: checks all markdown files:
    • GUIDE.md has a link to ./old_path.md that 404s. Fixed to ./new_path.md.
    • README.md badge links to correct path ✓
  5. Trash Removal:
    • __pycache__/ in 3 directories -> cleaned
    • .tmp files in kitchen/ -> deleted
    • LOG.md is 312 lines (past 300 cap) -> seals to .saipen/logs/LOG-002.md via crash-safe temp+rename
    • Fresh LOG.md starts with E-### continuing from sealed segment
  6. Freshness Check: VERSION matches README badge. git status clean. validate.py PASS.
  7. LOG: clean -> done @a1b2c3d
  8. STATE -> DONE

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

Clone this wiki locally