Why Wai?
wai — pronounced like “why” — is a workflow manager for AI-driven development. It can also be read as “way”, and that’s intentional: the tool’s focus is capturing why it was built that way.
The Problem
You come back Monday morning. The code is there — merged, deployed, working. But nobody remembers why approach X was chosen over Y. The research that ruled out three alternatives? Lost in a chat thread. The design constraint that shaped the API? Buried in a meeting note nobody bookmarked. The trade-off that made the architecture click? It lived in someone’s head, and they moved on.
This happens constantly in AI-assisted development, where code is produced fast but reasoning evaporates even faster:
- Context resets every session. AI agents start fresh each time. The research you did yesterday is gone unless you manually re-explain it.
- Decisions outlive their rationale. Code survives; the thinking behind it doesn’t. Six months later, nobody can explain why the system works the way it does.
- Handoffs lose signal. Switching between agents, or between human and agent, means re-discovering context that already existed.
- Config drift. AI instructions (
CLAUDE.md,.cursorrules) fall out of sync across tools, so agents get inconsistent guidance.
How Wai Helps
Wai addresses each of these pain points directly:
| Pain point | How wai solves it |
|---|---|
| Context resets every session | wai close captures session state; wai prime restores it. Agents resume where they left off. |
| Decisions outlive their rationale | wai add research, wai add design, and wai add plan preserve the why alongside the what. |
| Handoffs lose signal | wai handoff create generates a high-context summary that carries reasoning across sessions and agents. |
| Config drift | The sync engine keeps agent configs aligned from a single source of truth. |
At a Glance
wai connects your thoughts and your codebase:
- 🧠 Capture — Record research, designs, and decisions as you work.
- 🗺️ Context — Advance projects through phases: Research → Design → Plan → Implement → Review → Archive.
- 🔄 Sync — Keep AI instructions automatically aligned from one source of truth.
- 📦 Handoff — Generate high-context session summaries for yourself or other agents.
How It Fits Together
┌──────────────────────────────────────────────────────────┐
│ .wai/ │
│ │
│ ┌─ Projects ──┐ ┌─ Areas ──┐ ┌─ Resources ─────────┐ │
│ │ my-feature/ │ │ ops/ │ │ agent-config/ │ │
│ │ research/ │ │ docs/ │ │ skills/ rules/ │ │
│ │ designs/ │ └──────────┘ │ reflections/ │ │
│ │ plans/ │ │ pipelines/ │ │
│ │ handoffs/ │ ┌─ Archives ┐ └──────────────────────┘ │
│ └─────────────┘ │ old-proj/ │ │
│ └───────────┘ │
├──────────────────────────────────────────────────────────┤
│ Phases: research → design → plan → implement → review │
│ Plugins: git · beads · openspec · custom │
│ Sync: .wai/resources/ ──→ .claude/ .cursorrules etc. │
└──────────────────────────────────────────────────────────┘
Key Capabilities
- PARA Method Storage: Logical organization into Projects, Areas, Resources, and Archives.
- Phase Tracking: Structured workflow from initial research to final archive.
- Sync Engine: Single source of truth for agent configurations across multiple tools.
- Plugin System: Integration with
git,beads,openspec, and more. - Reasoning Oracle: Ask natural language “why” questions about your codebase with
wai why.
Where to Go Next
Depending on your role, different parts of the docs will be most useful:
- 👤 Adopting wai in your own repo? Start with the Quick Start, then read How to Adopt Wai for a step-by-step guide.
- 🔧 Contributing to wai itself? This repo dogfoods wai — it uses wai, beads, and openspec to manage its own development. See Development and Architecture, and read
AGENTS.mdfor the session workflow. - 🤖 AI assistant? Follow the instructions in
AGENTS.mdat the repo root. Key commands:wai prime(session start),wai close(session end),bd ready(find work).
Design Principles
-
🛣️ Desire Path Alignment — Pave the cowpaths; make common workflows shortest.
wai statussuggests the next command based on your current phase — if you’re in research, it nudges you towardwai add research; when research is captured, it suggests advancing to design. -
🩹 Self-Healing Errors — Errors suggest fixes, not just report problems.
wai doctor --fixauto-repairs common workspace issues. Typos in commands get “Did you mean?” suggestions. Error messages include the exact command to fix the problem. -
🌊 Progressive Disclosure — Simple by default, powerful when needed.
wai initasks nothing beyond a project name.-vshows more detail,-vvreveals internals,-vvvshows everything. Beginners see clean output; power users get full diagnostics. -
💡 Context-Aware — Offer smart next steps based on your current project state. Wai auto-detects your toolchain (git, beads, openspec) by scanning for workspace markers and adapts its suggestions accordingly — no configuration required.
A note on authorship
All the code in this repository was generated by a large language model. This is not a confession, nor an apology. It’s a fact, like the one that says water boils at a hundred degrees at sea level: neutral, technical, and with consequences one discovers later.
What the human did is what tends to happen before and after things come into existence: thinking. Reviewing requirements, arguing about edge cases, understanding what needs to be built and why, deciding how the system should behave when reality —which is capricious and does not read documentation— confronts it with situations nobody anticipated. The hours of planning, of design, of reading specifications until exhaustion dissolves the boundary between understanding and hallucination.
The LLM writes. The human knows what it should say.
There is a distinction, even if looking at the commit history makes it hard to find. The distinction is that a machine can produce correct code without understanding anything, the same way a calculator can solve an integral without knowing what time is. Understanding what that integral is for, whether it actually solves the problem, whether the problem was the right problem to begin with — that remains human territory. For now.
Release Status
Generated artifact (docs.yml, from Cargo.toml + git ref). Do not hand-edit — the repo source files remain authoritative.
- Version: v2026.10.19
- Built from: main @ c4685f8
Installation
The easiest way to install wai is using a package manager.
Homebrew (macOS & Linux)
brew tap charly-vibes/charly
brew install wai
Scoop (Windows)
scoop bucket add charly https://github.com/charly-vibes/scoop-charly.git
scoop install wai
From Binary (All Platforms)
Download the latest pre-compiled binary for your architecture from the GitHub Releases page.
- Unpack the archive.
- Move the
waibinary to a directory in your PATH (e.g.,/usr/local/binorC:\Windows\System32).
From Source (Rust Developers)
Requires Rust (stable toolchain).
cargo install --path .
This installs the wai binary to ~/.cargo/bin/.
⚠️ WARNING: Ensure
~/.cargo/bin/is in your PATH and has precedence. If you’ve previously installedwaivia a package manager, the cargo version might be shadowed.
Verify Installation
which wai # Check which binary is being used
wai --version # Check version
wai --help # Check help
Common Installation Issues
“wai: command not found”
Problem: The directory containing the wai binary is not in your shell’s PATH.
Solution (macOS/Linux):
Add this to your shell profile (.bashrc, .zshrc, or .profile):
export PATH="$HOME/.cargo/bin:$PATH"
Solution (Windows):
Add %USERPROFILE%\.cargo\bin to your User PATH environment variable.
Quick Start
Get up and running with wai in 5 minutes.
1. Run the Interactive Tutorial
The best way to learn is by doing. Run:
wai tutorial
This interactive guide covers the PARA method, project phases, and basic commands in a safe sandbox.
2. Initialize Your Workspace
Navigate to your project directory and initialize:
wai init
This creates a .wai/ directory as the single source of truth for all reasoning and workflow state. Everything wai tracks lives here: artifacts, configs, plugin definitions, and project metadata. Commit this directory alongside your code.
3. Create a Project
In wai, a “Project” is an active work item with a specific goal. Create your first one:
wai new project my-feature
Projects use phases instead of jumping straight to code. This ensures research and design reasoning exist before implementation. When you or an agent revisits the project later, the why is already captured.
4. Capture Research
Projects start in the Research phase. Record your initial thoughts or findings:
wai add research "Evaluated options A and B. Choosing A for performance."
This creates a dated Markdown artifact in .wai/projects/my-feature/research/. The artifact persists across sessions and won’t disappear when an agent’s context resets.
5. Advance Through Phases
As your work progresses, advance the project’s phase:
# Advance: Research → Design
wai phase next
# Add a design artifact
wai add design "New API will use standard REST patterns."
# Optionally: deliberate the design with a decision matrix (opt-in)
wai matrix init "Which storage engine should we adopt?"
wai matrix approach add event-sourcing
wai matrix criterion add operational-cost
# fill cells by writing files directly:
# echo "Full audit trail." > .wai/projects/myproj/designs/matrix/approaches/02-event-sourcing/01-operational-cost/fact.md
# touch .wai/projects/myproj/designs/matrix/approaches/02-event-sourcing/01-operational-cost/green
wai matrix decide "02-event-sourcing" "Best audit story at acceptable ops cost."
wai phase next # gate checks the matrix is decided and current
Phases (research → design → plan → implement → review → archive) guide what kind of work and artifacts are expected at each stage. They’re flexible — skip forward or go back as needed. Projects without a decision matrix skip the gate entirely — see Decision Matrix.
6. Check Your Progress
Get a context-aware overview of your workspace:
wai status
Status is the context-aware next-step command. It shows active projects, their current phases, plugin context (git status, open issues), and smart suggestions for what to do next based on your current state. It’s the first thing to run at the start of any session.
Next Steps
Now that you’ve got the basics down, explore the more powerful features of wai:
- Commands Reference — Comprehensive list of all commands and flags.
- PARA Method — Learn how
waiorganizes your work. - Project Phases — Master the workflow from Research to Archive.
- Sessions — The prime→close lifecycle for session continuity.
- Agent Config Sync — Keep your AI tools in sync.
Troubleshooting
If you run into issues, check the Troubleshooting guide or run:
wai doctor # Check workspace health
Commands
Complete CLI reference for wai.
Table of Contents
- Global Flags
- Workspace & Initialization
- Projects & Artifacts
- Agent Configuration
- AI-Driven Workflows
- Decision Matrix
- Plugin System
- Doctor & Health Checks
Global Flags
Available for all commands:
| Flag | Description |
|---|---|
-v, --verbose | Increase verbosity (-v, -vv, -vvv) |
-q, --quiet | Suppress non-error output |
--json | Output machine-readable JSON |
--no-input | Disable interactive prompts |
--yes | Auto-confirm actions with defaults |
--safe | Run in read-only safe mode (blocks write operations) |
Safe mode
--safe prevents all write operations. Commands that modify state — add, sync, move, pipeline start/next/init/approve/lock/bypass, phase next/back/set, and import — will exit with an error. Read-only commands like status, search, doctor, pipeline verify, and pipeline current work normally.
Workspace & Initialization
Commands for managing the wai workspace and checking repo hygiene.
| Command | Description |
|---|---|
wai init [--name <name>] | Initialize wai in current directory |
wai tutorial | Run interactive quickstart tutorial |
wai ls [--root <dir>] [--depth <n>] [--timeout <sec>] | List all wai workspaces under a root directory (default: $HOME) |
wai doctor [--fix] | Diagnose and repair wai workspace health (see checks) |
wai way [--fix <CHECK>] | Check and scaffold repository best practices |
wai import <path> | Import existing tool configs (.claude/, .cursorrules) |
wai init
Creates the .wai/ directory structure and a default config.toml in the current repository. Run once per repo. If you omit --name, wai uses the directory name.
# Initialize in the current repo
wai init
# Initialize with an explicit workspace name
wai init --name "my-api"
Note:
wai initis idempotent — running it again in an initialized repo only fills in missing files; it won’t overwrite your existing config or artifacts.
wai import
Pulls in existing tool configuration files from another tool’s directory (e.g., .claude/, .cursorrules) and registers them as wai-managed agent configs. Useful when adopting wai in a repo that already has agent instructions. See Adopt Wai in an Existing Repo for a step-by-step guide.
# Import Claude Code config from .claude/
wai import .claude/
# Import from a Cursor rules file
wai import .cursorrules
wai way
Audits your repository against AI-friendliness best practices: checks for CLAUDE.md, .editorconfig, skill files, and similar scaffolding. Unlike wai doctor, which focuses on the .wai/ workspace, wai way focuses on the repository as a whole.
It also runs a project artifact completeness check: scans
.wai/projects/<project>/{research,handoffs,designs,plans,reviews}/ for
stub documents (frontmatter plus fewer than 5 body lines), so
session-mined findings don’t silently evaporate. Single-line structured
records (UPPERCASE-KEY: ...) are exempt.
# Check which best practices are missing
wai way
# Scaffold any missing skill files
wai way --fix skills
Choosing the Right Tool
- Use
wai doctorwhen your.wai/directory is missing, a project phase is stuck, or a sync command is failing. - Use
wai waywhen you want to improve your overall repository for AI friendliness (e.g., addingCLAUDE.md,.editorconfig, orSKILL.mdfiles).
Projects & Artifacts
Items & Phases
| Command | Description |
|---|---|
wai new project <name> | Create a new project (also new area, new resource) |
wai move <item> <category> | Move an item between PARA categories |
wai status [--json] | Check project status and suggest next steps |
wai show [<name>] | Show PARA overview or details for a specific item |
wai phase [show|next|back|set] | Show or change the current project phase |
Available phases: research, design, plan, implement, review, archive
See Project Phases and Organizing with PARA for conceptual background.
wai new
Creates a new PARA item and scaffolds its directory structure under .wai/.
# Start a new feature project
wai new project user-auth
# Create an area for ongoing work
wai new area platform-reliability
# Add a shared resource
wai new resource api-design-guidelines
wai move
Moves an item between PARA categories. Use this when a project completes and needs archiving, or when scope shifts (e.g., a finished project becomes an area of ongoing maintenance).
# Archive a finished project
wai move user-auth archives
# Promote a resource to an active project
wai move api-design-guidelines projects
wai status
Shows the active project, current phase, recent activity, and next-step suggestions. Run this at the start of a session to orient yourself.
wai status
wai status --json | jq '.projects[].phase'
wai show
Without arguments, shows a PARA overview of all items. With a project name, shows that project’s phase, artifacts, and recent history.
# Overview of all projects and areas
wai show
# Detailed view of a specific project
wai show user-auth
wai phase
Reads or changes the current project phase. Phases gate which artifact types are expected, for example, you should add research before advancing to design.
# Check the current phase
wai phase show
# Advance to the next phase
wai phase next
# Jump to a specific phase
wai phase set implement
# Step back one phase (e.g., to add missing design artifacts)
wai phase back
Note:
wai phase nextdoes not prevent you from advancing even if the current phase has no artifacts — it just changes the phase label. Missing artifacts will show up inwai statussuggestions.
Adding Artifacts
| Command | Description |
|---|---|
wai add research <content> | Add research notes (also plan, design) |
wai add review --reviews <filename> | Add a review artifact for an existing artifact |
wai add <type> --file <path> | Import artifact from file |
wai add <type> --tags <tags> | Add tagged artifact (frontmatter-based) |
wai add <type> --bead <id> | Link artifact to a beads issue ID |
wai add <type> --project <name> | Add to specific project (instead of current) |
wai add <type> --corrects <path> | Create an addendum correcting a locked artifact |
Artifacts are the core of wai — they capture the why behind your decisions so future agents and contributors can reconstruct your reasoning. Each artifact is a Markdown file timestamped and stored under .wai/projects/<name>/<type>/.
Choosing an Artifact Type
- Research (
wai add research) — Use for gathering information, exploring problem spaces, and evaluating options.- Example: “Evaluated two DB engines; chose PostgreSQL for its JSONB support.”
- Design (
wai add design) — Use for making architectural decisions and defining system structure.- Example: “Proposed microservices architecture with EventBridge for communication.”
- Plan (
wai add plan) — Use for breaking down implementation into specific, actionable steps.- Example: “Step 1: Scaffold auth service. Step 2: Implement JWT middleware.”
- Review (
wai add review) — Use for recording validation results against an existing artifact.- Example:
wai add review --reviews 2026-04-15-findings.md --verdict pass --severity "critical:0,high:1" - Requires
--reviews <filename>to specify the target artifact. - Optional:
--verdict(pass/fail/needs-work),--severity(level:count pairs),--produced_by(skill name).
- Example:
Examples
# Capture a quick research note inline
wai add research "Considered Redis vs Memcached; chose Redis for pub/sub support"
# Import a detailed design from a file
wai add design --file architecture-decision.md
# Link an artifact to a beads issue for traceability
wai add plan "Scaffold the service layer first" --bead wai-abc1
# Add a research note to a specific project (not the active one)
wai add research "Benchmark results" --project payment-service
# Correct a locked artifact without modifying the original
wai add research --corrects .wai/projects/auth/research/2026-01-10.md \
"Correction: the Redis pub/sub approach has 50ms latency at scale"
Note on
--corrects: You can only correct a locked artifact (one with a SHA-256 sidecar). To lock an artifact, runwai pipeline lockat the relevant pipeline step. The correction is stored as a linked addendum — the original is not modified.
Searching & Timeline
| Command | Description |
|---|---|
wai search <query> | Search across all artifacts |
wai search --type <type> | Filter by type (research/plan/design/handoff) |
wai search --in <project> | Search within specific project |
wai search --tag <tag> | Filter by tag (repeatable) |
wai search --regex | Use regex patterns for query |
wai search --latest | Return only the most recently dated match |
wai search -C <n> | Show N lines of context around each match |
wai search --include-memories | Include bd memories in search results |
wai timeline <project> | View chronological project timeline |
wai timeline --from <date> | Filter by date range (YYYY-MM-DD) |
wai search
Searches artifact content across your wai workspace. Results include file paths and matching lines. Use --latest to find the most recent decision on a topic rather than all mentions.
# Find all artifacts mentioning a topic
wai search "authentication"
# Find only the most recent research on a topic
wai search "database" --type research --latest
# Regex search with context lines
wai search "api.*error" --regex -C 3
# Search within a specific project
wai search "caching" --in payment-service
# Include bd memories in the search sweep
wai search "retry policy" --include-memories
wai timeline
Shows all artifacts for a project in chronological order, making it easy to trace how a decision evolved across sessions.
wai timeline user-auth
wai timeline user-auth --from 2026-01-01 --to 2026-03-01
Agent Configuration
See Agent Config Sync for how projections work.
| Command | Description |
|---|---|
wai sync | Overwrite agent configs to tool-specific locations |
wai sync --status | Check sync status without modifying files |
wai sync --from-main | Sync resources from main git worktree |
wai config list | List all agent config files |
wai config add <type> <file> | Add agent config (skill/rule/context) |
wai config edit <path> | Safe: Edit config file in $EDITOR |
wai resource list skills | List all available skills |
wai add skill <name> [--template <tpl>] | Scaffold a new skill (templates: gather, create, tdd, rule-of-5, ubiquitous-language) |
wai resource install <skill> [--global|--from-repo <path>] | Install a skill globally or from another repo |
wai resource export <skills...> --output <file> | Export skills to a tar.gz archive |
wai resource import skills [--from <dir>] | Import skills from a directory |
wai resource import archive <file> [--yes] | Import skills from a tar.gz archive |
⚠️ WARNING:
wai syncis destructive to your target files. Target locations are defined in.wai/resources/agent-config/.projections.yml— the built-inclaude-codetarget writes to.claude/commands/. Always edit the.wai/source files; changes to the projected copies will be overwritten on the next sync.
wai sync
Writes your .wai/ agent configs out to their tool-specific target locations. Run after editing any config in .wai/ to push changes out to the agent tools.
# Write all configs to their targets
wai sync
# Preview what would change without writing
wai sync --status
# Sync from main branch when working in a git worktree
# (use when .wai/ lives on main but your branch doesn't have it)
wai sync --from-main
wai config
Manages the list of agent config files tracked by wai. Use wai config add to register a new file and wai config edit to safely modify a tracked config in your editor (edits the source in .wai/, not the projected copy).
# See what config files are registered
wai config list
# Register a new skill file
wai config add skill .wai/resources/skills/my-skill.md
# Edit a tracked config (opens $EDITOR on the source file)
wai config edit .wai/resources/skills/my-skill.md
wai resource — Skill Lifecycle
Skills are reusable agent instruction files. Use wai resource to list, install, scaffold, or share them.
# See all available skills in this workspace
wai resource list skills
# Scaffold a new TDD skill from a template
wai add skill my-tdd-workflow --template tdd
# Install a skill from another repo (e.g., a shared team template)
wai resource install code-review --from-repo ../shared-skills
# Install globally so all your repos can use it
wai resource install deploy-checklist --global
wai add skillvswai config add: Usewai add skillto scaffold a new skill from a template (creates the file and registers it). Usewai config add skill <file>to register an existing file you created manually.
wai resource — Import/Export
Share skill bundles between repositories or teams using tar.gz archives.
# Export a set of skills to a shareable archive
wai resource export code-review deploy-checklist --output team-skills.tar.gz
# Import skills from a directory
wai resource import skills --from ../shared-skills/
# Import from an archive (prompts for confirmation per skill)
wai resource import archive team-skills.tar.gz
# Import from an archive without prompts
wai resource import archive team-skills.tar.gz --yes
AI-Driven Workflows
These commands require an LLM backend. Run wai why --no-llm or configure a provider before using them in automated contexts. See LLM Configuration under wai why.
Reasoning & Reflection
See Reasoning for conceptual background on how wai why and wai reflect work.
| Command | Description |
|---|---|
wai why <query> | Ask why a decision was made (LLM-powered) |
wai why <file-path> | Explain a file’s history and rationale |
wai reflect | Synthesize session context into a resource file |
wai reflect --save-memories | Save reflection bullets to bd memories |
wai why
Answers natural-language questions about your project by combining .wai/ artifacts with git history and querying an LLM. Results include an answer, a decision chain, and references to the artifacts that informed it.
# Ask a decision question
wai why "Why did we choose TOML over YAML for config?"
# Explain a specific file's history
wai why src/plugin.rs
# Run without LLM — falls back to wai search (useful offline)
wai why --no-llm "plugin architecture"
Backend selection and fallback behavior:
Wai auto-detects the available LLM backend in this order: Agent (if inside a Claude Code session), Claude API (ANTHROPIC_API_KEY), Claude CLI binary, Ollama. If no backend is available:
- By default, wai falls back to
wai searchon the same query (equivalent to--no-llm). - Set
fallback = "error"in[llm]config to get an explicit error instead.
# .wai/config.toml
[llm]
fallback = "error" # "search" (default) or "error"
Agent mode (zero-cost inside Claude Code):
When running inside a Claude Code session, set llm = "agent" to route the query through your agent instead of calling the API directly:
[llm]
llm = "agent"
Privacy: The first time you use an external backend (Claude API or Claude CLI), wai displays a privacy notice explaining that your artifact content will be sent to an external service. Set
privacy_notice_shown = truein[llm]to suppress it after you’ve acknowledged it.
wai reflect
Synthesizes accumulated session context (handoffs, research, conversation history) into a versioned reflection file in .wai/resources/reflections/. Run approximately every 5 sessions.
# Synthesize and write a reflection file
wai reflect
# Also save key bullets to bd memories for cross-session retrieval
wai reflect --save-memories
The reflection is automatically woven into managed blocks in CLAUDE.md / AGENTS.md so the next agent session starts with the patterns, conventions, and gotchas extracted from your session history. See Reasoning for the full synthesis cycle.
Session Management
See Sessions for the session lifecycle and how handoffs preserve context.
| Command | Description |
|---|---|
wai prime [--project <name>] | Orient at session start: phase, last handoff, next step |
wai close [--project <name>] | Wrap up session: create handoff and next steps |
wai handoff create <project> | Generate handoff document with plugin context |
wai prime
Runs at the start of a session to orient you: reads the last handoff, reports the current phase, and surfaces the next suggested step. It also lists the Prior context — the 5 newest research/design/review docs of the active project — so you don’t re-run investigations that already happened. Most Claude Code setups call this automatically via a startup hook.
# Orient for the active project
wai prime
# Orient for a specific project
wai prime --project payment-service
wai close
Wraps up the current session by creating a handoff document summarizing what was done and what comes next. Always run this before ending a session — it ensures the next session can resume cleanly. A startup hook in Claude Code detects a pending handoff and recovers context automatically.
# Close the active project session
wai close
# Close a specific project
wai close --project user-auth
Workflow:
wai closecallswai handoff createinternally. You rarely needwai handoff createdirectly unless you want a handoff mid-session without closing.
wai handoff
Generates a handoff document capturing the current session state, plugin context (beads status, openspec state), and next steps. Called automatically by wai close.
# Generate a handoff explicitly (mid-session)
wai handoff create user-auth
Feedback
File an issue against wai’s upstream repository with environment context attached.
| Command | Description |
|---|---|
wai feedback bug [--title <title>] | File a bug report with context |
wai feedback --from-last-error | Build report from the last wai error |
wai feedback --dry-run | Preview the issue without filing |
wai feedback
Automatically gathers environment context (OS, wai version, git remote, debug logs),
redacts secrets and paths, then files a GitHub issue via gh (with a fallback ladder
to --web or manual copy-paste).
# File a bug report (prompts for kind and title)
wai feedback bug
# File from the last error (derives title and body automatically)
wai feedback --from-last-error
# Preview what would be filed
wai feedback friction --title "slow startup" --dry-run
# Open a prefilled browser URL instead of using gh
wai feedback bug --title "crash on init" --web
Pipelines
See Pipelines for conceptual background on pipeline structure and gates.
| Command | Description |
|---|---|
wai pipeline list | List all available pipelines |
wai pipeline show <name> | View steps and gates for a pipeline |
wai pipeline init <name> | Scaffold a new TOML pipeline definition |
wai pipeline start <name> --topic="..." | Start a run with topic substitution |
wai pipeline next | Advance to the next step in the active run |
wai pipeline current | Reprint current step prompt (session recovery) |
wai pipeline status <name> | Show run status (use --run <id> for details) |
wai pipeline suggest [description] | Rank pipelines by keyword match |
wai pipeline gates [name] [--step=<id>] | Show gate requirements and live status |
wai pipeline check [--oracle=<name>] | Dry-run gate evaluation without advancing |
wai pipeline approve | Record human approval for current step |
wai pipeline validate [name] | Validate pipeline TOML definitions |
wai pipeline bypass <reason> | Record a disclosed gate bypass in the active run’s ledger (silent no-op with no active run) |
wai pipeline lock | Lock current step’s artifacts (SHA-256 hash sidecars) |
wai pipeline verify | Verify integrity of all locked artifacts |
# Start a research pipeline
wai pipeline start scientific-research --topic="Effect of caching on P99 latency"
# Check what step you're on after a session break
wai pipeline current
# See what gates must pass before advancing
wai pipeline gates scientific-research --step=generate
# Advance once gates are satisfied
wai pipeline next
# Lock artifacts at a milestone step
wai pipeline lock
Decision Matrix
Manage the project’s decision matrix (Design in Practice methodology). See Decision Matrix for the full model.
wai matrix init
wai matrix init "Which storage engine should we adopt?"
Scaffolds .wai/projects/<project>/designs/matrix/: problem.md (the A1),
criteria/, approaches/01-status-quo/ with _description.md, and an empty
decision.md template (never counts as decided). One matrix per project —
re-init fails and names the existing matrix.
wai matrix criterion add
wai matrix criterion add operational-cost
Creates criteria/NN-<name>.md and an empty cell directory in every
existing approach (rectangular by construction).
wai matrix approach add
wai matrix approach add event-sourcing
Creates approaches/NN-<name>/ with _description.md and an empty cell
directory for every existing criterion.
wai matrix decide
wai matrix decide "02-event-sourcing" "Best audit story at acceptable ops cost."
Validates the approach exists (errors list valid names), writes decision.md
(approach, rationale, UTC timestamp, design-doc pointer), and scaffolds
designs/<date>-<slug>.md with frontmatter and a decision-time snapshot of
the winning column’s facts.
wai matrix lint
wai matrix lint
Structural errors (non-zero exit): rectangularity, one marker per filled
cell, no empty fact.md, status-quo first. Methodology warnings (never
block): all-green column, undistinguished columns, judgment-in-text,
link-only cells, criteria-as-questions, status-quo-without-red,
decided-with-unfilled-cells, empty problem.md, stale decision.
wai matrix render
wai matrix render && open .wai/projects/<project>/designs/matrix/matrix.html
Generates a self-contained matrix.html (inline CSS, no JS) as a pure
function of the directory state — byte-identical for equal state. It is a
generated view: never committed, always regenerable.
All subcommands accept --project <name> (otherwise resolved via
WAI_PROJECT or auto-detection).
Plugin System
| Command | Description |
|---|---|
wai plugin list | List all plugins (built-in and custom) |
wai plugin enable <name> | Enable a plugin |
wai <plugin> <command> | Pass-through to plugin commands (e.g. wai beads list) |
See Plugin System for how auto-detection and pass-through work.
# See which plugins are active
wai plugin list
# Pass a command through to the beads plugin
wai beads ready
# Pass a command through to the openspec plugin
wai openspec list
Doctor Checks
wai doctor runs the following checks. Use --fix to auto-repair where possible.
# Run all checks
wai doctor
# Auto-fix any repairable issues
wai doctor --fix
| Check | What it verifies |
|---|---|
| Directory structure | Required .wai/ subdirectories exist |
| Configuration | .wai/config.toml is parseable and valid |
| Version | Config version is compatible with installed wai |
| Plugin tools | External tools (git, beads, openspec) are installed and reachable |
| Agent config sync | Projections are in sync between source and target files |
| Project state | Phase state files are valid and consistent |
| Custom plugins | TOML plugin definitions parse correctly |
| README badge | Repository README includes a wai badge |
| Claude Code session hook | Claude Code hooks are configured for wai |
| Skills in repo | Skill files are valid and importable |
| Agent tool coverage | Agent instructions reference available skills |
| Agent instructions | CLAUDE.md / AGENTS.md files are present and well-formed |
| Managed block staleness | Auto-generated sections are up to date |
| Pipeline definitions | Pipeline TOML files parse correctly with valid gates |
| WAI_PROJECT env var | Environment variable matches active project |
| Artifact locks | Locked artifacts match their SHA-256 hashes |
Examples
Basic Workflow
# Initialize and create project
wai init
wai new project my-feature
# Orient at session start
wai prime
# Capture research before designing
wai add research "Evaluated options A and B, chose A for performance"
wai phase next
# Add design decisions
wai add design "Architecture uses microservices pattern"
wai phase next
# Close session with a handoff
wai close
Search and Timeline
# Search with filters
wai search "authentication" --type research
wai search "api.*error" --regex -C 3
# Find the most recent decision on a topic
wai search "caching strategy" --latest
# View project history
wai timeline my-feature
wai timeline my-feature --from 2026-02-01 --to 2026-02-15
Reasoning
# Ask a question grounded in your artifacts
wai why "Why did we choose event sourcing over CQRS?"
# Explain a file's purpose from its git history
wai why src/event_store.rs
# Force offline/search mode
wai why --no-llm "event store design"
# Synthesize accumulated context into a reflection
wai reflect
JSON Output for Automation
# Get structured data
wai status --json | jq '.projects[] | .name'
wai search "config" --json | jq '.results[].path'
wai plugin list --json
wai way --json | jq '.summary.pass'
Troubleshooting
Common issues and solutions for wai.
Commands Not Working
“wai: command not found”
Problem: Wai is not in your PATH after installation.
Solution:
# Check if cargo bin is in PATH
echo $PATH | grep cargo
# If not, add to your shell profile (~/.bashrc, ~/.zshrc, etc.)
export PATH="$HOME/.cargo/bin:$PATH"
# Reload shell
source ~/.bashrc # or ~/.zshrc
“Project not found” or “Not initialized”
Problem: Running wai commands outside of an initialized directory.
Solution:
# Check if you're in a wai workspace
ls -la .wai/
# If not, initialize or navigate to the correct directory
wai init
# or
cd /path/to/your/wai/workspace
Error example:
Error: wai::error::not_initialized
╭─[command]
│ wai status
╰────
help: Run 'wai init' to initialize wai in this directory
Sync Issues
⚠️ WARNING:
wai syncis destructive to your target files (e.g.,.cursorrules,.claude/config.json). It will overwrite any manual changes in these files with the versions from your.wai/resources/agent-config/source directory.
Sync conflicts - target file manually edited
Problem: You edited a synced file directly and wai sync overwrote your changes, or you want to keep manual changes before syncing.
Solution:
- Always edit source files, not targets. Use
wai config listto find sources. - If you’ve already edited the target, back up your changes before running
wai sync. - Use
wai sync --statusto see what will be changed before applying.
# Recommended workflow:
# 1. Check status
wai sync --status
# 2. Edit the source file correctly
wai config edit rules/my-rule.md
# 3. Apply sync
wai sync
Symlinks not working on Windows
Problem: Symlink strategy fails on Windows.
Solution: Wai automatically falls back to file copies on Windows. If you see errors:
# Check sync status
wai sync --status
# Run doctor to diagnose
wai doctor
# Try auto-fix
wai doctor --fix
Alternatively, switch to inline or reference strategy in .projections.yml.
“Permission denied” during sync
Problem: Wai can’t write to target directory.
Solution:
# Check target directory permissions
ls -ld .claude/
# Fix permissions
chmod u+w .claude/
# Or run sync with appropriate permissions
sudo wai sync # Last resort, not recommended
Plugin Issues
Plugin not detected
Problem: Plugin shows as “not detected” in wai plugin list.
Solution:
# Check if detector file/directory exists
ls -la .beads/ # for beads
ls -la .git/ # for git
ls -la openspec/ # for openspec
# Install the plugin tool
cargo install beads # or appropriate installation
# Verify detection
wai plugin list
Custom plugin not loading
Problem: TOML plugin in .wai/plugins/ not appearing.
Solution:
# Check TOML syntax
cat .wai/plugins/my-plugin.toml
# Verify file extension (.toml)
ls .wai/plugins/
# Check for TOML errors
wai doctor
# Example valid plugin:
cat > .wai/plugins/example.toml << 'EOF'
name = "example"
description = "Example plugin"
[detector]
type = "directory"
path = ".example"
[[commands]]
name = "status"
description = "Show status"
passthrough = "example status"
read_only = true
EOF
Plugin command fails
Problem: wai <plugin> <command> returns an error.
Solution:
# Verify plugin tool is installed and in PATH
which beads
which mytool
# Test command directly
beads list
mytool status
# Check plugin definition
wai plugin list --json | jq '.plugins[] | select(.name=="myplugin")'
Search & Timeline Issues
Search returns no results
Problem: Can’t find artifacts you know exist.
Solution:
# Check if you're searching the right project
wai search "query" --in project-name
# Try without filters
wai search "query"
# Use case-insensitive search (regex mode)
wai search "(?i)query" --regex
# Verify artifacts exist
wai timeline my-project
wai show my-project
Timeline shows wrong dates
Problem: Artifacts appear in unexpected order.
Solution: Timeline is sorted by filename date (YYYY-MM-DD prefix). Artifacts are created with the current date by default.
# Check actual filenames
ls .wai/projects/my-project/research/
# Files are named: YYYY-MM-DD-slug.md
# Timeline sorts by this date, not file modification time
Doctor Command Issues
Doctor runs 16 checks covering directory structure, configuration, plugins, agent configs, pipelines, artifact locks, and more. See the full list in Commands — Doctor Checks.
Doctor reports issues but –fix doesn’t work
Problem: wai doctor --fix doesn’t repair all issues.
Solution: Some issues require manual intervention:
# Run doctor to see all issues
wai doctor
# Check which issues can't be auto-fixed
# Doctor will show suggestions for manual fixes
# Common manual fixes:
# 1. Corrupted config - restore from backup or re-init
# 2. Missing directories - create manually or re-init
# 3. Permission issues - fix with chmod/chown
Doctor false positives
Problem: Doctor reports issues that aren’t actually problems.
Solution:
# Check specific validation
wai doctor --json | jq .
# Some "warnings" are informational
# Only "error" severity items need fixing
# If you believe it's a false positive, file an issue:
# https://github.com/charly-vibes/wai/issues
Artifact Integrity Issues
Locked artifact verification fails
Problem: wai pipeline verify or wai doctor reports hash mismatches.
Solution: A mismatch means a locked artifact was modified after locking. This can happen if you edited it directly instead of creating an addendum.
# See which artifacts failed
wai pipeline verify
# If the edit was intentional, create an addendum instead:
# 1. Restore the original (git checkout the file)
git checkout -- .wai/projects/my-project/research/2026-04-15-findings.md
# 2. Record corrections as an addendum
wai add research --corrects=.wai/projects/my-project/research/2026-04-15-findings.md "corrected details"
# 3. Verify again
wai pipeline verify
If you need to re-lock after a legitimate change, delete the .lock sidecar and run wai pipeline lock again.
“artifact missing” in verify output
Problem: A .lock file references an artifact that no longer exists.
Solution:
The artifact was deleted after locking. Either restore it from git history or remove the orphaned .lock file:
# Find orphaned lock files
wai pipeline verify
# Restore from git
git checkout -- <path-to-artifact>
# Or remove the orphaned lock
rm <path-to-artifact>.lock
Phase Management Issues
Can’t advance to next phase
Problem: wai phase next doesn’t work or gives unexpected results.
Solution:
# Check current phase
wai phase show
# Phases are: research → design → plan → implement → review → archive
# Can't advance past archive
# If stuck, set phase directly
wai phase set implement
# Check phase history
wai phase show # Shows all transitions
Phase history looks wrong
Problem: Phase history shows unexpected transitions.
Solution:
Phase history is stored in .wai/projects/<name>/.state. This file tracks all transitions with timestamps.
# View state file
cat .wai/projects/my-project/.state
# If corrupted, you can manually edit (advanced)
# Or reset to a phase:
wai phase set research # Starts fresh from research
Artifact Issues
Tags not working
Problem: Tags don’t appear or can’t search by tags.
Solution: Tags are stored in YAML frontmatter for research artifacts:
# Add tags correctly (comma-separated, no spaces around commas)
wai add research "Finding" --tags "api,security,auth"
# NOT: --tags "api, security, auth" # Extra spaces cause issues
# Check frontmatter
head -10 .wai/projects/my-project/research/*.md
# Should see:
# ---
# tags: [api, security, auth]
# ---
Can’t import file
Problem: wai add research --file path.md fails.
Solution:
# Check file exists and is readable
ls -la path.md
cat path.md
# Use absolute or relative path
wai add research --file ./notes/research.md
wai add research --file /full/path/to/research.md
# Check file isn't binary
file notes/research.md # Should say "text"
JSON Output Issues
JSON output malformed
Problem: --json flag produces invalid JSON.
Solution:
# Ensure no extra output
wai status --json --quiet
# Check for errors on stderr
wai status --json 2>&1 | jq .
# Validate JSON
wai status --json | jq empty
Can’t parse JSON in scripts
Problem: Automation scripts fail to parse wai JSON output.
Solution:
# Capture only stdout
wai status --json 2>/dev/null | jq .
# Handle errors separately
if ! output=$(wai status --json 2>&1); then
echo "Error: $output" >&2
exit 1
fi
echo "$output" | jq .
Performance Issues
Commands are slow
Problem: Wai commands take a long time to execute.
Solution:
# Check project size
du -sh .wai/
# Large artifact counts can slow search/timeline
find .wai/projects -name "*.md" | wc -l
# Use filters to limit scope
wai search "query" --in specific-project -n 10
wai timeline project --from 2026-02-01
# For very large projects, consider archiving old work
wai move old-project archives
Getting Help
Where to find more help
Resources:
- Built-in help:
wai <command> --help - Verbose help:
wai --help -v(shows advanced options) - Status check:
wai doctor(diagnoses workspace issues) - GitHub Issues: https://github.com/charly-vibes/wai/issues
- Documentation: Check
docs/directory
Filing a bug report
Include:
- Wai version:
wai --version - Operating system:
uname -a - Command that failed: Full command with flags
- Error message: Complete error output
- Doctor output:
wai doctor
# Create comprehensive debug report
{
echo "=== Version ==="
wai --version
echo -e "\n=== System ==="
uname -a
echo -e "\n=== Doctor ==="
wai doctor
echo -e "\n=== Config ==="
cat .wai/config.toml
} > wai-debug-report.txt
Then attach wai-debug-report.txt to your issue.
PARA Method
Why PARA? Without structure, project artifacts end up scattered across flat directories, wikis, Slack threads, and local notes. Finding that design decision from three weeks ago becomes an archaeological dig. PARA gives every artifact a clear home based on its lifecycle stage — active work goes in Projects, ongoing responsibilities in Areas, reference material in Resources, and completed work in Archives. You always know where to look.
Wai organizes artifacts using the PARA method — a system for organizing digital information into four categories:
.wai/
├── projects/ ← Active work with a goal and phases
│ ├── auth-feature/ research/ designs/ plans/ handoffs/
│ └── api-redesign/ research/ designs/ plans/ handoffs/
├── areas/ ← Ongoing responsibilities (no end date)
│ └── security/
├── resources/ ← Reference material and reusable assets
│ ├── agent-config/ skills/ rules/ context/
│ ├── reflections/
│ └── pipelines/
└── archives/ ← Completed items (searchable, hidden from status)
└── old-feature/
Projects
Active work with a defined goal and deadline. Each project has its own directory under .wai/projects/ containing research notes, plans, designs, and handoff documents.
.wai/projects/my-app/
├── .state # Phase state machine (YAML)
├── research/ # Date-prefixed research notes
├── plans/ # Date-prefixed plan documents
├── designs/ # Date-prefixed design documents
└── handoffs/ # Date-prefixed handoff documents
Areas
Ongoing areas of responsibility with no end date. These live under .wai/areas/.
Resources
Reference material and reusable assets. Stored under .wai/resources/:
.wai/resources/
├── agent-config/ # Single source of truth for agent configs
│ ├── skills/
│ ├── rules/
│ ├── context/
│ └── .projections.yml
├── templates/
└── patterns/
Archives
Completed or inactive items moved here for reference. Located at .wai/archives/.
Moving between categories
Use wai move to reclassify items as their status changes:
wai move my-app archives # Archive a completed project
Project Phases
Why phases? When teams skip straight to code, they build the wrong thing — or the right thing the wrong way. Decisions get made implicitly, trade-offs go unrecorded, and the first sign of trouble triggers a rewrite. Formalizing research → design → plan → implement → review → archive doesn’t slow you down; it forces the reasoning to exist before the code, so when you revisit the project later, the why is already captured.
Projects in wai progress through six phases:
┌──────────────────────────────────────────┐
│ │
▼ │
┌──────────┐ ┌────────┐ ┌──────┐ ┌─────────────┐ ┌────────┐ ┌─────────┐
│ research │──▶│ design │──▶│ plan │──▶│ implement │──▶│ review │──▶│ archive │
└──────────┘ └────────┘ └──────┘ └─────────────┘ └────────┘ └─────────┘
▲ ▲ │
└──────────────┴────────────────────────┘
(back-transitions allowed)
Phases
- Research — Gather information, explore the problem space, understand constraints
- Design — Define architecture, make key decisions, document trade-offs
- Plan — Break work into tasks, define milestones, set priorities
- Implement — Build the solution, write code, integrate components
- Review — Validate the work, run tests, gather feedback
- Archive — Complete the project, generate final handoff, move to archives
Managing phases
wai phase # Show current phase
wai phase next # Advance to next phase
wai phase back # Return to previous phase
wai phase set design # Jump to a specific phase
Flexibility
Transitions are flexible — skip forward or go back as needed. Phase history is tracked with timestamps so you can see how a project evolved over time.
Adding artifacts by phase
Each phase has associated artifact types. Wai encourages capturing the right kind of documentation at each stage:
- Research phase →
wai add research "..." - Design phase →
wai add design "..." - Plan phase →
wai add plan "..."
Archive Phase vs. Category
The word “archive” is used in two ways in wai, and they serve different purposes:
1. The Archive Phase (wai phase set archive)
This is a status for a project. It indicates that the project is complete, all final handoffs are generated, and no further work is planned. It stays in its current PARA category (usually Projects).
Use when: A project is finished but you still want it to appear in wai status and your active workspace overview.
2. The Archives Category (wai move my-project archives)
This is a storage location. Moving an item to archives reclassifies it in the PARA system, moving its directory from .wai/projects/ to .wai/archives/.
Use when: You want to declutter your workspace. Archived items are hidden from default wai status views and most context suggestions, but remain fully searchable.
Recommended Workflow:
- Set phase to
archivewhen the work is done. - Generate a final handoff (
wai close). - Move to the
archivescategory when you no longer need it in your active projects list.
Sessions
Context is expensive. Every time an AI agent starts a new session, it begins with a blank slate — no memory of what was tried, what failed, or what decision was made and why. Humans face the same problem at smaller scale: you close your laptop Friday, and by Monday the thread of reasoning has frayed.
Wai’s session lifecycle exists to solve this: capture context at the end of a session, and restore it at the beginning of the next one.
The Prime → Work → Close Loop
A wai session follows a three-step loop:
┌─────────┐ ┌──────┐ ┌───────┐
│ prime │ ───▶ │ work │ ───▶ │ close │
└─────────┘ └──────┘ └───────┘
▲ │
└──────────────────────────────┘
-
wai prime— Orient yourself. Prime reads the latest handoff, shows active projects and their phases, surfaces plugin context (git status, open issues), and suggests next steps. It also warns (advisory, silent when green) on cross-agent collision signals: agent-provenance stash entries and unexpired agent lock-files under.wai/. If a previous session was interrupted, it detects this automatically. -
Work — Do your actual work: add artifacts, advance phases, write code. Wai stays out of the way.
-
wai close— Capture state. Close generates a handoff document summarizing the session, writes a.pending-resumesignal, and shows what to do before ending (close issues, commit, push).
Resume Detection
When you run wai prime after a wai close, wai checks for a .pending-resume file. If one exists and is less than 12 hours old, prime enters ⚡ RESUMING mode:
- It reads the linked handoff document
- Extracts the
## Next Stepssection - Displays them prominently so you (or an agent) can pick up exactly where you left off
This is what makes session continuity work across agent boundaries — the next agent doesn’t need to rediscover context; it’s handed a precise resumption point.
What Goes Into a Handoff
A handoff document is a Markdown file stored in .wai/projects/<name>/handoffs/. It contains:
- Session summary — What was accomplished
- Current state — Active phase, open issues, uncommitted changes
- Plugin context — Git status, beads issue counts, and other plugin-contributed data (gathered via the
on_handoff_generatehook) - Next steps — Concrete actions for the next session
- Decisions made — Key choices and their rationale
wai close vs wai handoff create
Both generate handoff documents, but they serve different purposes:
| Command | When to use |
|---|---|
wai close | End of a session. Generates a handoff and writes the .pending-resume signal so the next wai prime can detect it. |
wai handoff create | Mid-session or explicit handoff to another person/agent. Generates the document without the resume signal. |
Use wai close when you’re done working. Use wai handoff create when you need to hand context to someone else but aren’t stopping yet.
The Autonomous Loop
For AI agents running in autonomous mode, the session loop becomes a tight cycle:
wai prime— orient (detects ⚡ RESUMING if mid-task)- Work on one task
wai close— capture stategit commitand push- Clear context (e.g.,
/clear)
The next session starts with wai prime again, which shows RESUMING with exact next steps. This pattern keeps agents productive across context window boundaries without losing the thread.
Reasoning
Capturing artifacts — research notes, design decisions, plans — is the foundation. But artifacts alone don’t answer the questions that come up later: Why did we choose this approach? What patterns have emerged across sessions? What does this file’s history tell us?
Wai’s reasoning features bridge this gap with two LLM-powered commands that query and synthesize your captured knowledge.
wai why — The Reasoning Oracle
wai why answers natural-language questions about your project by combining your artifacts with git history and feeding them to an LLM.
How It Works
- Context gathering — Wai collects relevant PARA artifacts (research, designs, plans) and recent git history, scoped to your query.
- LLM query — The gathered context and your question are sent to the configured LLM backend.
- Structured response — The answer comes back with a decision chain and references to the artifacts that informed it.
Query Types
You can ask wai why two kinds of questions:
# Ask a question about your project
wai why "Why did we choose TOML over YAML for config?"
# Ask about a specific file's history and purpose
wai why src/config.rs
Questions work best when they’re specific and tied to decisions your project has already made. The oracle is only as good as the artifacts you’ve captured — it queries what you recorded.
When It Shines
- Onboarding: A new contributor asks “why does the plugin system use auto-detection?” and gets an answer grounded in actual design artifacts, not guesses.
- Revisiting decisions: Six months later, you wonder why a particular architecture was chosen. The oracle traces it back through research and design notes.
- File archaeology: Pointing
wai whyat a file explains its role in the project based on commit history and related artifacts.
wai reflect — Project Synthesis
Where wai why answers specific questions, wai reflect steps back and synthesizes patterns across your entire project history.
How It Works
- Context aggregation — Wai gathers conversation transcripts, handoff documents, and session history up to a character budget.
- Pattern synthesis — An LLM distills the accumulated context into recurring patterns, conventions, and architectural notes.
- Persistent output — The synthesis is written as a versioned Markdown file in
.wai/resources/reflections/. - Instruction updates — Wai detects instruction files (
CLAUDE.md,AGENTS.md) and updates them with the new reflection, so agents pick up the patterns automatically.
When to Run It
Run wai reflect approximately every 5 sessions, or whenever you feel the project has accumulated enough new context to be worth synthesizing. It’s not meant to run after every change — it’s a periodic distillation.
wai reflect
What It Produces
The output is a reflection file containing:
- Project conventions — Naming patterns, code style preferences, framework choices that emerged organically
- Architectural notes — How components relate, where boundaries are, what invariants matter
- Gotchas — Things that tripped you up and shouldn’t trip someone else
These reflections feed back into agent instructions via managed blocks, so the next agent session starts with accumulated project wisdom — not just the raw artifacts.
LLM Configuration
Both commands support multiple backends:
- Claude API — Uses the Anthropic REST API directly (requires
ANTHROPIC_API_KEY) - Claude CLI — Delegates to the
claudebinary - Ollama — Local LLM for offline use
Wai auto-detects the available backend. No configuration is needed if you have one of these set up.
How They Build on Artifacts
Both wai why and wai reflect are only as useful as the artifacts you’ve captured. They don’t hallucinate project context — they query and synthesize what exists in your .wai/ directory and git history.
This creates a virtuous cycle:
- You capture research, designs, and decisions with
wai add wai whymakes that knowledge queryable on demandwai reflectdistills it into persistent patterns- Those patterns inform the next session via managed blocks
- The next session captures more artifacts, and the cycle continues
Decision Matrix
The decision matrix is wai’s representation of the central artifact from the
Design in Practice
methodology (Rich Hickey, “Design in Practice”; Alex Miller,
“Design in Practice in Practice”). Where wai add design records the
conclusion, the matrix captures the deliberation: the approaches
considered, the criteria that mattered, the facts gathered, and the judgment
made on each intersection.
One matrix per project
The matrix lives at a fixed location inside the project’s design area:
.wai/projects/<project>/designs/matrix/
├── problem.md # A1: the decision being deliberated
├── criteria/ # rows: one definition file per criterion
│ ├── 01-impact.md
│ └── 02-risk.md
├── approaches/ # columns
│ ├── 01-status-quo/ # always first
│ │ ├── _description.md
│ │ ├── 01-impact/
│ │ │ ├── fact.md # the aspect — facts, not judgment
│ │ │ └── red # judgment marker
│ │ └── 02-risk/
│ │ └── fact.md # no marker yet → not assessed
│ └── 02-event-sourcing/
│ └── ...
├── decision.md # current decision (written by `wai matrix decide`)
└── matrix.html # generated on demand, never committed
It is a standing surface, re-anchored by editing problem.md as new
decisions arise, and it grows over the project’s lifetime — new approaches
are born in it, new criteria appear as deliberation makes them salient.
A1: start with the problem
problem.md holds the answer to the methodology’s first question — what
decision are you trying to make? It is rendered as the banner in
matrix.html and shown by wai status during the design phase. Re-anchor
the matrix for a new decision by rewriting it.
The cell: fact and judgment separated
Each cell holds exactly two things:
fact.md— the aspect: how the approach meets the criterion. Facts, not judgment. “Audit trail exists by construction”, not “this is good”.- One marker file — empty, named
neutral,green,yellow, orred. The judgment lives in exactly one place, and the encoding cannot be malformed: there is no syntax to break.
Completeness is defined by the fact, never the color. A cell with a
missing or empty fact.md is not yet assessed — the renderer shows a gray
placeholder, never a judgment color. neutral is a legitimate judgment
(“clear, nothing special”), distinct from incomplete.
Filling a cell is two trivial file operations — this is the primary editing path, for humans and agents alike:
# fill a cell
echo "Audit trail exists by construction." > approaches/02-event-sourcing/01-impact/fact.md
touch approaches/02-event-sourcing/01-impact/green
# change a judgment
rm approaches/02-event-sourcing/01-impact/green
touch approaches/02-event-sourcing/01-impact/yellow
The ? convention: write a line starting with ? anywhere in the matrix to
record an open question — wai search "?" finds them. Keep criteria
statements; questions stay searchable.
Commands
The CLI exists only where one logical action spans many directories:
| Command | Behavior |
|---|---|
wai matrix init "<problem>" | Scaffold problem.md, criteria/, approaches/01-status-quo/, decision.md template |
wai matrix criterion add <name> | Add criteria/NN-name.md + a cell dir in every approach |
wai matrix approach add <name> | Add approaches/NN-name/ with _description.md + empty cells for all criteria |
wai matrix decide <approach> "<rationale>" | Write decision.md + scaffold a design doc with a decision-time snapshot |
wai matrix lint | Structural errors + methodology warnings |
wai matrix render | Generate self-contained matrix.html |
There is deliberately no wai matrix set: filling a cell is writing one
file and touching one marker — sugar over trivial file I/O would only obscure
the model.
Linting: structure is enforced, methodology is taught
wai matrix lint reports structural errors (non-zero exit):
rectangularity, exactly one known marker per filled cell, no empty fact.md,
status-quo-first.
Methodology warnings never block — each maps 1:1 to a tip from the source
talks: all-green column (“are you rationalizing?”), undistinguished columns
(likely a missing criterion), judgment-in-text, link-only cells, criteria
phrased as questions, status quo with no red cell (Miller: show what’s wrong
with today), deciding with unfilled cells, empty problem.md, and stale
decisions (matrix edited after deciding).
The design → plan gate
Leaving the design phase requires the matrix to be decided and current:
decision.md names an existing approach, and no file under approaches/ or
criteria/ is newer than the decision timestamp recorded inside
decision.md (content timestamps survive clone/rebase; mtimes don’t).
Edited-after-decision blocks the transition with a self-healing message;
ambiguous timestamps (e.g. a fresh clone, where everything shares the
checkout time) downgrade to a warning, never a false block. Projects without
a matrix are never gated.
Deciding
wai matrix decide "02-event-sourcing" "Best audit story at acceptable ops cost." does two things:
- Writes
decision.md— approach, rationale, UTC timestamp, design-doc pointer. A scaffoldeddecision.mdnames no approach, so a bareinitnever passes the gate. - Scaffolds
designs/<date>-<slug>.mdwith standard frontmatter and a decision-time snapshot of the winning column’s facts. The matrix keeps growing; the design doc records what was true when decided.
The human/agent then fleshes out the design doc’s narrative — rationale,
trade-offs — with the matrix one wai search away.
Adoption
The matrix is opt-in: nothing exists until wai matrix init. Projects
that don’t use it behave exactly as before — no gating, no status output, no
handoff sections.
Plugin System
Why plugins? Every team uses different tools — issue trackers, spec managers, version control. Building all of these into wai would make it opinionated and brittle. Instead, wai auto-detects what’s already in your workspace and integrates through a plugin architecture. You get seamless context (git status in handoffs, open issues in
wai status) without wai prescribing your toolchain.
Wai auto-detects and integrates with external tools through a flexible plugin architecture.
Built-in Plugins
Beads
- Detection:
.beads/directory - Description: Issue tracking with tasks, bugs, and dependencies
- Commands:
list,show,ready(read-only) - Hooks:
on_handoff_generate— Includes open issues in handoffson_status— Shows issue statistics
Example:
wai beads list # Pass-through to beads plugin
wai beads ready # Show issues ready to work on
Git
- Detection:
.git/directory - Description: Version control integration
- Hooks:
on_handoff_generate— Includes git statuson_status— Shows recent commits
OpenSpec
- Detection:
openspec/directory - Description: Specification and change management
- Integration: Status display shows active specs and change proposals with progress
Plugin Commands
Pass-through commands allow direct access to plugin functionality:
wai <plugin> <command> [args...]
Example:
wai beads list --status=open
wai beads show beads-123
Plugin Hooks
Plugins can inject context into wai workflows through hooks:
Available Hooks
| Hook | When Triggered | Purpose |
|---|---|---|
on_status | wai status called | Add plugin context to status output |
on_handoff_generate | wai handoff create called | Include plugin state in handoffs |
on_phase_transition | Phase changes | React to project phase changes |
Custom Plugins
Wai scans the .wai/plugins/ directory at your workspace root for any files with a .toml extension.
Example Plugin Definition
name = "my-tool"
description = "Custom tool integration"
[detector]
type = "directory"
path = ".mytool" # Relative to workspace root
[[commands]]
name = "list"
description = "List items"
passthrough = "mytool list"
read_only = true
[[commands]]
name = "sync"
description = "Sync data"
passthrough = "mytool sync"
read_only = false
[hooks.on_status]
command = "mytool stats"
inject_as = "mytool_stats"
[hooks.on_handoff_generate]
command = "mytool status --format=summary"
inject_as = "mytool_context"
Detector Types
- directory — Detect by directory presence. The
pathattribute is relative to the workspace root. - file — Detect by file presence. The
pathattribute is relative to the workspace root. - command — Detect by command availability. The
path(orcommand) attribute is the shell command to execute (must return exit code 0).
Note: For the
commanddetector in TOML, use thepathfield to specify the command to run (e.g.path = "mytool --version").
Command Attributes
- name — Command name (e.g.,
list) - description — Human-readable description
- command — Shell command to execute
- read_only — Whether command modifies state (respects
--safemode)
Managing Plugins
List All Plugins
wai plugin list
Shows:
- Plugin name and description
- Detection status (detected/not found)
- Available commands
- Configured hooks
Enable/Disable Plugins
wai plugin enable my-tool
wai plugin disable my-tool
Note: Built-in plugins cannot be disabled.
JSON Output
Get structured plugin information:
wai plugin list --json
Returns:
{
"plugins": [
{
"name": "beads",
"description": "Issue tracking",
"detected": true,
"commands": ["list", "show", "ready"],
"hooks": ["on_status", "on_handoff_generate"]
}
]
}
Safe Mode
Plugin commands that modify state are blocked in safe mode:
wai beads list --safe # OK - read-only
wai my-tool sync --safe # Blocked if not read_only
Plugin Troubleshooting
Plugin Not Detected
Symptom: wai plugin list shows plugin as “not detected”
Common Causes:
-
Detector file/directory missing
# Check if detector path exists ls -la .beads/ # for beads plugin ls -la .git/ # for git plugin ls -la openspec/ # for openspec plugin -
Plugin tool not installed
# Verify tool is available which beads which mytool # Install if missing cargo install beads -
Custom plugin TOML syntax error
# Validate TOML cat .wai/plugins/my-plugin.toml # Check for common issues: # - Missing required fields (name, description, detector) # - Wrong detector type (must be: directory, file, or command)
Plugin Command Fails
Symptom: wai <plugin> <command> returns error
Debugging Steps:
# 1. Verify plugin is detected
wai plugin list | grep myplugin
# 2. Test command directly
mytool command args
# 3. Check command definition
wai plugin list --json | jq '.plugins[] | select(.name=="myplugin") | .commands'
# 4. Verify passthrough is in PATH
which mytool
# 5. Check for command output issues
mytool command 2>&1 | head
Custom Plugin Not Loading
Symptom: Custom plugin in .wai/plugins/ doesn’t appear
Checklist:
- ✅ File has
.tomlextension - ✅ File is in
.wai/plugins/directory - ✅ TOML syntax is valid
- ✅ Required fields present:
name,description,detector - ✅ Detector path exists (for directory/file detectors)
Example Valid Plugin:
name = "example-tool"
description = "Example tool integration"
[detector]
type = "directory"
path = ".example"
[[commands]]
name = "status"
description = "Show status"
passthrough = "example status"
read_only = true
[[commands]]
name = "sync"
description = "Sync data"
passthrough = "example sync"
read_only = false
[hooks.on_status]
command = "example stats"
inject_as = "example_stats"
Hook Output Not Showing
Symptom: Plugin hooks defined but output doesn’t appear in status/handoffs
Debugging:
# 1. Check if plugin is detected
wai plugin list | grep myplugin
# 2. Verify hook command runs successfully
example stats # Run hook command directly
# 3. Check hook definition
wai plugin list --json | jq '.plugins[] | select(.name=="example") | .hooks'
# 4. Look for hook output in status
wai status -v # Verbose mode shows more detail
# 5. Check JSON output for hook_outputs
wai status --json | jq '.hook_outputs'
Permission Errors
Symptom: “Permission denied” when running plugin commands
Solutions:
# 1. Check plugin tool permissions
ls -l $(which mytool)
# 2. Verify tool is executable
chmod +x $(which mytool)
# 3. For safe mode issues, check read_only flag
wai plugin list --json | jq '.plugins[] | select(.name=="myplugin") | .commands[] | {name, read_only}'
Detector Not Working
Symptom: Plugin should be detected but shows as “not detected”
Detector Types and Requirements:
Directory Detector:
[detector]
type = "directory"
path = ".mytool" # Directory must exist at workspace root
Check: ls -la .mytool/
File Detector:
[detector]
type = "file"
path = "mytool.config" # File must exist at workspace root
Check: ls -la mytool.config
Command Detector:
[detector]
type = "command"
path = "mytool --version" # Command must exit 0 and be in PATH
Check: which mytool && mytool --version
Getting Help
If you can’t resolve plugin issues:
# Create debug report
{
echo "=== Plugin List ==="
wai plugin list
echo -e "\n=== Plugin JSON ==="
wai plugin list --json
echo -e "\n=== Custom Plugins ==="
ls -la .wai/plugins/
echo -e "\n=== Doctor Check ==="
wai doctor
} > plugin-debug.txt
File an issue at https://github.com/charly-vibes/wai/issues with plugin-debug.txt attached.
See Also
- Commands Reference - Plugin management commands
- Troubleshooting - Plugin-specific troubleshooting
- JSON Output - Plugin JSON schema
Pipelines
Why pipelines? Some tasks are too complex or error-prone for a single pass. When an AI agent tries to do research, validation, and synthesis all at once, errors compound — context drifts, assumptions go unchecked, and the final output is built on shaky foundations. Pipelines break these tasks into discrete steps with validation gates between them, so each step is verified before the next one begins.
Pipelines are ordered, multi-step workflows that guide you through a structured process. Each step provides a prompt with deliverables and instructions, and you advance through steps sequentially.
Pipelines are useful when a task is too large or too error-prone for a single pass — for example, research that spans many subtasks, or a process where intermediate validation prevents compounding errors. If your work fits naturally into wai’s project phases without extra structure, you probably don’t need a pipeline.
Prerequisite: an initialized wai workspace (wai init). See Quick Start.
Overview
wai pipeline list # List available pipelines
wai pipeline show <name> # View steps and gates
wai pipeline start <name> --topic="<objective>" # Start a run
wai pipeline next # Mark current step done, move to next
Pipelines are defined as TOML files in .wai/resources/pipelines/. When you run wai init, built-in templates are installed into this directory. You can modify your local copy without affecting the built-in defaults.
Creating Custom Pipelines
Pipelines are TOML files with a simple structure:
[pipeline]
name = "my-workflow"
description = "What this pipeline does"
[pipeline.metadata]
when = "When to use this pipeline"
skills = ["skill-a", "skill-b"] # Optional: skills used by steps
[[steps]]
id = "step-one"
prompt = """
{topic}: Instructions for this step.
Deliverables:
- What to produce
Record findings: `wai add research "..."`
Advance: `wai pipeline next`
"""
[[steps]]
id = "step-two"
prompt = """
{topic}: Instructions for this step.
"""
The {topic} placeholder is replaced with the --topic value when the run starts.
Place custom pipelines in .wai/resources/pipelines/ and run wai init to refresh the managed block in CLAUDE.md.
Pipeline Gates
Steps can optionally define gates — conditions that must be satisfied before advancing. Gates enforce validation at step boundaries and are checked when you run wai pipeline next.
Gate tiers
Gates evaluate in order. The first failure blocks advancement — wai pipeline next prints the failing gate and what’s missing, and blocks until the condition is satisfied.
| Tier | Type | Purpose |
|---|---|---|
| 1 | Structural | Verify the step produced expected outputs (artifact count/type) |
| 2 | Procedural | Verify the validation process was followed (reviews exist, verdicts pass) |
| 3a | Oracle | Domain-specific machine-verifiable checks (user-written scripts) |
| 3b | Approval | Forced human checkpoint |
Configuring gates in TOML
Gate sections go inside the [[steps]] entry they belong to. Here is a complete step with all four gate tiers:
[[steps]]
id = "generate-validate-accrue"
prompt = """
{topic}: Execute subtasks with intermediate validation.
...
"""
[steps.gate.structural]
min_artifacts = 1
types = ["research"]
[steps.gate.procedural]
require_review = true
review_verdict = "pass"
max_critical = 0
max_high = 0
[[steps.gate.oracles]]
name = "dimensional-analysis"
description = "Verify dimensional consistency"
timeout = 300
[steps.gate.approval]
required = true
message = "Review all accrued artifacts before advancing"
Oracle scripts
Oracles are user-written scripts that perform domain-specific checks:
- Location:
.wai/resources/oracles/<name>.shor.wai/resources/oracles/<name>.py - Contract: receives the artifact path as an argument, exits 0 on pass, writes failure reason to stderr
- Timeout: default 30 seconds, configurable per oracle
Gate commands
wai pipeline gates <name> # Show gate requirements per step
wai pipeline check # Dry-run gates without advancing
wai pipeline approve # Human approval for current step
wai pipeline validate <name> # Validate pipeline TOML and gate config
Disclosing gate bypasses
Hooks cannot self-record a --no-verify bypass — the flag skips them. If
you bypass a git hook while a pipeline run is active, record the bypass
discipline at bypass time:
wai pipeline bypass "skipped pre-push hook: flaky timing test wai-z25x"
The command appends a timestamped entry (timestamp + reason) to the active
run’s state ledger and wai pipeline status surfaces the bypass count and
the most recent reason. Bypass telemetry is a ledger, not enforcement — it
makes disclosed bypasses pokeable instead of invisible. With no active run
the command is a silent no-op (nothing recorded, no error).
Built-in: Scientific Research Pipeline
The scientific-research pipeline is designed for frontier-level theoretical or computational research where an LLM generates mathematical derivations, proofs, or data analysis across many subtasks and a human supervisor needs systematic validation.
It addresses three common failure modes in AI-assisted research:
- Context drift — the research gradually shifts away from the original problem
- Sycophancy — the model confirms what it thinks you want rather than what’s true
- Hallucinated data smoothing — gaps are filled with plausible but unverified claims
Starting a run
wai pipeline start scientific-research --topic="Your research objective here"
This creates a pipeline run and places you at step 1. Each step provides a detailed prompt explaining what to do, what deliverables to produce, and how to record them.
Steps
The pipeline has five framing steps (Describe, Diagnose, Delimit, Direction, Decompose), a core execution loop (Generate-Validate-Accrue), and two closing steps (Synthesize, Final Review).
Every step ends with recording artifacts and advancing:
wai add research "findings..." # or design/plan as appropriate
wai pipeline next
1. Describe
Capture the research problem neutrally. Focus on observed symptoms, signals, metrics, boundary conditions, and known constraints. Do not propose solutions or hypotheses yet.
Deliverables: neutral problem statement, known constraints, data sources, success criteria.
2. Diagnose
Generate and test competing hypotheses — at least three. For each, state its predictions and identify confirming/refuting evidence. Use negative progress (ruling out false leads) rather than converging too early.
Deliverables: hypothesis map, evidence for/against each, eliminated paths.
3. Delimit
Define explicit boundaries and scope. This is the primary defense against context drift. Document what is in scope, what is explicitly out, constraints, and assumptions taken as given.
Deliverables: scope document (referenced throughout remaining steps).
4. Direction
Select the research approach using a decision matrix. Compare surviving hypotheses against feasibility, rigor, falsifiability, and compute cost. Include a null hypothesis baseline. Document what would cause you to revisit the decision.
Deliverables: decision matrix, selected approach with justification.
5. Decompose
Break the selected approach into a master task tree of discrete, independently verifiable subtasks. Each subtask gets a unique ID, input dependencies, expected output format, and validation criteria.
Deliverables: task tree (created as beads issues with dependencies).
bd create --title="<subtask>" --description="<details>" --type=task
bd dep add <blocked> <blocker>
wai add plan "task decomposition..."
6. Generate-Validate-Accrue (core loop)
Execute each subtask from the task tree. For every subtask:
- Generate — produce the derivation, code, analysis, or argument
- Validate — run
/ro5(Rule of 5, a wai review skill) on the artifact:- Accuracy — verify facts, citations, mathematical correctness
- Completeness — check for skipped steps, missing edge cases
- Clarity — ensure unambiguous terminology and notation
- Actionability — confirm output is usable by the next subtask
- Integration — check consistency with all previously accrued artifacts
- Accrue — if validation passes, commit the artifact:
wai add research "<subtask findings>" bd close <subtask-id>
Critical rules:
- Do not skip validation. Do not accrue unvalidated artifacts.
- If a subtask contradicts a previously accrued artifact, halt and surface the contradiction for human review.
- Fix and re-validate before accruing if validation fails.
7. Synthesize
Assemble the final output from all accrued artifacts. Check for logical flow, notation consistency, gap detection, and whether boundary conditions from the delimit step are satisfied.
Deliverables: coherent final output (paper, report, derivation).
8. Final Review
Run /ro5 on the complete synthesized output. Verify:
- The result satisfies success criteria from step 1
- The scope document from step 3 was respected
- The decision matrix from step 4 is still valid
- All beads subtasks are closed
If critical issues are found, route back to step 6 for the specific subtask that introduced the error.
Visual overview
┌─────────┐ ┌───────────┐ ┌─────────┐ ┌───────────┐ ┌───────────┐
│ Describe │──▶│ Diagnose │──▶│ Delimit │──▶│ Direction │──▶│ Decompose │
│ │ │ │ │ │ │ │ │ │
│ Problem │ │ Hypotheses│ │ Scope │ │ Decision │ │ Task tree │
└─────────┘ └───────────┘ └─────────┘ └───────────┘ └─────┬─────┘
│
▼
┌──────────────┐ ┌─────────────┐ ┌─────────────────────────────────┐
│ Final Review │◀──│ Synthesize │◀──│ Generate → Validate → Accrue │
│ │ │ │ │ (repeat per subtask) │
│ Quality gate │ │ Assembly │ └─────────────────────────────────┘
└──────────────┘ └─────────────┘
Built-in: TDD + Rule of 5 Pipeline
The tdd-ro5 pipeline is designed for autonomous implementation work where an agent should keep moving without routine confirmations, but must prove correctness before shipping.
Start it with:
wai pipeline start tdd-ro5 --topic="Your feature or bug fix"
The pipeline uses nine gated steps:
- Orient — run
wai prime,wai status, available work discovery, andwai searchbefore editing. - Plan — record desired behavior, out of scope, test cases, and verification commands.
- Red — write failing tests and record expected failure evidence.
- Green — implement the minimum code and pass relevant tests.
- Refactor — tidy safely while tests remain green.
- RO5U Review — run Universal Rule of 5 review and record findings without fixing yet.
- Fix Review — address review findings and keep tests green.
- Quality Ledger — record Changed, Verified, Review, Risks, and Next.
- Ship Close — inspect the diff, update linked workflow tools, commit atomically, and run
wai close.
Review and fixing are intentionally separate steps: the review step observes and records evidence; the fix step applies bounded remediation. Push/release/deploy remains outside the default pipeline unless explicitly authorized by project policy or user instruction.
Built-in: Epic-Orchestrator Pipeline
The epic-orchestrator pipeline is designed for epic execution where a lead agent orchestrates only — one ready child ticket per run — and subagents do the implementation. It encodes the orchestrator + subagents pattern as enforceable steps instead of hoping agents follow prose: the lead’s job is claim → gates → brief → spawn → verify → ship → STOP, never inline implementation.
Starting a run
wai pipeline start epic-orchestrator --topic="<child ticket id>"
Each run handles exactly one child ticket. The next ticket starts a fresh run — the loop ends in an explicit STOP at the ticket boundary and never chains past it.
Steps
- Claim — orient (
wai prime,wai status,bd ready) and claim exactly one ready, unblocked child issue atomically (bd update <id> --claim). Write the per-ticket state file (see below). - Gates — run the project’s pre-work quality gates and establish a green test-suite baseline so later failures are attributable to this change only. No implementation yet.
- Brief — write the subagent brief as a committed repo artifact at
.wai/projects/<project>/briefs/<slug>.md, with mandatory## Why(delegation rationale),## Completion criteria(runnable commands only — exit 0 = done), and## Spawn model(model plus a context ceiling expressed as≤ N%of the actual model window; fixed token counts are invalid). Commit the brief before spawning so the subagent starts from a clean tree. - Spawn — spawn a named, resumable subagent session for the brief, streaming output to a known log path the orchestrator can tail. Spawn is a named session (retry is a fresh
-retry-suffixed session, never an in-place resume). - Verify — verify before trust. With a second model family configured, a read-only verifier session (
subagent:<ticket>:verify) cross-checks the implementor’s report against reality: commits vsgit log, report claims vs ticket-tracker state. - Ship — inspect the diff, commit atomically, update the ticket tracker and openspec tasks. Push only when project policy or user instruction explicitly authorizes it.
- STOP — hard stop at the ticket boundary. Record the final checkpoint and start the next ticket as a new run.
Every step ends with recording an artifact (wai add), appending a step id + sha checkpoint to the state file, and wai pipeline next.
Per-ticket state file
The claim step creates a durable state file at .wai/projects/<project>/runs/<ticket>.state, e.g.:
ticket: wai-hr0w
branch: main
brief_path: .wai/projects/<project>/briefs/<slug>.md
step_history: []
- claim @ 52c6de8604ad86f87c4a6a3defe4800a23b3b1bf
- gates @ 52c6de8604ad86f87c4a6a3defe4800a23b3b1bf
- brief @ 939dae26e2b7aefa0e4200d09a41c4259029d4b4
It records the ticket id, the branch, the brief path (empty until the brief step), and a step history of step id + sha checkpoints appended before each advance.
Retry and drift: if the state file already exists at claim, the retry reads it and runs a drift check before resuming — it refuses to resume when HEAD advanced without a completed step accounting for the advance. A mid-run advance is expected (the implementor commits) and is never flagged as drift. Retries resume from the last completed gate, not from the beginning.
Refusal conditions:
- Spawn refuses to run without a committed brief at its recorded path.
- Spawn refuses to run without the state file — the spawn must be resumable through it.
- The retry-entry drift check refuses to resume a state file whose HEAD advanced without an accounting step.
Single-model degradation
The primary verify path spawns a verifier from a different model family. Single-model setups degrade to lead-side checks instead of a spawned verifier: record the branch head at verify entry, diff git log/git diff against the report, run the repo’s test suite, and check the ticket tracker. This degradation is non-blocking — the run may advance once the lead-side checks pass. A contradiction between the report and reality always blocks the run, degraded or not.
Oracle requirement
The verify and ship steps carry a tests-pass oracle gate, and the verify step additionally carries a verify-evidence oracle: a review artifact may record CONFIRM only when it cites the artifacts it read and includes fresh test-run output — evidence gaps must be recorded as REVIEW_REQUIRED. wai pipeline init epic-orchestrator ships both scripts (see Oracle scripts) to .wai/resources/oracles/, so the gates resolve out of the box; if you remove one, advancing past those steps fails.
Provenance: the evidence base and design proposal for this pipeline live in the orchestrator-tooling project (
~/.wai/projects/orchestrator-tooling/); the openspec change isopenspec/changes/add-epic-orchestrator-template/.
Artifact Locking
Steps can declare lock = true to freeze their artifacts with SHA-256 hashes when you advance past them. This prevents accidental modification of validated work — once a step’s artifacts are locked, any change will be caught by wai pipeline verify or wai doctor.
How it works
When a step with lock = true completes (via wai pipeline next), wai computes a SHA-256 hash of each artifact tagged with that step and writes a .lock sidecar file alongside it. The sidecar records the hash, run ID, step ID, and timestamp.
You can also lock manually at any time:
wai pipeline lock # Lock current step's artifacts now
Verifying integrity
wai pipeline verify # Check all locked artifacts across the workspace
Verify reports:
- Missing artifacts — a
.lockfile exists but the artifact was deleted - Hash mismatches — an artifact was modified after locking
wai doctor also checks artifact lock integrity as part of its health checks.
Correcting locked artifacts
Locked artifacts should not be edited directly. Instead, create an addendum — a new artifact that references the original:
wai add research --corrects=<path-to-locked-artifact> "correction details"
This preserves the audit trail: the original artifact stays intact and the addendum records what changed and why.
Configuring lock in pipeline TOML
Add lock = true to any step definition:
[[steps]]
id = "synthesize"
lock = true
prompt = """
{topic}: Assemble findings into a coherent output.
"""
Command reference
| Command | Description |
|---|---|
wai pipeline list | List all available pipelines |
wai pipeline show <name> | View steps and gates for a pipeline |
wai pipeline start <name> --topic="..." | Start a new run |
wai pipeline next | Advance to the next step |
wai pipeline current | Reprint the active step |
wai pipeline current --json | Emit machine-readable active run context |
wai pipeline status | Alias for machine-readable active run context |
wai pipeline gates <name> | Show gate requirements |
wai pipeline check | Dry-run gate evaluation |
wai pipeline approve | Human approval for current step |
wai pipeline validate <name> | Validate pipeline TOML |
wai pipeline lock | Lock current step’s artifacts (SHA-256) |
wai pipeline verify | Verify integrity of all locked artifacts |
See Also
- Project Phases — the phase system pipelines build on
- Plugin System — beads issue tracking used in task decomposition
- Commands Reference — full command documentation
Agent Config Sync
Why a single source of truth? When agent instructions live in multiple files (
CLAUDE.md,.cursorrules,.gemini/), they inevitably drift apart. One tool gets the updated security rules, another doesn’t. Copy-pasting between configs is tedious and error-prone. Wai solves this by storing configs once and projecting them to each tool’s expected location — edit in one place, sync everywhere.
Wai maintains a single source of truth for agent configurations and syncs them to tool-specific locations using configurable projection strategies.
Directory Structure
Agent configs are stored in .wai/resources/agent-config/:
.wai/resources/agent-config/
├── .projections.yml # Sync configuration
├── skills/ # Agent skills
│ ├── code-review.md
│ └── commit.md
├── rules/ # System rules
│ ├── security.md
│ └── style.md
└── context/ # Context files
└── project-context.md
Projection Strategies
Configure syncs in .wai/resources/agent-config/.projections.yml:
1. Symlink Strategy
Creates target directory with symlinks (or copies on Windows) to source files.
Note on Windows: Windows doesn’t support symlinks in all configurations (requires Developer Mode or admin privileges). Wai automatically falls back to file copies when symlinks aren’t available.
Use when: Tools expect a directory structure with individual files.
projections:
- strategy: symlink
sources:
- skills/
target: .claude/skills/
Result:
.claude/skills/code-review.md→ symlink to.wai/resources/agent-config/skills/code-review.md.claude/skills/commit.md→ symlink to.wai/resources/agent-config/skills/commit.md
2. Inline Strategy
Concatenates multiple source files into a single target file.
Use when: Tools expect a single configuration file (e.g., .cursorrules).
projections:
- strategy: inline
sources:
- rules/base.md
- rules/security.md
- rules/style.md
target: .cursorrules
Result:
<!-- AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY -->
<!-- Source: .wai/resources/agent-config/rules/base.md -->
[content of base.md]
<!-- Source: .wai/resources/agent-config/rules/security.md -->
[content of security.md]
<!-- Source: .wai/resources/agent-config/rules/style.md -->
[content of style.md]
3. Reference Strategy
Creates a markdown file listing paths to source files.
Use when: Tools can follow references to external files.
projections:
- strategy: reference
sources:
- context/
target: .agents/context-refs.md
Result:
# Agent Context References
This file references agent context files managed by wai.
## Files
- .wai/resources/agent-config/context/project-context.md
Specialized Targets
Wai provides built-in specialized targets that handle complex tool-specific transformations automatically.
Claude Code (claude-code)
The claude-code target is a high-level projection that translates hierarchical skills into Claude Code custom slash commands.
Instead of manual file mapping, use the special target: claude-code:
projections:
- target: claude-code
How it works:
- Source Discovery: It automatically scans
.wai/resources/agent-config/skills/for hierarchical directories (e.g.,skills/git/commit/SKILL.md). - Translation:
- It translates the directory hierarchy into a human-readable skill name (e.g.,
git/commit→Git: Commit). - It updates the frontmatter of the destination file to match Claude Code’s expected format (including
name,description, andcategory).
- It translates the directory hierarchy into a human-readable skill name (e.g.,
- Destination: Files are synced to
.claude/commands/<category>/<action>.md. - Smart Syncing:
wai sync --statususes file modification times (mtime) to detect if Claude Code commands are out of date with your source skills.
Note: “Flat” skills (e.g., skills/my-skill/SKILL.md) are skipped by this target. Only hierarchical skills (e.g., skills/category/action/SKILL.md) are processed to ensure clean command grouping in Claude Code.
Configuration Format
Full .projections.yml example:
projections:
# Symlink skills to Claude Code
- strategy: symlink
sources:
- skills/
target: .claude/skills/
# Inline rules to Cursor
- strategy: inline
sources:
- rules/base.md
- rules/security.md
target: .cursorrules
# Reference context files
- strategy: reference
sources:
- context/
target: .gemini/context-refs.md
Commands
Check Sync Status
wai sync --status
Shows:
- Current projections
- Source files
- Target status (in sync / out of sync)
- Files that would be created/updated
Apply Sync
wai sync
Applies all configured projections:
- Creates/updates symlinks
- Regenerates inline files
- Updates reference files
Managing Configs
Add New Config
wai config add skill my-skill.md
Copies my-skill.md to .wai/resources/agent-config/skills/my-skill.md.
List Configs
wai config list
Shows all configs organized by type (skills, rules, context).
Edit Config
wai config edit skills/my-skill.md
Opens config in $EDITOR (or $VISUAL, falls back to vi).
Import Existing Configs
wai import .claude/
wai import .cursorrules
Imports existing tool configs into wai’s single source of truth.
Workflow
- Add/Edit configs in
.wai/resources/agent-config/ - Check status:
wai sync --status - Apply sync:
wai sync - Verify:
wai doctor
Doctor Checks
The wai doctor command validates:
- Projection configuration syntax
- Source files exist
- Target directories are writable
- Symlinks are valid
- Inline files match sources
- Reference files are current
Auto-fix mode can repair common issues:
wai doctor --fix
Conflict Resolution
Important: Wai always overwrites target files during sync. The source files in .wai/resources/agent-config/ are the single source of truth.
What Happens When You Edit Synced Files
If you manually edit a synced target file (e.g., .cursorrules, .claude/skills/my-skill.md):
- Your changes will be overwritten the next time you run
wai sync - No warning is given - wai assumes sources are authoritative
Best Practices
✅ DO:
- Edit files in
.wai/resources/agent-config/ - Use
wai config edit skills/my-skill.md - Run
wai sync --statusbefore syncing to preview changes - Keep sources under version control
❌ DON’T:
- Edit target files directly (
.cursorrules,.claude/skills/, etc.) - Manually create files in target directories
- Expect wai to merge changes from targets back to sources
Missing Source Files
If a source file listed in .projections.yml is missing:
- Sync behavior:
wai syncwill skip the missing file and continue with the remaining sources. Forinlinestrategies, the output file will be generated without the missing content. - Reporting:
wai sync --statuswill not show a specific error, but thetargetmay appear as “out of sync”. - Diagnosis: Run
wai doctorto identify exactly which source files are missing from your configuration.
Recovering Manual Edits
If you accidentally edited a target file:
# Copy your changes to a backup
cp .cursorrules my-changes-backup.md
# Check what the source contains
cat .wai/resources/agent-config/rules/*.md
# Manually merge your changes into the source files
wai config edit rules/base.md
# Re-sync to apply
wai sync
Migration Workflow
When importing from existing tool configs:
# Import existing configs (one-time)
wai import .cursorrules
wai import .claude/
# From now on, edit only in .wai/resources/agent-config/
wai config edit rules/imported-rules.md
# Sync to propagate changes
wai sync
Benefits
- Single Source of Truth — Edit once, sync everywhere
- Version Control — All configs tracked in
.wai/ - Consistency — Same configs across all tools
- Flexibility — Different strategies for different tools
- Auditability — Clear projection configuration
- No Conflicts — Unidirectional sync prevents merge conflicts
See Also
- Commands Reference - Config management commands
- Troubleshooting - Sync troubleshooting guide
- Quick Start - Getting started with config sync
Ubiquitous Language
Domain-driven design talks about a ubiquitous language — a shared vocabulary that developers and domain experts use consistently in code, conversations, and documentation. Without it, agents guess at terminology and hallucinate synonyms: is “order” the same as “purchase”? Does “customer” overlap with “user”? Is “shipment” the same as “delivery”?
Wai gives teams a first-class home for this vocabulary under .wai/resources/ubiquitous-language/.
The Directory Layout
.wai/resources/ubiquitous-language/
├── README.md # navigation index (required)
├── shared.md # cross-context terms (optional)
└── contexts/
├── orders.md
├── inventory.md
└── billing.md
Three layers:
README.md— a lightweight index that describes the tree, lists available bounded contexts (self-contained parts of the domain with their own consistent terminology, e.g. Orders, Billing), and tells agents how to navigate it. This is the only file agents read by default.shared.md— optional. Holds terms that are genuinely shared across multiple bounded contexts. Keep it short; most terms belong in a context file.contexts/*.md— one file per bounded context. Each file records the preferred term, a concise definition, discouraged synonyms or anti-terms, and related terms. Each bounded context should be a single.mdfile directly undercontexts/. Subdirectories and non-Markdown files are not currently recognized bywai way.
Getting Started
Create the directory and a minimal index:
mkdir -p .wai/resources/ubiquitous-language/contexts
Then write README.md as a short navigation guide:
# Ubiquitous Language
This directory contains domain terminology for this project.
## Bounded Contexts
- [Orders](contexts/orders.md) — fulfillment, line items, cancellation
- [Inventory](contexts/inventory.md) — SKUs, stock levels, reservations
## Usage
Read this file first. Open only the context file(s) relevant to your task.
Add a bounded-context file when you encounter ambiguous or domain-specific terms:
# Orders Context
## Order
**Definition:** A customer's confirmed intent to purchase one or more items.
**Anti-terms:** Do not use "cart" or "basket" — those refer to the pre-checkout state, not a confirmed order.
**Related:** Line Item, Fulfillment, Cancellation
Run wai way after setup to confirm the tree is fully configured.
Progressive Disclosure
Agents work better when they load terminology on demand rather than dumping an entire glossary into context. The layout is designed for this:
- Agent reads
README.mdto learn what contexts exist. - Agent opens only the bounded-context file(s) relevant to the current task.
- Agent ignores unrelated context files entirely.
The managed block injection (see below) is what makes agents aware of this pattern — the directory layout alone is not enough. Running wai sync is the step that teaches agents to navigate it correctly.
This matters in large codebases with many domains — loading every term file wastes context and increases noise.
wai way Detection
wai way checks the state of your ubiquitous-language tree and surfaces it alongside other project health signals:
| State | Result |
|---|---|
README.md + at least one contexts/*.md | PASS — fully configured |
README.md + shared.md, no context files | INFO — valid skeleton, add context files |
README.md only | INFO — needs bounded-context files |
Directory exists, no README.md | INFO — index required first |
| Directory absent | INFO — not yet set up, with suggestion |
Run wai way to see the result alongside other project health checks.
Managed Block Injection
When wai sync regenerates your CLAUDE.md, AGENTS.md, or .wai/AGENTS.md managed blocks, it checks whether README.md exists. If it does, it injects a usage note:
## Ubiquitous Language
If `.wai/resources/ubiquitous-language/README.md` exists, read it first as the
navigation index, then open only the bounded-context files relevant to the task.
Avoid loading every terminology file unless the work truly spans multiple contexts.
Every agent reading your CLAUDE.md will automatically know where the vocabulary lives and how to use it without you having to explain it in each session prompt.
Maintenance Workflow
Use the ubiquitous-language skill template to scaffold a skill that keeps the tree up to date:
wai add skill update-terminology --template ubiquitous-language
The generated skill guides an agent to:
- Search existing artifacts and code for domain terminology.
- Identify the appropriate bounded context for each term.
- Update
README.md,shared.md, or the relevantcontexts/*.mdfile. - Prefer incremental edits over rewriting the whole tree.
Run the skill whenever new domain concepts emerge or existing terms need clarification. Invoke it directly with wai skill run update-terminology or by referencing the generated SKILL.md in your agent prompt.
See Also
wai way— project health check command that detects the ubiquitous-language tree state- Managed Blocks — how
wai syncinjects guidance intoCLAUDE.mdandAGENTS.md wai add skill— scaffold skill templates includingubiquitous-language
Toolchain Synergy
Wai is the suite orchestrator for the full charly-vibes toolchain — eight tools that together cover the complete lifecycle from proposal to implementation to archival. Each tool owns a distinct concern and is detected automatically by its on-disk marker:
| Tool | Owns | Detection Signal | Question it answers |
|---|---|---|---|
| wai | Reasoning and context | .wai/ | Why was this decision made? |
| bd (beads) | Tasks and work items | .beads/ | What needs to be done? |
| openspec | Specifications and proposals | openspec/ | What should the system look like? |
| pretender | Structural code quality (AST linting) | pretender.toml | Does the code match our rules? |
| dont | Decision-logged conventions | .dont/ | What have we agreed not to do? |
| espectacular | Spec-to-test correspondence | .espectacular/ | Does the test match the spec? |
| testaruda | Test harness & property testing | testaruda.toml | Is the behavior correct? |
| vampiro / crua / livin | Spec-stage static analysis (planned) | TBD | Does the design hold up under analysis? |
All tools live under the charly-vibes GitHub organisation except:
- beads — gastownhall/beads (issue tracking with Dolt-backed sync).
- openspec — openspecio/openspec (specification management lifecycle).
When to Use What
| I need to… | Use |
|---|---|
| Record why I chose approach X over Y | wai add research "..." |
| Track a bug or task | bd create --title="..." |
| Propose a system change with requirements | openspec create <id> |
| Lint code for structural quality | pretender check . |
| Enforce a team convention with a decision log | dont define |
| Verify spec-to-test correspondence | ah check (espectacular) |
| Run property or harness tests | testaruda check |
| Resume where I left off | wai prime |
| Find available work | bd ready |
| Validate a proposal is complete | openspec validate --strict |
| Search past decisions | wai search "..." |
| Close a completed task | bd close <id> |
| Archive a deployed change | openspec archive <id> |
How They Integrate
All tools connect through wai’s plugin system, which auto-detects each tool by its on-disk marker:
- beads — detected when
.beads/exists. Open issue counts appear inwai status, andwai handoff createincludes issue context in handoff documents. - openspec — detected when
openspec/exists. Active change proposals and their progress appear inwai status. - pretender — detected when
pretender.tomlexists. Wai can help bootstrap its config viawai way. - dont — detected when
.dont/exists. Dont managed blocks inAGENTS.mdare refreshed bywai sync. - espectacular — detected when
.espectacular/exists. Espectacular signals (spec-test gaps) are surfaced inwai status. - testaruda — detected when
testaruda.tomlexists. Test harness state is reported inwai status. - vampiro / crua / livin — detection signals to be defined as the tools
ship (expected:
vampiro.toml,crua.toml,livin.tomlor equivalent config files). Currently spec-stage only — presence is tracked via their spec documents (e.g.crua-ears-spec.md,vampiro-ears-spec.md). The trio’s state will appear inwai statusonce detected.
Cross-references tie them together: beads tickets reference openspec tasks
(e.g., add-why-command:7.1 in the description), and completing a beads ticket
means checking the box in the openspec tasks.md. Wai’s wai doctor --suite
will eventually validate suite-wide consistency (see wai-bdqw.8).
Detection is additive and optional — each tool works independently, but when multiple are present wai becomes the unified dashboard.
Worked Example: Adding a Feature
Here’s how a ticket flows through the core trio (wai + beads + openspec):
# 1. Propose the change in openspec
openspec create add-search-filters
# Edit the spec: requirements, acceptance criteria, task breakdown
# 2. Create beads tickets for the implementation tasks
bd create --title="Add --tag flag to search" --description="add-search-filters:3.1"
bd create --title="Add --type flag to search" --description="add-search-filters:3.2"
# 3. Research the approach in wai
wai add research "Evaluated regex vs glob for tag matching — chose glob for simplicity"
# 4. Work the ticket
bd update wai-abc1 --status in_progress
wai add design "Tags stored in YAML frontmatter, filtered at search time"
# 5. Close the loop
bd close wai-abc1
# Check [x] for task 3.1 in openspec's tasks.md
With the suite tools integrated, the workflow extends further:
# Enforce code quality conventions
dont define "No unwrap() in library code"
# Verify spec-to-test coverage before merging
ah check # espectacular — does the test match the spec?
testaruda check # property-based test coverage
# Lint for structural quality
pretender check .
What You Lose by Skipping One
- Without wai: Tasks get done, but nobody remembers why decisions were made. Six months later, the code is a black box.
- Without beads: Reasoning is captured, but there’s no task decomposition, no dependency tracking, and no way to find available work.
- Without openspec: Changes happen ad hoc — no requirements, no acceptance criteria, no validation that the system matches the spec.
- Without pretender: Code quality standards are enforced by human review alone — slower, more inconsistent, and harder to enforce in CI.
- Without dont: Conventions live in READMEs or Slack — unenforceable and easy to forget.
- Without espectacular: Specs and tests drift independently; no automated signal that they disagree.
- Without testaruda: Property-based and harness testing must be set up manually, with no unified test dashboard.
- Without vampiro/crua/livin (planned): Spec-stage analysis must be done manually or deferred until implementation.
Each tool is optional. Wai works fine alone. But together, the full suite covers the entire lifecycle — from proposal through implementation, quality assurance, and archival.
See also: Suite Conventions for canonical policies on edition, license, version scheme, and justfile setup.
Suite Conventions
This document defines the canonical policies for the charly-vibes tool suite. It covers the infrastructure-level conventions (edition, license, versioning, justfile setup) that every suite tool should follow.
Design principles, verb grammar, flag consistency, error patterns, and AIX artefacts are documented in the genesis tool-craft playbook.
Current State vs Policy
Unless a tool documents a deliberate deviation below, it SHOULD conform to the
canonical policy. Deviations are tracked and converging through the
wai-bdqw.6 task.
1. Rust Edition
Canonical: 2024 (the latest stable edition as of 2026).
| Tool | Current | Status |
|---|---|---|
| wai | 2024 | ✅ |
| genesis | 2024 | ✅ |
| dont | 2024 | ✅ |
| pretender | 2021 | 🎯 update to 2024 |
| espectacular | 2021 | 🎯 update to 2024 |
| testaruda | 2021 | 🎯 update to 2024 |
| vampiro / crua / livin | TBD | 🎯 start with 2024 |
Rationale: 2024 adds unsafe attributes in scope, if let chains
without nesting, and impl Trait in RPIT — all useful patterns in the
suite’s codebase. The two-cycle lag policy means tools on 2021 should
migrate before the next edition.
2. License
Canonical: Apache-2.0.
| Tool | Current | Status |
|---|---|---|
| pretender | Apache-2.0 | ✅ |
| dont | Apache-2.0 | ✅ |
| espectacular | Apache-2.0 | ✅ |
| testaruda | Apache-2.0 | ✅ |
| genesis | Apache-2.0 | ✅ |
| vampiro / crua / livin | Apache-2.0 (vampiro) | ✅ planned |
| wai | MIT | ⚠️ deliberate deviation |
Rationale: Apache 2.0 is the suite standard — it provides express patent grant and is the de-facto standard for Rust open-source CLI tools. Wai uses MIT as a deliberate choice (permissive, no notice requirement in binary distributions). A future suite MAY dual-license or converge on a single license; this is not blocked on the current state.
3. Version Scheme
Canonical: Semantic Versioning (SemVer) 0.x.y or MAJOR.MINOR.PATCH.
| Tool | Current | Status |
|---|---|---|
| pretender | 0.3.1 | ✅ SemVer |
| dont | 0.2.2 | ✅ SemVer |
| espectacular | 0.3.0 | ✅ SemVer |
| testaruda | 0.2.4 | ✅ SemVer |
| genesis | 0.2.0 | ✅ SemVer |
| vampiro / crua / livin | TBD | 🎯 start with 0.1.0 |
| wai | 2026.7.16 (CalVer) | ⚠️ deliberate deviation |
Rationale: crates.io requires SemVer for crate dependencies, and every
CLI tool in the suite ships as a crate. Wai uses CalVer because its releases
are coupled to the project timeline (weekly-ish), not to API stability
contracts — the wai binary is never depended on as a library. The suite
standard is SemVer; wai’s CalVer is a documented outlier.
Convention: Tools at 0.x.y MAY bump minor (0.x+1.0) for breaking
changes until 1.0.0. Once stable, follow SemVer strictly.
4. Just Recipes
Canonical recipe set (every tool ships these four):
| Recipe | Purpose | Output |
|---|---|---|
default | Build + test (or --list if build/test not applicable) | just |
build | Compile the tool | just build |
test | Run the test suite | just test |
validate | Full quality gate (clippy + test + fmt) | just validate |
Optional recipes (tool-specific):
| Recipe | Purpose | Examples |
|---|---|---|
install | Install the tool | cargo install --path . |
publish | Release to crates.io | cargo publish |
docs | Build documentation | mdbook build docs |
prime / status | Orchestrator workflows | wai, dont, espectacular |
Canonical recipe NOT to use: ah (testaruda uses this for its test
runner — rename to test for consistency).
| Tool | default | build | test | validate | Status |
|---|---|---|---|---|---|
| wai | build+test | ✅ | ✅ | ✅ | ✅ |
| pretender | --list | ✅ | ✅ | ✅ | ✅ |
| dont | --list | ✅ | ✅ | ✅ | ✅ |
| espectacular | --list | ✅ | ✅ | ✅ | ✅ |
| testaruda | --list | ✅ | ✅ (as ah) | ❌ | 🎯 rename ah → test, add validate |
| vampiro / crua / livin | build+test | ✅ | ✅ | ✅ | 🎯 start aligned |
5. Justfile Shell
Canonical:
set shell := ["bash", "-uc"]
The -u flag treats unset variables as errors, preventing silent failures in
recipe pipelines. The -c flag is required by just for shell execution.
| Tool | set shell | Status |
|---|---|---|
| wai | ["bash", "-uc"] | ✅ |
| genesis | ["bash", "-uc"] | ✅ |
| vampiro | ["bash", "-uc"] | ✅ planned |
| crua | ["bash", "-uc"] | ✅ planned |
| livin | ["bash", "-uc"] | ✅ planned |
| dont | ["bash", "-cu"] | 🎯 add -u |
| pretender | absent | 🎯 add set shell |
| espectacular | absent | 🎯 add set shell |
| testaruda | absent | 🎯 add set shell |
6. Default Just Recipe
Canonical: just runs build + test (not --list).
A fresh clone should be buildable with a single just command. Using
--list as default means the developer must look up the recipe name before
building, which is friction for new contributors.
| Tool | Default | Status |
|---|---|---|
| wai | build test | ✅ |
| genesis | build test | ✅ |
| vampiro | build | 🎯 add test |
| crua | build | 🎯 add test |
| livin | build | 🎯 add test |
| pretender | --list | 🎯 change to build test |
| dont | --list | 🎯 change to build test |
| espectacular | --list | 🎯 change to build test |
| testaruda | --list | 🎯 change to build test |
Summary of Required Changes
| Tool | Edition | License | Version | Just recipes | Shell | Default |
|---|---|---|---|---|---|---|
| pretender | ⬆️ 2024 | ✅ | ✅ | ✅ | ➕ add | 🔁 → build test |
| dont | ✅ | ✅ | ✅ | ✅ | 🔧 -cu→-uc | 🔁 → build test |
| espectacular | ⬆️ 2024 | ✅ | ✅ | ✅ | ➕ add | 🔁 → build test |
| testaruda | ⬆️ 2024 | ✅ | ✅ | 🔧 ah→test, ➕ validate | ➕ add | 🔁 → build test |
| vampiro | 🆕 2024 | ✅ | 🆕 0.1.0 | ✅ | ✅ | 🔧 → build test |
| crua | 🆕 2024 | ✅ | 🆕 0.1.0 | ✅ | ✅ | 🔧 → build test |
| livin | 🆕 2024 | ✅ | 🆕 0.1.0 | ✅ | ✅ | 🔧 → build test |
✅ = conforms · 🎯 = target · ➕ = missing · 🔧 = needs change · ⬆️ = upgrade · 🆕 = initial setup
Each tool SHOULD implement its own changes as separate tickets. This document is the suite-level source of truth that those tickets trace to.
References
- genesis tool-craft playbook — design principles, verb grammar, flag consistency, error handling, AIX
- Toolchain Synergy — full tool list and integration surfaces
wai-bdqw.6— tracking ticket
How to Adopt Wai in an Existing Repository
This guide walks through adding wai to a repository that already has code, history, and an established workflow.
Prerequisite: Install wai first — see the Installation page.
1. Initialize the Workspace
From your repository root:
wai init
This creates a .wai/ directory. Commit it — wai artifacts are designed to live alongside your code.
2. Create a Project for Your Current Work
If you’re actively working on something, create a project for it:
wai new project my-current-feature
If you have multiple workstreams, create one project per feature or initiative.
3. Capture What You Already Know
Don’t start from scratch — import the reasoning that already exists:
# Record decisions you've already made
wai add research "Chose PostgreSQL over SQLite for concurrent write support"
wai add design "REST API with versioned endpoints (/v1/, /v2/)"
# Import existing notes or docs
wai add research --file docs/architecture-notes.md
Set the phase to match where you actually are:
wai phase set implement # if you're already writing code
4. Set Up Agent Config Sync (Optional)
If you use AI assistants (Claude Code, Cursor, etc.), consolidate your configs:
# Import existing configs into wai's single source of truth
wai import .cursorrules
wai import .claude/
# Check what was imported
wai config list
# Sync back to tool locations
wai sync
5. Start Using the Session Loop
From now on, use wai prime at the start of each session and wai close at the end:
# Beginning of session
wai prime # Shows status, phase, suggestions
# ... do your work, capture decisions as you go ...
wai add research "Discovered edge case with auth tokens"
# End of session
wai close # Creates handoff for next session
6. Check Your Setup
Verify everything is healthy:
wai doctor # Workspace health check
wai way # Repository best practices
What Not to Do
- Don’t try to backfill all history. Capture decisions going forward. The value compounds over time.
- Don’t skip phases. Even if you set the phase to
implement, record the reasoning that got you there. - Don’t forget to commit
.wai/. It’s part of your repository.
JSON Output
All major wai commands support --json flag for machine-readable output, enabling integration with scripts, automation tools, and other software.
Usage
wai <command> --json
JSON output is written to stdout, errors to stderr. This allows you to separate data from errors:
# Capture JSON output only
wai status --json > status.json
# Capture errors only
wai status --json 2> errors.log
# Capture both separately
wai status --json > status.json 2> errors.log
# Pipe JSON directly to processing tools
wai status --json | jq '.projects[].name'
Supported Commands
Status
wai status --json
Output:
{
"project_root": "/path/to/project",
"projects": [
{
"name": "my-app",
"phase": "implement",
"path": ".wai/projects/my-app"
}
],
"plugins": [
{
"name": "beads",
"detected": true,
"description": "Issue tracking"
},
{
"name": "git",
"detected": true,
"description": "Version control"
}
],
"hook_outputs": {
"git_status": "M src/main.rs\n",
"beads_stats": "Open: 5, Closed: 12"
},
"openspec": {
"specs": ["cli-core", "plugin-system"],
"changes": [
{
"name": "add-feature-x",
"progress": 75
}
]
},
"suggestions": [
{
"pattern": "ImplementPhaseActive",
"suggestion": "Consider running tests",
"command": "cargo test"
}
]
}
Search
wai search "authentication" --json
Output:
{
"query": "authentication",
"results": [
{
"path": ".wai/projects/my-app/research/2026-02-15-auth-research.md",
"type": "research",
"project": "my-app",
"line": 12,
"context": [
"Evaluated JWT vs session-based authentication.",
"Chose JWT for stateless API design.",
"Will store tokens in httpOnly cookies."
]
}
]
}
Timeline
wai timeline my-app --json
Output:
{
"project": "my-app",
"entries": [
{
"date": "2026-02-15",
"type": "research",
"title": "auth-research",
"path": ".wai/projects/my-app/research/2026-02-15-auth-research.md"
},
{
"date": "2026-02-16",
"type": "design",
"title": "api-design",
"path": ".wai/projects/my-app/designs/2026-02-16-api-design.md"
}
]
}
Plugin List
wai plugin list --json
Output:
{
"plugins": [
{
"name": "beads",
"description": "Issue tracking",
"detected": true,
"commands": [
{
"name": "list",
"description": "List issues",
"read_only": true
},
{
"name": "show",
"description": "Show issue details",
"read_only": true
}
],
"hooks": [
{
"type": "on_status",
"command": "bd stats"
},
{
"type": "on_handoff_generate",
"command": "bd list --status=open"
}
]
}
]
}
Resource List
wai resource list skills --json
Output:
{
"skills": [
{
"name": "code-review",
"path": ".wai/resources/agent-config/skills/code-review.md"
},
{
"name": "commit",
"path": ".wai/resources/agent-config/skills/commit.md"
}
]
}
Error Handling
Errors are returned as JSON when --json is used:
{
"code": "wai::error::project_not_found",
"message": "Project 'missing-app' not found",
"help": "Use 'wai show' to list available projects",
"details": null
}
JSON Schema Stability
Current Policy: JSON output schemas are considered stable within a major version.
- ✅ Safe: Adding new optional fields
- ✅ Safe: Adding new values to enums
- ❌ Breaking: Removing fields
- ❌ Breaking: Changing field types
- ❌ Breaking: Renaming fields
Recommendation: When writing automation scripts, handle unknown fields gracefully and validate expected fields exist.
Example resilient parsing:
# Good - checks for field existence
if jq -e '.projects[]? | select(.name == "my-app")' status.json; then
echo "Project exists"
fi
# Good - provides defaults for missing fields
jq '.projects[]? | {name, phase: (.phase // "unknown")}' status.json
Processing with jq
Use jq for powerful JSON processing:
# Extract project names
wai status --json | jq '.projects[].name'
# Get all research artifacts
wai search ".*" --regex --type research --json | jq '.results[].path'
# Count plugins detected
wai plugin list --json | jq '[.plugins[] | select(.detected)] | length'
# Get recent timeline entries
wai timeline my-app --json | jq '.entries | .[-5:]'
# Check if sync is needed
wai sync --status --json | jq '.projections[] | select(.status != "in_sync")'
Automation Examples
CI/CD Integration
#!/bin/bash
# Check if handoff exists for current branch
BRANCH=$(git branch --show-current)
HANDOFFS=$(wai search "$BRANCH" --type handoff --json | jq -r '.results[].path')
if [ -z "$HANDOFFS" ]; then
echo "No handoff found for branch $BRANCH"
exit 1
fi
Slack Notifications
#!/bin/bash
# Send status to Slack
STATUS=$(wai status --json)
PROJECTS=$(echo "$STATUS" | jq -r '.projects[] | "\(.name): \(.phase)"' | tr '\n' ', ')
curl -X POST "$SLACK_WEBHOOK" \
-H 'Content-Type: application/json' \
-d "{\"text\":\"Project Status: $PROJECTS\"}"
Dashboard Generation
import json
import subprocess
# Get status
result = subprocess.run(['wai', 'status', '--json'], capture_output=True, text=True)
status = json.loads(result.stdout)
# Generate HTML dashboard
html = "<h1>Project Status</h1>"
for project in status['projects']:
html += f"<div><strong>{project['name']}</strong>: {project['phase']}</div>"
print(html)
Non-Interactive Mode
Combine --json with --no-input for fully automated scripts:
wai status --json --no-input
wai search "query" --json --no-input
This prevents any interactive prompts that might block automation.
Safe Mode
Use --safe with --json for read-only automation:
wai status --json --safe
Ensures no modifications occur during automated queries.
See Also
- Commands Reference - Global flags documentation
- Troubleshooting - JSON troubleshooting
- Quick Start - Getting started with JSON
Workflow Detection
Wai automatically detects project patterns and provides context-aware suggestions based on your current state.
How It Works
When you run wai status, wai analyzes:
- Current project phase
- Number and type of artifacts
- Plugin state (git status, open issues, etc.)
- Recent activity
Based on this analysis, it detects workflow patterns and suggests relevant next steps.
Detected Patterns
NewProject
Condition: Project exists but has no artifacts yet, in research phase.
Suggestions:
- Add initial research with
wai add research "..." - Import existing research with
wai add research --file notes.md - Run tutorial for guidance:
wai tutorial
Example:
$ wai status
Project: my-app
Phase: research
Artifacts: 0
Pattern: NewProject
Suggestions:
- Start gathering research: wai add research "Initial findings"
- Import existing notes: wai add research --file notes.md
ResearchPhaseMinimal
Condition: In research phase with few (≤1) research artifacts.
Suggestions:
- Continue gathering information
- Add more research artifacts
- Consider when you have enough to move to design
Example:
$ wai status
Project: my-app
Phase: research
Research artifacts: 1
Pattern: ResearchPhaseMinimal
Suggestions:
- Add more research: wai add research "Additional findings"
- When ready, advance: wai phase next
ReadyToImplement
Condition: In plan or design phase with design documents created.
Suggestions:
- Move to implement phase
- Review designs before starting
- Set up development environment
Example:
$ wai status
Project: my-app
Phase: design
Design artifacts: 2
Plan artifacts: 1
Pattern: ReadyToImplement
Suggestions:
- Ready to implement: wai phase next
- Review designs: wai search "design" --in my-app
- Create handoff: wai handoff create my-app
ImplementPhaseActive
Condition: Currently in implement phase.
Suggestions:
- Run tests regularly
- Document implementation decisions
- Consider moving to review when done
Example:
$ wai status
Project: my-app
Phase: implement
Pattern: ImplementPhaseActive
Suggestions:
- Run tests: cargo test
- Document decisions: wai add design "Implementation notes"
- When done, advance: wai phase next
Context-Aware Commands
Suggestions include specific commands tailored to your project:
$ wai status
Project: api-server
Phase: implement
Plugin: beads (5 open issues)
Plugin: git (uncommitted changes)
Suggestions:
- Review open issues: wai beads ready
- Check git status: git status
- Run tests: cargo test
- Commit changes: git add -A && git commit
Plugin Integration
Workflow detection incorporates plugin context:
With beads plugin:
- Suggests reviewing open issues
- Recommends closing completed work
- Highlights blockers
With git plugin:
- Detects uncommitted changes
- Suggests creating commits
- Recommends pushing to remote
With openspec plugin:
- Shows active change proposals
- Displays implementation progress
- Suggests next specification steps
JSON Output
Get structured workflow information:
wai status --json | jq '.suggestions'
Output:
[
{
"pattern": "ReadyToImplement",
"suggestion": "Move to implement phase",
"command": "wai phase next"
},
{
"pattern": "ReadyToImplement",
"suggestion": "Review designs before implementing",
"command": "wai search \"design\" --in my-app"
}
]
Custom Patterns
While wai detects common patterns automatically, you can create custom workflow patterns through plugins.
Example Custom Pattern Plugin
name = "my-workflow"
description = "Custom workflow detector"
[hooks.on_status]
command = """
if [ -f .needs-review ]; then
echo "Ready for review - run: make review"
fi
"""
inject_as = "custom_workflow"
Best Practices
Follow Suggestions
Wai’s suggestions are designed to guide you through proven workflows:
- Research → gather information
- Design → make decisions
- Plan → break down work
- Implement → build
- Review → validate
- Archive → document and close
Ignore When Needed
Suggestions are guidance, not rules. Feel free to:
- Skip phases that don’t apply
- Go back when you need more research
- Add artifacts in any phase
- Move forward at your own pace
Use with Plugins
Workflow detection works best with plugins:
- beads — Track concrete tasks alongside high-level workflow
- git — Keep version control in sync with project phases
- openspec — Align specifications with implementation phases
Disable Suggestions
To hide workflow suggestions:
wai status --quiet
Or suppress output:
wai status -q
See Also
- Project Phases - Understanding workflow stages
- Commands Reference - Status command details
- JSON Output - Programmatic access to suggestions
Implementation Status
At-a-glance view of wai’s implemented commands and their relation to formal
change proposals tracked in openspec/.
Commands
| Command | Description |
|---|---|
wai init | Initialize wai in any directory |
wai tutorial | Run the interactive quickstart tutorial |
wai status | Project overview and next-step suggestions |
wai prime | Orient the session; detect resume state |
wai close | Capture session state and signal pending resume |
wai handoff create <project> | Generate a handoff document explicitly |
wai show | Inspect projects, areas, and resources |
wai ls | List all wai workspaces under a root |
wai new | Create projects, areas, and resources |
wai add | Add research, plans, designs, and reviews |
wai search | Full-text artifact search with tag filtering |
wai timeline | Chronological artifact view across projects |
wai why | Ask the LLM oracle about design decisions |
wai reflect | Synthesize project patterns into CLAUDE.md |
wai sync | Pull remote artifact updates |
wai move | Relocate projects and areas |
wai import | Import existing AI tool configs (.claude/, .cursorrules) |
wai phase | Show, advance, or set the current project phase |
wai doctor | Diagnose and repair workspace health |
wai way | Check and scaffold repository best practices |
wai config | Inspect workspace configuration |
wai resource | Manage skills, rules, and context resources |
wai plugin | Enable and disable workspace plugins |
wai pipeline | Run structured multi-step research workflows |
wai project | Session-scope a project (WAI_PROJECT env var) |
wai trace | (Planned) Import session traces from agent tools |
For the authoritative list run wai --help.
Change Proposals
Formal changes are tracked in openspec/changes/. Each entry links a
capability to the reasoning that motivated it. Status values come from
openspec list; task counts from tasks.md in each change directory.
| Change | Status | Related Commands |
|---|---|---|
add-cross-tool-trace-ingestion | In progress (0/10) | wai trace, wai reflect |
add-artifact-integrity | Complete | wai pipeline lock/verify, wai doctor |
add-project-resolution | Complete | wai project use, wai ls |
Run openspec list for the full list including archived changes.
Capability Specs
Stable capabilities have formal specs in openspec/specs/. These define the
expected behavior independently of any single change.
Run openspec list --specs to see current specs.
Release History
Releases follow calendar versioning (vYYYY.M.N). See the
GitHub Releases page for the
full changelog.
Frequently Asked Questions
General
What is wai?
Wai (pronounced “why”) is a command-line workflow manager for AI-driven development. It helps you capture and organize the research, reasoning, and decisions behind your code - the “why” that’s often lost between sessions.
How is wai different from other documentation tools?
Most tools focus on what you built. Wai captures why you built it that way:
- Research findings and trade-offs
- Design decisions and alternatives considered
- Implementation plans and reasoning
- Session handoffs with context
Do I need to use git with wai?
No, wai works independently. However, wai integrates nicely with git through the plugin system, including git status in handoffs and status output.
Can I use wai with existing projects?
Yes! Run wai init in any directory to start using wai. You can import existing documentation with wai import or wai add research --file.
Usage
Which phase should I be in?
Phases are guidelines, not gates. Use what makes sense:
- Research - Exploring, learning, gathering information
- Design - Making architectural decisions
- Plan - Breaking down implementation steps
- Implement - Writing code
- Review - Testing, validating, refining
- Archive - Wrapping up, documenting outcomes
You can skip phases or go backward anytime.
How do I choose between projects, areas, and resources?
PARA method:
- Projects - Active work with a goal and end date (e.g., “user-auth-feature”)
- Areas - Ongoing responsibilities without end date (e.g., “performance-monitoring”)
- Resources - Reference material (e.g., agent configs, templates)
- Archives - Completed or inactive items
Should I use wai for every project?
Wai is most valuable for:
- Complex features requiring research and design
- Work spanning multiple sessions
- Collaboration requiring knowledge transfer
- Projects where “why” matters (architecture decisions, trade-offs)
For quick fixes or trivial changes, standard git commits may be enough.
How often should I create handoffs?
Create handoffs when:
- Ending a work session (especially multi-hour sessions)
- Switching context to another project
- Handing work to another developer
- Taking a break and might forget context
Think of handoffs as “save points” for your reasoning.
Agent Configuration
What’s the difference between skills, rules, and context?
- Skills - Task-specific instructions (e.g., “how to review code”, “how to commit”)
- Rules - System-wide constraints (e.g., “always add tests”, “follow security practices”)
- Context - Project-specific background (e.g., “architecture overview”, “team conventions”)
Which sync strategy should I use?
| Strategy | Use When | Example |
|---|---|---|
| Symlink | Tool expects directory of files | Claude Code, Aider |
| Inline | Tool expects single concatenated file | Cursor (.cursorrules) |
| Reference | Tool can follow paths | Custom scripts |
See Agent Config Sync for details.
Can I use multiple sync strategies?
Yes! You can have different projections for different tools:
projections:
- strategy: symlink
sources: [skills/]
target: .claude/skills/
- strategy: inline
sources: [rules/]
target: .cursorrules
What happens if I edit synced files directly?
Wai will overwrite them on the next sync. Always edit source files in .wai/resources/agent-config/, never the synced targets.
Plugins
How do I create a custom plugin?
Create a TOML file in .wai/plugins/:
name = "my-tool"
description = "My tool integration"
[detector]
type = "directory"
path = ".mytool"
[[commands]]
name = "status"
description = "Show status"
passthrough = "mytool status"
read_only = true
[hooks.on_status]
command = "mytool stats"
inject_as = "mytool_stats"
See Plugin System for complete guide.
Can I disable built-in plugins?
No, built-in plugins (git, beads, openspec) cannot be disabled. They’re only active when their detector finds the relevant files (e.g., .git/ for git).
Why isn’t my plugin detected?
Common reasons:
- Detector path doesn’t exist (e.g.,
.mytool/directory missing) - TOML syntax error in plugin definition
- Plugin tool not installed or not in PATH
Run wai doctor to diagnose plugin issues.
Workflow & Patterns
What are workflow patterns?
Wai automatically detects your project state and suggests next steps:
- NewProject - No artifacts yet → suggests adding research
- ResearchPhaseMinimal - Few artifacts → suggests gathering more info
- ReadyToImplement - Designs complete → suggests moving to implementation
- ImplementPhaseActive - Currently implementing → suggests testing
Can I customize workflow suggestions?
Not yet, but it’s planned. For now, you can ignore suggestions that don’t fit your workflow.
How does wai know what to suggest?
Wai analyzes:
- Current project phase
- Number and type of artifacts
- Plugin state (git status, open issues, etc.)
- Recent activity
Based on this, it matches patterns and suggests relevant commands.
Technical
Where is data stored?
Everything is in .wai/ directory:
.wai/
├── config.toml # Project configuration
├── projects/ # Active projects with artifacts
├── resources/ # Agent configs, templates
└── plugins/ # Custom plugin definitions
Safe to version control with git!
Is wai data portable?
Yes! The entire .wai/ directory can be:
- Committed to git
- Copied to another machine
- Backed up
- Shared with team members
Can I use wai in CI/CD?
Yes! Use non-interactive mode with JSON output:
wai status --json --no-input
wai search "query" --json --no-input
wai doctor --json --no-input
Does wai work offline?
Yes, wai is completely local. No network required.
What’s the performance impact?
Minimal. Wai is a lightweight CLI tool. Most commands complete in milliseconds. Large projects (hundreds of artifacts) may see slower search/timeline commands, but typically still under 1 second.
Troubleshooting
Command not found after installation
Add cargo bin to PATH:
export PATH="$HOME/.cargo/bin:$PATH"
Add to ~/.bashrc or ~/.zshrc to make permanent.
Doctor reports issues I don’t understand
Run with verbose mode:
wai doctor -v
Check Troubleshooting for common issues.
My synced files keep getting overwritten
This is expected behavior. Wai syncs from source files in .wai/resources/agent-config/ to target locations. Always edit source files, never the synced targets.
See Agent Config Sync - Conflict Resolution.
Search returns no results but files exist
Check:
- Are you searching the right project? Use
--in project-name - Is the search term exact? Try regex mode:
--regex - Do artifacts exist? Check:
wai timeline project-name
Getting More Help
- Documentation: Read full docs in
docs/directory - Tutorial: Run
wai tutorialfor interactive guide - Command help:
wai <command> --help - Workspace health:
wai doctor - GitHub Issues: https://github.com/charly-vibes/wai/issues
See Also
- Quick Start - Get started in 5 minutes
- Commands Reference - Complete command list
- Troubleshooting - Common problems and solutions
- Concepts - Deep dive into wai’s design
Glossary
Domain-specific terms used throughout the wai documentation.
Addendum
A correction artifact that references a locked artifact via --corrects=<path>. Preserves the original’s integrity while recording what changed and why. See Pipelines — Artifact Locking.
Artifact
A dated Markdown file capturing reasoning at a specific point in time. Types include research, design, plan, handoff, and review. Stored in project subdirectories under .wai/projects/. See Project Phases.
Artifact lock
A SHA-256 hash sidecar (.lock file) written alongside a pipeline artifact to freeze its content. Created automatically when a step with lock = true advances, or manually via wai pipeline lock. Verified by wai pipeline verify and wai doctor. See Pipelines — Artifact Locking.
Frontmatter
YAML metadata at the top of an artifact file (between --- markers). Contains fields like title, date, tags, and project name. Used by wai search for filtering and by wai why for context gathering.
Handoff
A session context transfer document generated by wai close or wai handoff create. Contains a session summary, current state, plugin context, and next steps. Enables continuity across sessions and agents. See Sessions.
Managed block
An auto-generated section in instruction files (AGENTS.md, CLAUDE.md) delimited by <!-- WAI:START --> / <!-- WAI:END --> markers. Updated automatically by wai init and wai reflect. Do not edit manually — changes will be overwritten.
Oracle
The LLM-powered reasoning engine behind wai why. Queries your project artifacts and git history to answer natural-language questions about design decisions. See Reasoning. Not to be confused with oracle scripts — see Pipeline gate.
Oracle script
A user-defined validation script executed during pipeline gate checks. Placed in .wai/resources/oracles/ and referenced from pipeline TOML definitions. Exit 0 = pass, non-zero = fail. See Pipelines — Gates.
PARA An organizational system with four categories: Projects (active work with a goal), Areas (ongoing responsibilities), Resources (reference material), Archives (completed items). See PARA Method.
Phase One of six lifecycle stages a project moves through: research → design → plan → implement → review → archive. Phases guide what kind of work and artifacts are expected. See Project Phases.
Pipeline An ordered, multi-step workflow defined in TOML. Pipelines structure complex tasks (like research) into sequential steps with validation between them. See Pipelines.
Pipeline gate A condition that must be satisfied before advancing to the next pipeline step. Gate tiers include structural (artifact counts), procedural (review verdicts), oracle (custom scripts), and approval (human checkpoints). See Pipelines — Gates.
Pipeline run
An active execution of a pipeline, scoped to a topic. Created with wai pipeline start and advanced with wai pipeline next. State is tracked so you can resume across sessions.
Review artifact
An artifact that records validation results against another artifact. Created with wai add review --reviews <target>. Includes optional verdict (pass/fail/needs-work), severity counts, and the producing skill name. Used by pipeline procedural gates to enforce review requirements. See Commands — Adding Artifacts.
Plugin
An integration module that connects wai with external tools (git, beads, openspec). Plugins are auto-detected based on workspace markers (e.g., .git/, .beads/). See Plugin System.
Projection
A sync strategy that maps source files in .wai/resources/agent-config/ to tool-specific target locations. Strategies include symlink, inline, and reference. See Agent Config Sync.
Hook
A plugin extension point triggered during wai operations. Hooks like on_status and on_handoff_generate let plugins inject context into wai’s output. See Plugin System — Hooks.
Passthrough
A plugin command that delegates directly to the underlying tool. For example, wai beads list passes through to the beads CLI. See Plugin System — Commands.
Safe mode
A read-only execution mode activated by the --safe global flag. Blocks all write operations (add, sync, move, pipeline start/next/init/approve/lock, phase changes, import). Read-only commands work normally. See Commands — Safe mode.
Reflection
A synthesized summary of project patterns, conventions, and architectural notes produced by wai reflect. Stored as versioned Markdown in .wai/resources/reflections/ and injected into instruction files. See Reasoning.
Session
A unit of work bounded by wai prime (start) and wai close (end). Sessions preserve context across agent restarts and context window boundaries. See Sessions.
Development
Prerequisites
Architecture Overview
wai is built as a modular CLI tool in Rust, focusing on local-first storage and tool-agnostic integration.
For a deeper dive into the codebase structure and ADRs, see Architecture.
Core Systems
1. Registry & Workspace (src/workspace.rs, src/config.rs)
Manages the .wai/ directory structure and the PARA method (Projects, Areas, Resources, Archives).
- Project state: Tracked via
.statefiles in each project. - Artifacts: Stored as date-prefixed markdown files with optional frontmatter.
2. Plugin System (src/plugin.rs)
A flexible architecture for detecting and interacting with external tools.
- Built-in plugins:
git,beads,openspec. - Custom plugins: Loaded from
.wai/plugins/*.toml. - Hooks: Allows tools to inject context into
wai status(on_status) andwai handoff create(on_handoff_generate). - Passthrough: Direct execution of tool commands (e.g.,
wai beads list).
3. Agent-Config Sync Engine (src/sync_core.rs, src/commands/sync.rs)
Syncs a single source of truth for agent configurations to tool-specific locations.
- Projections: Defined in
.projections.yml. - Strategies:
symlink,inline(concatenation),reference(path listing), andcopy. - Specialized Targets: Built-in logic for tools like
claude-code.
4. Reasoning Oracle (src/llm.rs, src/commands/why.rs)
Interfaces with LLMs (Claude, Ollama) to answer natural language questions about the codebase using project artifacts as context.
5. Pipelines (src/commands/pipeline.rs)
Multi-step, prompt-driven workflows that track run IDs and automatically tag artifacts.
Building
just build # Debug build
just build-release # Release build
Testing
just test # Run all tests
just test-verbose # Run tests with output
just test-one <name> # Run a specific test
Linting & formatting
just lint # Run clippy
just fmt # Format code
just fmt-check # Check formatting without changes
Full CI pipeline
Run the same checks that CI runs:
just ci
Documentation
Build and preview the docs locally:
just docs # Build docs
just docs-serve # Live preview at localhost:3000
Requires mdBook:
cargo install mdbook
Architecture
This page describes wai’s internal architecture for contributors who want to understand or modify the codebase.
High-Level Structure
Wai is a modular Rust CLI organized into five core subsystems:
src/
├── main.rs # Entry point
├── cli.rs # Clap argument definitions
├── commands/ # One file per subcommand
│ ├── status.rs # wai status
│ ├── add.rs # wai add
│ ├── search.rs # wai search
│ ├── prime.rs # wai prime
│ ├── close.rs # wai close
│ ├── why.rs # wai why (reasoning oracle)
│ ├── reflect.rs # wai reflect (synthesis)
│ ├── doctor.rs # wai doctor
│ ├── way.rs # wai way (best practices)
│ ├── pipeline.rs # wai pipeline
│ └── ...
├── workspace.rs # Registry & PARA directory management
├── config.rs # Config loading (.wai/config.toml)
├── plugin.rs # Plugin detection, hooks, passthrough
├── sync_core.rs # Agent config sync engine
├── llm.rs # LLM backend abstraction
├── suggestions.rs # Context-aware next-step suggestions
└── help.rs # Tiered help system
Subsystems
1. Registry & Workspace
Files: src/workspace.rs, src/config.rs
Manages the .wai/ directory structure and the PARA method. Project state is tracked via .state files. Artifacts are stored as date-prefixed Markdown files with optional YAML frontmatter.
2. Plugin System
Files: src/plugin.rs
Auto-detects external tools by scanning for workspace markers (.git/, .beads/, openspec/). Plugins contribute context through hooks (on_status, on_handoff_generate, on_phase_transition) and expose commands via passthrough. Custom plugins are loaded from .wai/plugins/*.toml.
3. Agent Config Sync Engine
Files: src/sync_core.rs, src/commands/sync.rs
Projects agent configurations from .wai/resources/agent-config/ to tool-specific locations using configurable strategies (symlink, inline, reference, copy). Specialized targets like claude-code handle complex tool-specific transformations.
4. Reasoning Oracle & Synthesis
Files: src/llm.rs, src/commands/why.rs, src/commands/reflect.rs
Interfaces with LLMs (Claude API, Claude CLI, Ollama) to answer questions about the codebase (wai why) and synthesize project patterns (wai reflect). The LlmClient trait abstracts backend differences.
5. Pipelines
Files: src/commands/pipeline.rs
Multi-step, prompt-driven workflows defined in TOML. Tracks run state, supports pipeline gates (structural, procedural, oracle, approval), and auto-tags artifacts with run IDs.
Design Decisions
Significant trade-offs and architectural choices are captured as wai artifacts. Run wai search "design" to browse design decisions, or check .wai/resources/reflections/ for synthesized project patterns.
Agent Config Sync
Purpose
Define how wai manages AI agent configurations as a single source of truth, with projections to tool-specific formats like .claude/, .cursorrules, .windsurfrules, and AGENTS.md.
Problem Statement
Modern development involves multiple AI coding assistants (Claude Code, Cursor, Windsurf, etc.), each requiring its own configuration format and location. Maintaining consistent agent instructions across these tools leads to configuration drift, duplicated effort, and inconsistent behavior. Developers need a single source of truth for agent configurations that can be projected to each tool’s expected format automatically.
Design Rationale
Single Source of Truth
Storing all agent configuration in .wai/resources/agent-config/ is a Type 1 decision. This centralizes skills, rules, and context files in one location, making them versionable, reviewable, and consistent. Tool-specific files become projections of this canonical source rather than independent configurations.
Projection Strategies
Three projection strategies (symlink, inline, reference) provide flexibility for different tool requirements. This is a Type 2 decision — the strategies may evolve, but the concept of projecting from a single source is foundational.
- Symlink: Creates filesystem symlinks from tool locations to the canonical files. Most efficient, but requires symlink support.
- Inline: Concatenates source files into a single output file with auto-generated headers. Works everywhere, but requires re-running sync after changes.
- Reference: Generates an index file pointing to
.wai/locations. Lightweight, but requires tool support for following references.
Auto-Generated Headers
Projected files include # Auto-generated by wai — do not edit directly headers to prevent accidental direct edits and make the generation pipeline visible.
Scope and Requirements
This spec covers the storage, organization, and projection of agent configuration files.
Non-Goals
- Defining the content or semantics of agent rules/skills
- Managing tool-specific settings beyond agent instructions (e.g., Cursor’s editor settings)
- Automatic detection and sync on file change (manual
wai syncis required) - Remote or team-wide config sharing
Requirement: Agent Config Storage
Agent configurations SHALL be stored in a structured directory within .wai/resources/.
Scenario: Config directory structure
- WHEN wai is initialized
- THEN the agent-config directory structure is:
.wai/resources/agent-config/ ├── skills/ # Reusable agent capabilities ├── rules/ # Behavioral guidelines ├── context/ # Project-specific context └── .projections.yml
Requirement: Projections Configuration
A .projections.yml file SHALL define how configs are projected to tool-specific locations.
Scenario: Projections file format
- WHEN configuring projections
- THEN
.projections.ymlfollows this format:projections: - target: .claude/ strategy: symlink sources: - skills/ - rules/ - target: .cursorrules strategy: inline sources: - rules/ - context/ - target: AGENTS.md strategy: inline sources: - context/
Requirement: Sync Command
The CLI SHALL provide a wai sync command to execute projections.
Scenario: Execute projections
- WHEN user runs
wai sync - THEN the system reads
.projections.yml - AND generates projected files according to each target’s strategy
- AND reports which files were created or updated
Scenario: Check sync status
- WHEN user runs
wai sync --status - THEN the system shows which projections are up-to-date and which need syncing
- AND does not modify any files
Requirement: Config Management
The CLI SHALL support managing agent config files.
Scenario: Add a skill
- WHEN user runs
wai config add skill <file> - THEN the system copies the file to
.wai/resources/agent-config/skills/
Scenario: Add a rule
- WHEN user runs
wai config add rule <file> - THEN the system copies the file to
.wai/resources/agent-config/rules/
Scenario: List configs
- WHEN user runs
wai config list - THEN the system shows all files in skills/, rules/, and context/ directories
Requirement: Import Existing Configs
The CLI SHALL support importing configurations from existing tool-specific files.
Scenario: Import from Claude directory
- WHEN user runs
wai import .claude/ - THEN the system detects Claude-specific config files
- AND copies them into the appropriate agent-config subdirectories
Scenario: Import from cursorrules
- WHEN user runs
wai import .cursorrules - THEN the system reads the cursorrules file
- AND imports the content as agent rules
Requirement: Auto-Generated Headers
Projected files SHALL include headers indicating they are auto-generated.
Scenario: Generated file header
- WHEN a file is generated via
wai sync - THEN it begins with a comment:
# Auto-generated by wai — do not edit directly - AND includes the source path for reference
Requirements
Requirement: Claude Code Built-in Projection Target
The sync system SHALL support claude-code as a built-in projection target that
automatically maps hierarchical wai skills to Claude Code command files with
translated frontmatter.
Scenario: Built-in target activation
- WHEN a projection defines
target: claude-code - THEN the system treats it as a built-in target, not a filesystem path
- AND scans
skills/<category>/<action>/SKILL.mdfor all hierarchical skills
Scenario: Skill file generated at correct path
- WHEN
wai syncprocesses aclaude-codetarget - AND a skill exists at
skills/issue/gather/SKILL.md - THEN the system writes
.claude/commands/issue/gather.md - AND creates the
.claude/commands/issue/directory if it does not exist
Scenario: Frontmatter translation
- WHEN a wai SKILL.md has frontmatter
name: issue/gatheranddescription: "Gather issues from codebase" - THEN the generated Claude Code file has frontmatter:
name: "Issue: Gather" description: "Gather issues from codebase" category: "Issue" - AND the skill body is written unchanged after the frontmatter block
- AND the
namefield is derived by capitalising the first letter of each path segment and joining with:(e.g.,issue/gather→Issue: Gather)
Scenario: Auto-generated header
- WHEN a Claude Code file is generated by
wai sync - THEN the
---frontmatter delimiter is on line 1 of the generated file (required for frontmatter parsers that enforce strict position) - AND the file body (after the closing
---of the frontmatter) begins with:<!-- Auto-generated by wai — do not edit directly --> - AND the source path is noted (e.g.,
<!-- Source: skills/issue/gather/SKILL.md -->)
Requirement: Hierarchical Skill Names
Skill names SHALL support a single / separator to enable category/action grouping
that maps directly to Claude Code’s invocation path convention (/category:action).
Scenario: Create hierarchical skill
- WHEN user runs
wai resource add skill issue/gather - THEN the system creates
.wai/resources/agent-config/skills/issue/gather/SKILL.md - AND the skill is listed with name
issue/gather
Scenario: Flat names unchanged
- WHEN user runs
wai resource add skill my-skill - THEN the system creates
.wai/resources/agent-config/skills/my-skill/SKILL.md - AND existing flat naming behavior is preserved
Scenario: Invalid hierarchical names rejected
- WHEN user provides a skill name with two or more slashes (e.g.,
a/b/c) - THEN the system rejects it with a clear error: only one
/is allowed
Scenario: Empty segments rejected
- WHEN user provides a name with an empty segment (e.g.,
/gatherorissue/) - THEN the system rejects it with an error explaining both segments must be non-empty
Scenario: Category grouping in list output
- WHEN user runs
wai resource list skills - AND hierarchical skills exist (e.g.,
issue/gather,issue/create) - THEN skills are displayed with their full hierarchical name (e.g.,
issue/gather) - AND the JSON output includes a
categoryfield for hierarchical skills
Scenario: Frontmatter name for hierarchical skill
- WHEN user runs
wai resource add skill issue/gather - THEN the generated SKILL.md frontmatter contains
name: issue/gather(the full hierarchical name, not just the action segment) - AND this name is what
add-claude-code-projectionreads for frontmatter translation
Scenario: Flat-name collision with category directory rejected
- WHEN a flat skill named
issuealready exists atskills/issue/SKILL.md - AND user runs
wai resource add skill issue/gather - THEN the system errors with a message explaining that
issueis already a flat skill and cannot also be used as a category name - AND suggests renaming the existing flat skill before creating the category
Requirement: Skill Template Library
The CLI SHALL provide built-in templates that scaffold common agent pipeline skill patterns when creating a new skill.
Scenario: Create skill from template
- WHEN user runs
wai resource add skill issue/gather --template gather - THEN the system creates
SKILL.mdwith the gather template body - AND the template uses
$ARGUMENTS,$PROJECT,$REPO_ROOTplaceholders - AND the SKILL.md is ready to use without further editing of placeholders
Scenario: Available templates
- WHEN user runs
wai resource add skill <name> --template <name> - THEN the system accepts the following template names:
gather— research stub:wai search $ARGUMENTS, codebase exploration,wai add researchcreate— creation stub: artifact retrieval viawai search --latest, item loop with output trackingtdd— test-first stub: RED/GREEN/REFACTOR loop withcargo test/just checkrule-of-5— review stub: 5-pass review with convergence check and APPROVED / NEEDS_CHANGES / NEEDS_HUMAN verdict
Scenario: Unknown template name rejected
- WHEN user runs
wai resource add skill <name> --template unknown-template - THEN the system rejects the command with an error
- AND lists the valid template names in the error message
Scenario: No template gives bare stub
- WHEN user runs
wai resource add skill <name>without--template - THEN the system creates the existing minimal stub (no regression)
Scenario: Templates are portable
- WHEN a template-generated SKILL.md is used in a different project
- THEN all project-specific values are provided via
$ARGUMENTS,$PROJECT, or$REPO_ROOTat runtime — no hardcoded project names exist in the template
agnostic-capabilities Specification
Purpose
TBD - created by archiving change refactor-way-agnostic. Update Purpose after archive.
Requirements
Requirement: Agnostic Repository Best Practice Checks
The wai way command SHALL report on agnostic repository capabilities rather than specific tool implementations. Each check SHALL include its intent and success criteria to provide context for both human users and AI agents.
Scenario: Check output with intent and success criteria (Verbose)
- GIVEN a project with a
justfile - WHEN user runs
wai way -v - THEN the output SHALL show the capability name “Command standardization” instead of “Task runner”
- AND the output SHALL include an “Intent:” line with the agnostic purpose of the check
- AND the output SHALL include a “Success:” line with the agnostic criteria for passing the check
Scenario: Check output with intent and success criteria (JSON)
- GIVEN any project
- WHEN user runs
wai way --json - THEN the JSON payload SHALL include
intentandsuccess_criteriafields for every check result - AND these fields SHALL be optional (
nullif not provided) to ensure backward compatibility
Scenario: Agnostic Check Mapping
The system SHALL map tool-specific checks to agnostic capabilities, each with defined intent and success criteria:
| Capability | Intent | Success Criteria |
|---|---|---|
| Command standardization | Provide a single, tool-agnostic entry point for common repository tasks (build, test, deploy). | A standard interface exists for common tasks. |
| Pre-commit quality gates | Prevent low-quality commits by running automated checks before code is saved to history. | Automated checks run automatically before code is committed. |
| Consistent formatting | Ensure consistent code formatting across different editors and IDEs. | Project-wide style rules are enforced by a shared configuration file. |
| Project documentation | Provide essential project identity, onboarding, and legal/contribution guidance. | Essential files provide project context and rules. |
| AI-agent context | Provide persistent “rules of the road” and project context for AI collaborators. | Persistent instructions define coding standards and context for AI assistants. |
| LLM-friendly context | Provide machine-readable project context and navigation for LLMs. | Machine-readable project documentation (llm.txt) exists. |
| Extended agent capabilities | Enhance agent functionality with specialized iterative review and commit workflows. | Specialized agent workflows are active. |
| Integration & automation | Streamline repository interactions (PRs, issues, releases) from the CLI. | CLI tools are configured for seamless integration with the hosting provider. |
| Automated verification | Ensure code quality and correctness through automated builds and tests on every change. | Every change is automatically validated by a remote build/test pipeline. |
| Reproducible environments | Provide a standardized, containerized environment for all contributors. | A configuration exists for a consistent, reproducible dev environment. |
| Automated delivery | Automate the process of building, packaging, and publishing software releases. | Software releases and distribution are fully automated. |
Requirement: Plugin Agnostic Context Support
The plugin system SHALL allow TOML-defined plugins to define their own intent and success_criteria.
Scenario: Plugin with custom context
- GIVEN a plugin TOML with
intentandsuccess_criteriadefined - WHEN the plugin definition is parsed
- THEN these fields are available on the
PluginDefstruct - AND default to
Noneif not present in the TOML
CLI Core
Purpose
Define the core command structure and patterns for the wai CLI, including the verb-noun command hierarchy, global flags, and foundational commands for managing PARA-organized artifacts, project phases, agent config sync, handoffs, and cross-artifact search.
See also: onboarding spec for first-run and no-args welcome behavior.
Problem Statement
For wai to effectively support development and research projects, it requires a stable and predictable foundation. Without a clearly defined and consistent core command structure and project organization, users would face a steep learning curve, inconsistent interactions, and an unstable platform for automation. This lack of a standardized and predictable interface would hinder adoption and make it difficult to build reliable workflows around wai.
Design Rationale
The design of the CLI core follows a few key principles to establish a stable foundation that is intuitive, consistent, and extensible, making it a reliable platform for future growth.
Command Structure: Verb-Noun
The chosen verb-noun pattern (e.g., wai new project) is a foundational Type 1 decision for wai’s grammar. It was selected for its readability and similarity to natural language, establishing a predictable and consistent rhythm for the user. This stable grammar makes commands easy to discover and remember, and crucially, enables future extensibility by providing a clear framework for applying existing verbs to new nouns. An alternative noun-verb pattern (e.g., wai project new) was considered but deemed less intuitive for wai’s action-oriented approach.
Core Verbs
The primary verbs (new, add, show, move) provide a minimal, orthogonal set of operations. Additional top-level commands (phase, sync, config, handoff, search, timeline, doctor) provide direct access to frequently-used workflows that don’t fit the verb-noun pattern naturally.
PARA-Based Organization
Wai organizes artifacts using the PARA method (Projects, Areas, Resources, Archives). This replaces the previous bead-centric model with a proven organizational framework. Beads (.beads/) is an external tool that wai detects via its plugin system but does not manage directly.
Scope and Requirements
This spec covers the foundational elements of the CLI.
Non-Goals
- The detailed implementation of every command’s functionality.
- The internal plugin execution model (covered in plugin-system spec).
- Specific output formats like JSON or YAML, beyond the standard text output.
- A graphical user interface.
Requirement: Command Structure
The CLI SHALL use consistent verb-noun command patterns with primary verbs: new, add, show, move, plus dedicated top-level commands for phase, sync, config, handoff, search, timeline, why, reflect, and doctor.
Scenario: Create new items
- WHEN user runs
wai new project <name>,wai new area <name>, orwai new resource <name> - THEN the system creates the requested PARA item with appropriate directory structure
Scenario: Add artifacts and resources to a project
- WHEN user runs
wai add research <content>,wai add plan <content>,wai add design <content>, orwai add skill <name> - THEN the system creates the requested artifact or resource file in the appropriate directory
Scenario: Add skill — creates skill file
- WHEN user runs
wai add skill <name> - THEN the system creates a skill file at
.wai/resources/skills/<name>.md(or.wai/resources/skills/<category>/<action>.mdfor hierarchical names) - AND the same name validation rules apply as for
wai resource add skill: flat or one-level-hierarchical, lowercase letters/digits/hyphens only
Scenario: Add skill with template
- WHEN user runs
wai add skill <name> --template <template> - THEN the system creates the skill file pre-populated with the named template
- AND valid built-in templates are:
gather,create,tdd,rule-of-5
Scenario: Deprecated alias still works
- WHEN user runs
wai resource add skill <name> - THEN the system emits a one-line deprecation warning to stderr:
⚠ 'wai resource add skill' is deprecated. Use: wai add skill <name> - AND creates the skill file identically to
wai add skill <name> - AND exits with the same exit code as
wai add skill
Scenario: Show information
- WHEN user runs
wai show <item> - THEN the system displays the requested information
Scenario: Move items between PARA categories
- WHEN user runs
wai move <item> archives - THEN the system moves the item to the archives category
Scenario: Manage project phases
- WHEN user runs
wai phase,wai phase next,wai phase set <phase>, orwai phase back - THEN the system shows or transitions the current project’s phase
Scenario: Sync agent configurations
- WHEN user runs
wai sync - THEN the system projects agent configs to tool-specific locations
Scenario: Manage agent configs
- WHEN user runs
wai config add skill <file>,wai config list, orwai config edit <path> - THEN the system manages agent configuration files
Scenario: Generate handoffs
- WHEN user runs
wai handoff create <project> - THEN the system generates a handoff document enriched with plugin data
Scenario: Search artifacts
- WHEN user runs
wai search <query> - THEN the system searches across all
.wai/artifacts
Scenario: View timeline
- WHEN user runs
wai timeline <project> - THEN the system displays a chronological view of the project’s artifacts
Scenario: Ask reasoning questions
- WHEN user runs
wai why <query> - THEN the system uses LLM synthesis to answer why decisions were made
- AND displays relevant artifacts, decision chains, and suggestions
- AND gracefully falls back to
wai searchif no LLM available
Scenario: Reflect on session history
- WHEN user runs
wai reflect - THEN the system reads accumulated handoffs and artifacts
- AND optionally accepts a conversation transcript via
--conversation <file> - AND uses LLM synthesis to surface project-specific conventions, gotchas, and patterns
- AND shows a unified diff of old vs proposed REFLECT block content
- AND requires user confirmation before writing to CLAUDE.md and/or AGENTS.md
- AND updates whichever AI config files exist in the repo root by default
- AND fails with a clear diagnostic if no LLM is available (does not fall back)
Scenario: Diagnose workspace health
- WHEN user runs
wai doctor - THEN the system runs diagnostic checks against the workspace
- AND reports pass/warn/fail status for each check with fix suggestions
- AND exits with code 0 when all checks pass, 1 when any check fails
Requirement: Global Flags
The CLI SHALL support global verbosity and quiet flags that work with all commands.
Scenario: Verbose output (level 1)
- WHEN user passes
-vor--verbose - THEN output includes additional context and metadata
Scenario: Verbose output (level 2)
- WHEN user passes
-vvor--verbose --verbose - THEN output includes debug information
Scenario: Verbose output (level 3)
- WHEN user passes
-vvvor--verbose --verbose --verbose - THEN output includes trace-level details
Scenario: Quiet mode
- WHEN user passes
-qor--quiet - THEN only errors are shown
Scenario: Non-interactive mode
- WHEN user passes
--no-input - THEN the system disables interactive prompts and fails with a diagnostic error if input is required
Scenario: Auto-confirm
- WHEN user passes
--yes - THEN the system proceeds with default choices for confirmations
Scenario: Safe mode
- WHEN user passes
--safe - THEN the system runs in read-only mode and refuses operations that mutate state, returning a diagnostic error with a suggested non-safe command
Requirement: JSON Output
Commands that return multi-line structured information SHALL support --json output for machine parsing.
Scenario: Status as JSON
- WHEN user runs
wai status --json - THEN the system outputs JSON containing phase, plugin statuses, and suggestion lists
Scenario: Search as JSON
- WHEN user runs
wai search <query> --json - THEN the system outputs JSON containing matches with file paths, line numbers, and context
Scenario: Timeline as JSON
- WHEN user runs
wai timeline <project> --json - THEN the system outputs JSON containing entries with date, type, title, and path
Scenario: Plugin list as JSON
- WHEN user runs
wai plugin list --json - THEN the system outputs JSON containing plugin name, status, and detector metadata
Requirement: Project Initialization
The CLI SHALL provide wai init to initialize a project in the current directory.
Scenario: Interactive initialization
- WHEN user runs
wai initwithout arguments - THEN the system prompts for project name (defaulting to directory name)
- AND creates
.wai/structure with PARA directories (projects, areas, resources, archives, plugins) - AND creates default agent-config directory with
.projections.yml - AND auto-detects available plugins (beads, openspec, git)
Scenario: Named initialization
- WHEN user runs
wai init --name my-project - THEN the system creates the project with the specified name without prompting
Scenario: Already initialized
- WHEN user runs
wai initin an already-initialized directory - THEN the system shows a warning and suggests
wai status
Requirement: Status Command
The CLI SHALL provide wai status to show project overview and suggest next steps.
Scenario: Show project phase and status
- WHEN user runs
wai status - THEN the system displays the current project’s phase
- AND shows plugin status summaries (beads issues, openspec changes, git status)
- AND shows contextual suggestions based on current phase
Scenario: Contextual suggestions
See context-suggestions for the complete suggestion logic.
Requirement: Doctor Command
The CLI SHALL provide wai doctor to diagnose workspace health and report issues with actionable fix suggestions.
Scenario: Directory structure check
- WHEN
wai doctorruns - THEN it verifies that all expected
.wai/subdirectories exist (projects, areas, resources, archives, plugins) - AND reports pass if all present, fail with
mkdirsuggestion for each missing directory
Scenario: Configuration validation
- WHEN
wai doctorruns - THEN it attempts to parse
.wai/config.toml - AND reports pass if valid, fail with the parse error and suggestion to check the file
Scenario: Plugin tool availability
- WHEN
wai doctorruns and plugins are detected - THEN it checks whether each detected plugin’s CLI tool is installed (e.g.,
git,bd,openspec) - AND reports pass if reachable, warn if not installed with install guidance
Scenario: Agent config sync status
- WHEN
wai doctorruns and.projections.ymlexists - THEN it validates the projections file parses correctly
- AND checks whether each projection target exists and is up to date
- AND reports pass if synced, warn if targets are missing with
wai syncsuggestion
Scenario: Project state integrity
- WHEN
wai doctorruns and projects exist - THEN it validates each project’s
.statefile parses as valid YAML with a recognized phase - AND reports pass if valid, fail with the error for each invalid state file
Scenario: Custom plugin validation
- WHEN
wai doctorruns and.wai/plugins/contains YAML files - THEN it validates each plugin YAML parses correctly as a PluginDef
- AND reports pass if valid, fail with the parse error for each invalid file
Scenario: Summary output
- WHEN all diagnostic checks complete
- THEN the system prints a summary line with total pass, warn, and fail counts
- AND exits with code 0 if no failures, code 1 if any failures
Scenario: Not initialized
- WHEN user runs
wai doctoroutside a wai workspace - THEN the system reports the standard not-initialized error with
wai initsuggestion
Requirements
Requirement: Way Command
The CLI SHALL provide wai way to validate repository best practices and provide opinionated recommendations (“the wai way”) using a dedicated status model separate from wai doctor.
Scenario: Repository standards check
- WHEN
wai wayruns - THEN it checks for repository best practices as defined in repository-best-practices
- AND includes checks for task runner, git hook manager (prek/pre-commit), EditorConfig, documentation, AI instructions, llm.txt, agent skills, CI/CD, and dev containers
- AND reports each check as WayStatus::Pass (✓) or WayStatus::Info (ℹ) with actionable suggestions
Scenario: Works without wai initialization
- WHEN user runs
wai wayin any directory (wai workspace or not) - THEN the command succeeds and runs all repository checks
- AND does NOT require
.wai/to exist - AND helps users prepare repositories before running
wai init
Scenario: Summary output
- WHEN all checks complete
- THEN the system prints a summary: “X/Y best practices adopted”
- AND suggests quick-start priorities if many checks are info status
- AND always exits with code 0 (recommendations never fail)
Scenario: Output format
- WHEN
wai wayruns - THEN output is grouped under “The wai way” header
- AND uses ✓ (green) for WayStatus::Pass, ℹ (blue) for WayStatus::Info
- AND each check follows format: “Category: Status (details)”
- AND includes actionable fix text with URLs (in parentheses) for each WayStatus::Info
- AND supports
--jsonflag for machine-readable output - AND critical recommendations (missing .gitignore/README.md) display with ⚠️ marker
Scenario: Fix skills
- WHEN user runs
wai way --fix skills - THEN the system scaffolds missing recommended agent skills (rule-of-5-universal, commit)
- AND skips skills that already exist
- AND exits with code 0
- AND does NOT run the normal check output (fix mode is separate from check mode)
Requirement: Session Close Command
wai close SHALL write a .pending-resume signal after every successful handoff
creation.
Scenario: Pending-resume written on success
- WHEN
wai closesuccessfully creates a handoff document - THEN the system writes
.wai/projects/<project>/.pending-resumecontaining the path to the new handoff, relative to the project directory - AND this file is not mentioned in the command’s terminal output
- AND the file appears in the uncommitted-changes list (it is a tracked
workspace artifact, committed with other
.wai/changes)
Requirement: Global Workspace View
The CLI SHALL provide wai ls to scan for wai workspaces under a root directory and
display each project’s phase and open issue count as a single line per project.
The expected terminal output shape is:
why-command [review] 3 open, 2 ready
para [plan] 7 open, 0 ready
rizomas [implement] 1 open, 1 ready
Columns are left-aligned and padded to the longest project name in the result set. The
counts column is a global toggle: it appears for ALL rows when at least one workspace
has beads data (rows without beads show a blank cell), and is omitted entirely when no
workspace has beads. When no workspaces are found, the system prints a single message
indicating the root that was scanned. When two projects in different workspaces share the
same name, a short path suffix disambiguates each: name (~/path/to/repo).
The default root is $HOME; the default depth is 3. Both are overridable via flags.
The filesystem walker never follows symlinks.
Scenario: Workspaces found — table rendered
- WHEN user runs
wai lsand at least one.wai/config.tomlexists under$HOMEat depth ≤ 3 - THEN the system displays one line per (workspace, project) pair
- AND each line shows the project name, phase in brackets, and beads counts when available
Scenario: No workspaces found
- WHEN user runs
wai lsand no.wai/config.tomlis found under the root - THEN the system prints
No wai workspaces found under <root>
Scenario: Custom root
- WHEN user runs
wai ls --root <path> - THEN the system scans from
<path>instead of$HOME
Scenario: Custom depth
- WHEN user runs
wai ls --depth <n> - THEN the system limits filesystem traversal to
<n>levels below the root
Scenario: At least one workspace has beads — counts column shown globally
- WHEN at least one discovered workspace has
.beads/present andbdis installed - THEN the counts column appears for all rows in the output
- AND rows for projects in beads-enabled workspaces show
N open, M ready - AND rows for projects in workspaces without beads show a blank counts cell
Scenario: No workspace has beads — counts column omitted
- WHEN no discovered workspace has
.beads/present orbdis not installed anywhere - THEN the counts column is omitted entirely from the output
Scenario: Multiple projects in one workspace
- WHEN a discovered workspace contains more than one project
- THEN each project appears as a separate line in the output
Scenario: Duplicate project names across workspaces
- WHEN two projects from different workspaces share the same name
- THEN each line appends a short path suffix to disambiguate:
name (~/path/to/repo)
Scenario: Invalid root path
- WHEN user runs
wai ls --root <path>and<path>does not exist - THEN the system fails with a diagnostic error naming the invalid path
Requirement: Session Orientation Command
wai prime SHALL detect a .pending-resume signal and render a ⚡ RESUMING
block when the referenced handoff is dated today.
Scenario: Resume mode — today’s handoff
- WHEN user runs
wai prime - AND
.wai/projects/<project>/.pending-resumeexists - AND the referenced handoff file exists and its frontmatter
dateequals today’s date - THEN the system renders a
⚡ RESUMINGblock before the plugin status lines - AND the block shows the handoff date and one-line snippet on the first line
- AND the block shows the contents of the handoff’s
## Next Stepssection immediately below, rendered as described in “Resume mode — next steps rendering” - AND the normal
• Handoff:line is omitted (replaced by the RESUMING block) - AND the
.pending-resumefile is NOT modified or deleted
Scenario: Resume mode — next steps rendering
- WHEN the RESUMING block is rendered
- THEN the
Next Steps:label is printed indented two spaces from the left margin, with no##heading markers and with a trailing colon - AND each content line from the
## Next Stepssection is printed indented four spaces from the left margin - AND blank lines and lines starting with
<!--within the section are skipped
Scenario: Resume mode — next steps present
- WHEN the handoff referenced by
.pending-resumecontains a## Next Stepssection with renderable content (non-blank, non-comment lines) - THEN the RESUMING block shows the
Next Steps:label followed by the items
Scenario: Resume mode — no next steps section
- WHEN the handoff referenced by
.pending-resumedoes not contain a## Next Stepssection, or the section contains only blank lines and HTML comments - THEN the RESUMING block shows only the
⚡ RESUMING: {date} — '{snippet}'header line with no indented items
Scenario: Signal not consumed by prime
- WHEN user runs
wai primeand a RESUMING block is rendered - THEN the
.pending-resumefile is NOT modified or deleted - AND a subsequent
wai primecall in the same session renders the same RESUMING block again
Scenario: Stale signal — not today’s handoff
- WHEN user runs
wai prime - AND
.wai/projects/<project>/.pending-resumeexists - AND the referenced handoff’s frontmatter
dateis before today, or the date field is missing or unparseable - THEN the system ignores the signal entirely
- AND renders the normal
• Handoff:line using the latest handoff
Scenario: Missing handoff — signal ignored
- WHEN user runs
wai prime - AND
.pending-resumeexists but the referenced file does not exist on disk - THEN the system ignores the signal
- AND renders the normal
• Handoff:line (or omits the line if no handoffs exist at all)
Context Suggestions
Purpose
Define context-aware suggestion patterns that help users discover the next logical step based on current project state and phase.
Problem Statement
A status command that only presents data often leaves the user with the question, “What should I do next?” Without proactive guidance, users experience decision fatigue, make suboptimal choices about where to focus effort, and lose workflow momentum. This spec proposes a Type 1 commitment to integrating a proactive suggestion system within the wai status command, bridging the gap between information and action, and making the user more effective.
Design Rationale
The suggestion system is designed to be proactive, integrated, and based on project phase awareness, representing Type 1 decisions that establish a core UX pattern.
- Integrated with
status: Placing suggestions directly within thewai statusoutput is a deliberate Type 1 decision. It establishes a proactive UX pattern wherewaiguides the user immediately after reviewing the project’s state, reducing cognitive load and driving workflow. - Phase-Based Priority: Suggestions are driven by the current project phase (research, design, plan, implement, review, archive) and available plugin data. Each phase has natural next actions that wai can suggest contextually.
Scope, Dependencies, and Requirements
This spec defines the logic for generating suggestions within the wai status command.
Dependencies
- Project State Machine: The suggestion logic depends on the phase definitions outlined in the
project-state-machinespec. - Plugin System: Plugins (beads, git, openspec) provide additional context for richer suggestions.
Non-Goals
- Implementation of suggested actions — suggestions are informational only
- Suggestions in commands other than
wai status - Exact UI/formatting — this spec defines logic, not presentation
Requirements
Requirement: Phase-Based Suggestions
The status command SHALL provide contextual next-step suggestions based on the
current project phase. When the project is in the design phase and has a
decision matrix, wai status SHALL additionally show the matrix’s current
problem statement, its cell completion count, and a suggestion for the next
unfilled cell.
Scenario: Research phase
- WHEN project is in “research” phase
- THEN suggest adding research notes:
wai add research "..." - AND suggest advancing when ready:
wai phase next
Scenario: Plan phase
- WHEN project is in “plan” phase
- THEN suggest adding a plan:
wai add plan "..." - AND suggest advancing to design:
wai phase next
Scenario: Design phase with a matrix
- GIVEN a project in the design phase with a matrix having 5 of 6 cells filled
- WHEN
wai statusruns - THEN suggestions include the problem statement,
5/6 cells filled, and a pointer to the unfilled cell
Scenario: Design phase without a matrix
- GIVEN a project in the design phase that never initialized a matrix
- WHEN
wai statusruns - THEN no matrix information or suggestion is shown
Requirement: Plugin-Enhanced Suggestions
When plugins are active, suggestions SHALL incorporate plugin context.
Scenario: Beads plugin active
- WHEN beads plugin reports open issues
- THEN status includes issue count and suggests reviewing:
wai beads list
Scenario: Git plugin active
- WHEN git plugin reports uncommitted changes
- THEN status includes change summary
Requirement: Empty Project Suggestions
When a project has no artifacts, suggestions SHALL guide initial setup.
Scenario: New empty project
- WHEN project has no research, plans, or designs
- THEN suggest starting with research:
wai add research "..." - AND suggest checking phase:
wai phase
Requirement: Pipeline Suggestions
When pipelines are configured, suggestions SHALL surface pipeline discovery and recovery actions.
Scenario: Active pipeline run
- WHEN a pipeline run is active (resolved from
WAI_PIPELINE_RUNenv var or.wai/resources/pipelines/.last-run) - THEN status emits a “⚡ PIPELINE ACTIVE:
<name>step N/M” line in a Pipeline section - AND suggests reprinting the current step:
wai pipeline current
Scenario: Pipelines available but no active run
- WHEN no active pipeline run exists
- AND
.wai/resources/pipelines/contains at least one valid.tomlpipeline definition - THEN status emits an “Available pipelines” section listing each pipeline with name, description, and step count
- AND suggests discovering pipelines:
wai pipeline suggest
Scenario: Stale pipeline pointer
- WHEN
.last-runpointer exists but the referenced run file is missing - THEN the stale pointer is silently ignored
- AND status falls back to the “available pipelines” or idle state
Requirement: Suggestion Output Blocks
Status output SHALL include a clearly labeled suggestion block for human and machine parsing.
Scenario: Suggestion block formatting
- WHEN status suggestions are shown
- THEN they appear under a
Suggestions:heading - AND each suggestion includes a short label and a suggested command
Scenario: Suggestions as JSON
- WHEN user runs
wai status --json - THEN the suggestions are returned as an array with
labelandcommandfields
Requirement: Stale Phase Detection
The status command SHALL detect when a project has not advanced phases in more than 14 days and surface a suggestion to either advance or archive.
Detection criteria:
- Current phase is NOT
archive - Time elapsed since the current phase started exceeds 14 days
- Applies to all non-archive phases (research, design, plan, implement, review)
Scenario: Project stuck in implement phase
- WHEN a project is in
implementphase - AND the phase started more than 14 days ago
- THEN
wai statusincludes a stale-phase suggestion - AND the suggestion offers
wai phase nextto advance - AND the suggestion offers
wai move <name> archivesto abandon
Scenario: Active project within threshold is not flagged
- WHEN a project’s current phase started 13 days ago
- THEN
wai statusdoes NOT include a stale-phase suggestion for that project
Scenario: Archived project is not flagged
- WHEN a project is in
archivephase regardless of elapsed time - THEN
wai statusdoes NOT include a stale-phase suggestion for that project
Scenario: Stale signal in JSON output
- WHEN the user runs
wai status --jsonand a project is stale - THEN the suggestions array includes an entry with a label indicating staleness
- AND includes commands for advancing or archiving
Requirement: Completion Readiness Signal
The status command SHALL detect when a project in review phase has at least
one handoff artifact and surface a suggestion to archive it.
Detection criteria:
- Current phase is
review - At least one handoff artifact exists in the project’s
handoffs/directory
Scenario: Review phase with handoff suggests archiving
- WHEN a project is in
reviewphase - AND the project has at least one handoff artifact
- THEN
wai statusincludes a completion-readiness suggestion - AND the suggestion offers
wai move <name> archives - AND the suggestion offers
wai phase nextas an alternative
Scenario: Review phase without handoff does not trigger
- WHEN a project is in
reviewphase - AND the project has zero handoff artifacts
- THEN
wai statusdoes NOT include a completion-readiness suggestion for that project
Scenario: Completion signal in JSON output
- WHEN the user runs
wai status --jsonand a project looks complete - THEN the suggestions array includes an entry indicating the project is ready to archive
decision-matrix Specification
Purpose
TBD - created by archiving change add-decision-matrix. Update Purpose after archive.
Requirements
Requirement: Matrix location and identity
The decision matrix SHALL be a single directory tree per project at
.wai/projects/<project>/designs/matrix/. It SHALL contain problem.md
(the decision being deliberated), criteria/, approaches/, and
decision.md. The filesystem is the source of truth; the CLI is sugar over
plain file operations.
Scenario: Init scaffolds the matrix
- GIVEN a project without a matrix
- WHEN
wai matrix initruns with a problem statement - THEN
designs/matrix/containsproblem.md,criteria/,approaches/01-status-quo/with_description.md, and an emptydecision.md
Scenario: One matrix per project
- GIVEN a project that already has
designs/matrix/ - WHEN
wai matrix initruns - THEN the command fails with an error naming the existing matrix
Requirement: Cell encoding
Each cell SHALL be the directory
approaches/<approach>/<criterion>/ containing fact.md (the aspect: facts,
not judgment) and exactly one judgment marker file named neutral, green,
yellow, or red. A cell is incomplete if and only if fact.md is
missing or empty. neutral is a legitimate judgment, distinct from
incomplete.
Scenario: Neutral judgment is explicit
- GIVEN a cell with a non-empty
fact.mdand a marker file namedneutral - WHEN
wai matrix lintruns - THEN the cell passes validation
Scenario: Multiple markers are a structural error
- GIVEN a cell containing both
greenandredmarker files - WHEN
wai matrix lintruns - THEN lint exits non-zero and names the offending cell
Scenario: Missing fact means incomplete, not judged
- GIVEN a cell directory with a marker but no
fact.md - WHEN
wai matrix lintruns - THEN the cell is reported as incomplete
Requirement: Status quo first
wai matrix init SHALL create approaches/01-status-quo/ first, and lint
SHALL report an error if it is missing.
Scenario: Init creates status quo
- GIVEN a project without a matrix
- WHEN
wai matrix initruns - THEN
approaches/01-status-quo/_description.mdexists
Requirement: Multi-operation helpers
wai matrix criterion add <name> SHALL create the criterion definition file
and cell directories in every existing approach.
wai matrix approach add <name> SHALL create the approach directory with
_description.md and empty cell directories for every existing criterion.
These exist because one logical action spans multiple directories; no command
is provided for single-cell writes, which are direct file edits.
Scenario: Criterion add touches every approach
- GIVEN a matrix with two approaches
- WHEN
wai matrix criterion add "operational-cost"runs - THEN
criteria/NN-operational-cost.mdexists - AND
approaches/*/03-operational-cost/exists for every approach
Requirement: Deciding produces a current-answer marker and a design doc
wai matrix decide <approach> <rationale> SHALL validate the approach
directory exists, write decision.md (selected approach, rationale, date,
pointer to the design doc), and scaffold a design artifact in
designs/<date>-<slug>.md with standard frontmatter (tracks supported) and
a decision-time snapshot of the winning column’s cell texts.
Scenario: Decide writes both artifacts
- GIVEN a matrix with two approaches and filled cells
- WHEN
wai matrix decide "02-event-sourcing" "rationale text"runs - THEN
decision.mdnames approach02-event-sourcing - AND a new design artifact exists in
designs/containing the rationale and the winning column’s aspect texts
Scenario: Decide rejects unknown approach
- GIVEN no approach directory matches the argument
- WHEN
wai matrix decideruns - THEN the command fails, listing valid approach names
Requirement: Deterministic HTML render on demand
wai matrix render SHALL generate a self-contained matrix.html (inline
CSS, no JS) as a pure function of the directory state: problem.md banner,
criteria as rows, approaches as columns, marker files as judgment chips,
assessment key included. Output is deterministic (byte-identical for equal
input) and is a generated view — it SHALL NOT be committed or treated as a
source of truth. Empty cells render as a gray “not yet assessed” placeholder,
never a judgment color.
Scenario: Same state, same output
- GIVEN an unchanged matrix directory
- WHEN
wai matrix renderruns twice - THEN both runs produce byte-identical HTML
Scenario: Unfilled cell is not a judgment
- GIVEN an approach/criterion pair with no
fact.md - WHEN
wai matrix renderruns - THEN that cell renders with a neutral “not yet assessed” placeholder that is not colored green, yellow, or red
Requirement: Structural lints
wai matrix lint SHALL enforce, as errors (non-zero exit):
- Rectangularity: every approach directory contains a cell directory for every criterion
- Exactly one non-empty-named marker from {neutral, green, yellow, red} per filled cell
- No empty
fact.mdfiles 01-status-quopresent as first column
Scenario: Missing cell in one approach fails lint
- GIVEN an approach directory lacking a cell directory present in the other approaches
- WHEN
wai matrix lintruns - THEN exit code is non-zero and the missing path is named
Requirement: Methodology lints are warnings
wai matrix lint SHALL report, as warnings that never affect exit code:
- All-green column (possible rationalization)
- Undistinguished columns (identical cell texts across approaches for all criteria — likely a missing criterion)
- Subjective judgment words as the body of
fact.md - Link-only cells (bare URL, no summary text)
- Criteria definitions phrased as questions (trailing
?) - Status-quo column with no red cell (something important was missed — per Miller, “Design in Practice in Practice”)
- Decision recorded while the selected approach has unfilled cells
- Empty
problem.md - Matrix files newer than the decision timestamp in
decision.md(stale decision; inconclusive timestamp comparison after a fresh clone downgrades to this warning rather than a gate block)
Scenario: All-green column warns but passes
- GIVEN one approach whose filled cells all have
greenmarkers - WHEN
wai matrix lintruns - THEN a warning names the approach
- AND exit code is 0
Scenario: Undistinguished columns warn
- GIVEN two approaches whose cell texts are identical for every criterion
- WHEN
wai matrix lintruns - THEN a warning suggests a distinguishing criterion is missing
Requirement: Design-to-plan phase gate
The design → plan phase transition SHALL be blocked when a matrix exists
and any of the following hold: problem.md is empty, decision.md does not
record a selected approach that exists under approaches/, or any file under
approaches/ or criteria/ has an mtime strictly newer than the decision
UTC timestamp recorded inside decision.md. Staleness checks whose
comparison is inconclusive (equal or missing timestamps, e.g. after a fresh
clone) SHALL downgrade to a warning instead of blocking. The failure message
SHALL be self-healing: it names the offending files and points at
wai matrix decide. Projects without a matrix are never gated.
Scenario: Current decision passes the gate
- GIVEN a matrix whose
decision.mdnames an existing approach and no matrix file is newer than the recorded decision timestamp - WHEN
wai phase nextadvances from design - THEN the transition proceeds
Scenario: Scaffolded decision does not pass the gate
- GIVEN a freshly initialized matrix whose
decision.mdis still the template (no approach recorded) - WHEN the design → plan transition is attempted
- THEN the transition is blocked
- AND the message indicates no decision has been made
Scenario: Edited-after-decision blocks the gate
- GIVEN a cell file modified after
decision.mdwas written - WHEN the design → plan transition is attempted
- THEN the transition is blocked
- AND the message names the stale-decision condition and suggests
wai matrix decide
Scenario: Ambiguous timestamps after a fresh clone warn instead of blocking
- GIVEN a decided matrix checked out fresh from git so that all matrix files share the checkout timestamp
- WHEN the design → plan transition is attempted
- THEN the transition proceeds
- AND a stale-decision warning is reported with a pointer to
wai matrix lint
Scenario: No matrix means no gate
- GIVEN a project that never ran
wai matrix init - WHEN the design → plan transition is attempted
- THEN the transition proceeds as before this change
Requirement: Status and handoff matrix awareness
wai status in the design phase SHALL show the current problem statement,
cell completion count, and a suggestion for the next unfilled cell.
wai close handoffs SHALL include the problem statement, the selected
approach with rationale, and links to both the matrix directory and the
scaffolded design doc.
Scenario: Status shows completion
- GIVEN a matrix with 5 of 6 cells filled
- WHEN
wai statusruns during the design phase - THEN output includes the problem statement,
5/6 cells filled, and a pointer to the unfilled cell
doctor-auto-fix Specification
Purpose
TBD - created by archiving change add-doctor-fix-flag. Update Purpose after archive.
Requirements
Requirement: Doctor command accepts –fix flag
The wai doctor command SHALL accept a --fix flag that automatically applies fixes for diagnosed issues where safe to do so.
Scenario: User runs doctor with –fix
$ wai doctor --fix
GIVEN workspace has fixable issues
WHEN user runs wai doctor --fix
THEN system prompts for confirmation
AND applies fixes for all confirmed issues
AND displays success/failure for each fix
AND exits with code 0 if all succeeded, 1 if any failed
Requirement: Auto-fix respects global flags
The doctor –fix flow SHALL respect global flags for confirmation and safety.
Scenario: Skip confirmation with –yes
$ wai doctor --fix --yes
GIVEN workspace has fixable issues
WHEN user runs wai doctor --fix --yes
THEN system skips confirmation prompt
AND applies all fixes immediately
Scenario: JSON output with –fix
$ wai doctor --fix --json
GIVEN workspace has fixable issues
WHEN user runs wai doctor --fix --json
THEN system outputs structured JSON with fixes_applied and fixes_failed arrays
AND skips interactive confirmation
Scenario: Refuse in safe mode
$ wai doctor --fix --safe
GIVEN workspace has any state
WHEN user runs wai doctor --fix --safe
THEN system refuses with SafeModeViolation error
AND exits with non-zero code
Requirement: Missing PARA directories are auto-fixable
The doctor –fix flow SHALL create missing directories including PARA directories, agent-config subdirectories, and resource subdirectories.
Scenario: Fix missing directories
- GIVEN
.wai/archives/directory is missing - WHEN user runs
wai doctor --fix --yes - THEN system creates
.wai/archives/directory - AND reports success for “Directory structure” fix
Scenario: Fix missing agent-config subdirectories
- GIVEN
.wai/resources/agent-config/skills/directory is missing - WHEN user runs
wai doctor --fix --yes - THEN system creates the missing agent-config subdirectory
- AND reports success for “Directory structure” fix
Scenario: Fix missing resource subdirectories
- GIVEN
.wai/resources/templates/directory is missing - WHEN user runs
wai doctor --fix --yes - THEN system creates the missing resource subdirectory
- AND reports success for “Directory structure” fix
Scenario: Fix missing default files
- GIVEN
.wai/.gitignoreis missing - WHEN user runs
wai doctor --fix --yes - THEN system creates the default
.gitignorefile - AND reports success for “Directory structure” fix
Requirement: Stale projections are auto-fixable
The doctor –fix flow SHALL re-sync stale projections using the appropriate strategy (symlink, inline, or reference).
Scenario: Fix stale inline projection
GIVEN a projection with strategy “inline” is out of sync
WHEN user runs wai doctor --fix --yes
THEN system calls sync_core::execute_inline() for that projection
AND reports success for “Projection →
Requirement: Missing project .state files are auto-fixable
The doctor –fix flow SHALL create default .state files for projects that are missing them (Warn status only, not corrupted files with Fail status).
Scenario: Fix missing .state file
GIVEN project “my-project” exists without .state file
WHEN user runs wai doctor --fix --yes
THEN system creates .wai/projects/my-project/.state with ProjectState::default()
AND reports success for “Project state: my-project” fix
Scenario: Skip corrupted .state file
GIVEN project has corrupted .state file (invalid YAML)
WHEN user runs wai doctor --fix --yes
THEN system does NOT overwrite the corrupted file
AND reports no fix available
Requirement: Missing AGENTS.md managed block is auto-fixable
The doctor –fix flow SHALL inject the wai managed block into AGENTS.md if it exists but is missing the block.
Scenario: Fix missing managed block
GIVEN AGENTS.md exists without wai managed block
WHEN user runs wai doctor --fix --yes
THEN system calls inject_managed_block() with detected plugins
AND reports success for “Agent instructions” fix
Requirement: Non-fixable issues are identified
The doctor –fix flow SHALL NOT attempt to fix issues that require manual intervention or external dependencies.
Scenario: Cannot fix missing plugin tools
GIVEN check reports missing CLI tool (e.g., bd not in PATH)
WHEN user runs wai doctor --fix --yes
THEN system does NOT attempt to install the tool
AND reports “No fixable issues” (if only non-fixable issues exist)
Scenario: Cannot fix corrupted config.toml
GIVEN config.toml is missing or invalid
WHEN user runs wai doctor --fix --yes
THEN system does NOT attempt to create/fix config
AND suggests running wai init instead
Requirement: Version staleness check
The wai doctor command SHALL compare the workspace version (from config.toml) against the running binary version and report when they differ.
Scenario: Workspace version matches binary
- WHEN
config.tomlproject.versionequalsenv!("CARGO_PKG_VERSION") - THEN check reports Pass with message “Version current”
Scenario: Workspace version is stale
- WHEN
config.tomlproject.versiondiffers fromenv!("CARGO_PKG_VERSION") - THEN check reports Warn with message showing both versions
- AND fix suggestion says “Run: wai init (to update workspace)”
Scenario: Fix version staleness
- WHEN user runs
wai doctor --fix --yeswith stale version - THEN system calls
ensure_workspace_currentto repair workspace - AND config.toml version is updated to current binary version
- AND any missing directories or files are also created
Error Recovery
Purpose
Define self-healing error message patterns that suggest fixes instead of just reporting problems, making errors educational and actionable.
Problem Statement
Cryptic, unhelpful error messages are a major source of user frustration in command-line tools. When an error occurs and the application simply reports “failed” or “invalid input,” it forces the user to halt their workflow, consult external documentation, and waste time diagnosing the issue. This increases cognitive load and creates a steep, frustrating learning curve. This spec represents a Type 1 commitment to transforming this experience by making errors educational and actionable, significantly enhancing user productivity and satisfaction.
Design Rationale
The error recovery strategy for wai is to treat errors not as failures, but as opportunities to guide the user toward the correct action, representing Type 1 decisions that establish a core UX pattern and architectural dependency.
- Actionable, “Self-Healing” Errors: This is a Type 1 decision for
wai’s core user experience. Instead of just reporting what went wrong,waierrors will explain the problem and suggest the specific command to fix it. This approach makes the tool feel more like a helpful assistant and less like a rigid instruction parser, significantly reducing user friction. - Use of
miette: The selection of themiettelibrary is a Type 1 architectural dependency. It was chosen specifically for its ability to produce rich, diagnostic error messages with features like error codes, actionable help text, and code snippets, which are key components of our “self-healing” error philosophy. - Diagnostic Codes: Every
wai-specific error includes a stable, machine-readable code (e.g.,wai::project::not_found). This is a Type 1 decision for error identification, aiding in debugging, enabling more specific documentation, and providing a reliable way to reference errors in tests or external tools.
Scope and Requirements
This spec defines the user-facing format and content for common, recoverable errors in wai.
Non-Goals
- Internal Error Logging: This spec focuses on the user-facing error experience and does not cover how errors are logged internally for developer analysis.
- Automated Fixes: The system will only suggest corrective actions; it will not execute commands automatically on the user’s behalf.
- Localization: All error messages will be presented in a single language.
- Exhaustive Error Catalog: This document specifies the pattern for key errors but is not an exhaustive list of every possible error condition; rather, it defines the approach to error messaging.
Requirements
Requirement: Diagnostic Error Format
All errors SHALL include a diagnostic code and actionable help text using miette.
Scenario: Error structure
- WHEN any error occurs
- THEN the error includes a code (e.g.,
wai::project::not_found) - AND the error includes help text with a suggested fix
- AND when
--jsonis provided, the system outputs a JSON error object withcode,message,help, anddetails
Requirement: Project Not Initialized Error
When commands require a project context but none exists, the error SHALL suggest initialization.
Scenario: Missing project context
- WHEN user runs a project-scoped command outside a project
- THEN error message is “No project initialized in current directory”
- AND help suggests “Run
wai initorwai new project <name>first” - AND the diagnostic code is
wai::project::not_initialized
Requirement: Project Not Found Error
When a referenced project doesn’t exist, the error SHALL suggest how to find valid projects.
Scenario: Invalid project reference
- WHEN user references a project name that doesn’t exist
- THEN error message is “Project ‘{name}’ not found”
- AND help suggests “Run
wai show projectsto see available projects” - AND the diagnostic code is
wai::project::not_found
Requirement: Area Not Found Error
When a referenced area doesn’t exist, the error SHALL suggest alternatives.
Scenario: Invalid area reference
- WHEN user references an area name that doesn’t exist
- THEN error message is “Area ‘{name}’ not found”
- AND help suggests “Run
wai show areasto see available areas” - AND the diagnostic code is
wai::area::not_found
Requirement: Resource Not Found Error
When a referenced resource doesn’t exist, the error SHALL suggest alternatives.
Scenario: Invalid resource reference
- WHEN user references a resource name that doesn’t exist
- THEN error message is “Resource ‘{name}’ not found”
- AND help suggests “Run
wai show resourcesto see available resources” - AND the diagnostic code is
wai::resource::not_found
Requirement: Invalid Phase Transition Error
When a phase transition is invalid, the error SHALL show valid options.
Scenario: Invalid transition
- WHEN user attempts an invalid phase transition (e.g., already at the last phase and running
phase next) - THEN error message is “Invalid phase transition from ‘{from}’ to ‘{to}’”
- AND help lists valid target phases from the current phase
- AND the diagnostic code is
wai::phase::invalid_transition
Requirement: Config Sync Error
When agent config sync fails, the error SHALL explain what went wrong and suggest remediation.
Scenario: Sync failure
- WHEN a projection fails during
wai sync - THEN error message describes which projection failed and why
- AND help suggests checking
.projections.ymlconfiguration - AND the diagnostic code is
wai::config::sync_failed
Requirement: Handoff Error
When handoff generation fails, the error SHALL explain the issue.
Scenario: Handoff generation failure
- WHEN
wai handoff createfails - THEN error message describes the failure (e.g., project not found, template missing)
- AND help suggests the corrective action
- AND the diagnostic code is
wai::handoff::failed
Requirement: Plugin Not Found Error
When a plugin doesn’t exist, the error SHALL suggest how to find available plugins.
Scenario: Missing plugin
- WHEN user references a plugin that isn’t installed
- THEN error message is “Plugin ‘{name}’ not found”
- AND help suggests “Run
wai plugin listto see available plugins” - AND the diagnostic code is
wai::plugin::not_found
Handoff System
Purpose
Define first-class handoff artifacts that capture session context, decisions, and next steps for seamless transitions between work sessions or between human and AI collaborators.
Problem Statement
Context loss between work sessions is one of the biggest productivity drains in software development. When a developer (or AI agent) picks up work, they spend significant time reconstructing what was done, what decisions were made, and what comes next. Handoff documents formalize this context transfer, but without tooling support they are inconsistently created and often incomplete. A built-in handoff system ensures that context is captured systematically and enriched with data from other tools.
Design Rationale
First-Class Artifact
Making handoffs a first-class artifact type rather than ad-hoc notes is a Type 1 decision. This ensures they have consistent structure, are stored in predictable locations, and can be enriched by plugins (e.g., beads issues, git status, openspec changes).
Template-Based Generation
Handoffs are generated from templates with frontmatter metadata. This is a Type 2 decision — templates can evolve, but the pattern of structured generation with metadata is foundational.
Plugin Enrichment
The handoff generation process calls plugin hooks to gather contextual data. This means a handoff can automatically include:
- Open beads issues and their status
- Recent git commits and uncommitted changes
- OpenSpec changes in progress
Scope and Requirements
This spec covers the handoff artifact format, generation command, and plugin integration points.
Non-Goals
- Automatic handoff generation (handoffs are explicitly created by the user)
- Handoff consumption or parsing by other tools
- Multi-format output (PDF, HTML, etc.)
- Collaborative editing of handoffs
Requirement: Handoff Format
Handoffs SHALL be markdown files with structured frontmatter, including dedicated
sections for operational nuances that serve as high-signal input to wai reflect.
Scenario: Handoff file structure
- WHEN a handoff is generated
- THEN it follows this format:
--- date: 2026-01-22 project: my-project phase: implement agent: claude --- # Session Handoff ## What Was Done <!-- Summary of completed work --> ## Key Decisions <!-- Decisions made and rationale --> ## Gotchas & Surprises <!-- What behaved unexpectedly? Non-obvious requirements? Hidden dependencies? --> ## What Took Longer Than Expected <!-- Steps that needed multiple attempts. Commands that failed before the right one. --> ## Open Questions <!-- Unresolved questions --> ## Next Steps <!-- Prioritized list of what to do next --> ## Context <!-- Plugin-enriched context (beads, git, etc.) -->
Requirement: Handoff Generation
The CLI SHALL provide a command to generate handoff documents.
Scenario: Create handoff
- WHEN user runs
wai handoff create <project> - THEN the system generates a handoff from the default template
- AND enriches it with data from enabled plugins
- AND stores it in
.wai/projects/<project>/handoffs/YYYY-MM-DD-session-end.md
Scenario: Handoff with plugin data
- WHEN generating a handoff with the beads plugin enabled
- THEN the Context section includes open beads issues and their status
- WHEN generating a handoff with the git plugin enabled
- THEN the Context section includes recent commits and uncommitted changes
Requirement: Handoff Storage
Handoffs SHALL be stored in the project’s handoffs directory with date prefixes.
Scenario: Handoff location
- WHEN a handoff is created for project “my-app”
- THEN it is stored at
.wai/projects/my-app/handoffs/YYYY-MM-DD-session-end.md - AND multiple handoffs per day are differentiated by suffix
Requirements
Requirement: Pending-Resume Signal
wai close SHALL write a .pending-resume file to the project directory after
every successful handoff creation, enabling wai prime to detect resume context
without requiring the user to manually open the handoff.
Scenario: Signal written on close
- WHEN
wai closesuccessfully creates a handoff - THEN the system writes
.wai/projects/<project>/.pending-resume - AND the file contains the path to the new handoff, relative to the project
directory (e.g.
handoffs/2026-02-24-session-end.md)
Scenario: Signal overwritten on repeated close
- WHEN user runs
wai closemore than once (same day or different days) - THEN the
.pending-resumefile is overwritten with the path of the newest handoff
Requirement: Handoff Decision-Matrix Summary
When the project has a decision matrix, handoffs SHALL additionally include a decision-matrix summary: the problem statement, the selected approach with rationale (or “not decided yet”), the matrix directory link with cell completion count, and the scaffolded design doc link when a decision exists.
Scenario: Handoff includes matrix summary
- GIVEN a project with a matrix whose
decision.mdrecords a decision - WHEN a handoff is generated
- THEN it includes the problem statement, the selected approach with rationale, and links to the matrix directory and the design doc
Scenario: Handoff without a matrix
- GIVEN a project that never initialized a matrix
- WHEN a handoff is generated
- THEN no matrix section is added and the format is unchanged
Help System
Purpose
Define progressive disclosure patterns for help and command output, showing simple information by default with more detail available on demand.
Problem Statement
Effective command-line tools require an intuitive and helpful user assistance system. Without one, users face a steep learning curve, leading to frustration and inefficient use. This spec addresses the need for a help system that serves both audiences effectively by being clear, concise, and progressively more detailed on demand, representing a Type 1 commitment to an improved user experience. A “one-size-fits-all” help output is insufficient, being either too verbose for novices trying to perform a simple task, or too sparse for experts needing advanced details.
Design Rationale
The design of the help system is centered on the principle of progressive disclosure, which represents a Type 1 architectural decision for help content structure and rendering logic, significantly enhancing usability for all user levels.
- Progressive Disclosure: By default, help is concise and focused on common use cases. Users can request more detail using verbosity flags (
-v,-vv). This commits to a layered content structure and respects the user’s attention, avoiding overwhelming them with irrelevant information while still making advanced details accessible. This pattern is consistent with the CLI’s global verbosity flags. - In-line Usage Examples: Including practical examples directly within the help output is a highly effective way to teach users how to perform common tasks, reducing the need to consult external documentation.
- Adherence to Convention: Using the standard
--helpand-hflags ensures that the help system is immediately familiar and predictable to anyone with prior CLI experience.
Scope and Requirements
This spec defines the user-facing behavior and output structure of the CLI’s help system.
Non-Goals
- Help Content Generation: This spec defines the desired output and behavior of the help system. The internal mechanism for authoring and maintaining help text is an implementation detail not covered here.
- Interactive Help Systems: Features like a
man-style pager, guided tutorials, or interactive prompts are out of scope. - Localization: Translating help content into multiple languages is not covered by this specification.
- Web-based Documentation: This spec is limited to the help available directly within the CLI application.
Requirements
Requirement: Basic Help
All commands SHALL provide --help with usage examples.
Scenario: Root help
- WHEN user runs
wai --helporwai -h - THEN the system shows a brief description of wai
- AND lists all top-level commands with one-line descriptions
- AND shows global flags (
-v,-q,--help,--version,--json,--no-input,--yes,--safe)
Scenario: Command help
- WHEN user runs
wai <command> --help - THEN the system shows command description, arguments, and options
- AND includes at least one usage example
Scenario: Subcommand help
- WHEN user runs
wai <command> <subcommand> --help - THEN the system shows subcommand-specific description and options
- AND includes examples relevant to that subcommand
Scenario: No arguments shows contextual help
- WHEN user runs
waiwith no arguments - THEN the system defers to onboarding behavior for context-aware output
Requirement: Usage Examples
All help output SHALL include practical usage examples.
Scenario: Command examples
- WHEN user views help for any command
- THEN the help includes an “Examples” section
- AND examples show realistic use cases with expected outcomes
Scenario: Example formatting
- WHEN examples are displayed
- THEN each example shows the command invocation
- AND optionally includes a brief explanation of what it does
Requirement: Progressive Disclosure
Help SHALL support brief and detailed modes for different user needs.
Scenario: Brief help (default)
- WHEN user runs
wai <command> --help - THEN the system shows concise help focused on common usage
- AND omits advanced options and edge cases
Scenario: Detailed help
- WHEN user runs
wai <command> --help --verboseorwai <command> --help -v - THEN the system shows comprehensive help including all options
- AND includes advanced usage patterns and configuration details
Scenario: Help verbosity levels
- WHEN user increases verbosity (
-v,-vv,-vvv) - THEN help output includes progressively more detail:
-v: all options including advanced ones-vv: adds environment variables and configuration-vvv: adds internal details and debugging information
managed-block Specification
Purpose
TBD - created by archiving change add-managed-block-openspec-checklist. Update Purpose after archive.
Requirements
Requirement: Openspec step in session-close checklist
The generated WAI block’s session-close checklist SHALL include a step to mark
completed openspec tasks [x] when the openspec plugin is detected. The step
SHALL appear after the beads steps (if present) and before wai reflect.
Scenario: Openspec detected at init time
- WHEN
wai initorwai reflectruns - AND the openspec plugin is detected
- THEN the generated WAI block’s “Ending a Session” checklist includes:
[ ] openspec tasks.md — mark completed tasks [x]
Scenario: Openspec not detected
- WHEN
wai initorwai reflectruns - AND the openspec plugin is NOT detected
- THEN the generated WAI block does NOT include the openspec checklist step
Requirement: Cross-tool tracking convention
When both beads and openspec plugins are detected, the generated WAI block SHALL include a “Tracking Work Across Tools” section that defines the cross-reference convention for linking beads tickets to openspec task IDs.
The section SHALL appear after the “Capturing Work” section and before “Ending a Session”.
The convention SHALL specify:
- When creating a beads ticket for an openspec task, include the task reference
(format:
<change-id>:<phase>.<task>, e.g.add-why-command:7.1) in the ticket description. - When closing a beads ticket linked to an openspec task, also check the
corresponding box (
[x]) in the change’stasks.md.
Scenario: Both plugins detected
- WHEN
wai initorwai reflectruns - AND both beads and openspec plugins are detected
- THEN the generated WAI block includes a “Tracking Work Across Tools” section with the cross-reference format and sync rule
Scenario: Only one plugin detected
- WHEN
wai initorwai reflectruns - AND only one of beads or openspec is detected (not both)
- THEN the “Tracking Work Across Tools” section is NOT included
Requirement: Pre-claim implementation check
The generated WAI block’s “Starting a Session” section SHALL include a pre-claim guard (when beads is detected) reminding the agent to verify an issue is not already implemented before claiming it.
Scenario: Beads detected — pre-claim note present
- WHEN
wai initorwai reflectruns - AND the beads plugin is detected
- THEN the “Starting a Session” section includes a note after
bd readythat reads: before claiming an issue, read the relevant source files to confirm the work is not already done
Scenario: Beads not detected — no pre-claim note
- WHEN
wai initorwai reflectruns - AND the beads plugin is NOT detected
- THEN no pre-claim note is included
Requirement: Epic closure reminder in session-close checklist
The generated WAI block’s session-close checklist bd close step SHALL include
a note (when beads is detected) to also close the parent epic when the last
sub-task of a group is completed.
Scenario: Beads detected — epic note on close step
- WHEN
wai initorwai reflectruns - AND the beads plugin is detected
- THEN the
bd close <id>checklist step includes an inline comment noting that parent epics should be closed when their last sub-task is done
Scenario: Beads not detected — no epic note
- WHEN
wai initorwai reflectruns - AND the beads plugin is NOT detected
- THEN no epic closure reminder is included
Requirement: Available Pipelines in managed block
The generated WAI block SHALL include an “Available Pipelines” section when
pipelines with [pipeline.metadata] are installed, listing each pipeline’s name,
when description, and start command. The section SHALL also note that pipeline
steps may have gates and reference wai pipeline gates for gate details.
Scenario: Pipelines with metadata installed
- WHEN
wai initruns - AND
.wai/resources/pipelines/contains one or more pipelines with[pipeline.metadata] - THEN the generated WAI block includes an “Available Pipelines” table with columns: Pipeline, When to Use, Start command
- AND a note: “Pipeline steps have gates that enforce artifact creation, review coverage, and oracle checks before advancement.”
Scenario: No pipelines installed
- WHEN
wai initruns - AND no pipelines exist in
.wai/resources/pipelines/ - THEN no “Available Pipelines” section is generated
Scenario: Pipeline without metadata
- WHEN a pipeline exists but lacks
[pipeline.metadata] - THEN that pipeline is NOT included in the “Available Pipelines” table
- AND
wai doctorwarns about the missing metadata
Requirement: Managed block staleness detection
wai doctor SHALL detect when the managed block in CLAUDE.md or AGENTS.md is
out of date relative to the current workspace state (installed pipelines,
plugins, skills). Detection SHALL compare the generated block content against
the actual content between WAI:START and WAI:END markers.
Scenario: Block is stale after pipeline added
- WHEN
wai doctorruns - AND a pipeline with metadata has been added since the last
wai init - AND the CLAUDE.md managed block does not include that pipeline
- THEN doctor reports warning: “CLAUDE.md managed block outdated — run ‘wai init’ to refresh”
Scenario: Block is current
- WHEN
wai doctorruns - AND the managed block content matches what would be generated
- THEN no staleness warning is reported
Scenario: AGENTS.md also checked
- WHEN
wai doctorruns - AND AGENTS.md exists with WAI:START/WAI:END markers
- THEN staleness detection runs on AGENTS.md as well
Scenario: User-modified managed block always shows stale
- WHEN
wai doctorruns - AND the user has manually edited content between WAI:START and WAI:END markers
- THEN doctor reports the block as outdated
- AND running
wai initwill overwrite the user’s modifications (content between markers is managed by wai)
Onboarding
Purpose
Define the first-run experience and welcome flow that helps new users get started quickly with wai.
This spec owns the no-args welcome behavior for both first-run (no project) and in-project contexts.
Problem Statement
The initial user experience with a new command-line tool can be a significant barrier to adoption. If a user runs wai for the first time without arguments and is met with a cryptic error, an overwhelming help page, or an unhelpful generic message, it can lead to frustration, confusion, and ultimately, abandonment of the tool. This spec represents a Type 1 commitment to improving this fundamental user experience. Even experienced users inside a project might run wai without arguments and benefit from quick, context-relevant reminders or next steps rather than a full help display.
Design Rationale
The onboarding experience is designed to be intuitive, context-aware, and minimalist, providing immediate value without unnecessary complexity. The Context-Aware “No-Args” Behavior is a Type 1 decision for the fundamental user experience.
- Context-Aware “No-Args” Behavior: Tailoring the output based on whether a project exists (
.wai/directory) provides immediate, relevant guidance. For first-time users, it suggests how to begin; for in-project users, it offers quick access to common next actions. This avoids generic responses, reduces user friction, and establishes a proactive engagement pattern. - Minimalist Guidance: Instead of an interactive wizard or verbose documentation, the system offers direct, actionable command suggestions. This respects the CLI user’s preference for efficiency and direct control, allowing them to quickly engage with the tool.
Scope and Requirements
This spec exclusively defines the output and suggested actions when the wai command is executed without any arguments.
Non-Goals
- Full Implementation of Suggested Commands: This spec outlines what to suggest, but not the detailed implementation of commands like
wai initorwai new project. - Interactive Setup Wizards: The onboarding process is non-interactive, relying on clear textual suggestions.
- Complex User Preference Tracking: This spec does not cover tracking user preferences or progress beyond detecting the presence of a project.
Requirements
Requirement: Welcome Screen
When wai is run without arguments and no project is detected, it SHALL show a welcoming entry point.
Scenario: No project detected
- WHEN user runs
waiwith no arguments - AND no
.wai/directory exists in current or parent directories - THEN the system shows “wai - Workflow manager for AI-driven development”
- AND shows context: “No project detected in current directory”
- AND suggests:
wai init,wai new project,wai --help - AND includes a note that detailed help is available via
wai --help
Requirement: Project Context Welcome
When wai is run without arguments inside a project, it SHALL show project-relevant suggestions.
Scenario: Inside project
- WHEN user runs
waiwith no arguments - AND a
.wai/directory exists - THEN the system suggests:
wai status,wai phase,wai new project - AND includes a note that detailed help is available via
wai --help
Requirement: Comprehensive re-initialization
When wai init is run in an already-initialized workspace, it SHALL comprehensively repair the workspace to match the current version’s expectations, not just update config and managed blocks.
Scenario: Re-init creates missing directories
- WHEN user runs
wai initin an initialized workspace - AND some expected directories are missing (e.g.
.wai/resources/agent-config/skills/) - THEN system creates all missing directories
- AND reports what was created
Scenario: Re-init creates missing default files
- WHEN user runs
wai initin an initialized workspace - AND
.wai/.gitignoreor.wai/resources/agent-config/.projections.ymlis missing - THEN system creates the missing default files
- AND does not overwrite existing files
Scenario: Re-init updates version
- WHEN user runs
wai initin an initialized workspace - AND config.toml version differs from binary version
- THEN system updates config.toml version to current binary version
Scenario: Re-init is idempotent
- WHEN user runs
wai inittwice in succession - THEN the second run produces no errors
- AND the workspace state is identical after both runs
PARA Structure
Purpose
Define the PARA-based organizational structure for wai, where artifacts are categorized into Projects, Areas, Resources, and Archives within the .wai/ directory.
Problem Statement
Development workflows generate diverse artifacts — research notes, design documents, plans, handoffs, and configuration files. Without a consistent organizational framework, these artifacts become scattered and hard to find, leading to context loss between sessions and across team members. The PARA method (Projects, Areas, Resources, Archives) provides a proven categorization framework that maps naturally to how developers think about their work: active projects with defined outcomes, ongoing areas of responsibility, reference resources, and completed/inactive items.
Design Rationale
PARA Method
The PARA categorization (Projects, Areas, Resources, Archives) is a Type 1 foundational decision for wai’s organizational model. It was selected because:
- Projects have defined outcomes and timelines, matching active development work
- Areas represent ongoing responsibilities without end dates (e.g., infrastructure, documentation standards)
- Resources hold reference material used across projects (agent configs, templates, patterns)
- Archives preserve completed or inactive items for future reference
This four-category model is simple enough to learn immediately yet expressive enough to handle real-world complexity.
Per-Project Subdirectories
Each project contains standard subdirectories (research/, plans/, designs/, handoffs/) to provide consistent internal structure. This is a Type 2 decision — the specific subdirectories may evolve, but the pattern of structured subdirectories is foundational.
Date-Prefixed Filenames
Artifacts use date-prefixed filenames (e.g., 2026-01-20-initial-research.md) for chronological sorting. This convention enables timeline views and makes recency immediately visible in file listings.
Scope and Requirements
This spec defines the directory structure and organizational rules for artifacts within .wai/.
Non-Goals
- Content format of individual artifacts (covered by other specs)
- Full-text search across artifacts (covered by timeline-search spec)
- State machine for project phases (covered by project-state-machine spec)
- Plugin storage and configuration (covered by plugin-system spec)
Requirement: PARA Directory Structure
The .wai/ directory SHALL organize artifacts into four PARA categories.
Scenario: Initialize PARA structure
- WHEN user runs
wai init - THEN the system creates the following directory structure:
.wai/ ├── config.toml ├── projects/ ├── areas/ ├── resources/ │ ├── agent-config/ │ ├── templates/ │ └── patterns/ ├── archives/ └── plugins/
Requirement: Project Structure
Each project SHALL have a consistent internal directory structure.
Scenario: Create new project
- WHEN user runs
wai new project <name> - THEN the system creates:
.wai/projects/<name>/ ├── .state ├── research/ ├── plans/ ├── designs/ └── handoffs/ - AND initializes
.statewith the default phase
Scenario: Create new area
- WHEN user runs
wai new area <name> - THEN the system creates:
.wai/areas/<name>/ ├── research/ └── plans/
Scenario: Create new resource
- WHEN user runs
wai new resource <name> - THEN the system creates the directory
.wai/resources/<name>/
Requirement: Date-Prefixed Filenames
Artifacts SHALL use date-prefixed filenames for chronological sorting.
Scenario: Add artifact with date prefix
- WHEN user adds a research note, plan, design, or handoff
- THEN the filename follows the pattern
YYYY-MM-DD-<slug>.md - AND the artifact is sorted chronologically in directory listings
Requirement: Archival
Items SHALL be movable to archives to keep active categories clean.
Scenario: Archive a project
- WHEN user runs
wai move <project> archives - THEN the system moves the project directory from
projects/toarchives/ - AND preserves all project contents and history
Scenario: Archive an area
- WHEN user runs
wai move <area> archives - THEN the system moves the area directory from
areas/toarchives/
pipeline-resource Specification
Purpose
TBD - created by archiving change add-pipeline-resource. Update Purpose after archive.
Requirements
Requirement: Pipeline Definition
The CLI SHALL support defining ordered multi-skill pipelines where each stage declares the skill to invoke and the artifact type it produces.
Scenario: Create a pipeline
- WHEN user runs:
wai pipeline create issue-pipeline --stages="issue/gather:research,issue/create:tickets,issue/review:audit" - THEN the system saves the pipeline definition in
.wai/resources/pipelines/issue-pipeline.yml - AND validates that each stage references a known skill name
Scenario: Invalid stage format rejected
- WHEN a
--stagesvalue contains an entry without theskill:artifactformat - THEN the system rejects it with a clear error showing the expected format
Requirement: Pipeline Run Lifecycle
The CLI SHALL support running a pipeline and tracking per-step completion.
Scenario: Start a pipeline run
- WHEN user runs
wai pipeline start issue-pipeline --topic="ant-forager" - THEN the system validates the pipeline definition (blocking on errors)
- AND generates a run ID (e.g.,
issue-pipeline-2026-02-25-ant-forager) - AND stores initial run state in
.wai/pipeline-runs/<run-id>.yml - AND outputs the run ID and a hint to invoke the first step
Scenario: Step artifact tagged with run and step ID
- WHEN a skill runs in the context of a pipeline run
- AND the environment variable
WAI_PIPELINE_RUN=<run-id>is set or.wai/.pipeline-runexists - AND the skill calls any
wai add <type>command (research, plan, design, review, or handoff) - THEN the artifact is automatically tagged with
pipeline-run:<run-id>andpipeline-step:<step-id>
Scenario: Advance pipeline to next step
- WHEN user runs
wai pipeline next - AND all configured gates for the current step pass (or no gates configured)
- THEN the system marks the current step complete
- AND outputs the next step prompt (or completion message if last step)
Scenario: Advance blocked by gate failure
- WHEN user runs
wai pipeline next - AND a gate check fails
- THEN the system does NOT advance
- AND outputs the failure reason and suggests corrective action
Scenario: Advance past last step rejected
- WHEN user runs
wai pipeline next - AND all steps are already marked complete
- THEN the system errors with a message indicating the pipeline run is finished
- AND suggests starting a new run with
wai pipeline start
Scenario: Advance with unknown run ID
- WHEN user runs
wai pipeline next - AND no active run exists
- THEN the system errors with a clear message and lists available pipelines
Requirement: Pipeline Status
The CLI SHALL provide a status view showing per-run, per-stage completion state.
Scenario: View pipeline status
- WHEN user runs
wai pipeline status issue-pipeline - THEN the system lists all runs with per-stage status:
- Stage name and skill
- Status: pending / complete
- Artifact path (if complete)
Scenario: View single run detail
- WHEN user runs
wai pipeline status issue-pipeline --run <run-id> - THEN the system shows detailed state for that run only
Requirement: Step-Level Artifact Tagging
Artifacts created during a pipeline run SHALL be tagged with both
pipeline-run:<run-id> and pipeline-step:<step-id> where step-id is the
ID of the currently active step in the run state.
Scenario: Artifact created during active step
- WHEN
wai add research "findings"is called - AND a pipeline run is active with run ID
sci-2026-04-02-qcd - AND the current step is
describe - THEN the artifact frontmatter includes:
tags: [pipeline-run:sci-2026-04-02-qcd, pipeline-step:describe]
Scenario: No active pipeline run
- WHEN
wai add research "findings"is called - AND no pipeline run is active
- THEN no pipeline tags are injected (existing behavior unchanged)
Scenario: Retroactive tagging not supported
- WHEN
wai pipeline nextadvances from stepdecomposeto stepgenerate - AND the user then creates an artifact intended for step
decompose - THEN the artifact is tagged with
pipeline-step:generate(the current step) - AND the user must use
--tags pipeline-step:decomposeto override manually
Requirement: Review Artifact Type
The CLI SHALL support a review artifact type created via wai add review.
Review artifacts SHALL have structured frontmatter with reviews (target
artifact filename, scoped to the current project), verdict (pass, fail, or
needs-work), and optional severity (object with critical, high, medium, low
counts) and produced_by (skill name) fields. The --reviews target SHALL be
validated against existing artifacts in the current project at creation time.
Scenario: Create a review artifact
- WHEN user runs
wai add review "Accuracy: all citations verified..." --reviews 2026-04-02-nlo-structure.md - AND
2026-04-02-nlo-structure.mdexists in the current project - THEN the system creates a file in
.wai/projects/<project>/reviews/ - AND the frontmatter includes
reviews: 2026-04-02-nlo-structure.md
Scenario: Review with structured metadata
- WHEN user runs
wai add review "..." --reviews artifact.md --verdict pass --produced-by ro5 --severity critical:0,high:1,medium:3,low:2 - THEN the frontmatter includes:
reviews: artifact.md verdict: pass produced_by: ro5 severity: {critical: 0, high: 1, medium: 3, low: 2} - AND
produced_byis informational only (no automatic severity parsing) - AND
--severityaccepts comma-separatedlevel:countpairs; omitted levels default to 0
Scenario: Review without target rejected
- WHEN user runs
wai add review "..."without--reviews - THEN the system rejects with error: “review requires –reviews
”
Scenario: Invalid verdict rejected
- WHEN user runs
wai add review "..." --reviews x.md --verdict excellent - THEN the system rejects with error listing valid values: pass, fail, needs-work
Scenario: Review target does not exist
- WHEN user runs
wai add review "..." --reviews nonexistent.md - AND no artifact named
nonexistent.mdexists in the current project - THEN the system rejects with error: “artifact ‘nonexistent.md’ not found in project ‘
’”
Requirement: Pipeline Gate Protocol
The CLI SHALL evaluate pipeline gates in strict order when wai pipeline next
is called on a step with gates configured. A gate is a validation check on a
pipeline step. Gates are organized into four tiers: structural (artifact
existence), procedural (review coverage), oracle (domain-specific checks), and
approval (human checkpoint). The first failing tier SHALL block advancement with
a descriptive reason. Steps without gates SHALL advance freely (existing behavior).
Scenario: Structural gate blocks on missing artifacts
- WHEN step
generatedeclares[steps.gate.structural]withmin_artifacts = 1, types = ["research"] - AND user runs
wai pipeline next - AND no research artifacts exist tagged with this step and run
- THEN advancement is blocked with message: “Step ‘generate’ requires at least 1 research artifact(s). Found 0.”
Scenario: Procedural gate blocks on missing review
- WHEN step declares
[steps.gate.procedural]withrequire_review = true - AND a research artifact exists for this step
- AND no review artifact references that research artifact
- THEN advancement is blocked with message: “Artifact ‘2026-04-02-findings.md’ has no review.”
Scenario: Procedural gate scopes reviewable types
- WHEN step declares
[steps.gate.procedural]withrequire_review = trueandreview_types = ["research", "plan"] - AND a research artifact and a design artifact exist for this step
- THEN the procedural gate requires a review for the research artifact
- AND the design artifact is not required to have a review (not in
review_types)
Scenario: Procedural gate defaults exclude reviews
- WHEN step declares
[steps.gate.procedural]withrequire_review = trueand noreview_types - THEN the procedural gate requires reviews for all artifact types EXCEPT review artifacts
- AND review artifacts are never required to have reviews of their own
Scenario: Procedural gate blocks on severity threshold
- WHEN step declares
[steps.gate.procedural]withmax_critical = 0 - AND a review artifact exists with
severity: {critical: 2} - THEN advancement is blocked with message: “Review of ‘findings.md’ has 2 critical findings (max: 0).”
Scenario: Oracle gate blocks on script failure
- WHEN step declares an oracle named
dimensional-analysis - AND the oracle script exits with code 1 and stderr “Dimensional mismatch in eq. 14”
- THEN advancement is blocked with message: “Oracle ‘dimensional-analysis’ failed for ‘findings.md’: Dimensional mismatch in eq. 14”
Scenario: Oracle timeout
- WHEN an oracle declares
timeout = 30 - AND the oracle script does not exit within 30 seconds
- THEN the oracle is killed and treated as a failure with message: “Oracle ‘name’ timed out after 30s”
Scenario: Approval gate blocks until approved
- WHEN step declares
[steps.gate.approval]withrequired = true - AND all other gates pass
- AND the step has not been approved via
wai pipeline approve - THEN advancement is blocked with message: “This step requires human approval. Run ‘wai pipeline approve’ when ready.”
Scenario: Approval gate passes after approval
- WHEN
wai pipeline approvehas been run for the current step - AND all other gates pass
- THEN
wai pipeline nextadvances to the next step
Scenario: Approval invalidated by new artifacts
- WHEN
wai pipeline approvehas been run for the current step - AND new artifacts are created for this step after the approval timestamp
- THEN the approval is invalidated
- AND
wai pipeline nextblocks with message: “Approval invalidated — new artifacts created after approval. Run ‘wai pipeline approve’ again.”
Scenario: No gates configured
- WHEN a step has no gate configuration in TOML
- THEN
wai pipeline nextadvances immediately (existing behavior)
Requirement: Oracle Script Resolution
Oracle gates SHALL resolve scripts by name from .wai/resources/oracles/.
Resolution SHALL probe for <name>, <name>.sh, and <name>.py in order,
selecting the first match. Resolved scripts MUST be executable (shebang +
executable permission) and SHALL be invoked directly, not via an interpreter
prefix. An explicit command field in the oracle TOML SHALL override name
resolution and is executed as-is via the shell.
Scenario: Name-based resolution with executable script
- WHEN oracle declares
name = "dimensional-analysis"withoutcommand - AND
.wai/resources/oracles/dimensional-analysis.pyexists and is executable - THEN the system executes
.wai/resources/oracles/dimensional-analysis.py <artifact-path>
Scenario: Explicit command override
- WHEN oracle declares
name = "custom-check"withcommand = "python research/validate.py" - THEN the system executes
python research/validate.py <artifact-path>via the shell - AND name resolution is skipped
Scenario: Oracle not found
- WHEN oracle declares
name = "nonexistent"withoutcommand - AND no file matching the name exists in
.wai/resources/oracles/ - THEN
wai pipeline validatereports a warning - AND the oracle gate fails at runtime with: “Oracle ‘nonexistent’ not found in .wai/resources/oracles/”
Scenario: Ambiguous oracle resolution
- WHEN oracle declares
name = "check"withoutcommand - AND both
.wai/resources/oracles/check.shand.wai/resources/oracles/check.pyexist - THEN the system selects the first match in probe order (
check.sh) - AND
wai pipeline validatereports a warning: “oracle ‘check’ has multiple matches, using ‘check.sh’”
Scenario: Oracle not executable
- WHEN oracle resolves to
.wai/resources/oracles/check.py - AND the file is not executable (missing execute permission)
- THEN the oracle gate fails with: “Oracle ‘check’ is not executable. Run: chmod +x .wai/resources/oracles/check.py”
Scenario: Cross-artifact oracle
- WHEN oracle declares
scope = "all" - THEN the system invokes the oracle once, passing all matching artifact
paths as arguments:
<oracle> <path1> <path2> ... <pathN> - AND the oracle can read all artifacts for cross-artifact consistency checks (e.g., notation consistency, conservation laws)
Scenario: Default oracle scope is per-artifact
- WHEN oracle does not declare
scope - THEN the system invokes the oracle once per applicable artifact:
<oracle> <artifact-path>
Requirement: Pipeline Show Command
The CLI SHALL support wai pipeline show <name> displaying the pipeline
description, metadata, steps, and per-step gate configuration.
Scenario: Show pipeline with gates
- WHEN user runs
wai pipeline show scientific-research - THEN the system displays: pipeline name, description, metadata (when, skills), step list with gate summary per step (e.g., “structural + procedural + oracles + approval”), and oracle directory path
Scenario: Show nonexistent pipeline
- WHEN user runs
wai pipeline show nonexistent - THEN the system errors with message listing available pipelines
Requirement: Pipeline Gates Command
The CLI SHALL support wai pipeline gates [pipeline-name] [--step=<id>] to
show gate requirements and live status. With an active run (and no arguments),
it shows live status for the current step. Without an active run, the pipeline
name is required and --step selects the step to display.
Scenario: Gates with active run
- WHEN a pipeline run is active at step
generate-validate-accrue - AND user runs
wai pipeline gates - THEN the system displays each gate tier with pass/fail/blocked status and counts (e.g., “✗ min 1 research artifact — found 0”)
Scenario: Gates without active run
- WHEN no pipeline run is active
- AND user runs
wai pipeline gates scientific-research --step=generate-validate-accrue - THEN the system displays gate definitions (not live status) for that step
Scenario: Gates on step without gates
- WHEN a pipeline run is active at a step with no gate configuration
- AND user runs
wai pipeline gates - THEN the system displays: “No gates configured for step ‘
’.”
Scenario: Gates without active run and no pipeline name
- WHEN no pipeline run is active
- AND user runs
wai pipeline gateswithout arguments - THEN the system errors: “No active pipeline run. Specify a pipeline name: wai pipeline gates
”
Requirement: Pipeline Check Command
The CLI SHALL support wai pipeline check to evaluate all gates for the current
step without advancing. An optional --oracle=<name> flag SHALL run a single
oracle against all applicable artifacts. Output SHALL include per-tier status
with pass/fail/blocked indicators and a summary result.
Scenario: Check all gates
- WHEN user runs
wai pipeline check - THEN the system evaluates structural, procedural, oracle, and approval gates
- AND reports pass/fail/blocked per tier with details (counts, reasons)
- AND reports a summary: “Result: PASS” or “Result: BLOCKED — resolve N failures”
- AND does NOT advance the step
Scenario: Check on step without gates
- WHEN user runs
wai pipeline check - AND the current step has no gate configuration
- THEN the system reports: “No gates configured for step ‘
’. Result: PASS”
Scenario: Check single oracle
- WHEN user runs
wai pipeline check --oracle=dimensional-analysis - THEN the system runs only that oracle against all applicable artifacts
- AND reports per-artifact pass/fail with stderr output on failure
Requirement: Pipeline Approve Command
The CLI SHALL support wai pipeline approve to record human approval for the
current step. Approval SHALL be stored as a timestamp in the run state YAML.
Approval is invalidated if any artifact tagged with the current step has a
creation timestamp later than the approval timestamp.
Scenario: Approve current step
- WHEN a pipeline run is active
- AND user runs
wai pipeline approve - THEN the run state records an approval timestamp for the current step
- AND the system confirms: “Approved step ‘step-id’. Run ‘wai pipeline next’ to advance.”
Scenario: Approve without active run
- WHEN no pipeline run is active
- AND user runs
wai pipeline approve - THEN the system errors: “No active pipeline run.”
Requirement: Pipeline Validate Command
The CLI SHALL support wai pipeline validate [name] to check pipeline TOML
definitions for correctness. Validation SHALL also run during wai doctor
and before wai pipeline start.
Scenario: Validate a valid pipeline
- WHEN user runs
wai pipeline validate scientific-research - AND the TOML is well-formed with valid gates and existing oracles
- THEN the system reports success with step count and gate summary
Scenario: Validate catches missing metadata
- WHEN a pipeline lacks
[pipeline.metadata] - THEN validation reports warning: “missing [pipeline.metadata] — pipeline won’t appear in managed block”
Scenario: Validate catches missing oracle
- WHEN a pipeline references oracle
check-dimsand no matching file exists - THEN validation reports warning: “gate oracle ‘check-dims’ — command not found”
Scenario: Validate catches non-executable oracle
- WHEN a pipeline references oracle
check-dimsand the file exists but is not executable - THEN validation reports warning: “gate oracle ‘check-dims’ — not executable”
Scenario: Validate catches duplicate names
- WHEN two TOML files declare the same
pipeline.name - THEN validation reports error: “duplicate pipeline name”
Scenario: Start blocked by validation errors
- WHEN user runs
wai pipeline start broken-pipeline --topic="test" - AND the pipeline has validation errors (not warnings)
- THEN the system refuses to start and shows the errors
Requirement: Pipeline Metadata
Pipeline TOML definitions SHALL support an optional [pipeline.metadata]
section with when (string describing when to suggest the pipeline) and
skills (list of skill names the pipeline depends on).
Scenario: Metadata in TOML
- WHEN a pipeline defines:
[pipeline.metadata] when = "Frontier-level research requiring systematic validation" skills = ["design-practice", "ro5"] - THEN
wai pipeline showdisplays the metadata - AND
wai pipeline validatechecks that referenced skills are installed
Scenario: Missing metadata
- WHEN a pipeline omits
[pipeline.metadata] - THEN the pipeline functions normally but
wai pipeline validatewarns that it won’t appear in the managed block
Plugin System
Purpose
Define the plugin architecture that allows extending wai with additional capabilities, including YAML-based configuration, hook points, command pass-through, and built-in plugins for common tools.
Problem Statement
As the wai tool matures, the diversity of user needs for specialized functionality and integrations will grow. Without a robust extension mechanism, wai risks becoming either bloated from incorporating every niche feature request, or insufficient for users with specific workflow demands. A plugin system is a foundational Type 1 architectural decision needed to prevent core bloat, meet community-driven and user-specific extension needs, and keep the core tool lean, focused, and maintainable.
Design Rationale
YAML-Based Plugin Configuration
Plugins are configured via YAML files in .wai/plugins/, replacing the earlier TOML-based manifest approach. YAML provides better support for complex nested structures like hook definitions and command mappings. Each plugin declares:
- Detector patterns: How to detect if the plugin’s tool is present (e.g.,
.beads/directory,.git/directory) - Commands: CLI commands the plugin provides or passes through to external tools
- Hooks: Event handlers for project lifecycle events
Hook Points
Plugins can respond to lifecycle events through defined hook points. This is a Type 1 decision establishing the integration pattern:
on_project_create— called when a new project is createdon_phase_transition— called when a project changes phaseon_handoff_generate— called when generating a handoff documenton_status— called when displaying project status
Built-in Plugins
Three plugins ship with wai as built-ins:
- beads — detects
.beads/directory, provides issue data for handoffs and status - openspec — detects
openspec/directory, provides spec change data - git — detects
.git/directory, provides commit history and status
Command Pass-Through
Plugins can register commands that pass through to external CLIs. For example, wai beads list delegates to bd list --json. This provides a unified interface while leveraging existing tools.
Scope and Requirements
This spec covers the plugin configuration format, lifecycle hooks, command routing, and built-in plugin definitions.
Non-Goals
- Plugin registry or marketplace
- Plugin sandboxing or security model
- Plugin versioning or dependency resolution
- Remote plugin installation
Requirement: Plugin Configuration
Plugins SHALL be configured via YAML files in .wai/plugins/.
Scenario: Plugin config format
- WHEN a plugin is defined
- THEN its configuration file follows this format:
name: beads description: Integration with beads issue tracker detector: type: directory path: .beads/ commands: - name: list description: List beads issues passthrough: bd list --json - name: show description: Show beads issue details passthrough: bd show hooks: on_handoff_generate: command: bd list --status=open --json inject_as: open_issues on_status: command: bd stats --json inject_as: beads_status
Requirement: Plugin Detection
Plugins SHALL auto-detect whether their associated tool is present.
Scenario: Auto-detect on init
- WHEN user runs
wai init - THEN the system checks each built-in plugin’s detector pattern
- AND enables plugins whose tools are detected
Scenario: Detector types
- WHEN a plugin has a directory detector
- THEN the system checks for the specified directory relative to project root
- WHEN a plugin has a file detector
- THEN the system checks for the specified file
Requirement: Plugin Hooks
Plugins SHALL respond to lifecycle events through hook points.
Scenario: Hook execution
- WHEN a lifecycle event occurs (e.g., project creation, phase transition)
- THEN the system calls all registered hooks for that event
- AND collects hook output for use by the triggering command
Scenario: Handoff enrichment
- WHEN generating a handoff
- THEN the system calls
on_handoff_generatehooks on all enabled plugins - AND injects the collected data into the handoff template
Requirement: Command Pass-Through
Plugins SHALL support routing CLI commands to external tools.
Scenario: Plugin command execution
- WHEN user runs
wai <plugin-name> <command> - THEN the system looks up the command in the plugin’s command list
- AND executes the passthrough command
Scenario: Safe mode passthrough
- WHEN user passes
--safe - THEN the system refuses passthrough commands unless the plugin command is explicitly marked
read_only: true - AND returns a diagnostic error that suggests rerunning without
--safe
Scenario: Non-interactive passthrough
- WHEN user passes
--no-input - THEN the system refuses passthrough commands that would prompt for input and returns a diagnostic error
Requirement: Plugin Management
The CLI SHALL support listing, enabling, and disabling plugins.
Scenario: List plugins
- WHEN user runs
wai plugin list - THEN the system shows all known plugins with their status (enabled/disabled/not detected)
Scenario: List plugins as JSON
- WHEN user runs
wai plugin list --json - THEN the system outputs JSON containing plugin name, status, and detector metadata
Scenario: Enable plugin
- WHEN user runs
wai plugin enable <name> - THEN the system enables the specified plugin
Scenario: Disable plugin
- WHEN user runs
wai plugin disable <name> - THEN the system disables the specified plugin without removing its configuration
Project Reflection
Purpose
Define the wai reflect command, which synthesizes accumulated session context
into project-specific AI-assistant guidance and writes the result to a versioned
resource file in .wai/resources/reflections/.
Problem Statement
As projects accumulate sessions and artifacts (research, designs, plans, handoffs), valuable project-specific conventions, gotchas, and architectural patterns remain buried in session history. The CLAUDE.md and AGENTS.md managed blocks provide generic tool instructions but contain nothing project-specific — every new AI session must rediscover the same codebase patterns from scratch.
wai why answers specific questions reactively. wai reflect complements it
proactively: given accumulated session context, ask the LLM “what project-specific
context should AI assistants know that isn’t already documented?” and inject the
answer into CLAUDE.md and/or AGENTS.md as a persistent, project-aware section.
Design Rationale
Three-Tier Context Model
Context sources are prioritized from richest to most distilled:
- Conversation transcripts — raw Claude session content (ephemeral unless captured)
- Handoffs — structured session summaries with gotchas and next steps
- Artifacts — research, design, and plan documents
LLM-Required (No Fallback)
Unlike wai why, wai reflect does not fall back to search. Reflection requires
LLM synthesis to surface non-obvious patterns; keyword search cannot substitute.
Resource File Storage
wai reflect writes each run to a new dated file in .wai/resources/reflections/.
Files accumulate across sessions, are committed and versioned, and are searchable
via wai search. A slim WAI:REFLECT:REF block in CLAUDE.md/AGENTS.md points
agents to the resource directory and instructs them to search before starting work.
Scope and Requirements
This spec covers the wai reflect command, REFLECT block management, context
gathering, and the session nudge heuristic.
Non-Goals
- Streaming LLM responses during reflection
- Automatic reflection without user confirmation
- Reflection of non-wai project history
Requirements
Requirement: Reflect Command
The CLI SHALL provide wai reflect to synthesize accumulated session context
into project-specific AI-assistant guidance and inject it into CLAUDE.md and/or
AGENTS.md.
Scenario: Basic reflect run
- WHEN user runs
wai reflect - THEN the system reads all handoff files from all projects as the primary source
- AND reads research, design, and plan artifacts as secondary sources
- AND reads previous reflections from
.wai/resources/reflections/as additional context - AND sends a structured prompt to the configured LLM (reusing
[llm]config) - AND writes the result to
.wai/resources/reflections/<date>-<project>.md - AND prints the path of the written resource file
Scenario: Conversation transcript as input
- WHEN user runs
wai reflect --conversation <file> - THEN the system reads the file as plain text (any format accepted)
- AND includes it as the highest-priority context source in the LLM prompt
- AND caps the transcript at ~30K chars, truncating from the beginning (oldest exchange removed) to preserve the most recent content
- AND proceeds with handoffs and artifacts filling the remaining context budget
Scenario: Output target selection
-
WHEN user runs
wai reflectwithout--output -
THEN the system detects which of CLAUDE.md and AGENTS.md exist in the repo root
-
AND updates all files that exist (both, if both are present)
-
WHEN user runs
wai reflect --output claude.md -
THEN the system updates only CLAUDE.md, regardless of what exists
-
WHEN user runs
wai reflect --output agents.md -
THEN the system updates only AGENTS.md, regardless of what exists
-
WHEN user runs
wai reflect --output both -
THEN the system updates both CLAUDE.md and AGENTS.md
Scenario: No target file found
- WHEN user runs
wai reflectand neither CLAUDE.md nor AGENTS.md exist - THEN the system fails with a diagnostic error:
“No CLAUDE.md or AGENTS.md found — run
wai initfirst or create the target file”
Scenario: Dry run mode
- WHEN user runs
wai reflect --dry-run - THEN the system shows the resource file path that would be written
- AND exits without writing to any file
- AND still performs migration of any old WAI:REFLECT block if present
Scenario: Scoped to a project
- WHEN user runs
wai reflect --project <name> - THEN the system reads only artifacts from the specified project
- AND proceeds with LLM synthesis and injection as normal
Scenario: No LLM available
- WHEN user runs
wai reflectand no LLM backend is configured or reachable - THEN the system displays an informational message explaining that LLM is required
- AND suggests configuring
[why]in.wai/config.tomlor installing Ollama - AND does NOT fall back to search (reflection requires LLM synthesis)
Scenario: No handoffs and no conversation file
- WHEN user runs
wai reflectwith no--conversationfile - AND the workspace has no handoff artifacts
- THEN the system warns that no session context is available
- AND suggests running
wai handoff create <project>to capture session context - AND exits without calling the LLM
Requirement: Reflect Output Storage
The system SHALL write wai reflect output to a versioned resource file in
.wai/resources/reflections/ instead of injecting a full block into CLAUDE.md
or AGENTS.md.
Scenario: Reflect writes to resource file
- WHEN user runs
wai reflect - THEN the system writes the synthesized content to
.wai/resources/reflections/YYYY-MM-DD-<project>.md - AND the file is created (never overwritten; a second run on the same day
appends a
-2,-3suffix) - AND the file begins with YAML front-matter:
--- date: YYYY-MM-DD project: <project-name> sessions_analyzed: N type: reflection --- - AND the LLM-generated content follows the front-matter
Scenario: Resource file is searchable
- WHEN user runs
wai search "<topic>" - THEN reflection files in
.wai/resources/reflections/are included in search results
Scenario: Previous reflections included as context
- WHEN gathering context for a new
wai reflectrun - THEN existing files in
.wai/resources/reflections/are included as an additional context tier (lower priority than handoffs) - AND the LLM prompt instructs the LLM to extend and correct existing patterns rather than repeat them
Requirement: Slim Reference Block in CLAUDE.md / AGENTS.md
The system SHALL maintain a WAI:REFLECT:REF block in CLAUDE.md and/or AGENTS.md
that contains only a brief pointer to the resource files and a mandatory search instruction.
Scenario: wai init injects WAI:REFLECT:REF block
- WHEN user runs
wai init(fresh or refresh) - THEN the system injects or refreshes a
WAI:REFLECT:REF:START/ENDblock after theWAI:ENDmarker - AND the block instructs agents to run
wai search "<topic>"before starting research
Scenario: wai reflect does NOT touch CLAUDE.md
- WHEN user runs
wai reflect - THEN the system writes only to
.wai/resources/reflections/<date>-<project>.md - AND does NOT modify
CLAUDE.mdorAGENTS.md
Scenario: Migration from old WAI:REFLECT block
- WHEN user runs
wai reflect - AND
CLAUDE.mdorAGENTS.mdcontains an existingWAI:REFLECT:START/ENDblock - THEN the system migrates the block content to
.wai/resources/reflections/<today>-<project>-migrated.md(if not already migrated) - AND replaces the
WAI:REFLECT:START/ENDblock in all target files with the slimWAI:REFLECT:REF:START/ENDblock
Requirement: Search-Before-Research Instruction in Managed Block
The wai init managed block template SHALL include an explicit instruction for agents
to search for known patterns before beginning research or creating tickets.
Scenario: Managed block includes search instruction when companions detected
- WHEN
wai initgenerates the managed block - AND beads or openspec companion tools are detected
- THEN the managed block includes a search-before-research instruction
Scenario: No instruction without companions
- WHEN
wai initgenerates the managed block - AND no companion tools are detected
- THEN the managed block does NOT include the search instruction
Requirement: Context Sources and Budget
The system SHALL gather context in a three-tier priority order with dynamic budget allocation.
Scenario: Conversation transcript fills first tier
- WHEN
--conversation <file>is provided - THEN the transcript is the highest-priority source in the LLM prompt
- AND capped at ~30K chars, truncated from the beginning if larger
- AND the LLM prompt labels this source: “Conversation transcript (richest: raw session including failed attempts and surprises)”
Scenario: Handoffs fill second tier
- WHEN gathering context (with or without conversation transcript)
- THEN handoff files are read sorted by modification time (newest first)
- AND fill up to ~40K chars of the budget (or the remaining budget after the conversation transcript)
- AND the LLM prompt labels these: “Session handoffs (intent, next steps, gotchas captured at session end)”
Scenario: Secondary artifacts fill remaining budget
- WHEN context budget remains after handoffs
- THEN research, design, and plan artifacts fill the remaining ~30K chars
- AND the LLM prompt labels these: “Research and design artifacts (explicit decisions and domain knowledge)”
Scenario: Budget exceeded
- WHEN total content exceeds the budget (~100K chars)
- THEN each tier is truncated to its cap from the least-recent end
- AND the prompt includes a note that context was truncated
Scenario: Staleness flag
- WHEN the LLM prompt includes artifacts
- THEN each artifact is labeled with its creation date
- AND the prompt instructs the LLM to flag patterns from artifacts older than 6 months as “potentially stale — verify still applies”
Requirement: Reflect Metadata
The system SHALL track reflection run metadata in a dedicated file to support the session nudge heuristic.
Scenario: Metadata written after successful reflect
- WHEN
wai reflectsuccessfully writes to one or more target files - THEN the system writes
.wai/projects/<project>/.reflect-metacontaining:
where N is the number of handoff files processed in this runlast_reflected = "YYYY-MM-DD" session_count = N - AND the file is created if absent or overwritten if present
Scenario: Missing metadata treated as never reflected
- WHEN
wai closeorwai reflectreads.reflect-metaand the file does not exist - THEN the system treats
last_reflectedas the epoch (all handoffs are newer)
Requirement: Session Nudge
The system SHALL suggest running wai reflect from wai close when enough
sessions have accumulated without a reflect.
Scenario: Nudge after threshold exceeded
- WHEN user runs
wai closeand creates a handoff - AND 5 or more handoff files have mtime newer than the
last_reflecteddate in.wai/projects/<project>/.reflect-meta - THEN the system appends a suggestion after normal close output:
→ N sessions since last reflect — run 'wai reflect' to update <target>where<target>lists the AI config files found in the repo root - AND the nudge is informational only (does not block close or change exit code)
Scenario: No nudge when current
- WHEN user runs
wai close - AND fewer than 5 handoffs are newer than the last reflect
- THEN the system does NOT display the reflect nudge
Requirement: Improved Handoff Nuance Capture
The handoff template SHALL include dedicated sections for capturing operational nuances that are most valuable as reflect input.
Scenario: Handoff includes nuance sections
- WHEN user runs
wai handoff create <project> - THEN the generated handoff includes these sections (in addition to existing ones):
## Gotchas & Surprises <!-- What behaved unexpectedly? Non-obvious requirements? Hidden dependencies? --> ## What Took Longer Than Expected <!-- Steps that needed multiple attempts. Commands that failed before the right one. --> - AND both sections are empty template placeholders for the user to fill in
Scenario: Reflect prioritizes nuance sections
- WHEN building the LLM prompt and handoffs contain Gotchas or Longer-Than-Expected sections
- THEN the LLM prompt instructs the LLM to treat content in those sections as high-signal input for the Conventions and Common Gotchas sections of the REFLECT block
Requirement: Agent Backend for wai reflect
When running inside an agent session, wai reflect SHALL output the prepared
reflection context block to stdout — using the same [AGENT CONTEXT] /
[/AGENT CONTEXT] delimiters as wai why — rather than calling an external
LLM. The invoking agent synthesizes the REFLECT content and feeds it back via
--inject-content.
Scenario: Agent mode activated in wai reflect
- WHEN user (or agent) runs
wai reflect - AND
in_agent_session()returnstrue - AND no API key is configured
- THEN
wai reflectselects the Agent backend viadetect_backend() - AND outputs the prepared reflection context block delimited by
[AGENT CONTEXT]/[/AGENT CONTEXT]markers - AND prints a status line:
◆ Agent mode — context sent to agent. - AND prints a follow-up instruction:
Once the agent provides the REFLECT content, run: wai reflect --inject-content '<content>' - AND exits 0 without writing any resource file
Scenario: Agent provides reflect content via –inject-content
- WHEN the invoking agent synthesizes the REFLECT content from the context block
- AND runs
wai reflect --inject-content '<synthesized content>' - THEN
wai reflectskips the LLM call and uses the injected content directly - AND writes the content to
.wai/resources/reflections/<date>-<project>.md - AND completes normally (updates metadata, prints resource file path)
Scenario: Detection uses same three-env contract
- WHEN determining whether agent mode should activate for
wai reflect - THEN the system uses
in_agent_session()identically towai why:WAI_AGENT, thenCLAUDECODE, thenCURSOR_AGENT - AND the agent backend is selected by
detect_backend()using the shared[why]LLM config section
Scenario: Non-agent invocation unchanged
- WHEN
in_agent_session()returnsfalse - THEN
wai reflectbehaves exactly as before: calls the configured LLM backend and writes the result directly to the resource file - AND no
[AGENT CONTEXT]block is emitted
Project State Machine
Purpose
Define the phase-based state machine for projects, providing a structured workflow from initial research through completion and archival.
Problem Statement
Development projects progress through natural phases — from research and planning through design, implementation, and review. Without a formalized state model, the current phase of a project becomes ambiguous, making it difficult to provide contextual suggestions, generate meaningful handoffs, or track progress over time. A state machine provides the structure needed for phase-aware tooling while remaining flexible enough for real-world workflows where phases may be revisited.
Design Rationale
Six-Phase Model
The six-phase model (research → design → plan → implement → review → archive) is a Type 1 foundational decision. Unlike the simpler four-phase bead lifecycle it replaces at the project level, this model captures the full arc of a development effort:
- Research: Gathering context, understanding the problem space
- Design: Creating technical designs, API contracts, architecture
- Plan: Defining implementation steps, scope, and success criteria after design direction is selected
- Implement: Writing code, building features
- Review: Testing, code review, validation against requirements
- Archive: Completed work preserved for reference
Flexible Transitions
Unlike strict linear workflows, wai allows flexible transitions — users can skip forward or go back as needed. This is a deliberate Type 2 decision that prioritizes developer autonomy over process enforcement. The state machine tracks transitions for auditability without preventing valid workflow patterns.
File-Based State
Project state is stored as a YAML .state file within the project directory. This keeps state co-located with the project’s artifacts and naturally version-controllable.
Scope and Requirements
This spec defines the state machine phases, transitions, and persistence format for projects.
Non-Goals
- Automated phase transitions based on external signals
- Phase-specific validation rules (e.g., requiring certain artifacts before advancing)
- Multi-project phase coordination
- Custom user-defined phases
Requirement: Phase Definitions
Projects SHALL progress through defined phases that represent workflow stages.
Scenario: Default phase
- WHEN a new project is created
- THEN it starts in the “research” phase
Scenario: Phase list
- WHEN querying available phases
- THEN the system returns: research, design, plan, implement, review, archive
Requirement: Phase Transitions
The system SHALL support flexible phase transitions with history tracking.
Scenario: Advance to next phase
- WHEN user runs
wai phase next - THEN the project moves to the next sequential phase
- AND the transition is recorded with timestamp
Scenario: Set specific phase
- WHEN user runs
wai phase set <phase> - THEN the project moves to the specified phase
- AND the transition is recorded with timestamp
Scenario: Go back to previous phase
- WHEN user runs
wai phase back - THEN the project moves to the previous sequential phase
- AND the transition is recorded with timestamp
Scenario: Show current phase
- WHEN user runs
wai phase - THEN the system displays the current phase and phase history
Requirement: State Persistence
Project phase state SHALL be persisted in a YAML file within the project directory.
Scenario: State file format
- WHEN a project has phase state
- THEN it is stored in
.wai/projects/<name>/.stateas:current: plan history: - phase: research started: 2026-01-20T10:00:00Z completed: 2026-01-22T15:30:00Z - phase: plan started: 2026-01-22T15:30:00Z
Requirement: Phase History
The system SHALL maintain a complete history of phase transitions.
Scenario: Transition recorded
- WHEN a project changes phase
- THEN the system records the previous phase completion time
- AND records the new phase start time
- AND the history is visible via
wai phase
Requirements
Requirement: Matrix-Aware Design to Plan Transition
The system SHALL gate the design → plan phase transition on matrix currency
when a project has a decision matrix (designs/matrix/): problem.md must be
non-empty, decision.md must record a selected approach that exists under
approaches/, and no file under approaches/ or criteria/ may be newer
than the decision UTC timestamp recorded inside decision.md. Projects
without a matrix are never gated by it. The gate applies to every
design → plan transition path, including wai phase next and
wai phase set plan.
Scenario: Matrix gates design-to-plan when undecided
- GIVEN a project with a decision matrix whose
decision.mdis still the scaffolded template - WHEN the
design → plantransition is attempted - THEN the transition is blocked
- AND the failure message indicates no decision has been made and
suggests
wai matrix decide
Scenario: Matrix gates design-to-plan when stale
- GIVEN a project with a decision matrix whose cell or criterion files were modified after the recorded decision timestamp
- WHEN the
design → plantransition is attempted - THEN the transition is blocked
- AND the failure message names the offending files and suggests
wai matrix decide
Scenario: Inconclusive staleness warns instead of blocking
- GIVEN a decided matrix checked out fresh from git so that all matrix files share the checkout timestamp with the decision timestamp
- WHEN the
design → plantransition is attempted - THEN the transition proceeds
- AND a stale-decision warning is reported with a pointer to
wai matrix lint
Scenario: Set cannot bypass the gate
- GIVEN a project in the design phase with an undecided matrix
- WHEN user runs
wai phase set plan - THEN the transition is blocked with the same message as
wai phase next
Scenario: No matrix leaves transitions unchanged
- GIVEN a project that never initialized a matrix
- WHEN the
design → plantransition is attempted - THEN the transition behaves exactly as before this change
Reasoning Oracle
Purpose
Define the LLM-powered reasoning oracle that helps developers understand why code exists as it does by synthesizing context from artifacts, git history, and project metadata.
The term “oracle” refers to the system’s ability to proactively surface relevant context and synthesize reasoning chains from multiple sources, like consulting a knowledgeable advisor who can connect disparate information and explain the evolution of decisions.
This capability builds on the existing wai search command (see timeline-search) by adding an LLM synthesis layer that transforms keyword matches into reasoned explanations.
Problem Statement
As projects accumulate research notes, design documents, and plans, developers struggle to rediscover the reasoning behind past decisions. While wai search provides keyword matching, understanding why requires semantic synthesis: connecting related artifacts, building decision chains, and explaining trade-offs in natural language. These are tasks that LLMs excel at, making them ideal for reasoning discovery.
Design Rationale
LLM-First Architecture
This is a Type 1 decision: delegate reasoning to LLMs rather than implementing custom ranking algorithms. The design makes wai a context orchestrator that gathers artifacts and formats prompts, trusting the LLM to handle semantic understanding, relevance ranking, and narrative synthesis.
Why LLM-first:
- LLMs naturally understand semantic similarity (“config” ↔ “configuration”)
- LLMs rank by relevance (design docs > research notes for architectural questions)
- LLMs build reasoning chains (research → design → plan) without explicit programming
- Implementation is 3x simpler (~400 LOC vs ~1200 LOC for custom algorithms)
- Quality improves automatically as LLMs improve
Alternative considered: Custom keyword extraction + Jaccard similarity + temporal scoring. Rejected due to complexity, brittleness, and inferior results.
Multi-Backend Support
Support multiple LLM backends (Claude API, local Ollama, future: Gemini, OpenAI) via trait abstraction. Auto-detect available backend and gracefully degrade to wai search if no LLM is accessible.
Scope and Requirements
This spec covers the wai why command, LLM integration, and configuration.
Non-Goals
- Multi-turn conversation mode (future consideration)
- Custom ranking algorithms or ML models
- Vector embeddings or semantic search infrastructure
- Local-only operation (LLM is recommended but optional)
Requirements
Requirement: Why Command
The CLI SHALL provide wai why <query> to answer reasoning questions using LLM synthesis of gathered context.
Scenario: Natural language query
- WHEN user runs
wai why "why use TOML for config?" - THEN the system gathers all artifacts and git context
- AND sends a structured prompt to the configured LLM
- AND displays the LLM’s synthesized answer with relevant artifacts, decision chains, and suggestions
Scenario: File path query
- WHEN user runs
wai why src/config.rs - THEN the system detects the file path
- AND gathers git blame and log for that file
- AND gathers all artifacts (prioritizing those mentioning the file or from similar timeframe)
- AND asks the LLM to explain why this file exists
Scenario: Output format
- WHEN displaying the answer
- THEN the output shows:
- Direct answer to the question
- 3-5 relevant artifacts with relevance explanation
- Decision chain (temporal evolution of reasoning)
- Suggestions for further exploration
- AND artifact references include file paths for verification
Scenario: JSON output
- WHEN user runs
wai why <query> --json - THEN the system outputs structured JSON with:
query(original question)answer(LLM response text)artifacts(array of artifact paths with relevance indicators parsed from LLM response: “High”/“Medium”/“Low”)suggestions(array of suggested follow-up commands)
Note: The system handles diverse query types including natural language questions ("why use TOML for config?"), file paths (src/config.rs), design decisions ("why not async-std?"), feature rationale ("plugin system design"), and rejection rationale ("why was dynamic loading rejected?").
Requirement: LLM Backend Selection
The system SHALL support multiple LLM backends via configuration and context-aware auto-detection.
Scenario: Auto-detect backend inside an agent session
- WHEN user runs
wai whywith no explicit[why] llmconfig - AND
in_agent_session()returnstrue— i.e. at least one ofWAI_AGENT,CLAUDECODE, orCURSOR_AGENTis set and non-empty - THEN the system checks available backends in this priority order:
ANTHROPIC_API_KEYenv var set → Claude APIin_agent_session()true → Agent modeollamabinary + model available → Ollama
- AND uses the first available backend
- AND falls back to
wai searchwith a warning if none available
Note: Agent mode is preferred over Ollama inside any agent session because it requires no external service and uses the already-present LLM without subprocess overhead.
Scenario: Explicit agent mode outside an agent session
- WHEN
.wai/config.tomlcontains[why] llm = "agent" - AND
in_agent_session()returnsfalse(no supported agent env var set) - THEN the system warns: “agent mode requires an active agent session; no synthesized answer will be produced”
- AND still outputs the context block (allowing manual inspection)
- AND exits 0 — this is a misconfiguration warning, not a fatal error
Requirement: Graceful Degradation
The system SHALL fall back to wai search when LLM is unavailable or fails.
Scenario: No LLM available
- WHEN user runs
wai whywith no API key and no Ollama installed - THEN the system displays a warning that no LLM is available
- AND displays remediation guidance (install Ollama or set API key)
- AND runs
wai search <query>and displays keyword matches
Scenario: LLM API error with diagnostic codes
- WHEN LLM API returns error (rate limit, invalid key, network failure)
- THEN the system displays a miette diagnostic error with an appropriate code (e.g.,
wai::llm::invalid_api_key,wai::llm::rate_limit,wai::llm::network_error,wai::llm::model_not_found) - AND includes actionable remediation in the error help text
- AND falls back to
wai searchwith explanation
Scenario: Malformed LLM response
- WHEN LLM returns response that doesn’t match expected markdown format
- THEN the system displays the raw response with a warning about unexpected format
- AND shows the response anyway (user can still read it)
- AND does NOT fall back to search (LLM did respond, just oddly)
Requirement: Context Gathering
The system SHALL gather comprehensive context to send to the LLM while managing context size to stay within LLM limits.
Scenario: Gather artifacts
- WHEN preparing context for LLM
- THEN the system reads all artifacts from
.wai/:- Research notes from all projects
- Design documents from all projects
- Plans from all projects
- Handoffs from all projects
- AND includes artifact metadata (date, type, project)
Scenario: Gather git context for file queries
- WHEN the system detects the query as a file path
- AND the repository is a git repository
- AND the file is tracked by git
- THEN the system runs
git blame <file>to get line-level authorship and commit info - AND runs
git log --follow <file>to get file history - AND includes recent commits that touched the file
Scenario: Git unavailable or file not tracked
- WHEN query looks like a file path but:
- Repository is not a git repository, OR
- Git command fails, OR
- File is not tracked by git
- THEN the system skips git context gathering
- AND displays an informational message suggesting git initialization or file tracking for better context
- AND proceeds with artifacts-only context
Scenario: Gather project metadata
- WHEN preparing context
- THEN the system includes:
- Current project phase
- Recent commits (last 10)
- Active beads issues (if plugin detected)
- Active openspec changes (if plugin detected)
Scenario: Plugin-contributed context
- WHEN preparing context and detected plugins expose relevant data
- THEN the system MAY incorporate context from detected plugins via the plugin interface (e.g., beads issues, openspec changes)
- AND plugin context is included alongside artifacts and git context in the LLM prompt
Scenario: No artifacts available
- WHEN preparing context and
.wai/contains zero artifacts - THEN the system warns that no artifacts were found and suggests using
wai add - AND still proceeds with LLM call using only git context and project metadata
- AND the prompt instructs the LLM to note that no project artifacts were available
Scenario: Context size management for large projects
- WHEN total artifact content exceeds the configured model’s context budget
- THEN the system selects a subset of artifacts, prioritizing relevance to the query and recency
- AND informs the user that context was truncated and suggests
wai searchfor broader coverage - AND includes a truncation note in the prompt for LLM awareness
Requirement: Prompt Construction
The system SHALL build structured prompts that guide the LLM to produce consistent, useful answers.
Scenario: Basic prompt structure
- WHEN building a prompt
- THEN the prompt includes:
- Role definition (“You are an oracle…”)
- User question
- Project context (phase, commits)
- Artifacts with metadata (in escaped code blocks to prevent markdown injection)
- Git context (if file query)
- Task instructions (identify relevant artifacts, synthesize narrative, suggest next steps)
- Output format instructions (markdown sections)
- AND all artifact content is escaped or quoted to prevent:
- Markdown injection (triple backticks, special characters)
- Prompt injection (instructions embedded in artifacts)
- Format breaking (malformed markdown)
Scenario: Verbosity levels
- WHEN user runs
wai why <query>with global verbosity flags (-v,-vv,-vvv) - THEN the system provides progressively more detail:
-v: backend selected, artifact count, estimated cost-vv: full prompt sent to the LLM-vvv: raw LLM response, timing breakdown, token counts
Requirement: Cost Awareness
The system SHALL default to cost-effective LLM models and provide usage transparency.
Scenario: Default to cost-effective models
- WHEN using Claude without explicit model configuration
- THEN the system defaults to the most cost-effective available model
- AND allows users to configure a more capable model via the
modelconfig field
Note: The system SHALL warn when estimated query cost exceeds a configurable threshold (default $0.05) due to large context or expensive model selection.
Scenario: Display cost estimate
- WHEN user runs
wai why <query>with verbosity level 1 or higher (-v) - THEN the output includes estimated cost for the query
- AND shows token counts (input and output) at verbosity level 3 (
-vvv)
Requirement: Privacy Considerations
The system SHALL inform users when sending artifacts to external APIs and provide local alternatives.
Scenario: Privacy warning for external APIs
- WHEN using external LLM API (Claude, Gemini, OpenAI) for the first time
- AND
.wai/config.tomldoes not haveprivacy_notice_shown = true - THEN the system displays a one-time notice informing the user that artifacts will be sent to the external provider
- AND suggests local Ollama as a privacy-preserving alternative
- AND records acknowledgment in
.wai/config.toml - AND proceeds with the query after displaying the notice
Scenario: Local-only mode
- WHEN configured to use Ollama
- THEN the system processes all queries locally without network calls
- AND indicates local-only operation at verbosity level 1 or higher
Requirement: Badge Recommendation
The system SHALL nudge project maintainers to add a wai badge to their README, improving discoverability.
Scenario: Badge footer in wai why output
- WHEN user runs
wai why <query>(terminal mode, not--json) - AND the project root contains a README file (README.md, README.rst, README.txt)
- AND that README does not contain a wai badge (detected by
![markdown containing “wai” orimg.shields.ioURL containing “wai”) - THEN the system appends a one-line footer after the main output suggesting the badge markdown
Scenario: No README present
- WHEN user runs
wai why <query> - AND no README file exists at the project root
- THEN the system does NOT show a badge suggestion (no README → no context to add a badge)
Scenario: Badge already present
- WHEN user runs
wai why <query> - AND the README already contains a wai badge
- THEN the system does NOT show a badge suggestion
Scenario: Badge check in wai doctor
- WHEN user runs
wai doctor - AND a README exists but has no wai badge
- THEN the system reports a “README badge” check with
warnstatus - AND includes the badge markdown in the fix suggestion
- WHEN the README already has a wai badge
- THEN the “README badge” check reports
pass - WHEN no README exists
- THEN the “README badge” check is skipped entirely
Requirement: Documentation
The wai why command SHALL be self-documenting through help text, onboarding, and agent instructions.
Scenario: Help text
- WHEN user runs
wai why --help - THEN the output includes:
- Three query type categories with examples (natural language, file path)
- Full
[why]config section template showing all options - All LLM error codes with remediation hints
- Reference to
--no-llmfallback flag
Scenario: Tutorial integration
- WHEN user runs
wai tutorial - THEN the Core Commands step lists
wai why "<question>"with usage examples
Scenario: Agent instruction blocks
- WHEN
wai initcreates or updatesCLAUDE.md/AGENTS.md - THEN the wai managed block Quick Reference section includes
wai whyexamples
Requirement: Agent Backend
When running inside an agent session, the system SHALL delegate reasoning to the invoking agent by outputting the prepared context to stdout rather than calling an external LLM.
Scenario: Agent mode activated automatically
- WHEN
in_agent_session()returnstrue - AND no API key is configured
- THEN the system prints a brief status line indicating agent mode is active
- AND outputs the full prepared context block, delimited by
[AGENT CONTEXT]/[/AGENT CONTEXT]markers - AND exits cleanly — the invoking agent synthesizes the answer in its next response
Scenario: Detection env var priority
- WHEN determining whether agent mode should activate
- THEN the system checks env vars in this order:
WAI_AGENTnon-empty → agent mode (universal override)CLAUDECODEnon-empty → agent mode (Claude Code)CURSOR_AGENTnon-empty → agent mode (Cursor IDE)
- AND the first non-empty match activates agent mode
- AND all other unset env vars do not affect the result
Requirement: Claude CLI Backend
The system SHALL support delegating wai why queries to the claude binary in print mode, for users who have Claude Code installed but no direct API key configured.
Scenario: Claude CLI backend behaviour
- WHEN the Claude CLI backend is selected (auto or explicit)
- THEN the system spawns
claude -pwith the prompt passed via stdin - AND captures stdout as the LLM response
- AND processes and displays the response identically to the Claude API backend
Scenario: Claude CLI is not used inside Claude Code sessions (auto-detect)
- WHEN auto-detection runs
- AND
CLAUDECODEis non-empty (inside a Claude Code session) - THEN the Claude CLI backend is NOT selected (agent mode is preferred)
Rationale: Inside Claude Code, spawning claude -p requires bypassing the nested-session guard (CLAUDECODE=""). This is a fragile workaround; agent mode is the correct mechanism for that context.
Scenario: No LLM available — remediation guidance mentions agent mode
- WHEN no LLM backend is available and the system falls back to
wai search - AND
CLAUDECODEis set and non-empty - THEN the fallback warning mentions that running inside a Claude Code session should enable agent mode automatically
- AND suggests checking
[why] llm = "agent"as an explicit override if needed
repository-best-practices Specification
Purpose
The wai way command reports on agnostic repository capabilities rather than specific tool implementations. Each capability check includes its intent and success criteria to provide context for both human users and AI agents. Verbose output (-v) shows intent and criteria; JSON output (--json) always includes them.
Requirements
Requirement: Command Standardization
Intent: Provide a single, tool-agnostic entry point for common repository tasks (build, test, deploy). Success Criteria: A standard interface (justfile, Makefile, npm scripts) exists for common tasks.
The system SHALL check for a task runner (justfile or Makefile) and recommend adoption if missing. When a justfile is found, the system SHALL parse it for useful recipes and display contextual suggestions to help users discover key workflows.
Scenario: Task runner present
- WHEN
wai wayruns - THEN it checks for
justfileorMakefilein current directory - AND reports pass if either exists
- AND the capability name in output is “Command standardization”
Scenario: Justfile with useful recipes
- WHEN
wai wayruns and ajustfileis found - THEN it parses the justfile for known useful recipe names
- AND displays a message listing matched recipes
Scenario: No task runner
- WHEN
wai wayruns and neitherjustfilenorMakefileexists - THEN it reports info status
- AND suggests adding a justfile
Requirement: Pre-commit Quality Gates
Intent: Prevent low-quality commits by running automated checks before code is saved to history. Success Criteria: Automated checks (linters, tests) run automatically before code is committed.
The system SHALL check for git hook manager configuration (prek or pre-commit) and recommend prek if missing.
Scenario: Prek configured
- WHEN
wai wayruns and.prek.tomlexists - THEN it reports pass
- AND the capability name in output is “Pre-commit quality gates”
Scenario: Pre-commit configured (legacy)
- WHEN
wai wayruns and.pre-commit-config.yamlexists (but not.prek.toml) - THEN it reports pass
- AND suggests migrating to prek
Scenario: No hook manager config
- WHEN
wai wayruns and neither.prek.tomlnor.pre-commit-config.yamlexists - THEN it reports info status
- AND suggests adding prek
Requirement: Consistent Formatting
Intent: Ensure consistent code formatting across different editors and IDEs. Success Criteria: Project-wide style rules are enforced by a shared configuration file.
The system SHALL check for EditorConfig and recommend it for editor-agnostic formatting rules.
Scenario: EditorConfig present
- WHEN
wai wayruns and.editorconfigexists - THEN it reports pass
- AND the capability name in output is “Consistent formatting”
Scenario: No EditorConfig
- WHEN
wai wayruns and.editorconfigdoesn’t exist - THEN it reports info status
- AND suggests adding .editorconfig
Requirement: Project Documentation
Intent: Provide essential project identity, onboarding, and legal/contribution guidance. Success Criteria: Essential files (README, .gitignore, LICENSE) provide project context and rules.
The system SHALL check for essential documentation files (.gitignore, README.md, CONTRIBUTING.md, LICENSE) and recommend creating missing ones.
Scenario: All documentation present
- WHEN
wai wayruns and all four files exist - THEN it reports pass
- AND the capability name in output is “Project documentation”
Scenario: Missing critical files
- WHEN
wai wayruns and.gitignoreorREADME.mdare missing - THEN it reports info status with ⚠️ indicator
- AND suggests adding the missing critical files
Scenario: Partial documentation
- WHEN
wai wayruns and some files are present but not all - THEN it reports based on whether critical files exist
Scenario: No documentation
- WHEN
wai wayruns and none of the documentation files exist - THEN it reports info status
Requirement: AI-Agent Context
Intent: Provide persistent “rules of the road” and project context for AI collaborators. Success Criteria: Persistent instructions define coding standards and context for AI assistants.
The system SHALL check for AI assistant instructions file and recommend one if missing.
Scenario: CLAUDE.md present
- WHEN
wai wayruns andCLAUDE.mdexists - THEN it reports pass
- AND the capability name in output is “AI-agent context”
- AND if no WAI:REFLECT block is found, suggests running
wai reflect
Scenario: AGENTS.md present
- WHEN
wai wayruns andAGENTS.mdexists (but not CLAUDE.md) - THEN it reports pass
- AND suggests adding CLAUDE.md for Claude Code compatibility
Scenario: No AI instructions
- WHEN
wai wayruns and neitherCLAUDE.mdnorAGENTS.mdexists - THEN it reports info status
- AND suggests creating CLAUDE.md
Requirement: Automated Verification
Intent: Ensure code quality and correctness through automated builds and tests on every change. Success Criteria: Every change is automatically validated by a remote build/test pipeline.
The system SHALL check for CI/CD configuration and recommend setup if missing.
Scenario: GitHub Actions configured
- WHEN
wai wayruns and.github/workflows/contains at least one workflow file - THEN it reports pass
- AND the capability name in output is “Automated verification”
Scenario: Empty workflows directory
- WHEN
wai wayruns and.github/workflows/exists but is empty - THEN it reports info status
Scenario: GitLab CI or CircleCI configured
- WHEN
wai wayruns and.gitlab-ci.ymlor.circleci/config.ymlexists - THEN it reports pass
Scenario: No CI/CD configuration
- WHEN
wai wayruns and no CI/CD config is found - THEN it reports info status
- AND suggests setting up continuous integration
Requirement: Reproducible Environments
Intent: Provide a standardized, containerized environment for all contributors. Success Criteria: A configuration exists to spin up a consistent, reproducible dev environment.
The system SHALL check for dev container configuration and recommend it for environment consistency.
Scenario: Dev container directory exists
- WHEN
wai wayruns and.devcontainer/directory exists - THEN it reports pass
- AND the capability name in output is “Reproducible environments”
Scenario: Dev container file exists
- WHEN
wai wayruns and.devcontainer.jsonexists - THEN it reports pass
Scenario: No dev container
- WHEN
wai wayruns and neither.devcontainer/nor.devcontainer.jsonexists - THEN it reports info status
- AND suggests adding .devcontainer/
Requirement: LLM-Friendly Context
Intent: Provide machine-readable project context and navigation for LLMs. Success Criteria: Machine-readable project documentation (llm.txt) exists for AI tools.
The system SHALL check for llm.txt file and recommend it for AI-friendly project documentation.
Scenario: llm.txt present
- WHEN
wai wayruns andllm.txtexists - THEN it reports pass
- AND the capability name in output is “LLM-friendly context”
Scenario: No llm.txt
- WHEN
wai wayruns andllm.txtdoesn’t exist - THEN it reports info status
- AND suggests adding llm.txt
Requirement: Extended Agent Capabilities
Intent: Enhance agent functionality with specialized iterative review and commit workflows. Success Criteria: Specialized agent workflows (Rule of 5, Deliberate Commits) are active.
The system SHALL check for agent skills in .wai/resources/agent-config/skills/ and recommend rule-of-5-universal and commit. Skill identity is resolved by directory name OR by aliases declared in SKILL.md frontmatter.
Scenario: Both recommended skills present
- WHEN
wai wayruns and bothrule-of-5-universal(orro5) andcommitexist - THEN it reports pass
- AND the capability name in output is “Extended agent capabilities”
Scenario: Skills present via alias (ro5)
- WHEN a skill directory exists with
aliases: [ro5]in SKILL.md frontmatter - THEN that skill satisfies the
rule-of-5-universalcheck
Scenario: Partial skills configuration
- WHEN skills directory exists but one or both recommended skills are missing
- THEN it reports info status and lists what’s missing
Scenario: No skills configured
- WHEN
.wai/resources/agent-config/skills/does not exist - THEN it reports info status
Scenario: Skills directory empty
- WHEN
.wai/resources/agent-config/skills/exists but contains no SKILL.md files - THEN it reports info status
Requirement: Agent Skills Fix
The system SHALL provide wai way --fix skills to scaffold missing recommended skills.
Scenario: Fix scaffolds missing skills
- WHEN user runs
wai way --fix skills - THEN the system creates the skills directory if it does not exist
- AND creates
rule-of-5-universal/SKILL.mdif not present - AND creates
commit/SKILL.mdif not present - AND reports each created skill
Scenario: Fix skips existing skills
- WHEN user runs
wai way --fix skillsand a recommended skill already exists - THEN the system skips that skill and reports “already present”
Scenario: Unknown fix target
- WHEN user runs
wai way --fix <unknown> - THEN the system exits with an error: “Unknown fix target ‘{value}’. Available: skills”
Requirement: Integration & Automation
Intent: Streamline repository interactions (PRs, issues, releases) from the CLI. Success Criteria: CLI tools are configured for seamless integration with the hosting provider.
The system SHALL check for the GitHub CLI (gh) and recommend it for streamlined GitHub workflows.
Scenario: gh CLI available and authenticated
- WHEN
wai wayruns andghis on PATH andgh auth statussucceeds - THEN it reports pass
- AND the capability name in output is “Integration & automation”
Scenario: gh CLI available but not authenticated
- WHEN
wai wayruns andghis on PATH butgh auth statusfails - THEN it reports info status
- AND suggests running
gh auth login
Scenario: gh CLI not installed
- WHEN
wai wayruns andghis not on PATH - THEN it reports info status
- AND suggests installing gh
Requirement: Automated Delivery
Intent: Automate the process of building, packaging, and publishing software releases. Success Criteria: Software releases and distribution (packages, binaries) are fully automated.
The system SHALL check for a release pipeline in binary projects and recommend setup if missing. Library projects are exempt.
Scenario: Library project
- WHEN
wai wayruns and the project has no binary target - THEN it reports pass with “Library project — release pipeline not required”
- AND the capability name in output is “Automated delivery”
Scenario: Release tool detected
- WHEN
wai wayruns and goreleaser, cargo-dist, or a release workflow is found - THEN it reports pass
Scenario: No release pipeline
- WHEN
wai wayruns, the project has a binary target, and no release tool is found - THEN it reports info status
- AND suggests goreleaser or cargo-dist
Requirement: Verbose Output
The system SHALL show intent and success_criteria for each capability when --verbose (-v) is used.
Scenario: Verbose output includes agnostic context
- GIVEN any project
- WHEN user runs
wai way -v - THEN each capability line is followed by an “Intent:” line and a “Success:” line
- AND normal (non-verbose) output does not show these lines
Requirement: JSON Output
The system SHALL include intent and success_criteria in JSON output. These fields are optional (null if not set) for backward compatibility.
Scenario: JSON includes agnostic fields
- GIVEN any project
- WHEN user runs
wai way --json - THEN the JSON payload includes
intentandsuccess_criteriafor every check result
Requirement: Plugin Agnostic Context Support
The plugin system SHALL allow TOML-defined plugins to define their own intent and success_criteria.
Scenario: Plugin with custom context
- GIVEN a plugin TOML with
intentandsuccess_criteriadefined - WHEN the plugin definition is parsed
- THEN these fields are available on the
PluginDefstruct - AND default to
Noneif not present in the TOML
Scenario: TOML plugin file parsed correctly
- GIVEN a
.tomlplugin file in.wai/plugins/with content:name = "my-check" intent = "Ensure the repo has a CODEOWNERS file." success_criteria = "CODEOWNERS file exists in the repo root or .github/ directory." - WHEN the plugin loader scans
.wai/plugins/for*.tomlfiles - THEN the file is parsed with
toml::from_str - AND
intentandsuccess_criteriaare available on the resultingPluginDef - AND YAML files (
*.yml,*.yaml) are not loaded
Requirement: Output Format
The system SHALL format all checks consistently.
Scenario: All checks pass
- WHEN
wai wayruns and all checks return pass - THEN output shows checkmarks (✓) for each
- AND summary displays “excellent! All best practices adopted”
Scenario: Fresh repository
- WHEN
wai wayruns on a fresh repository with no tools configured - THEN output shows info markers (ℹ) for each check
- AND summary displays “0/{n} best practices adopted — quick-start: add README.md, justfile, .gitignore”
Research Management
Purpose
Define how research artifacts (notes, links, documents) are captured, organized, and stored within project and area subdirectories to support informed decision-making.
Problem Statement
Valuable insights, notes, and external resources in development and research workflows are often scattered, making it challenging to consistently link supporting research directly to specific projects or areas of work. This leads to lost context, hindered decision-making, and duplicated effort. A Type 1 strategic decision is made here to address this by integrating research management directly within wai’s PARA structure, ensuring research is organized alongside the work it supports.
Design Rationale
- Within PARA Structure: Research lives inside project or area subdirectories (e.g.,
.wai/projects/my-app/research/), not in a top-level directory. This keeps research co-located with its context and naturally scoped. - Date-Prefixed Files: Research entries use date-prefixed markdown filenames (e.g.,
2026-01-20-api-analysis.md) for chronological sorting and easy timeline integration. - Optional Association: Research can optionally reference external tracking (e.g., a beads issue ID via frontmatter) without requiring it. This keeps research useful even without external tools.
- File-based Storage: Storing research as transparent, accessible files ensures data portability and resilience. This avoids the overhead of a dedicated database and keeps user data accessible outside
wai.
Scope and Requirements
This spec focuses on the core functionality for capturing and organizing research within the PARA structure.
Non-Goals
- Editing and deleting existing research (use standard file operations)
- Full-text search (covered by timeline-search spec)
- Rich media or complex formatting
- Integration with external research management software
- Version control for individual entries (use git)
Requirements
Requirement: Adding Research
The CLI SHALL support capturing research content within a project or area.
Scenario: Add research to current project
- WHEN user runs
wai add research <content> - THEN the system creates a date-prefixed research file in the current project’s
research/directory - AND stores the content as markdown
Scenario: Add research to specific project
- WHEN user runs
wai add research <content> --project <name> - THEN the system creates the research entry in the specified project’s
research/directory
Scenario: Add research from file
- WHEN user runs
wai add research --file <path> - THEN the system copies the file content as a research entry with date prefix
Scenario: Research with frontmatter
- WHEN user runs
wai add research <content> --tags <tag1,tag2> - THEN the research file includes YAML frontmatter with tags
- AND optionally includes a
beadfield for external tracking association
skill-sharing Specification
Purpose
TBD - created by archiving change add-skill-sharing. Update Purpose after archive.
Requirements
Requirement: Global Skill Library
The system SHALL maintain a global skill library at ~/.wai/resources/skills/
that is available in all projects, with project-local skills taking priority
over global skills when names conflict.
Scenario: Global skill available in all projects
- WHEN a skill is installed globally via
wai resource install <skill> --global - THEN it is accessible in any project via
wai resource list skills - AND is marked as
[global]in the listing output
Scenario: Local skill overrides global
- WHEN a skill named
issue/gatherexists both locally and globally - THEN the local version is used in all operations within that project
- AND the global version remains unchanged
Requirement: Skill Installation
The CLI SHALL support installing skills from the current project or another local repository into the global library.
Scenario: Install skill globally
- WHEN user runs
wai resource install issue/gather --global - THEN the system copies the skill from the current project’s skills directory
to
~/.wai/resources/skills/issue/gather/SKILL.md - AND confirms the installation path
Scenario: Install skill from another repository
- WHEN user runs
wai resource install issue/gather --from-repo ../other-project - THEN the system copies the skill from
../other-project/.wai/resources/agent-config/skills/issue/gather/SKILL.mdinto the current project’s skills directory - AND confirms the installation path
Scenario: Hardcoded project names warned
- WHEN installing a skill whose content contains the literal value of the current project name or absolute paths beginning with the repository root
- THEN the system issues a warning listing the suspicious strings
- AND proceeds with installation (warning, not error)
Requirement: Skill Export and Import
The CLI SHALL support bundling skills for sharing and importing bundles from external sources.
Scenario: Export skills to archive
- WHEN user runs
wai resource export issue/gather impl/run --output skills.tar.gz - THEN the system creates a tar.gz archive containing the SKILL.md files
preserving the
<category>/<name>/SKILL.mddirectory structure
Scenario: Import skills from archive
- WHEN user runs
wai resource import skills.tar.gz - THEN the system extracts skill files into the current project’s skills directory
- AND prompts before overwriting any existing skill
- AND reports which skills were installed
Scenario: Non-interactive import with –yes
- WHEN user runs
wai resource import skills.tar.gz --yes - THEN the system overwrites existing skills without prompting
- AND reports all skills that were overwritten
Timeline & Search
Purpose
Define cross-artifact search and chronological timeline views that help users find and navigate artifacts across the entire .wai/ structure.
Problem Statement
As a project accumulates research notes, plans, designs, and handoffs across multiple projects and areas, finding specific information becomes increasingly difficult. Users need two complementary navigation modes: chronological (what happened when?) and content-based (where is this mentioned?). Without built-in search and timeline capabilities, users fall back to manual file browsing or external grep commands that lack context about wai’s organizational structure.
Design Rationale
Dual Navigation Modes
Providing both timeline and search views is a Type 2 decision based on two fundamental ways developers navigate information:
- Timeline answers “what happened?” — useful for reconstructing context, reviewing progress, and generating reports
- Search answers “where is this?” — useful for finding specific decisions, references, or artifacts
Project-Scoped and Global
Both timeline and search support project-scoped queries (most common) and global queries (cross-project discovery). This dual scope matches how developers think: usually focused on one project, occasionally needing to find something across all work.
Scope and Requirements
This spec covers the timeline and search commands and their filtering capabilities.
Non-Goals
- Full-text indexing or database-backed search
- Search ranking or relevance scoring
- Real-time search updates or watch mode
- Integration with external search tools
Requirement: Timeline View
The CLI SHALL provide a chronological view of artifacts within a project.
Scenario: Project timeline
- WHEN user runs
wai timeline <project> - THEN the system scans all dated artifacts in the project directory
- AND displays them chronologically with date, type, and title
Scenario: Timeline output format
- WHEN displaying a timeline
- THEN each entry shows:
- Date (from filename prefix)
- Artifact type (research, plan, design, handoff)
- Title or filename
- AND entries are sorted newest-first by default
Scenario: Timeline output as JSON
- WHEN user runs
wai timeline <project> --json - THEN the system outputs JSON entries with
date,type,title, andpath
Requirement: Search
The CLI SHALL provide full-text search across all artifacts.
Scenario: Global search
- WHEN user runs
wai search <query> - THEN the system searches across all
.wai/artifacts - AND displays matching files with context lines
Scenario: Type-filtered search
- WHEN user runs
wai search <query> --type research - THEN the system searches only within research artifacts
Scenario: Project-scoped search
- WHEN user runs
wai search <query> --in <project> - THEN the system searches only within the specified project’s artifacts
Scenario: Search output format
- WHEN displaying search results
- THEN each result shows:
- File path (relative to
.wai/) - Matching line with query highlighted
- Context (lines before and after the match)
- File path (relative to
Scenario: Search output as JSON
- WHEN user runs
wai search <query> --json - THEN the system outputs JSON results with
path,line_number,line, andcontext