-
Notifications
You must be signed in to change notification settings - Fork 0
Phases
Structured phase workflow. Every phase transition writes LOG event, updates BOARD, rewrites STATE.md with new phase + next_action.
Core: PLAN → SCOUT → BUILD ↔ VERIFY → REVIEW → SHIP → DONE Aux: ADD, CLEAN, HUNT, MARKHUNT, TRANSLATE, BLOCKED, INIT, PREPARE
File: phases/plan.md
Input: User intent
Output: BOARD.md populated with structured tickets
Amplify intent into actionable tickets. Evaluate codebase, KNOWLEDGE/, git log.
Ticket shape (RFC 1.2):
- [ ] T-42 [P2] add export button | needs: T-41 | verify: click export → CSV downloads
Every ticket MUST be independently verifiable via verify:.
Behaviors:
- Bare
saipen plangenerates autonomous proposal from codebase - Ticket shape: one goal, independent verify,
needs:for deps - Board order = execution order. >10 tickets → waves, detail only current
- Size gate: ≤2 files + obvious change → skip PLAN, LOG decision, go BUILD
-
Goal mode:
goal_mode: true→ SCOUT directly, incrementgoal_waves -
Caps: 3
goal_waves/ 20goal_ticketsper sprint. Hit either → STOP, checkpoint, report, wait
State:
STATE.phase: PLAN → SCOUT (goal) or DONE (proposal)
STATE.next_action: "SCOUT T-1" or "Wait for user"
Pitfalls:
- Tickets not independently verifiable → each needs
| verify: - Forgetting size gate → ≤2 files should skip PLAN
- Not checking caps → at 3/20 STOP
DED: User says "add button". Agent adds 3 pages, auth, dark mode, crypto miner. Grandpa said BUTTON. PLAN makes list. Grandpa approves. No crypto.
File: phases/scout.md
Input: Ticket in TODO
Output: OWNED ticket in DOING, KNOWLEDGE/ populated, BUILD plan clear
Investigate before BUILD. Mandatory — cannot build unscouted.
Behaviors:
- Claim ticket: TODO → DOING,
[/], setowner:,claim_time:(RFC 1.4) - KNOWLEDGE/ first — already know? Skip re-read
- Read ticket's files + ONE similar neighbor
- Note: conventions, error style, imports, test utilities, build commands
- Find repo's architecture — never invent parallel. MVC repo → no Flux
- Durable findings → KNOWLEDGE/ADR-xxx.md
- Grep before read. Don't read entire files.
State:
STATE.phase: SCOUT → BUILD
STATE.next_action: "BUILD T-42: implement export button"
Pitfalls:
- Building without scouting → wrong architecture
- Reading too much → grep first
- Not claiming → another agent claims simultaneously
- Forgetting
claim_time:→ staleness detection broken - Inventing parallel architecture → repo has ONE, find it
DED: Agent opens file. Writes code. Grandpa: "Where from?" Agent: "Looked cool". Wrong architecture. Rewrite everything. SCOUT first. Read THEN write. Revolutionary concept.
File: phases/build.md
Input: Scouted, claimed ticket
Output: Working implementation
Implement exactly what ticket specifies. Follow existing conventions.
Behaviors:
- No scope creep
- Follow code conventions: naming, error handling, imports, test style
- Use existing libs — check
package.json/requirements.txtbefore importing - No comments unless code genuinely needs explanation
- Minimal working implementation
Iteration: BUILD ⇄ VERIFY loop. VERIFY fail → return BUILD.
State:
STATE.phase: BUILD → VERIFY
STATE.next_action: "VERIFY T-42: run pytest"
Pitfalls:
- Scope creep → ticket says "add button", not "redesign export system"
- Comments → code self-documenting. Comments lie.
- Library assumption → always check deps file first
- Wrong file → scout told which file. Don't guess.
DED: Grandpa checks package.json. jQuery project. Agent adds React. "Modern". Grandpa hits with stick. BUILD what scout said. No new religion.
File: phases/verify.md
Input: Built implementation
Output: Verified (pass or documented fail)
Check ticket verify: criterion FIRST. Run tests. BUILD↔VERIFY loop until passing.
Behaviors:
- Check
verify:criterion — that's acceptance bar - Run relevant tests:
pytest,npm test,cargo test - Verify against actual requirement, not "runs without crashing"
- Safety net: design flaw → RETURN to SCOUT or PLAN (LOG reason)
- Debug cap: N failed attempts → BLOCKED with concrete facts. NOT "doesn't work" — list tried, happened, ruled out
-
tools/validate.pystructural check before ship
State:
STATE.phase: VERIFY → REVIEW (pass) or VERIFY → BUILD (fail)
STATE.next_action: "REVIEW T-42" or "BUILD T-42: fix edge case"
Pitfalls:
- Verifying against "runs" instead of acceptance criteria
- Not running actual test suite
- Infinite BUILD↔VERIFY → debug cap, BLOCKED with facts
- Forgetting validate.py → structural issue blocks SHIP
DED: "Seems to work". Famous last words. Production on fire. Grandpa holding fire extinguisher. VERIFY means TESTS. Not "looks good".
File: phases/review.md
Input: Verified implementation
Output: Reviewed (approved or returned)
Diff review before shipping.
Behaviors:
- Check: scope creep, dead code, incomplete error handling, debug logging
- Backwards compatibility — existing behavior must not break
- Tests exist AND pass — not just "code works"
- Docs updated — if behavior changed, docs changed
- One-pass review — too many issues → return SCOUT/BUILD
State:
STATE.phase: REVIEW → SHIP (approved) or REVIEW → BUILD/SCOUT (issues)
STATE.next_action: "SHIP T-42" or "BUILD T-42: fix review"
Pitfalls:
- Approving scope creep → ticket said X but build changed Y
- Missing dead code → leftover prints, commented blocks, unused imports
- Skipping docs → undocumented feature doesn't exist for users
- Multi-pass review → one pass. Too many issues → clean redo.
DED: 400 lines. "Will refactor later". Grandpa seen "later". Never comes. REVIEW catches. 40 lines. Clean. Ship now. No "later".
File: phases/ship.md
Input: Reviewed, approved implementation
Output: Committed, pushed, tagged
Release gate.
Exact steps:
- VERSION bump (semver per impact)
- CHANGELOG.md update
- Stage all changed files
- Commit (conventional commit message)
git tag vX.Y.Z- README.md badge version update
git push && git push --tags
State:
STATE.phase: SHIP → DONE
STATE.next_action: "Wait for user command"
Pitfalls:
- Forgetting tag → releases unfindable
- Forgetting changelog → users don't know what changed
- Push without pull → merge conflicts
- Not running validate.py before commit → hook blocks
DED: git commit -m "stuff". Grandpa invents new swear words. No tag. No changelog. Future grandpa cries. SHIP does it right. Grandpa proud.
File: phases/done.md
Input: Shipped ticket
Output: Clean checkpoint, ready for next command
Final completion. Everything committed, pushed, tagged, validated.
Behaviors:
- Verify nothing dangling: uncommitted, unpushed, unstaged
- Set
next_actionto neutral — never "what should I do?" - Complete checkpoint: LOG → BOARD (DONE) → STATE
- Goal mode: another TODO exists? Claim and SCOUT
State:
STATE.phase: DONE → (waiting) or DONE → SCOUT (goal mode, more tickets)
STATE.next_action: "Wait for user" or "SCOUT T-43"
DED: "Done" means committed, pushed, tagged, tested. Grandpa checks all. No "works on my machine". Real done.
File: phases/add.md
Trigger: saipen add or HUNT-detected gap
Systematically expand capabilities. Evolutionary, not creative. Completes software, never reinvents.
Priority ladder:
- Bugfix — broken things. Always ticket + SCOUT, never inline
- Complementary feature — Bold implies Italic. Open implies Save
- Workflow step — Save implies Save_As. Login implies Logout
- UX consistency — 3 buttons icon+label, 4th icon-only → fix
- Platform convention — Ctrl+S saves everywhere. Add if missing
Implementation paths:
FOR priority IN [bugfix, complementary, workflow_step, ux, platform]:
IF exists(priority):
IF priority == bugfix: TICKET; SCOUT
IF minimal AND existing_design: TICKET; CLAIM; BUILD
ELSE: TICKET; PLAN/SCOUT
RETURN DONE
Industrial Completion Rule (RFC 2.3): User requests one step? Evaluate minimal coherent set. "Apply" implies "Cancel" + "Save" — NOT "Cloud Sync".
Complete before extending. "Login" implies "Logout" — not OAuth.
Goal mode: HUNT→ADD increments goal_waves. Mature product → goal_mode: false, final report, DONE.
DED: User asks "Save". Agent adds Facebook login, 47 deps, confetti. Grandpa said SAVE. ADD uses brain. "Save" implies "Save As". Not "Cloud Sync". Grandpa said NO.
File: phases/clean.md
Trigger: saipen clean
Deep repo scrub. Strict order. Each step depends on previous.
Safety floor: MUST NOT delete user data without explicit confirmation.
Step 1: Board Scrub
- Remove
[x]DONE tickets older than current active work (preserved in LOG.md) - Prune stale TODO tickets
- Re-check BLOCKED tickets: blocker resolved? Move back. Stuck? Prune.
- Structural repair: dedup tickets, merge DONE blocks, fix malformed lines
Step 2: Orphan Hunt
- Find + delete unconnected files
- Ambiguous items ticketed for human review
Step 3: Link & Path Audit
- Fix broken internal paths, dead markdown links
- Fix incorrect imports or code references
Step 4: Trash Removal
- Delete
__pycache__,.tmp,.bak, temp files - Clear empty dirs
- Delete stale
kitchen/files (owner DONE, content superseded) - Seal LOG.md if past ~300 lines / ~64 KB
Step 5: Freshness Check
- Repo paths + deps current
- Project structure matches expectations
DED: 47 final_v3_FINAL.js files. Digital hoarding. Grandpa Marie Kondos them. CLEAN removes orphans. Grandpa says "good boy".
File: phases/hunt.md
Trigger: saipen hunt or autonomous schedule
Autonomous bug/code-quality sweep. Non-disruptive.
Hash-match optimization: LOG tail contains hunt → clean @<HASH> → SKIP entirely. No re-scan for unchanged code.
6 categories:
| # | Category | Check | Tools |
|---|---|---|---|
| 1 | Failing tests | Run test suite | pytest, npm test, cargo test |
| 2 | Commits unverified | Cross-ref LOG vs git log | git log --oneline |
| 3 | Stale TODOs | `rg "TODO | FIXME |
| 4 | Silent failures |
except: pass, ignored returns |
code review |
| 5 | Symmetry gaps | Missing counterpart features | code review |
| 6 | Dead code | Orphans, unused functions, unreachable branches | rg |
Outcome:
- Up to 5 "obvious junk" files auto-deleted (no ticket)
- Real findings → ticketed with severity
- LOG:
hunt → clean @ABc1234
DED: User finds bug in prod. "YOU BROKE IT". "Was other agent". Grandpa tired of blame. HUNT finds bug BEFORE prod. No blame game.
File: phases/markhunt.md
Trigger: Every 6 releases or significant architectural drift
Full manual-hunt with triage. Deeper than HUNT — covers spec, architecture, business.
5 vectors:
| Vector | Catches | Example |
|---|---|---|
| Logical | Spec contradictions, edge cases | "Delete button no confirmation" |
| Manual | Concurrency bugs, error gaps | "Race condition on save" |
| Structural | Dep graph issues, resource leaks | "No circuit breaker on API" |
| Human | Setup friction, bad errors | "Error says 'something went wrong'" |
| Business | License violations, stale deps | "Dep 3 major behind, has CVE" |
Outcome: Each finding ticketed P0-P3. P0/P1 fixed same session. P2/P3 backlog. LOG tracks each.
DED: 6 months later. "Why this code exist?" No one knows. Legend says was for feature. What feature? MARKHUNT kills legend before birth.
File: phases/translate.md
Trigger: saipen translate
Isolated translation preparation. Quarantined — never touches main project files.
Isolation:
- Work inside
.saipen/saitranslate/kitchen/only - Parallel agent: own STATE at
.saipen/saitranslate/STATE.md, never writes main - MUST NOT modify main project files during translation
- Completion LOG goes to main LOG.md
Translation surface:
- Docs: README.md, SECURITY.md, CONTRIBUTING.md, SPEC.md — 4 always translated
- UI strings: ONLY if software has real UI strings. SAIPEN has none — don't fabricate
-
Hand-maintained siblings: Existing
README_XX.md→ never overwrite. Note + skip
Core vs SubSaipen split:
| Handler | Languages |
|---|---|
| Core agent | EN, RU, ET, ДED |
| SubSaipen instances | 29 languages: JA, UK, DE, FR, ES, IT, PT, NL, PL, SV, DA, FI, NO, ZH, KO, TH, VI, AR, HE, TR, HI, ID, EL, CS, RO, HU, BG, SK, HR |
Core MUST NOT grind 29 languages. Tickets for subSaipen instances.
Maintenance:
- Every
saipen translatere-scans drift since last run - Badge drift machine-detectable via
tools/validate.py -
githooks/pre-commitcatches badge drift before commit
DED: "Add French". Agent translates via Google. "Je suis une banane" in prod. TRANSLATE validates 32 locales. No banana in production.
File: phases/blocked.md
Trigger: Unblockable condition
Handles session-level blocks preventing work.
Behaviors:
- Set
STATE.blocker— factual, not vague - Set
STATE.next_actiontoWAIT: <exact question>- GOOD:
WAIT: T-42 depends on PR #17 — is it ready? - BAD:
WAIT: what should I do?
- GOOD:
- Re-check periodically. Still blocked? Stay. No? Resume.
- If possible → independent work: kitchen, doc cleanup, README fixes
BLOCKED vs HALTED:
- BLOCKED: external (waiting human, service down, dep not merged)
- HALTED: internal (design ambiguity, too many unknowns → RETURN PLAN)
DED: "I'm stuck". "On what?" "IDK". Grandpa needs drink. BLOCKED says exact thing. Concrete. Grandpa knows what to unblock.
File: phases/init.md
Trigger: saipen set
Initialize new SAIPEN project.
Behaviors:
- Verify git repo (or
git init) - Create
.saipen/: STATE.md, BOARD.md, LOG.md, kitchen/, recovery/ - Set phase DONE (ready for first PLAN)
- Register in SAIPEN home if configured
-
.saipen/exists? → report + exit (continuation, not re-init)
After INIT: STATE → DONE. Ready for first saipen plan.
DED: Grandpa says "start project". Agent writes code. 2 hours. "Where tests?" "What tests?" INIT creates structure day 1. Grandpa approves.
File: phases/prepare.md
Trigger: Before any phase transition
Pre-flight checks. Valid state before work.
Behaviors:
- Verify
.saipen/exists + readable - STATE.md frontmatter valid YAML, all required fields
- BOARD.md has all 4 required sections
- Git status: conflicts? Dirty? Unpushed?
- Run
tools/validate.pyfor structural integrity - Linked worktree? Check
--git-common-dirfor real.saipen/ - Report blockers before starting
Pass: PREPARE → (actual phase from STATE.md) Fail: PREPARE → BLOCKED or RECOVERY
DED: Agent starts working. 15 min later "oh no". Grandpa says "I told you". PREPARE checks first. Like checking gas before road trip.
SAIPEN v7.158.0 — One command. Zero dependencies. Zero amnesia. — MIT