diff --git a/.agents/skills/wursor-bug-fix/SKILL.md b/.agents/skills/wursor-bug-fix/SKILL.md new file mode 100644 index 0000000..0f5e515 --- /dev/null +++ b/.agents/skills/wursor-bug-fix/SKILL.md @@ -0,0 +1,67 @@ +--- +name: wursor-bug-fix +description: "Reproduce a defect, root-cause it, and fix it with runtime evidence. Follow the repro-first discipline: never patch a symptom without proving the cause. For bugs in api/, web/, plugin/, infrastructure/, and e2e/. Adapted from pstack's bug-fix playbook." +--- + +# Wursor Bug Fix + +Reproduce a defect, root-cause it, fix it, and prove the fix with runtime evidence. + +## When to use + +Use this skill when: +- The user reports a symptom: "X is slow", "X crashes", "X returns the wrong value" +- A test fails and the failure is unexplained +- A behavior regressed +- A task involves fixing a defect rather than adding a feature + +## Playbook + +### Step 1 — Reproduce it first + +Do not touch code until the defect is reproduced with a reliable, minimal repro. + +- If there's a failing test, run it and confirm it fails for the stated reason +- If there's no test, write the smallest test or script that reproduces the symptom +- Capture the actual behavior: error message, stack trace, wrong value, timing +- The repro must be repeatable. "Sometimes it breaks" is not a repro; narrow it until it's deterministic + +### Step 2 — Root-cause it + +Trace the symptom back to its cause. Ask "why" repeatedly: + +1. Why does this output appear? → Because module A does X +2. Why does A do X? → Because B passed it the wrong input +3. Why did B pass the wrong input? → Because the schema validation at the boundary is missing + +Stop when the answer is a genuine defect, not another symptom. A root cause is a place where the code violates its own contract, not a place that "needs a guard." + +### Step 3 — State the root cause + +Write it down before fixing. "The sandbox GC destroys a container while the deploy verifier is still polling it, because the verifier checks status once and the GC doesn't check the verifier's lease." + +### Step 4 — Fix the root cause + +Apply the smallest change that fixes the cause at the point where it happens. Follow the principles: + +- **Fix root causes** — no nil-check that silences a crash +- **Laziness protocol** — the smallest correct change +- **Boundary discipline** — the guard belongs at the boundary, not in every consumer + +### Step 5 — Prove the fix + +- The repro from step 1 must now pass (the test, the script, the manual case) +- Run the surrounding test suite +- If the bug was a regression, add the repro as a permanent test so it cannot return silently + +### Step 6 — Report + +``` +## Root cause +[file.ts:42] — the verifier polls status without a lease; GC does not respect it +## Fix +[file.ts:52] — verifier now holds a short lease; GC skips leased containers +## Proof +- repro test added at [bug.test.ts] — passes before fix, fails after revert +- pnpm test:api — 412 passed, 0 failed +``` \ No newline at end of file diff --git a/.agents/skills/wursor-decision-log/SKILL.md b/.agents/skills/wursor-decision-log/SKILL.md new file mode 100644 index 0000000..d6501cf --- /dev/null +++ b/.agents/skills/wursor-decision-log/SKILL.md @@ -0,0 +1,53 @@ +--- +name: wursor-decision-log +description: "Write a reviewable decision trail for a non-trivial change in the Wursor repo. Logs the choices, alternatives, and tradeoffs so the trail can be audited later. Adapted from pstack's /show-me-your-work." +--- + +# Wursor Decision Log + +Log decisions as they are made so the trail is reviewable and auditable. + +## When to use + +Use this skill when: +- The task is complex enough that a reviewer might ask "why was this done this way?" +- The change involves a tradeoff (speed vs. cost, simplicity vs. completeness, two architectural forks) +- The user explicitly asks for a decision trail +- The task is a prototype or spike with a decision at the end (which path to commit to) + +## Playbook + +### Step 1 — Log each decision as you make it + +For each decision, record: + +``` +## Decision: [title] +- **Context:** what was the situation or constraint? +- **Options considered:** what were the alternatives? +- **Chosen:** which option was picked, and why? +- **Rejected:** why were the other options not chosen? +- **Reverted later?** (leave blank, filled only if this decision is ultimately undone) +``` + +### Step 2 — Keep the log in the conversation + +Append each decision to the running log in thread. At the end of the task, present the full log. + +### Step 3 — End with the full log + +``` +## Decision Log +### Decision: Sandbox storage backend +- **Context:** we need to persist sandbox state for GC and pause-to-disk +- **Options considered:** local filesystem on the VPS, Redis, S3 +- **Chosen:** local filesystem — fast, no extra service, but means we cannot rebalance containers across hosts +- **Rejected:** Redis (no need for byte-level blob storage), S3 (latency is too high for pause/resume on a warm container) +- **Reverted later?** — yes, when we moved to multi-host orchestration in Phase 3 +``` + +## Hard rules + +- Log every decision you would need to explain to a reviewer +- Be explicit about tradeoffs — "we chose X over Y because Z" is better than "we chose X" +- Do not log decisions that are obvious from the code (e.g., "I decided to use `const` instead of `let`") \ No newline at end of file diff --git a/.agents/skills/wursor-feature/SKILL.md b/.agents/skills/wursor-feature/SKILL.md new file mode 100644 index 0000000..f46dea3 --- /dev/null +++ b/.agents/skills/wursor-feature/SKILL.md @@ -0,0 +1,66 @@ +--- +name: wursor-feature +description: "Build new or changed behavior in the Wursor repo, from a named data shape, TDD-first, with a defined verification path. Includes a refactoring mode for behavior-preserving structural change. Adapted from pstack's feature playbook." +--- + +# Wursor Feature + +Build a new feature, or change behavior, with the rigor of a named data shape, a failing test first, and a defined verification path. + +## When to use + +Use this skill when: +- The task is "add X", "build Y", "change Z" +- A user story describes new behavior +- A refactoring preserves behavior while changing structure + +Do **not** use this for: one-line changes, copy edits, or bugs (use `wursor-bug-fix`). + +## Playbook + +### Step 1 — Name the data shape + +Before any code, define what the feature operates on. The core types, in concrete form: + +- What is the input? (request, event, message) +- What is the output? (response, deployed state, preview URL) +- What states does it pass through? (enumerate them) +- What can go wrong? (enumerate the errors) + +Write these as types or interfaces where the language supports it. For `api/` this usually means a TypeScript type or a Zod schema at the boundary. For `plugin/` a class or array-shaped response. + +### Step 2 — Write the failing test + +Following `wursor-tdd`: + +- One test per behavior, one assertion per test +- The test must fail before implementation +- Mocks at boundaries: Grok API, plugin API, Docker, filesystem + +### Step 3 — Implement + +Write the minimum code to pass the test(s). Follow the principles: + +- Foundational thinking — the types from step 1 drive the implementation +- Make operations idempotent — the feature must be retry-safe +- Boundary discipline — parse and validate external input at the boundary + +### Step 4 — Verify + +- The new tests pass +- The broader suite passes (`pnpm test:api`, `pnpm test:web`, or `phpunit` as appropriate) +- For UI features: the component renders in the browser/E2E test, not just "compiles" + +### Step 5 — Report + +``` +## What changed +- new module [x.ts] — does the specific thing, shaped by type T +## Data shape +- input: ..., output: ..., states: [...], errors: [...] +## Verification +- [feature.test.ts] — 4 tests, all pass +- full suite — green +## Follow-ups +- schema migration needed in [y.ts] when playbook runner lands +``` \ No newline at end of file diff --git a/.agents/skills/wursor-investigation/SKILL.md b/.agents/skills/wursor-investigation/SKILL.md new file mode 100644 index 0000000..c9ce6c2 --- /dev/null +++ b/.agents/skills/wursor-investigation/SKILL.md @@ -0,0 +1,56 @@ +--- +name: wursor-investigation +description: "A read-only question about the Wursor codebase, product, or architecture. How does X work, why was Y built this way, what does module Z depend on. Read code, docs, and history; answer with evidence and citations to files and lines. Adapted from pstack's /how and /why skills." +--- + +# Wursor Investigation + +Answer a read-only question about how the Wursor codebase works, or why it was built the way it was. No code changes. + +## When to use + +Use this skill when: +- The user asks "how does X work?" — a walkthrough of a subsystem +- The user asks "why was Y built this way?" — a rationale for a past decision +- The user asks "are we sure Z?" — a verification of an assumption +- A task starts with understanding before changing, and the understanding is the deliverable + +## Playbook + +### Step 1 — Restate the question in concrete terms + +Translate the user's question into a specific, checkable claim. "How do sandboxes work?" becomes "What are the states a sandbox passes through, and which code drives each transition?" + +### Step 2 — Read the code, not the summaries + +- Find the relevant module. Read its source and its tests. +- Follow the call graph two levels out: who calls this module, what does it call? +- For architecture questions (why is this shaped this way), read the PRD and IMPLEMENTATION for the lock-in notes, then check history for the pivot. + +### Step 3 — Gather evidence + +Collect: +- File paths and line numbers for every claim +- Actual function signatures and state transitions +- Test names that prove the current behavior +- For "why" questions: the commit or doc that recorded the decision + +### Step 4 — Answer with citations + +Every claim in the answer must point at a file and (where possible) a line or symbol. No answer of the form "it uses a manager" — show the manager, its interface, and its caller. + +### Step 5 — Flag uncertainty + +If a claim is not verifiable from the repo (behavior depends on an external system, a decision predates the current docs), say so explicitly. Do not pad with plausible-sounding unverified detail. + +## Output shape + +``` +## How X works +- [file.ts:12](../api/src/file.ts#L12) — this is the entry point +- ...walk the path... +## Why it's shaped this way +- PRD v2.0 §8.1 — the non-technical-first pivot forced the chat-preview-approve loop +## Things I could not verify +- ...explicit list... +``` \ No newline at end of file diff --git a/.agents/skills/wursor-precheck/SKILL.md b/.agents/skills/wursor-precheck/SKILL.md new file mode 100644 index 0000000..a16a651 --- /dev/null +++ b/.agents/skills/wursor-precheck/SKILL.md @@ -0,0 +1,63 @@ +--- +name: wursor-precheck +description: "The entry point for any non-trivial Wursor task. Reads the task, routes it to the right playbook skill, opens a todo list, and establishes the verification bar before any work starts. Use this whenever a task involves changing code, fixing a bug, building a feature, or investigating how the Wursor codebase works. Modeled on Cursor's pstack poteto-mode." +--- + +# Wursor Precheck (Router) + +This is the default entry point for non-trivial work in the Wursor repository. Its job is to make sure the right rigor applies to every task — before a single line is written. + +## When to use + +Use this skill at the start of any task that is more than a trivial one-line change. This includes: + +- Building or editing any module in `api/`, `web/`, `plugin/`, `infrastructure/`, or `e2e/` +- Fixing a bug, with or without a repro +- Adding a feature or changing behavior +- Investigating how something works, or why it was built a certain way +- Reviewing a diff or a pull request +- Writing a decision trail that should be reviewable later + +Do **not** use this for: trivial copy edits, one-line doc fixes, or tasks the user explicitly says are quick. + +## What to do on activation + +1. **Read the task.** Understand what the user is asking and why. If the request is ambiguous, ask a targeted clarifying question before proceeding. + +2. **Open a todo list.** The first item is always: *understand the current state of the relevant module(s) before changing anything.* + +3. **Route the task to the right playbook.** Read the request and pick the closest match: + +| Task shape | Route to skill | +|---|---| +| A read-only question — "how does X work", "why was Y built this way", "are we sure Z" | `wursor-investigation` | +| A defect with a symptom — reproduce, root-cause, fix with runtime evidence | `wursor-bug-fix` | +| New or changed behavior, built from a named data shape | `wursor-feature` | +| A behavior-preserving change to structure or shape | `wursor-feature` (refactoring mode) | +| A diff or PR that needs to be broken | `wursor-review` | +| Any code change that has a cheap test path | `wursor-tdd` (write the failing test first) | +| You want the decisions captured for later review | `wursor-decision-log` | + +When a task spans multiple playbooks, apply them in sequence: investigation first (understand), then bug-fix or feature (change), then review (verify). + +4. **Copy the playbook steps in verbatim.** Read the routed skill's SKILL.md and follow its steps exactly. Do not improvise a lighter version because the task "feels small." + +5. **Set the verification bar.** Before starting, state what "done" means for this task: + - What test will prove the change works? + - What command will the user (or a reviewer) run to verify? + - What artifact is the proof — a passing test, a screenshot, a running sandbox, a clean diff? + +6. **Do the work.** Execute the playbook. Keep the todo list updated. Surface findings in the reply as you go. + +7. **Report unslopped.** When done, write a reply framed for the person who asked, plus a short note for the maintainer (what changed, why, what the verification was). + +## Sticky behavior + +Once this skill has been activated for a session, keep applying it to subsequent turns in the same session if the task still matches a playbook. Stay out of the way when the user is clearly doing something trivial. The user can opt out at any time by saying so. + +## Hard rules + +- Never skip the todo list. +- Never skip stating the verification bar. +- Never mark a task done without the proof defined in step 5 — a self-report ("it compiles") is not proof. +- Never touch the live WordPress site, production credentials, or real user data from this repo. Everything here is code and infrastructure definitions; if a task seems to require live data, stop and ask. diff --git a/.agents/skills/wursor-principles/SKILL.md b/.agents/skills/wursor-principles/SKILL.md new file mode 100644 index 0000000..0e3f8ec --- /dev/null +++ b/.agents/skills/wursor-principles/SKILL.md @@ -0,0 +1,60 @@ +--- +name: wursor-principles +description: "The engineering principles for the Wursor codebase, adapted from Cursor's pstack principles. Reference this when deciding how to structure code, what tradeoffs to make, or how to verify work in api/, web/, plugin/, infrastructure/, and e2e/. It is the shared standard every playbook routes through." +--- + +# Wursor Engineering Principles + +These are the rules that govern how work gets done in this repository. Each is a rule, not a suggestion. When a playbook or task runs into a decision, resolve it against these principles. + +## Core + +1. **Laziness protocol** — Bias toward deletion and the smallest change that solves the problem. When two solutions are otherwise equal, the shorter one wins. When a feature is questionable, the version that removes more code wins. + +2. **Foundational thinking** — Apply before writing logic. Choose the core types and data shapes first (`Site`, `Sandbox`, `DeployLog`, `Playbook`, tool schemas). Get the data structures right so downstream code becomes obvious. Ask what concurrent actors share (warm pool, sandbox GC, SSE streams). + +3. **Redesign from first principles** — When a requirement genuinely changed, redesign as if the new requirement had been foundational from day one. Do not bolt the new behavior onto a structure that no longer fits. The non-technical-first pivot is the standing example: the chat-preview-approve loop is the whole product surface; do not reintroduce engineer-only UI. + +4. **Subtract before you add** — Remove dead weight, redundant validators, and stub references first, then build on the simpler base. If you find a module with placeholder code while working in it, delete the placeholder rather than working around it. + +5. **Minimize reader load** — Count the layers between a question and its answer, and the hidden state a reader must hold in their head. Collapse one-caller wrappers, shrink mutable scope, and prefer a function that returns a value over one that mutates shared state. + +6. **Outcome-oriented execution** — During planned rewrites or migrations, define explicit phase boundaries. Converge on the target architecture; do not preserve smooth intermediate states with throwaway compatibility code. + +7. **Experience-first** — This product is for non-technical WordPress site owners. Choose user delight over implementation convenience. Ship fewer polished features over more rough ones. When in doubt, the choice that a non-technical user would experience as simpler wins. + +8. **Exhaust the design space** — Before committing to a design with real tradeoffs, build 2–3 competing sketches (types, module boundaries, or prototypes) and compare side by side. Especially in the `api/src/playbooks/` and `api/src/sandbox/` modules. + +9. **Build the lever** — Apply to any non-trivial work: edits, migrations, analyses, checks. Build the tool that does it or proves it (a script, a codemod, a test harness, a skill your subagents follow) instead of working by hand. The tool is the artifact a reviewer can rerun. + +## Architecture + +10. **Model the domain** — Encode the domain in structures instead of scattered conditionals. A `Playbook` is a type, not a switch statement. A `SandboxStatus` is a state machine, not a string comparison in three files. + +11. **Boundary discipline** — Concentrate guards at system boundaries (API routes, plugin REST API, Docker client, LLM client, filesystem). Trust internal types; keep business logic in pure functions that cannot corrupt state. + +12. **Type-system discipline** — Make illegal states unrepresentable. Use TypeScript discriminated unions for tool-call results and sandbox states. Parse external data (Grok responses, plugin API payloads, Docker events) at the boundary with a schema validator; never trust unvalidated external shapes inside business logic. + +13. **Make operations idempotent** — Converge to the same end state regardless of partial prior runs. Deploys, sandbox spins, and plugin installs must be retry-safe. If a step can partially fail, design the operation to be re-run until it reaches a known state. + +14. **Migrate callers, then delete legacy APIs** — Migrate callers and delete the old API in the same wave instead of preserving compatibility layers. No parallel legacy paths. + +15. **Separate before serializing shared state** — Eliminate shared mutable state first; only serialize when one shared writer is a real invariant. The sandbox manager and warm pool must not serialize on a single mutex that everything else waits on. + +## Verification + +16. **Prove it works** — Apply after completing a task, before declaring done. Verify against the real artifact: run the test, start the sandbox, hit the endpoint, read the actual value, inspect the diff. Not a proxy, not a self-report, not "it compiles." + +17. **Fix root causes** — Trace each symptom to its root cause and fix it there. Reproduce first. Ask "why" until you reach the source. Resist nil-checks and guards that silence crashes instead of fixing them. + +18. **Sequence verifiable units** — Apply to multi-step work (sweeps, migrations, runs of similar edits). Break work into small units that each end in a verifiable state. Check each before the next. Order delivery so the sequence proves itself to a reviewer. + +## Delegation + +19. **Guard the context window** — Route bulk to subagents; keep summaries in the main thread, not raw payloads. When a task involves many similar files, delegate the sweep and bring back a tight report. + +20. **Never block on the human** — Proceed, present the result, let the human course-correct after the fact. Reserve confirmation for irreversible actions (deploys to a live site, deleting data, changing auth). + +## Meta + +21. **Encode lessons in structure** — Encode a rule as a lint rule, a type, a schema, a runtime check, or a script instead of more text. If you find yourself repeating the same correction in prose, turn it into a check the code enforces. diff --git a/.agents/skills/wursor-review/SKILL.md b/.agents/skills/wursor-review/SKILL.md new file mode 100644 index 0000000..fd54c06 --- /dev/null +++ b/.agents/skills/wursor-review/SKILL.md @@ -0,0 +1,72 @@ +--- +name: wursor-review +description: "Review a diff or pull request in the Wursor repo across multiple lenses: correctness, security, domain modeling, type discipline, and the non-technical-first product bar. Adapted from pstack's /interrogate and the code-quality lens." +--- + +# Wursor Review + +Review a diff or PR across several lenses. The point is to break it, not to bless it. + +## When to use + +Use this skill when: +- The user asks to "review this PR" or "review this diff" +- A change is about to be committed and deserves a second pass +- A subagent produced work that needs a skeptical read + +## Playbook + +### Step 1 — Read the diff fully + +Read every changed file in full, not just the diff summary. Read the tests that accompany the change. If there are no tests, that is finding #1. + +### Step 2 — Review across lenses + +Go through each lens in order: + +**Correctness** +- Does the code do what the tests claim? +- Are the state transitions sound? (sandbox states, deploy phases, playbook steps) +- Are there race conditions? (GC vs. verifier, warm pool vs. spin-up) +- Is the code idempotent? What happens on a retry after partial failure? + +**Security & safety** +- Is external input validated at the boundary? (Grok responses, plugin API payloads, webhook bodies) +- Are tokens and secrets handled correctly? (never logged, never in URLs, encrypted at rest) +- Can this change touch the live site unexpectedly? (deploys, migrations, plugin installs) +- Are expensive operations gated? (paid plugins, SEO-affecting URL changes — the no-surprise rule) + +**Domain modeling** +- Is the domain encoded in types, or scattered conditionals? +- Are states modeled as a state machine, not string comparisons? +- Would a new engineer understand the boundaries from the types alone? + +**Type discipline** +- Are external shapes validated at the boundary? +- Are illegal states unrepresentable? +- Are there `any` escapes or unvalidated casts? + +**The product bar** +- Does this serve the non-technical user? (no engineer-only UI leaks) +- Does it honor the chat-preview-approve loop? (no settings screens, no toggles, no diffs for the user) +- Is the change experienced as simpler, or more complex? + +### Step 3 — Rank findings + +- **Blocker** — incorrect behavior, security hole, live-site risk +- **Should fix** — violates a principle, missing test for changed behavior, race +- **Nit** — style, naming, tiny refactor + +### Step 4 — Write the review + +``` +## Verdict: [approve / request changes] +## Blockers +1. ... +## Should fix +2. ... +## Nits +3. ... +## What's good +- the state machine in [x.ts] is clean; the tests at [y.test.ts] prove the transition +``` \ No newline at end of file diff --git a/.agents/skills/wursor-tdd/SKILL.md b/.agents/skills/wursor-tdd/SKILL.md new file mode 100644 index 0000000..0e371e8 --- /dev/null +++ b/.agents/skills/wursor-tdd/SKILL.md @@ -0,0 +1,103 @@ +--- +name: wursor-tdd +description: "Write a failing test first, then implement, then verify. For any code change in api/ (Node.js + TypeScript), web/ (React + TypeScript), plugin/ (PHP), or infrastructure/ (Docker) that has a measurable test path. Adapted from pstack's /tdd skill." +--- + +# Wursor TDD + +Write the failing test first, then the implementation, then verify the test passes. This is the default workflow for any code change in this repository. + +## When to use + +Use this skill when: +- Fixing a bug with a measurable test path +- Building a new feature with unit-testable boundaries +- Adding a helper, utility, or pure function +- Refactoring where behavior should be preserved +- The task tells you the test path is cheap or fast + +Do **not** use this for: configuration-only changes, non-code documentation, or infrastructure scripts whose test would be a full e2e run. + +## Playbook + +### Step 1 — Understand what's being tested + +Read the relevant module. Understand the function signature, the inputs, the outputs, and the side effects. For `api/` modules, check the existing `__tests__/` or `tests/` directory for patterns. + +### Step 2 — Write the failing test + +One test per behavior. One assertion per test. + +```typescript +// Example for api/ modules +import { describe, it, expect } from 'vitest'; + +describe('SandboxMirror', () => { + it('fetches site info from the plugin API', async () => { + const mirror = new SandboxMirror('https://example.com', 'token'); + const info = await mirror.fetchSiteInfo(); + expect(info.theme).toBeDefined(); + expect(info.plugins).toBeInstanceOf(Array); + }); +}); +``` + +```php +// Example for plugin/ modules +class WursorAuthTest extends WP_UnitTestCase { + public function test_generates_six_character_code() { + $auth = new Wursor_Auth(); + $code = $auth->generate_pairing_code(); + $this->assertEquals(6, strlen($code)); + $this->assertMatchesRegularExpression('/^[A-Z0-9]{6}$/', $code); + } +} +``` + +### Step 3 — Run the test. It must fail. + +Do not proceed until the test runner confirms the test fails. A test that passes before implementation is a test that tests nothing. + +```bash +# api/ — vitest +pnpm test -- --grep "SandboxMirror" +# plugin/ — phpunit +phpunit --filter test_generates_six_character_code +``` + +### Step 4 — Implement the minimum code to pass + +Write the implementation. No more than what's needed to make the test pass. + +### Step 5 — Run the test. It must pass. + +Same command as step 3. The test must pass. + +### Step 6 — Refactor + +Clean up the implementation and the test. Remove debug code, rename unclear variables, extract helpers if they exist. The test should still pass. + +### Step 7 — Verify with the broader test suite + +Run the relevant test suite to make sure nothing is broken: + +```bash +# api/ +pnpm test:api +# web/ +pnpm test:web +# plugin/ +phpunit +``` + +### Step 8 — Report + +State what was tested, what the test proved, and what the broader suite showed. + +## Hard rules + +- No implementation code is written without a failing test. +- One test per behavior. One assertion per test. +- Tests are deterministic: no network calls in unit tests. Mock the Grok API, the plugin API, Docker, and the filesystem. +- The test must fail before the implementation. If it passes, the test is wrong. +- Coverage floor: api/ and web/ ≥ 90% line coverage. plugin/ ≥ 80%. \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..69cf8c5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,51 @@ +# Wursor — Agent Guide + +This repository is **Wursor**, the agentic WordPress management platform. Before starting any non-trivial task, read this file and follow the skill routing below. + +## The product, in one line + +Non-technical WordPress site owners describe what they want; Wursor makes it happen in a cloud sandbox, shows a live preview, and deploys on approval. The interface is chat → preview → approve. Nothing else. + +## Repo layout + +``` +api/ Node.js + TypeScript API server (session manager, agent orchestrator, + playbook runner, sandbox manager, deploy manager, plugin client) +web/ React + TypeScript frontend (chat, preview, approve/reject, deploy history) +plugin/ WordPress plugin (PHP) — the connector on the user's hosting +infrastructure/ Docker images, warm pool, GC, deploy scripts +e2e/ Playwright end-to-end tests +PRD.md Product requirements (v2.0 — non-technical-first) +IMPLEMENTATION.md TDD build guide with 8-sprint Phase 1 plan +``` + +## Skill routing — use the precheck first + +The `.agents/skills/` directory is a family of rigor skills modeled on Cursor's pstack. **The entry point for any non-trivial task is `wursor-precheck`** — it routes to the right playbook and sets the verification bar. + +| Task shape | Skill | +|---|---| +| Any non-trivial task — start here | `wursor-precheck` | +| How does X work / why was Y built this way | `wursor-investigation` | +| A defect — reproduce, root-cause, fix | `wursor-bug-fix` | +| New behavior, TDD-first from a data shape | `wursor-feature` | +| Review a diff / PR across lenses | `wursor-review` | +| Any code change with a test path | `wursor-tdd` | +| Capture a reviewable decision trail | `wursor-decision-log` | +| Structure, tradeoffs, verification standards | `wursor-principles` | + +## Hard rules + +1. **Tests first.** No implementation without a failing test (see `wursor-tdd`). Coverage floors: api/ + web/ ≥ 90%, plugin/ ≥ 80%. +2. **Prove it works.** A task is not done on self-report — run the test, start the sandbox, hit the endpoint. +3. **Non-technical-first.** The user never sees a diff, a terminal, a settings screen, or an error log. If a change would leak engineer-only UI into the product, it's wrong. +4. **Safety.** Never touch a live WordPress site, production credentials, or real user data from this repo. Sandboxes are the only environment code runs against. +5. **Decisions are logged.** Non-trivial choices get a decision-log entry (see `wursor-decision-log`). + +## Stack notes + +- Backend: Node.js + TypeScript, Express/Fastify, PostgreSQL (Wursor data), Redis (SSE/queue) +- Frontend: React + TypeScript, Vite +- Sandboxes: Docker on VPS, pre-baked WordPress image, overlayfs layers, media proxied (not copied) +- Plugin: standard WordPress PHP plugin, REST API + token auth +- Tests: vitest (api, web), phpunit (plugin), Playwright (e2e)