Idea → Done conductor (v0.9.29)¶
Working name for a platform capability whose home is https://ship.rafaelgonzalezalbes.com. Near-term priority: a status board (ideas → tickets → workflow step → deploy/live). End vision: also chat there to develop ideas, agree, create tasks, and dispatch workers. Plane / Forgejo / Woodpecker remain underneath.
Status: board MVP live on ship.* (human-test lane + test packs); staging TLS for testingN hardening in progress. Build order lean: board first, then chat/dispatch.
Doc version detail: v0.9.29 (borrow catalog: Testsigma skip + Shep ship-UI steal).
Audience: humans + coding agents (PM assist + delivery workers).
Related: Implementation Blueprint, Agreement template, Agent patterns to borrow, Ship normalized events (D19b dispatch contract), Team workflow, MCP overview, Platform overview, DNS, Secrets, Apps VPS, Metrics / Netdata, Monitoring / Kuma, Portfolio.
Living doc
Source of truth while we refine. Update when chat decisions change. We keep designing the workflow in chat; the board is the principal visibility tool.
Mental model — workflow + visibility¶
Workflow (keep designing now): discovery → review pack → agree → Plane → worker → CI → QA/review → testingN (you test) → (if feedback: micro-agree fix loop) → production → live verify → Done.
Visibility (principal near-term product): orchestrator status board — see initiatives, tickets, automatic workflow step, deployed/live. Helpful control tower; does not replace designing the workflow itself.
Later on the same subdomain: chat + create tasks + dispatch workers (full front door).
NOW (priority): ship.* board = see stage / deploy / live
MEANWHILE: refine workflow in Cursor / docs
LATER: chat + agree + dispatch workers on ship.*
UNDERNEATH: Plane + Forgejo + Woodpecker + deploy
| Role | Who / what | Job |
|---|---|---|
| You (PM) | Human | Develop ideas (chat today in Cursor; later on orchestrator), agree, watch board |
| AI co-pilot | Cursor now; orchestrator chat later | Help refine, draft agreement, propose tasks |
| Orchestrator board | ship.* MVP |
Principal UI now: epic radar + stage + deploy/live |
| Orchestrator chat/dispatch | Same host, later | Front door for ideas + start workers |
| Plane | pm.* |
Ticket SoR |
| Workers | Coding agents | Implement after dispatch |
| Forgejo / Woodpecker | git / ci | PR + pipeline |
Goal¶
- Keep designing the workflow (discovery → agree → tickets → workers → live Done).
- Principal near-term UI: orchestrator status board — see ideas, tickets, workflow step, deploy/live.
- Each ticket reaches Done only when live-tested and working.
- Daily token budget bounds autonomous loops.
- Later on the same host: chat + create tasks + start workers.
Stages¶
flowchart TD
Open[Open orchestrator] --> Discover[0 Discovery chat]
Discover --> Tasks[1 Recognize 1+ tasks]
Tasks --> Package[2 Agreement package]
Package --> Agree[3 Agreement gate]
Agree --> Plane[4 Create Plane tickets]
Plane --> Dispatch[5 Dispatch workers]
Dispatch --> Execute[6 Execute / PR]
Execute --> CI[7 CI]
CI -->|red| Fix[Fix + budget]
Fix --> CI
CI -->|green| Preview[8 Preview / UX]
Preview --> Ship[9 Ship]
Ship --> Live[10 Live verify]
Live -->|pass| TicketDone[11 Ticket Done]
TicketDone --> Dispatch
Dispatch -->|all done| Report[12 Initiative report]
| # | Stage | Where |
|---|---|---|
| 0–3 | Discovery → agreement | Orchestrator chat |
| 4 | Create tickets | Orchestrator writes Plane |
| 5 | Dispatch workers | Orchestrator queues / starts workers |
| 6–11 | Build → live Done | Workers + Forgejo + Woodpecker; status on orchestrator |
| 12 | Initiative report | Orchestrator |
Orchestrator product (D18 / D18b / D19 / D20)¶
Priority (D20 — locked)¶
| Phase | What | Why |
|---|---|---|
| 1 — Board (principal now) | Ideas/epics, tickets, workflow step, deployed/live | Helpful tool to see the automatic workflow |
| 2 — Workflow automation | Agree → Plane → workers → CI → live (keep designing) | The actual delivery engine |
| 3 — Chat + dispatch on site | Open orchestrator, talk, create tasks, start workers | Full front door (end vision) |
Board is not the whole product — it is the most important visibility tool for now while we continue defining the workflow.
Surfaces on ship.*¶
| Surface | Priority | Purpose |
|---|---|---|
| Status board | MVP first | Ideas, tickets, stage, deploy/live, waiting_on, cost/spend, ready-to-merge later |
| Wallet | With board | Daily/monthly $ vs cap (H31); price catalog freshness |
| Chat | Later | Develop ideas on-site (PM + AI) |
| Task create | Later | After agree, write Plane + queue |
| Workers | Later | Dispatch / pause / budget / resource wait |
| Controls | Later | Freeze (H14), away (H21), ship windows (H24), park (H36) |
ship.* board (MVP)
├── Idea: Improve Idea→Done docs delivery · waiting_on: resources_apps
│ ├── T1 content live verify ✓ deployed ✓
│ └── T2 nav waiting · apps VPS RAM high — deploy paused
└── Idea: Portfolio CTA discovery / agreement
Stage labels: discovery | agreement | queued | execute | ci | preview | ship | live_verify | done | blocked_budget | waiting (with reason — see D26).
Plane vs ship board¶
| Need | Plane (pm.*) |
Ship board (ship.*) |
|---|---|---|
| Issue SoR | Yes | Reads / links |
| See automatic workflow step | No | Yes (MVP) |
| Deploy / live | Manual | Yes (MVP) |
| Chat / dispatch | No | Later on same host |
Hosting (D18b / D18e — locked)¶
| Choice | Decision |
|---|---|
| URL | https://ship.rafaelgonzalezalbes.com |
| Why | Subdomain of your existing domain → no extra domain cost (only DNS A record + Traefik) |
| Not for now | Buying a separate name like shipfast.com / .app — costs money; revisit only if you want a public brand later |
| VPS | Infra 85.215.32.166 + Traefik TLS |
| DNS (when we build) | IONOS A ship → 85.215.32.166 |
| Auth | Team-only (D18d) |
Product nickname can stay “orchestrator / Idea→Done”; the host is ship.*.
Delivery playbook (workflow) — v0.9.2¶
Discovery stays human+AI chat. Agree and post-agree gates keep growing as we learn (D22). Board only shows stages.
Before agree (mandatory review pack)¶
You must be shown, clearly (chat now; later orchestrator UI):
- Concept — what we are building (goal, out of scope, what “done” looks like). Visual/summary of the idea.
- Ticket list — every ticket that will be created, with the full information inside each (title, acceptance, repo/surface, UX?, checks).
- Order — T1 → T2 → …
- Cost band (H13 / D27) — rough less / mid / more LLM cost for this idea across the connections we will use; you pick a band (or raise later if stuck)
- Time band (H17) — rough soon / days / longer calendar effort next to cost
- Blast radius (H30) — primary: docs | app | infra | secrets
- Dependencies (H29) — which tickets wait on which (if more than sequential default)
Agree = you confirm the concept + those exact tickets + cost/time bands + blast, and you want the initiative developed until the end (through live Done).
(Or park the review pack without Plane — H36.)
Then → create those Plane tickets immediately (W1). No second confirm.
Per-ticket path (after Plane)¶
| Stage | Actor | Does | Exit when |
|---|---|---|---|
| 4 Create Plane | Conductor | Create tickets as in the review pack | Ids exist |
| 5 Dispatch | Conductor | Start coding worker on next ticket (not deploy) | Worker started |
| 6 Execute | Worker | Branch + implement + Forgejo PR | PR open |
| 7 CI | Woodpecker + worker | Green; fix red within budget | CI green |
| 7b QA + review | Auto QA + code reviewers | QA + review; work matches agreed idea/tickets | Pass |
| 8 Test deploy | CI / conductor | Claim a testingN slot; deploy what the ticket needs; send you the link (and notes if infra/secrets) | Slot claimed + ready |
| 8b Human test | You | You test on that slot (URL and/or checklist for infra) | You approve |
| 8c Ready to merge | Conductor | Ticket appears on ready-to-merge list (chat now / board later); release testing slot when done | Listed |
| 9 Ship (production) | You authorize → worker executes | You pick from list or press board button → merge + prod deploy | Prod up |
| 10 Live verify | Checks | Production matches agreement | Pass |
| 11 Ticket Done | Conductor | Plane Done | Closed |
| 12 Initiative | Conductor | All tickets Done → report | Complete |
Sequencing (v1)¶
- One active ticket at a time per initiative.
- Next ticket only after previous Done (or you skip).
- You can pause anytime.
- No production before your test on a testingN slot (or approved infra checklist).
- No Done without production live verify.
W3 / W4 / W5 explained¶
| # | Meaning | Status |
|---|---|---|
| W3 | Docs on production: auto check vs human read | Locked — see below |
| W4 | Dispatch = start coding worker (not deploy). Manual “work T1” now; auto-dispatch later | Locked — see Workers + secrets |
| W5 | One idea across multiple repos? | Locked — single-repo now; multi-repo later |
W3 — docs verify (locked)¶
Two different things:
| Layer | Who | Purpose |
|---|---|---|
| Auto check / auto QA | Worker / CI | Formal checks for the ticket/task (page loads, expected text/section present, link OK). Needed so the ticket can pass live verify. |
| Human read | You | You also open docs sometimes to get an idea / sanity-check. Not every glance is a hard gate; it is normal PM practice and can block Done if you say something is wrong. |
So: A + B — auto QA owns ticket evidence; you still read docs when useful.
Locked this round¶
| # | Decision |
|---|---|
| W1 | Review pack (concept + full tickets) before agree; agree = confirm all → Plane immediate |
| W2 | Before prod: auto QA + code review + idea match → test subdomain + you test link → then production |
| W2b | Merge human-gated: system builds ready-to-merge list; you pick; later orchestrator board button; not silent auto-merge |
| W3 | Docs: auto QA for the ticket; you also read docs when you want context / can reject if wrong |
| W4 | Manual “work T1” now; auto-dispatch is the goal |
| W5 | v1: one idea → one repo (keep it easy); later: multi-repo initiatives allowed |
| D22 | Agree/QA conditions grow as we discover more rules |
| D23 | Testing slots required (not built yet) — see D23b |
| D23b | Slots = testing1 / testing2 / testing3 on existing domain (shared; claim/release) |
| D24 | Worker roles per step; concurrency 1 |
Testing slots (D23b / D23c — locked)¶
Not per-app names (test-docs.*). Shared disposable slots on the same domain (no extra domain cost):
| Slot | URL (when built) |
|---|---|
| testing1 | https://testing1.rafaelgonzalezalbes.com |
| testing2 | https://testing2.rafaelgonzalezalbes.com |
| testing3 | https://testing3.rafaelgonzalezalbes.com |
D23c — slots are swappable hosts (the point):
Each testingN is an empty bay, not “the portfolio host forever.” On claim, the ticket says what to mount (portfolio, WearLab, docs, a small infra preview, …). Traefik points that hostname at that deploy. On release, wipe the bay (containers/files/staging env for that slot) so the next ticket can put something else there.
| Rule | Detail |
|---|---|
| One claim per slot | Board shows ticket + what app is mounted now |
| Swap freely | Same testing1 can be portfolio today, WearLab tomorrow |
| Scope v1 apps | Prefer devops-related + portfolio first; WearLab allowed when needed |
| Wipe on release | No leftover app or staging secrets for the next claim |
| Ship vs testing | ship.* = control tower; testingN.* = try changes |
D23g — which VPS (locked):
| Piece | Where | Why |
|---|---|---|
| Ship (board, later chat/dispatch, secrets broker control) | Infra VPS (85.215.32.166) |
Same home as Forgejo / Woodpecker / platform |
testing1–testing3 deploys (containers, Traefik routes for those hostnames) |
Apps VPS (82.165.177.110) |
App runtime; swap portfolio / WearLab / whatever there |
| Wipe / reset for a slot | Script on Apps VPS (triggered from ship/CI on infra) | Clears that bay only |
| DNS | IONOS: ship → infra; testing1/2/3 → apps |
Infra VPS does not host the testing app containers. Ship orchestrates; apps VPS runs the test bays.
How you approve a ticket (D23d)¶
| Situation | Auto / worker tests | You still |
|---|---|---|
| App / UI / docs | Worker runs Docker tests (unit/e2e/smoke) locally and/or against testingN |
Open URL, sanity check, OK |
| Infra with a reachable service on slot | Smoke (HTTP/health) + Docker where it fits | Spot-check URL if useful |
| Infra with no page (DNS, WP secret, SOPS-only, …) | Auto checks where possible (dry-run script, dig, secret name present, compose config validate, …) |
Short checklist sign-off for now |
Human checklist stays for no-page infra for now. Add automation wherever it is possible — workers (coder / qa / test-deploy) should run their own tests in Docker (compose test profile, docker run test image, CI step) before asking you. You are the last gate, not the only test.
Never surprise-prod.
Human Staging Test Gate — Fix & Feedback Loop (D23f — locked)¶
When testing on a testingN slot reveals minor bugs, UI alignment issues, or necessary tweaks (in-scope adjustments without requiring a new Plane ticket), the workflow uses a Micro-Agreement Pack to ensure alignment before burning tokens:
flowchart TD
Staging[Testing on testingN slot] --> Feedback[1 You submit feedback & notes/evidence]
Feedback --> Pack[2 System generates Micro-Agreement Pack]
Pack --> Gate[3 Fast Human Approval Gate]
Gate -->|Approved| Worker[4 Worker applies fix on branch + runs CI]
Gate -->|Major Scope Change| ReAgree[Escalate to H16 Re-Agree]
Worker --> Deploy[5 Redeploy to SAME testingN slot]
Deploy --> ReTest[6 Updated notification + UX evidence to you]
ReTest --> Staging
| Step | Phase | Action |
|---|---|---|
| 1 | Feedback Submission | You test testingN and submit feedback (chat, board comment, or screenshot evidence). Ticket stage moves to feedback_received. |
| 2 | Micro-Agreement Pack | AI co-pilot analyzes feedback and outputs a mini-proposal: Root Cause, Proposed Fix Plan (1–3 technical points), Scope Check (in-scope), and Retry Budget Delta (e.g. Attempt 1 of 3). |
| 3 | Fast Human Approval | You review and approve the micro-pack (or refine/escalate to H16 Re-Agree if it turns into a major scope change). |
| 4 | Worker Execution & CI | worker-execute applies code changes on the existing feature branch (ship/<initiative>/T<n>-<short>) → Oxlint/tests → Woodpecker CI. |
| 5 | Staging Redeploy | worker-test-deploy redeploys to the same active testingN slot (no slot re-claiming or wipe needed). Kuma verifies HTTP 200. |
| 6 | Updated Re-Test | System sends a single ping: "Fix applied to testing1 — ready for re-testing" with updated UX evidence (H28). |
Key rules for fix loops:
- Retry budget cap (H7): Maximum 3 fix attempts per ticket. If still failing after 3 attempts → waiting_on: budget / escalate to human.
- No new ticket required: Minor fixes stay on the active ticket & branch.
- Slot retention: Staging slot is retained during the fix loop (no extra claim/release churn).
Change classes (UX vs infra vs secrets)¶
| Class | Examples | Gate before prod |
|---|---|---|
| UX / app | Portfolio, WearLab, docs | Docker tests + testingN URL (D23d) |
| Infra | Traefik, compose, agent, DNS | Auto checks + URL or checklist (D23d) |
| Secrets | New API key, DB password | Staging inject on apps slot (D25c); prod via SOPS after you authorize |
Plain answers (D25b / D25d — were confusing)¶
“Exact SOPS filenames” only meant: which encrypted file under secrets/ will hold which keys? Not a new product. Locked lean names:
| File (when we create it) | Holds |
|---|---|
secrets/ship-workers.enc.env |
LLM / agent keys + tokens ship/workers need (Plane A) |
Existing secrets/*.enc.env + Woodpecker |
Real prod platform/app secrets (unchanged) |
| (no long-lived file) | Staging passwords for testingN — generated into tmpfs on apps VPS on claim, wiped on release (D25c) |
“Reveal UX” only meant: how do you learn the temporary staging password to log into testing1 without putting it in Plane or chat?
| Phase | How you get the staging password |
|---|---|
| Later (ship built) | Logged into ship.*, button like “show staging login for this slot” — shown once to you, not stored in tickets |
| Now (no ship UI yet) | Avoid random passwords when possible (fixed known staging test user in your password manager, not in git); or broker prints to a private channel you control — never Plane/PR/Discord public |
Still open¶
| # | Question |
|---|---|
| D23h | Concrete wipe script + Traefik labels for testingN on apps VPS (implement when building) |
| D10b | Exact daily token / CI-fix budget numbers |
| D19b | Worker runtime (Cursor / headless / CI / mix) for auto-dispatch — later compare Reasonix CLI, Kilo CLI, Microsoft Agent Framework (Python/.NET; steal HITL/handoff/checkpoint — borrow §8) |
Merge gate (W2b)¶
After testing-slot OK (and QA/review passed), tickets enter ready to merge — they do not merge by themselves.
| Phase | How |
|---|---|
| Now | You ask (e.g. “which tickets are ready to merge?”) → agent gives a list with details → you say which to merge (or none) → agent merges those |
| Later | Same list on ship board (ship.*) with a Merge (or approve) button per ticket / bulk |
Worker may prepare the merge (PR green, checks done) but you authorize merge via list or button.
Example¶
Discovery → review pack (concept + tickets)
→ you: agree
→ Plane created
→ “work T1” (dispatch coder)
→ PR + CI green
→ auto QA + code review + idea match
→ claim testingN → deploy / checklist → you test → you OK → release slot
→ ready-to-merge list → you authorize → production → live verify → Done
Discovery norms (PM assist)¶
- Prefer questions/options over jumping to code.
- Propose a task list when work emerges.
- Before agree: concept + full ticket contents (review pack).
- Wait for agree before Plane + workers.
- Status: mode + one next action.
- Expect more agree/QA conditions over time (D22).
Workers (D19 / D24)¶
Workers are the agents that perform delivery steps after tickets exist. Humans (you) still own agree and test-subdomain approval.
Fleet size (now)¶
| Setting | v1 |
|---|---|
| Concurrent workers | 1 |
| Why | Start small; watch behavior, cost, quality; grow slowly |
| Tickets in flight | 1 (matches D15) |
| Scale later | Raise concurrency only after we see what happens |
Until the orchestrator exists, that single worker is usually a Cursor agent session you start with “work T1”.
One worker role per step¶
We define a worker type for each delivery step. With fleet size 1, the same running worker acts as each role in order (puts on the next hat). Later we can run specialized workers in parallel.
| Worker id | Step | Responsibility |
|---|---|---|
worker-plane |
4 Create Plane | Create/update Plane tickets from the review pack |
worker-dispatch |
5 Dispatch | Claim next ticket; hand off to execute (or schedule) |
worker-execute |
6 Execute | Branch, implement, open Forgejo PR |
worker-ci |
7 CI | Watch Woodpecker; fix red within budget |
worker-qa |
7b QA + review | Run auto QA + request/apply code review; check idea match |
worker-test-deploy |
8 Test deploy | Claim testingN; deploy or prepare infra checklist; publish link/notes to you |
| (human) | 8b Human test | You test the slot (URL and/or checklist) — not a worker |
worker-ship |
9 Ship | Production merge/deploy after your OK |
worker-live |
10 Live verify | Run production checks from agreement |
worker-close |
11–12 Done | Plane Done + initiative report when all tickets finished |
Board should eventually show: active worker + role + ticket + step + waiting_on (even when only one worker exists).
Waiting on / server status (D26 — locked direction)¶
Workers must be smart about host health before starting heavy work (deploy, docker compose up, big builds). If the apps or infra VPS is already hot, starting more containers can take everything down.
Rule: before deploy/Docker/CI-trigger that hits a VPS, check server status. If not OK → wait (or fail closed), set waiting_on, do not thrash retries.
waiting_on |
Meaning |
|---|---|
human_agree |
Need your agree |
human_test |
Need your test on testingN / checklist |
human_merge |
Ready-to-merge; need your authorize |
slot_busy |
All testingN claimed |
ci |
Woodpecker still running / red |
budget |
Token or CI-fix budget exhausted |
secrets |
Broker/vault missing for this role |
resources_apps |
Apps VPS CPU/RAM/disk/load too high — do not deploy/docker yet |
resources_infra |
Infra VPS pressure — pause platform-heavy steps |
dependency |
Previous ticket / step not Done |
Signals (reuse what we have):
| Source | Use |
|---|---|
| Netdata (metrics) | CPU, RAM, disk, load on infra + apps |
| Uptime Kuma (monitoring) | Host/service up/down |
| Ship board (later) | Show ticket stage + why it’s waiting in plain text |
| Docker on target | docker info / disk before pull; refuse if disk critical |
Thresholds (v1 lean — tune later as D26b): e.g. don’t start a new slot deploy if apps RAM > ~85% or disk < ~15% free or 5‑min load absurdly high. Exact numbers TBD when building.
Worker behavior:
- Read status → if
resources_*, set stagewaiting+ reason; backoff; ping board/you. - When pressure drops, resume same step (no silent parallel second deploy).
- Coder may still write code locally while waiting on
resources_appsfor deploy — but must not push a deploy that piles on. - Board MVP should surface waiting reason as a first-class column (status board priority).
Rules¶
- Only 1 worker runs at a time (v1).
- That worker walks one ticket through steps 6→11 (plane/dispatch may be conductor/orchestrator).
- Do not start step N+1 until step N exit criteria pass (or human override).
- Human steps (agree, 8b test) never get auto-skipped.
- When we add worker #2, decide: second ticket in parallel vs specialized parallel roles (D17 / D24b).
- Never start deploy/Docker on a VPS that is resource-blocked (D26).
Runtime + auto-dispatch (D19b / D25)¶
| Phase | How a coding worker starts |
|---|---|
| Now | Ship board Work T1 / Dispatch enqueues a job; docker ship-worker claims it. With OpenRouter key → codes inside allowed_paths (D27c mid band); else briefing-only. Optional .woodpecker/ship-worker.yml |
| Target | Cursor Agent SDK session spawn + auto PR push when you enable write tokens |
Automatic start still respects: agree already done, fleet size 1, budget not exhausted, human gates (8b test) unchanged.
Event contract (D19b): When auto-dispatch routing lands, normalize Plane / Forgejo / Woodpecker signals into one vocabulary — ship-normalized-events.md (borrowed from Fullsend NormalizedEvent; no CEL engine yet).
API keys & secrets for workers (D25 — staging broker shipped; Plane A SOPS still later)¶
Workers that call LLMs, Plane, Forgejo, Woodpecker, etc. need credentials. Align with existing platform secrets (secrets): encrypted at rest, no long-lived plain files in git, least privilege.
Tickets and different worker roles must share a secure path without putting secret values in Plane, chat, or git. Model = capability refs in tickets + secrets broker + role allowlists.
Two planes (do not mix)¶
| Plane | What | Where values live |
|---|---|---|
| A — Worker platform | LLM keys, Plane/Forgejo/WP tokens the agent needs to run | SOPS / ship runtime / Woodpecker (D25) |
| B — Ticket / app target | Passwords, API keys, DB creds the change under test needs | Staging vault for testingN; prod only in existing SOPS / Woodpecker after you authorize ship |
Tickets never hold values¶
In review pack / Plane ticket body, only capability refs, e.g.:
needs_secrets: [STAGING_DB_URL, STAGING_API_TOKEN]secret_class: staging | prod-applyinject_at: testingN | woodpecker-ci | prod-runtime
Never: passwords, tokens, .env dumps, age private keys.
Secrets broker (Ship + slot-manager — staging path live)¶
A small broker (scripts + runtime today; ship service later) is the only component that decrypts and injects:
- Ticket/worker asks by name + role + slot (e.g.
testing2). - Broker checks role allowlist + ticket claim on that slot.
- Broker loads from the right vault (staging vs prod).
- Injects into tmpfs / process env / compose env for that step — not into Plane or chat.
- Worker sees env vars in the target process, or gets a short-lived handle; it must not echo values into logs, PRs, or Discord.
- Audit log:
role+secret_name+ticket+slot+ timestamp — never the value.
Staging inject into testingN (D25c — locked direction)¶
Goal: the app process on the slot gets staging env; workers and Plane never see raw values in messages.
Preferred path (most secure lean option):
- On claim, broker creates a slot-scoped staging bundle (generate random passwords or copy from a staging SOPS blob — never from prod).
- Writes values only to tmpfs on the Apps VPS (where
testingNruns), e.g./run/testing-slots/testing1.env(mode600, deploy user only). - Compose / Traefik on apps for that slot uses
env_file:pointing at that tmpfs path (or Docker secrets). - Worker (
worker-test-deploy) triggers deploy from ship/CI — it does notcatthe file into chat. - You learn staging login via D25d (ship “show password” later; password manager / private path now) — never Plane.
- On release: delete tmpfs file on apps, tear down that bay’s containers, revoke generated tokens.
Avoid (weaker):
- Pasting secrets into Woodpecker UI by hand for every ticket (error-prone; still better than chat).
- Putting staging values in the repo “encrypted later.”
- Reusing prod passwords on
testingN.
Workers: LLM workers get Plane A keys only. They never need Plane B staging file contents to write code (code uses process.env.X names). Only deploy/broker touches the file.
Role allowlist (v1 — fleet size 1, hats change)¶
Same running session switches role; broker still enforces which hat may touch which class:
| Role | May use (Plane A) | May request inject (Plane B) |
|---|---|---|
worker-execute |
LLM + Forgejo/Plane read-write as needed to code | No prod. Staging names only if needed to write config references |
worker-ci |
WP status; no LLM required | CI may receive staging inject via Woodpecker secrets for that pipeline |
worker-qa |
LLM + read URLs | Read-only checks; no secret values in reports |
worker-test-deploy |
Deploy path to testingN |
Staging vault → testingN inject (primary for D25c) |
worker-ship |
Merge + prod deploy trigger | Prod apply only after your merge/ship authorize (W2b); broker uses prod SOPS/WP |
worker-live / worker-close |
Read checks / Plane Done | No secret write |
| Human (you) | Ship UI / local age key for sops edit |
Approve prod apply; rotate keys |
With concurrency 1, only one role is active → only one allowlist applies at a time. When worker #2 exists (D24b), broker still scopes by role + ticket + slot.
Staging vs prod flow (secrets tickets)¶
Agree (ticket lists secret *names* only)
→ execute: code expects ENV names; no values in repo
→ test-deploy: broker generates or loads STAGING_* → inject testingN
→ you test slot (login with staging password you were given out-of-band
or via a one-time ship “reveal for slot” — never posted to Plane)
→ you authorize merge
→ ship: broker / CI applies PROD_* from SOPS/WP (separate values)
→ live verify → Done
→ release testingN; wipe staging inject for that slot (D23c)
Security rules (locked direction)¶
- No plain API keys / passwords in git, chat, Plane, PR bodies, Discord.
- Decrypt only into tmpfs / process env (same idea as
/run/infra-secrets). - Staging ≠ prod — different values always; testing slots never get prod passwords.
- Least privilege per role — execute cannot prod-apply; ship cannot run until you authorize.
- Fail closed — missing vault / wrong role → stop; ping human.
- Audit names only on ship board.
- Cursor-manual phase: your local Cursor keys stay local; do not copy into the repo “for later.”
- Prefer Woodpecker for prod deploy secrets already in use; workers trigger pipelines instead of holding full SSH when possible.
Secret classes (storage sketch)¶
| Secret class | Examples | Intended home (lean) |
|---|---|---|
| LLM / agent provider | OpenAI, Anthropic, OpenRouter, … | secrets/ship-workers.enc.env (D25b) — never plain in git |
| Plane / Forgejo / Woodpecker tokens | API tokens for ticket/PR/CI | Scoped tokens; MCP/bridge patterns where possible |
| Staging app secrets | DB/API for testingN |
Generated → tmpfs on apps VPS; wiped on release |
| Prod app / platform | Real passwords | Existing secrets/*.enc.env + Woodpecker — apply only on ship |
| Deploy / SSH / SFTP | CI deploy | Woodpecker repo secrets; avoid giving workers full prod SSH |
| Ship session | User auth to ship.* |
Separate from provider keys (D18d) |
Still open under D25: optional daily “allow auto-dispatch” gate only.
Agreement / preview / budgets¶
- Template: idea-to-done-agreement.template.md
- Preview / test:
testing1–testing3slots for human QA before production (D23b); local preview may still help workers. - Budget: daily tokens + ~3 CI fixes per ticket (D10b numbers TBD).
- Cost bands (D27 / H13): before agree, show rough more / mid / less LLM cost for the idea using the connections we will have (local cheap → mid API → strong API). Track spend during delivery against the chosen band.
- Wallet (D27c / H31): soft target ~€30/month across all ideas; hard caps via prepaid / workspace / OpenRouter guardrails; Cursor spend is separate.
Design principles¶
- Board first for visibility — see stages while we finish the workflow design.
- Workflow: review pack → agree → tickets → worker → CI → QA/review → testingN (you) → prod → live Done.
- Spine underneath = Plane + Forgejo + Woodpecker + VPS/IONOS.
- Human agree (concept + tickets) before Plane + workers.
- Done = live-tested on production per ticket.
- Budget-bounded autonomy.
- Agree/QA rules grow over time (D22).
- Chat/dispatch on orchestrator is end-state, not blocking board MVP.
- Steal patterns, not products — see agent-patterns-borrow.md (D38).
Scope v1¶
infra/devops + portfolio, one idea → one repo for now. Cross-repo work = separate ideas until multi-repo (W5 later) is enabled.
Non-goals¶
Board does not replace Plane; chat/dispatch can wait; no Done without live verify; orchestrator is not public.
Implementation sketch¶
Design workflow in Cursor (ongoing)
→ later: orchestrator board shows stages (MVP)
→ later: chat + agree + Plane + dispatch workers on same host
→ per ticket: PR → CI → preview → deploy → live verify → Done
Decisions locked¶
| # | Decision |
|---|---|
| D1 | Chat-first; Plane after agree |
| D1b | PM discovery; AI co-pilot; 1+ tasks |
| D2 | CI + preview/UX + live verify |
| D3 | Scope v1 = devops + portfolio |
| D4 | Done = live-tested per ticket |
| D5 | Auto-fix + daily token budget |
| D8 | Markdown agreement → Plane |
| D9 | Preview matrix as before |
| D10 | Budget shape as before |
| D15 | Sequential tickets in v1 |
| D18 | Idea→Done / orchestrator UI |
| D18b | Own subdomain on infra VPS |
| D18e | Host = ship.rafaelgonzalezalbes.com (free subdomain; no paid shipfast domain for now) |
| D19 | End vision: chat + create tasks + start workers on ship |
| D20 | Board/status principal near-term |
| D21 | Delivery playbook exists |
| D22 | Agree/QA conditions grow over time |
| D23 | Testing slots before production; you test (URL and/or checklist) |
| D23b | Slots = testing1–testing3.rafaelgonzalezalbes.com (claim/release; not per-app names) |
| D23c | Slots are swappable bays — mount portfolio / WearLab / docs / preview as the ticket needs; wipe on release |
| D23d | URL and/or checklist for you; plus auto/Docker tests by workers wherever possible |
| D23e | Tickets may be UX, infra, or secrets; staging secrets only on slots; prod secrets via SOPS (D25) |
| D23f | Staging test feedback loop: Micro-Agreement Pack (diagnosis, 1-3 fix points, scope check, retry delta) before code fix |
| D23g | Ship on infra VPS; testingN containers on apps VPS; wipe on apps; DNS accordingly |
| W1 | Agree confirms concept + ticket list → Plane immediate |
| W2 | QA + code review + idea match → testingN → you test → then prod |
| W2b | Merge via ready-to-merge list (chat now) / ship board button later; you choose; worker executes |
| W3 | Docs: auto QA for ticket; human also reads when useful / can reject |
| W4 | Dispatch = start coding worker; manual “work T1” now; auto-dispatch is the goal |
| W5 | v1: one idea → one repo; multi-repo later |
| D24 | Worker roles per step; fleet concurrency = 1 for now; grow slowly |
| D25 | Secrets: broker + capability refs in tickets; no values in Plane/chat/git; SOPS/runtime; least privilege; fail closed |
| D25b | Worker LLM/platform keys → secrets/ship-workers.enc.env; staging → tmpfs on apps (not a permanent SOPS file) |
| D25c | Staging inject = tmpfs env_file per slot on apps VPS; wipe on release; workers don’t print values |
| D25d | Staging password to you: ship “show for slot” later; until then password manager / private path — never Plane |
| D25f | Role allowlist for secret access; staging inject = worker-test-deploy; prod apply = worker-ship only after you authorize |
| D26 | Workers check server status before deploy/Docker; board shows waiting_on (incl. resources_apps / resources_infra); wait don’t thrash |
| D27 | LLM cost bands in review pack: less / mid / more across connections; track spend; over band → budget wait or raise |
| D27c | FinOps: ~€30 soft wallet, hard caps (prepaid/guardrails), provider matrix, Cursor ≠ worker keys |
| D27d | Price catalog + refresh (OpenRouter models API + manual rows); stale warning; “as of” on estimates |
| D27c | v1 FinOps stack: ~€30 soft wallet; €0 idle accounts; OpenRouter + Anthropic cap + OpenAI prepaid (no auto-top-up); Groq/Gemini mid; Ollama less; Cursor ≠ worker keys; no free-tier for private code; defer Azure/APIM/Bedrock PT/Vertex aux |
| H1–H13 | Hardening backlog locked (state, slots, DoD, stuck, rollback, artifacts, retries, context, pause, gates, report, dry-run, cost) |
| H14–H20 | Next ideas locked: kill/freeze, conflict guard, re-agree, time band, learn-from-Done, Kuma on slots, playbooks |
| H21–H28 | Day-2 locked: away, shadow, branches, ship windows, viewer role, incident pause, digest, UX evidence |
| H29–H36 | Planning/resilience locked: deps, blast-radius, wallet, failover, migration gate, external wait, soak, parking |
Hardening backlog — make it finish end-to-end (locked direction)¶
H1–H12 are accepted for the product (implement over time). Prefer stack we already have (Plane, Forgejo, Woodpecker, Netdata, Kuma, SOPS). H13–H36 add cost/time, safety, learning, day-2 ops, and planning controls.
Must-have for a real dry-run (do first)¶
| # | Idea | Why it unblocks “until the end” | Status |
|---|---|---|---|
| H1 | Machine-readable ticket state | Shared stage + waiting_on + slot + PR URL |
Shipped — Ship SQLite + board |
| H2 | Idempotent claim / release / wipe for testingN |
Scripts on apps VPS | Shipped — slot-manager + Ship remote-slot; wipe leaves warm whoami; warm all for idle HTTPS |
| H2b | Staging auto-tenant isolation | Ephemeral storage clear headers & session isolation per slot run | Partial — Clear-Site-Data on slots |
| H2c | Idle slot reclamation | Auto-snapshot build and release staging slot if idle > 24h | Partial — reclaim script + local/install-apps-reclaim-cron.sh |
| H3 | Definition of Done per ticket type | UX / docs / infra / secrets verify lists | Shipped — board Apply DoD |
| H4 | Stuck detector + escalation | Long wait → Discord #infra / ship |
Shipped — stuck strip + optional webhook |
| H5 | Rollback after ship | Undo last prod change | Shipped — previous_revision saved on ship; H9c auto-soak detects 5xx and triggers rollback receipt + notify |
| H6 | Artifact pack per step | Receipts for next role | Shipped — receipts timeline |
| H7 | Retry policy with budget | Flake vs real; stop infinite loops | Shipped — retry budget on board |
| H7c | DefectDojo false positive triage | Auto-submit triage for Gitleaks/Trivy findings to DefectDojo | Locked |
| H7d | Flake isolator | Zero-token retries for network/socket timeouts vs AI code fixes | Script exists — not in Ship loop yet |
| H8 | Context pack on dispatch | Briefing before “work T1” | Shipped — pack API + Work T1 |
| H8b | Automated base rebase & drift protection | Auto-rebase branch on main before PR/deploy; conflict resolution plan | Partial — rebase plan receipt only |
| H8c | Smart Graphify warm-up | Pre-load local ai-context graph on dispatch for instant imports context | Partial — pack commands + ship-work-t1.mjs |
| H9 | Pause / cancel / resume | Stop without orphan containers | Shipped — board (cancel wipes slot) |
| H9b | Pre-flight health gate | Validate compose config & VPS RAM headroom via Netdata before deploy | Shipped — Ship staging_deploy calls Apps preflight |
| H9c | Instant auto-rollback on 5xx | Ship probes live URL post-ship (3 min soak, 30s intervals); auto-rollback on 2 consecutive 5xx; auto-Done on pass | Shipped — soak scanner, auto-rollback receipt, notify, auto-Done |
| H10 | Notify only on gates | Ping when you must act | Shipped — gate webhooks + install-ship-discord-webhook.sh |
| H11 | Post-Done report | Close initiative with a receipt | Locked |
| H12 | Golden-path dry-run | Tiny docs idea before ship UI | Shipped — INFRA-101 |
| H13 | LLM cost bands (more / less) | Estimate + track spend per idea across model connections | Partial — bands on initiatives; wallet strip soft |
| H14 | Global kill / freeze | One switch stops all workers + optional wipe in-flight slots | Partial — freeze blocks actions (no auto wipe-all) |
| H15 | Path conflict guard | Block two ideas editing the same files/repos at once | Shipped — dispatch conflict + override |
| H16 | Re-agree on scope change | Mid-flight goal change → new review pack, not silent drift | Locked |
| H17 | Time band next to cost | Rough calendar time (hours/days) alongside $ bands | Locked |
| H18 | Learn from Done | After H11 report, suggest new agree/QA rules (D22) | Locked |
| H18b | Post-mortem debt collector | Scan commits post-Done for temporary TODOs/patches for next backlog | Locked |
| H19 | Kuma watch while slot claimed | Auto uptime check on testingN URL for the claim |
Locked |
| H20 | Idea playbooks / templates | Starter packs by type (docs, portfolio, WearLab, infra) | Locked |
| H21 | Away / AFK mode | Defer human-gate pings; queue until you’re back | Partial — board Away suppresses needs-you strip |
| H22 | Shadow / plan-only run | Worker plans + DoD check without writing git/deploy | Partial — Shadow plan on board |
| H23 | Branch & worktree naming | Predictable ship/… branches; easy cleanup |
Locked |
| H24 | Ship windows | Optional “no prod ship” hours/days unless you override | Locked |
| H25 | Teammate read board | Alex (etc.) can see status; cannot agree/merge/freeze | Locked |
| H26 | Incident auto-pause | Critical Kuma/Netdata → pause related ideas | Locked |
| H27 | Weekly ship digest | What finished / blocked this week (not spam) | Locked |
| H28 | UX evidence pack | Screenshots / short clip for human test gate | Shipped — board/API upload for ux/app @ human_test/staging_test; receipt + /evidence/… (no secrets) |
| H29 | Ticket dependency graph | Explicit waits (T2 after T1); visible on board | Locked |
| H30 | Blast-radius label | docs / app / infra / secrets → care level for ship | Partial — on initiatives / ticket_type |
| H31 | Wallet / quota dashboard | Daily·monthly $ + tokens across all ideas | Partial — real OpenRouter spend_eur sum vs €30/mo soft cap on board |
| H32 | LLM provider failover | Mid down → fall back less/more with note | Locked |
| H33 | Data / migration gate | DB/volume tickets: backup/migrate before ship | Locked |
| H34 | External wait reason | DNS, IONOS, tokens — waiting on outside action | Locked |
| H35 | Post-ship soak | Quiet Kuma window before Plane Done | Locked |
| H36 | Idea parking lot | Soft-park discovery drafts; revive later | Locked |
Deep dive — “do first” in plain English (H1–H5)¶
Today the workflow lives mostly in chat + your memory. That breaks when a new Cursor session starts, Discord is quiet, or two things happen at once. H1–H5 are the minimum plumbing so the path can finish even when people/agents change.
H1 — Shared ticket state (“one whiteboard everyone reads”)¶
Problem: You ask “where is T1?” and the answer is only in yesterday’s chat. The next worker guesses wrong.
H2 — Claim / wipe for testing1–3 (“rent the garage, then empty it”)¶
Problem: Someone deploys portfolio on testing1 and never cleans up. Next ticket thinks the bay is free, or finds the wrong app.
What it is: Three boring scripts (or one script with subcommands) on the apps VPS:
- claim — “ticket X owns testing2 now” (fail if already owned)
- deploy — put this app into that bay (Traefik points
testing2at it) - wipe / release — stop containers, delete that bay’s files/env, free the name
Idempotent means: running wipe twice is safe; claim twice for two tickets is not allowed.
Example: T1 claims testing1 → WearLab preview → you OK → wipe → T2 can put docs on testing1.
H2b — Staging Auto-Tenant Isolation (“clean state per test run”)¶
Problem: Deploying apps sequentially onto the same testingN slot leaves residual browser LocalStorage, cookies, or database state from previous tickets.
What it is: On every claim/deploy, inject ephemeral headers (Clear-Site-Data: "cache", "cookies", "storage") and app-level session prefixes so state never bleeds across ticket tests.
H2c — Idle Slot Reclamation (“reclaim forgotten test bays”)¶
Problem: A ticket sits on testing1 waiting for human approval for > 24 hours, blocking other waiting tickets from staging.
What it is: If a slot is approved or idle > 24h, ship snapshots the preview build artifact, releases the bay (testing1), and moves the ticket stage to waiting_on: slot_reclaimed. Re-claiming takes 30 seconds when you return.
H3 — Definition of Done per type (“what does finished mean?”)¶
Problem: Coder says “done”; you expected a live check. Or infra ticket has no URL and nobody knows what to verify.
What it is: A short checklist by ticket class, written into the agreement / ticket:
| Type | Auto checks (examples) | You still |
|---|---|---|
| UX / app | Tests in Docker, page loads on testingN |
Click around, say OK |
| Docs | Page/section exists, links OK | Skim when useful |
| Infra | Script/dig/config validate where possible |
Checklist sign-off if no page |
| Secrets | Staging inject OK; names only in ticket | Confirm staging login works; authorize prod later |
Worker may mark “auto DoD passed” only when that list is green. Your gate stays for human items.
H4 — Stuck detector (“don’t let work sleep forever”)¶
Problem: Ticket sits on waiting_on: resources_apps or CI for two days. Nobody notices.
What it is: A simple timer: if stage or waiting_on unchanged longer than N hours → ping Discord #infra (and later ship) with ticket + reason.
Example: “T2 waiting on human_merge for 24h” or “T1 waiting on resources_apps for 6h”.
Not smart AI — a clock + the H1 fields.
H5 — Rollback after ship (“undo the last production change”)¶
Problem: You authorize merge, prod breaks, and nobody knows how to go back.
What it is: Before/with ship, remember what was live (previous commit, image tag, or compose revision). If live verify fails or you say “revert”, run a known restore path.
Example: WearLab on apps was abc123; ship moves to def456; bad → redeploy abc123. Docs/SFTP: restore previous files from the last known good deploy artifact.
Without H5, “Done” is a one-way door.
Deep dive — workers reliable (H6–H9)¶
H1–H5 keep the path from getting lost. H6–H9 make workers less chaotic when they run.
H6 — Artifact pack per step (“leave a receipt”)¶
Problem: QA asks “did CI pass?” Coder says “I think so.” Test-deploy can’t find the PR. Everyone re-searches Forgejo/Woodpecker.
What it is: At the end of each role, write a small receipt into the ticket state (H1) or a comment:
| After role | Receipt examples |
|---|---|
| execute | branch name, pr_url |
| ci | pipeline URL, green/red, attempt count |
| qa | auto-check summary, review note |
| test-deploy | slot, URL, wipe-not-done flag |
| ship | prod URL, previous revision (for H5) |
Example: worker-qa opens T1 and already sees PR + green CI link — no guessing.
H7 — Retry policy with budget (“try again only when it makes sense”)¶
Problem: CI flakes once; worker keeps rebuilding forever and burns tokens/money. Or a real bug is retried 20 times with no change.
What it is: Two buckets:
| Kind | Examples | Action |
|---|---|---|
| Flake | Network blip, runner restart | Retry up to N times (budget) |
| Real | Test fails same way, compile error | Stop → set waiting_on → ping (H4) |
Daily token and CI-fix caps (D5/D10) apply. When budget is gone → waiting_on: budget, not silent loop.
Example: Pipeline red because runner died → retry once. Red because assertion failed → stop and report.
H7c — DefectDojo False Positive Triage (“don’t block on safe findings”)¶
Problem: Security scanners (Gitleaks, Trivy) report false positives or safe dev secrets, failing Woodpecker CI unnecessarily.
What it is: worker-qa inspects the scan finding in DefectDojo (security.rafaelgonzalezalbes.com). If it is a verified false positive, it submits a triage justification to DefectDojo for a 1-click human approve, avoiding blocked pipelines.
H7d — Flake Isolator (“zero-token retries for infra drops”)¶
Problem: Socket drops or Woodpecker runner restarts trigger expensive LLM code-fix loops when the code is fine.
What it is: The pipeline categorizes failures into Code Assertions (requires AI) vs Infra Flakes (network/runner timeout). Infra flakes trigger zero-token pipeline retries before invoking any LLM.
H8 — Context pack on “work T1” (“briefing before coding”)¶
Problem: New Cursor session starts “work T1” without the agreement, wrong repo, or tries to touch prod.
What it is: A fixed briefing the dispatcher (you now / ship later) gives the worker:
- Goal + acceptance from the agreement
- Repo / paths allowed
- Ticket type + DoD (H3)
- Current
stage/waiting_on(H1) - Forbidden: prod deploy, pasting secrets, silent merge
Example: Worker opens with “T1 docs only in infra/devops; no apps VPS prod; waiting_on empty → execute.”
H8b — Automated Base Rebase & Drift Protection (“keep branches fresh”)¶
Problem: main branch advances on Forgejo while a ticket is being coded, causing merge conflicts down the line.
What it is: Before opening a PR or deploying to testingN, worker-execute automatically rebases against main. If a merge conflict occurs, it outputs a Rebase Resolution Plan before modifying files.
H8c — Smart Graphify Warm-up (“instant codebase context”)¶
Problem: Coding worker spends time scanning unrelated codebase directories.
What it is: On dispatch, the worker immediately loads the local ai-context/ code graph (Graphify) to map relevant imports and dependencies in under 1 second.
H9 — Pause / cancel / resume (“stop without leaving a mess”)¶
Problem: You say “stop” mid-deploy. Containers keep running on testing2. Or you resume and a second deploy starts on top.
What it is:
| Command | Effect |
|---|---|
| pause | No new heavy steps; keep H1 state; may keep slot claimed but mark paused |
| cancel | Stop work + wipe slot if claimed (H2) + clear worker; ticket back to a safe stage |
| resume | Read H1; continue from last stage; do not double-claim |
H9b — Pre-Flight Health Gate (“validate before container update”)¶
Problem: Deploying container updates to Apps VPS (82.165.177.110) when RAM is low or compose syntax has an error causes container crashes.
What it is: worker-ship runs docker compose config validation and checks Netdata RAM/CPU limits on Apps VPS prior to pulling new images.
H9c — Instant Auto-Rollback on 5xx (“automatic safety net”)¶
Problem: Production deploy passes CI but returns HTTP 5xx errors live.
What it is: Uptime Kuma (status.*) monitors the production URL for 3 minutes post-deploy. If a 5xx occurs, ship triggers an instant H5 Rollback to the prior known good container tag without waiting for human intervention.
Depends on H1 + H2. Without them, pause is only a chat word.
Example: Apps VPS is hot (D26) → you pause T1 → later resume → same testing1 still claimed or re-claimed cleanly.
Deep dive — close the loop with you (H10–H12)¶
H10 — Notify only on gates (“ping when you must act”)¶
Problem: Discord floods with every log line; you mute it and miss the real ask.
What it is: Alerts only when something needs a human (or a hard stop):
- Ready for your test on
testingN - Ready to merge
- Blocked on resources / budget / secrets
- Stuck too long (H4)
Not: every commit, every CI minute, every Docker pull.
Example: One message: “T1 ready — https://testing1.… — please test.”
H11 — Post-Done report (“initiative closed with a receipt”)¶
Problem: All tickets green in Plane, but you don’t know what went live, whether the slot was wiped, or leftover risk.
What it is: When the last ticket is Done, a short report (Plane comment / Discord / ship):
- What shipped + prod URLs
- PRs merged
- Slot wiped? yes/no
- Open risks (if any)
- Rollback pointer (H5) if relevant
Example: “Initiative X complete. Docs live at … Slot testing1 wiped. No open risks.”
H12 — Golden-path dry-run (“prove the path before building ship”)¶
Problem: We design forever and never learn where the path breaks in real life.
What it is: One tiny idea (docs-only is best) run manually with Cursor “work T1”, through:
agree → Plane → PR → CI → (checklist or mini test) → your OK → merge → live verify → Done
Use whatever H1–H5 pieces already exist (even a markdown state file). Do this before investing in ship UI.
Example: “Add one sentence to Idea→Done docs” as the only ticket — proves handoffs end to end.
H13 / D27 — LLM cost bands (“how much will this idea cost?”)¶
Problem: You agree to an idea without knowing whether workers will burn a little local/cheap inference or a lot of expensive API calls. Different LLM connections (local Ollama, Groq, Cursor/IDE, Anthropic, OpenRouter, …) have very different prices.
What it is: Before agree, the review pack includes a rough cost band for the whole initiative, comparing routes:
| Band | Typical connection (examples) | When to prefer |
|---|---|---|
| Less $ | Local Ollama / small open models | Docs, simple edits, routine classify |
| Mid $ | Groq / cheaper cloud APIs | Most coding tickets, normal QA |
| More $ | Strong IDE / frontier APIs | Hard architecture, tricky infra, stuck recovery |
Show estimate range (tokens × price table) and optional recommended mix (e.g. execute mid, qa less, stuck-recovery more).
During delivery: ship board (and H1 state) tracks spend so far vs estimate; if over band → waiting_on: budget or ask you to raise the band (ties H7 / D10).
Not exact billing in v1 — honest ranges + “we’re using connection X.” Exact meters when workers run outside Cursor.
Example (review pack snippet):
Cost band (estimate):
Less: ~$0.x–$y (local + light API)
Mid: ~$a–$b (recommended for this idea)
More: ~$c–$d (if we keep frontier model for all steps)
You pick: mid | raise to more if stuck
LLM provider stack & FinOps (D27c — locked direction)¶
Operational blueprint for ship / Idea→Done workers under a soft wallet of ~€30/month (H31). Aligns with cost bands (H13), failover (H32), SOPS (D25), and hard stops over soft email alerts.
Goals¶
- €0 idle — many provider accounts OK if unused and no base subscription / PTU / paid APIM.
- Hard spend stops where the platform supports them (prepaid, workspace caps, OpenRouter guardrails) — soft billing emails alone are not enough for autonomous loops.
- Server-side keys only — never in browser, Plane, PRs, or Discord.
- Cursor ≠ worker wallet — IDE subscription is separate from VPS worker API spend.
- Paid commercial APIs for private code — do not send repo/ticket content through free evaluation tiers that may train on prompts (e.g. Google AI Studio free).
Soft wallet (v1)¶
| Cap | Value | Behavior |
|---|---|---|
| Monthly soft target | ~€30 | H31 wallet; agree/review pack warns when near limit |
| On breach | waiting_on: budget or wallet |
Stop new dispatches; H10 ping; raise wallet or wait for next month |
| Per-idea | H13 less/mid/more | Chosen at agree; over band → pause or re-agree (H16) |
Exact € amounts and token meters = D27b (refresh official price tables before trusting any model $/MTok list).
Zero-base idle (create accounts freely if…)¶
| Provider / path | Idle ≈ €0 if… | Avoid |
|---|---|---|
| OpenAI API | Prepaid/pay-as-you-go; auto-top-up OFF | ChatGPT Team as “API”; leaving auto-recharge on |
| Anthropic API | Console API / workspace; no Team seat minimums | Claude Pro/Max as substitute for API keys |
| Google AI Studio Paid | PAYG project | Free tier for proprietary code |
| Groq Cloud | Standard developer project | — |
| OpenRouter | Credits only when topped up (fee on purchase) | Buying more credits than you will use before expiry |
| Local Ollama | Hardware/electricity only | Treating it as always-on without Netdata watch (D26) |
| Azure OpenAI / Bedrock / Vertex | On-demand only | PTUs, Provisioned Throughput, Vector Search, notebooks, paid APIM for quotas |
Defer for v1: Azure + APIM, Bedrock PT, Vertex auxiliary services — complexity and idle-fee risk; add only for EU/ZDR needs later.
v1 key matrix (recommended core)¶
| Band | Connection | Hard-cap method | SOPS / env (sketch) | Use for |
|---|---|---|---|---|
| Less | Ollama (infra VPS) and/or OpenRouter free / cheapest Flash-class | Local = €0 tokens; OR daily OpenRouter guardrail | LLM_LESS_* / local URL |
Classify, docs skim, routine |
| Mid | Groq and/or Gemini Flash-class (direct or via OpenRouter) | OpenRouter monthly guardrail and/or provider project quotas | LLM_MID_* |
Most execute/QA |
| More | Anthropic Sonnet-class and/or strong OpenAI model | Anthropic workspace spend cap; OpenAI prepaid balance, no auto-top-up | LLM_MORE_* |
Hard tickets, stuck recovery |
| Gateway | OpenRouter (optional hub) | Guardrails: daily/monthly $ → HTTP 402 | OPENROUTER_API_KEY |
Multi-model + unified cap |
| Human IDE | Cursor subscription | N/A (not worker wallet) | — | You in Cursor; not ship workers |
Suggested starting balances (illustrative, adjust): small OpenAI prepaid (e.g. $5–10) + OpenRouter credits + Anthropic workspace cap totaling near the €30 soft wallet — no auto-top-up anywhere.
Hard stop vs soft alert¶
| Mechanism | Stops requests? | Use for ship workers |
|---|---|---|
| Soft billing email / GCP budget alert | No (laggy) | Extra warning only |
| OpenAI hard monthly limit / $0 prepaid | Yes (e.g. 429) | Primary wallet slice |
| Anthropic workspace cap | Yes | More-band slice |
| OpenRouter Guardrails | Yes (e.g. 402) | Mid + multi-model |
| Rate quotas (RPM/RPD) | Throttle only | Safety net, not $ cap |
Worker behavior on 402/429 insufficient quota: fail closed → waiting_on: budget (H7), do not retry-burn.
Cascade guidance (volume, not a promise)¶
~70% calls → Less (local / cheapest)
~25% calls → Mid (Groq / Flash / Haiku-class)
~5% calls → More (Sonnet / strong GPT) — prefer cache/batch when available
H32 failover stays inside the same band first (e.g. mid: Groq → OpenRouter), then escalate band only with cost note / your OK.
Privacy (v1)¶
| Tier | Training on API prompts? | Use with infra/code? |
|---|---|---|
| Free evaluation (e.g. AI Studio free) | Often yes / human review | No |
| Paid commercial APIs | Typically no training (cite current TOS) | Yes |
| ZDR / EU regions | Enterprise options | Later if needed — not v1 blocker |
Secrets layout (workers)¶
| File | Holds |
|---|---|
secrets/ship-workers.enc.env |
LLM keys + worker platform tokens (Plane A) — when created |
Existing secrets/*.enc.env |
Prod platform secrets (unchanged) |
| Woodpecker repo secrets | CI-only inject for pipelines that need a key |
Decrypt to tmpfs / process env on infra (same pattern as /run/infra-secrets). Separate keys per env/role when possible (…_STAGING vs …_PROD). Rotate on leak immediately; cadence ~90 days when automated.
Cursor isolation (mandatory)¶
- Cursor Pro/Max = human workstation budget.
- Ship workers = SOPS API keys only.
- Do not paste worker keys into Cursor to “bypass” IDE limits if you want a clean €30 worker wallet (double-count risk).
Implement order (FinOps)¶
1. Anthropic workspace cap + OpenRouter guardrail + OpenAI prepaid (no auto-top-up)
2. SOPS ship-workers.enc.env (keys never in chat/Plane)
3. H13 bands on every review pack; H31 monthly wallet ~€30
4. Optional Ollama Less band when process is reliable
5. Defer Azure/Bedrock/Vertex; refresh D27b price table from official docs before locking $ numbers
Price catalog refresh (D27b — how “fresh pricing” enters our case)¶
Prices move. Estimates must read a catalog, not yesterday’s memory.
| Piece | Detail |
|---|---|
| Catalog | Generated JSON e.g. config/ship-llm-prices.json (or /var/lib/ship/… on infra) — rates only, no API keys |
| Connections map | Our ids → { band, model_slug, meterable, estimate_only } (Ollama, Groq, OR, Anthropic, Cursor=estimate_only) |
| Auto refresh | Cron / Woodpecker weekly (or ship Refresh prices): GET https://openrouter.ai/api/v1/models → read pricing.prompt / pricing.completion (USD per token) for slugs we use; write catalog + updated_at |
| Manual rows | Providers without a public price API (or Cursor placeholder) → you set $/1M in the map; refresh leaves them alone |
| Stale warning | If updated_at older than N days → review pack / wallet shows “prices may be stale” |
| Estimate | tokens_guess(playbook, tickets, blast) × catalog[connection] → less/mid/more ranges “as of \<date>” |
| Meter | Headless workers report real tokens → H31 wallet; Cursor stay soft until usage export exists |
| New connection | Key in SOPS → row in connections map → refresh (or manual rate) → appears in bands + H32 failover |
UI hook: Wallet strip shows “Prices as of … · Refresh”. Review pack always cites catalog date next to $ ranges.
How we handle “all of this” — UX layers (not one mega screen)¶
H1–H36 is a backlog, not 36 buttons on day one. Progressive disclosure on ship.*:
| Layer | When | What you see / do |
|---|---|---|
| 0 — Chat (now) | Today in Cursor | Full review pack in markdown; “work T1”; agents follow this doc |
| 1 — Board MVP | First ship build | Ideas/tickets, stage, waiting_on, slot, PR, cost band + spend, ready-to-merge |
| 2 — Wallet | With board | Day/month € vs ~€30; catalog age; Refresh prices |
| 3 — Gate controls | Next | Approve test, merge, pause, freeze, away, staging reveal |
| 4 — Chat on ship | Later | Discovery + agree UI (same pack fields, nicer form) |
| 5 — Advanced | Last | Deps graph, parking, playbooks, shadow, failover log — from ticket detail, not home |
Home stays calm:
ship home
→ idea row (stage · waiting_on · band/spend)
→ ticket detail (artifacts, evidence, actions)
→ Wallet (top): € used / cap · prices as of …
→ Owner controls: freeze · away · windows
Viewer (H25) = board + wallet totals only. Owner = controls + reveal + raise wallet/band.
Deep dive — next ideas (H14–H20)¶
H14 — Global kill / freeze (“big red stop”)¶
Problem: Something goes wrong on apps VPS (runaway Docker, bad loop). Pausing one ticket (H9) is not enough; you need everything to stop now.
What it is: A ship control (and a script/CI trigger before ship exists):
| Action | Effect |
|---|---|
| freeze | No new dispatches; running workers must checkpoint and stop heavy work |
| kill | freeze + cancel in-flight tickets that hold slots → wipe those bays (H2) |
| thaw | Allow dispatch again |
Board shows platform: frozen. Ties D26 (resources) — auto-suggest freeze if disk critical.
Example: Apps RAM pegged → you hit freeze → no new testingN deploys until thaw.
H15 — Path conflict guard (“don’t step on each other”)¶
Problem: Idea A and Idea B both touch docs/architecture/idea-to-done.md or the same WearLab service. Merges fight; testing slots show the wrong thing.
What it is: On agree / dispatch, declare touch set (repos + path globs). If another in-flight initiative overlaps → waiting_on: conflict until the other finishes or you override.
Example: Portfolio CTA still open → new “portfolio footer” idea waits or you explicitly allow parallel with eyes open.
H16 — Re-agree on scope change (“no silent drift”)¶
Problem: Mid-delivery you say “also add X.” Worker expands scope; original tickets/cost band no longer match.
What it is: Material changes (new ticket, bigger surface, secrets, prod risk) require a mini review pack + your re-agree. Small typo fixes inside acceptance do not.
Example: “Also refactor Traefik” mid docs ticket → stop → new T2 + cost band update → you agree again.
H17 — Time band (“how long, not only how much $”)¶
Problem: Cost band says mid $, but you needed it tonight and the estimate was three days of calendar time.
What it is: Next to H13, show rough duration:
| Band | Meaning (v1 rough) |
|---|---|
| Soon | Hours (tiny docs / one file) |
| Days | Normal multi-ticket |
| Longer | Infra + secrets + many gates |
Uses ticket count, type mix, and whether human gates will block overnight. Not a promise — a planning signal.
Example: Review pack: Cost: mid · Time: days (2 tickets + your test gate).
H18 — Learn from Done (“rules get smarter”)¶
Problem: Same failure repeats (forgot wipe, skipped checklist). D22 says rules grow, but nothing captures the lesson.
What it is: After H11 post-Done report, optional 1–3 proposed rule updates (agree checklist item, new auto DoD check, new waiting_on reason). You accept into the living doc / playbook.
Example: “Slot wasn’t wiped twice” → propose mandatory wipe check in H3 for test-deploy.
H19 — Kuma watch on claimed slots (“is testing1 actually up?”)¶
Problem: Worker says URL is ready; Traefik 502; you waste time. Or slot dies overnight and nobody knows.
What it is: On claim+deploy, create/enable an Uptime Kuma monitor for that testingN URL (or reuse a slot monitor). On wipe, disable/pause it. Down → waiting_on + H10 gate ping.
Example: testing2 502 for 5 minutes → Discord: “T1 testing slot down.”
H20 — Idea playbooks / templates (“don’t start from blank”)¶
Problem: Every discovery reinvented. Docs idea and WearLab idea need different tickets/DoD/cost defaults.
What it is: Named starters that fill review pack defaults:
| Playbook | Defaults |
|---|---|
| docs-only | One repo devops, checklist-light, cost less, time soon |
| portfolio-ui | UX DoD + testingN, cost mid |
| wearlab-service | Apps VPS + Docker tests + secrets names, cost mid/more |
| infra-platform | Checklist-heavy, maybe no URL, cost mid, time days |
You still edit; playbook only accelerates discovery → agree.
Example: Pick docs-only → H12 dry-run almost pre-filled.
Deep dive — day-2 ops & team (H21–H28)¶
H21 — Away / AFK mode (“don’t ping me at 3am”)¶
Problem: H10 gate pings fire while you sleep; Discord noise; stuck timer (H4) looks like neglect.
What it is: You set away on ship (or say “away until …” in chat for now). Effects:
- Gate pings queue (ready-to-test / ready-to-merge) — one digest when you return
- Stuck alerts still fire for resources / kill (safety), but not for
human_testwhile away - Workers may continue non-human steps; they must not auto-merge or prod-ship
Example: Away Fri–Sun → Monday: “3 tickets ready for your test.”
H22 — Shadow / plan-only (“rehearse without touching prod”)¶
Problem: You want to see what a worker would do (files, tickets, cost) before allowing writes.
What it is: Dispatch mode shadow: run H8 context + propose plan + estimate cost/time + list touch set (H15) — no branch push, no Plane writes, no deploy. Output is a plan artifact (H6). You then dispatch for real.
Example: “Shadow T1” → plan says touches wearlab compose → you switch to real execute.
H23 — Branch & worktree naming (“find and clean leftovers”)¶
Problem: Random branch names; abandoned worktrees; wipe (H2) doesn’t clean git.
What it is: Convention: ship/<initiative-id>/T<n>-<short> (and matching worktree path if used). Cancel/Done runs branch cleanup checklist (delete remote branch after merge; warn if open).
Example: ship/idea-docs-typo/T1-sentence — easy to grep and delete.
H24 — Ship windows (“not every hour is a good prod hour”)¶
Problem: Worker ready to ship at midnight; you’d rather merge in the morning.
What it is: Optional policy: prod ship (step 9) only in allowed windows (e.g. weekdays 10:00–20:00 Europe/Madrid) unless you override. Outside window → waiting_on: ship_window.
Example: Green Friday 23:00 → waits until Monday window or your override.
H25 — Teammate read board (“Alex can see, not steer”)¶
Problem: Teammate needs visibility; must not agree, merge, freeze, or reveal staging passwords.
What it is: Ship roles:
| Role | Can |
|---|---|
| Owner (you) | Agree, merge, freeze, reveal, cost raise |
| Viewer (teammate) | Read board, tickets, waiting_on, public URLs |
| Worker | Act only via allowlisted roles (D25f) |
Example: Alex opens ship → sees T2 waiting on your test — cannot press Merge.
H26 — Incident auto-pause (“platform on fire → stop ideas”)¶
Problem: Apps VPS or Traefik is down; workers keep deploying into the fire.
What it is: Critical Kuma/Netdata signals (infra or apps) → auto pause ideas that target that host (ties H9 + H14 suggest). Clear when green again (or you thaw).
Example: Apps disk full alert → all testingN / WearLab ships pause with waiting_on: incident.
H27 — Weekly ship digest (“quiet summary”)¶
Problem: Either spam (H10 fails) or radio silence — you forget what finished.
What it is: Once a week (or on demand): Done initiatives, still blocked + reasons, spend vs bands, slots wiped?. Discord #infra or email — one message.
Example: “This week: 2 Done, 1 waiting human_merge, spend mid band OK.”
H28 — UX evidence pack (“show me what changed”)¶
Problem: For UI tickets, “please test testing1” without before/after is slow; you don’t know what to look at.
What it is: For UX/app DoD (H3), worker attaches evidence: screenshot(s) or short capture of the changed surface, plus the testingN link. Stored as H6 artifacts — not secrets.
Example: Portfolio CTA ticket → before/after PNGs + testing2 URL in the ready-for-test ping.
Deep dive — planning & resilience (H29–H36)¶
H29 — Ticket dependency graph (“T2 really waits on T1”)¶
Problem: v1 is “one ticket at a time,” but the board doesn’t show why T2 is idle. Later, parallel workers need real edges.
What it is: Each ticket lists depends_on: [T1, …]. Dispatcher only starts a ticket when dependencies are Done (or you override). Board draws simple arrows / “blocked by T1.”
Example: T1 content Done → T2 nav unlocks automatically in the queue.
H30 — Blast-radius label (“how scary is this ship?”)¶
Problem: A docs typo and a secrets rotation look the same on the board until something breaks.
What it is: On agree, set one label (can be multi if needed, primary wins):
| Label | Meaning | Default care |
|---|---|---|
| docs | Content / MkDocs only | Light windows OK |
| app | Portfolio / WearLab UX | testingN + H28 evidence |
| infra | Traefik, compose, agents | Checklist + H24 windows |
| secrets | SOPS / passwords | Staging≠prod; ship only after you |
Drives H5 rollback depth, H24 windows, and notify urgency.
Example: Review pack: blast: infra → no midnight ship without override.
H31 — Wallet / quota dashboard (“the whole purse, not one idea”)¶
Problem: H13 is per-idea. Three mid-band ideas can still empty the month.
What it is: Ship (or a simple report) shows daily / monthly spend and tokens across initiatives vs caps (D10 / D27c ~€30 soft wallet). Over wallet → new dispatches wait (waiting_on: wallet) even if one idea’s band is fine.
Example: Monthly cap 80% used → board warns before you agree a new “more $” idea.
H32 — LLM provider failover (“don’t die when Groq is down”)¶
Problem: Chosen mid connection fails; worker stalls forever.
What it is: Ordered fallback list per band (e.g. mid: Groq → OpenRouter → local). On fail: switch, log provider name in H6 (never the key), optional small cost bump note. If all fail → waiting_on: llm.
Example: Groq 503 → auto try next mid; Discord only if all mid options fail.
H33 — Data / migration gate (“backup before you move the DB”)¶
Problem: Generic infra checklist misses volume/DB changes; ship without backup.
What it is: If ticket touch set includes DB, volumes, or migrate scripts → extra DoD before ship: backup taken / migrate plan / rollback data path. Blocks step 9 until green or you override.
Example: WearLab DB migrate ticket → waiting_on: migration_gate until backup artifact linked.
H34 — External wait reason (“stuck on IONOS, not on CI”)¶
Problem: DNS or a Forgejo token needs a human outside the worker. Looks like a bug.
What it is: waiting_on: external (+ note: dns, ionos, token_rotate, …). H10 pings you with that note; H4 stuck timer uses a longer grace for external.
Example: “T1 waiting_on: external (IONOS A record for testing3).”
H35 — Post-ship soak (“green for a few minutes, then Done”)¶
Problem: Live verify passes once; five minutes later prod 502; Plane already Done.
What it is: Optional after step 10: watch Kuma/health for N quiet minutes (default short for docs, longer for app/infra). Then Plane Done. Fail → H5 rollback path + reopen.
Example: WearLab ship → 15 min soak → Done. Docs → 2 min or skip.
H36 — Idea parking lot (“save the draft, don’t spam Plane”)¶
Problem: Discovery chat has a half-baked idea; creating Plane tickets too early clutters. Deleting the chat loses the review pack.
What it is: Park = store review-pack draft (concept, tickets, cost/time, blast) without Plane create. Board list: Parked. Revive = load draft → normal agree flow. Discard = delete draft.
Example: “Park WearLab dark mode” → three weeks later revive → agree → Plane.
Build order suggestion¶
H12 dry-run (manual) → H1 state + H2 slots → H3 DoD + H6 artifacts
→ H4 stuck + H7 retries + D26 resources
→ ship board MVP (reads H1) + H13/H17 cost+time + H30 blast + H29 deps
→ H10 notifies → H5 rollback → H14 freeze → auto-dispatch (W4)
→ H8/H9 + H11 + H15–H16 + H19–H20
→ H21 away + H24 windows + H25 viewer + H26 incident + H22 shadow
→ H23 branches + H27 digest + H28 UX evidence
→ H31 wallet + H32 failover + H33 migration + H34 external + H35 soak + H36 parking
Open (workflow + product)¶
| # | Topic |
|---|---|
| D23h | Wipe script + Traefik labels for testingN on apps (start of H2) |
| D10b | Exact daily token / CI-fix budget numbers (H7) |
| D27b | Wire refresh job + connections map file paths; Cursor metering export if any |
| D27e | Exact N-day stale threshold + default token_guess table per playbook |
| D27d | Exact prepaid/guardrail dollar splits inside the €30 wallet |
| D19b | Worker runtime (Cursor / headless / CI / mix) for auto-dispatch — later compare Reasonix CLI, Kilo CLI, Microsoft Agent Framework (Python/.NET; steal HITL/handoff/checkpoint — borrow §8) |
| D24b | When adding worker #2: parallel tickets vs parallel roles? |
| D26b | Exact Netdata thresholds / poll interval (D26 + H4) |
| D5b | Multi-repo initiative rules (when enabling W5 later) |
| D6–D20b | Prior open list (skills, budget, board sources, …) |
| D25e | Optional daily “allow auto-dispatch” gate |
| D37 | Optional later: evaluate TencentDB Agent Memory for cross-session chat/persona memory — only if OpenClaw/Hermes workers land or Plane+docs cannot hold team recall. Not for Graphify/code-context replacement. See AI_CONTEXT — Future: team agent memory. |
| D38 | Apply agent patterns to borrow when designing workers / auto-dispatch: symbolic offload, compound→Plane learnings, prefix-stable prompts, safe outputs (read-only default), Playwright-first app E2E, HITL/handoff/checkpoint (incl. Microsoft Agent Framework patterns), agent graphs / governed connectors (xpander patterns — not the product), Shep-inspired worktrees / CI-retry / feature graph for ship UI (not Shep-as-platform), Fullsend-inspired credential isolation / output schema / NormalizedEvent dispatch / two-phase review / behaviour tests (not Fullsend-as-platform). Products themselves stay skipped unless a dedicated decision reopens them. |
Changelog¶
| Version | Date | Notes |
|---|---|---|
| v0.9–v0.9.1 | 2026-08-03 | Board-first; delivery playbook |
| v0.9.2 | 2026-08-04 | Review pack; test subdomain human QA |
| v0.9.3 | 2026-08-04 | D24 workers: one role per step; concurrency 1 |
| v0.9.4 | 2026-08-04 | W3 docs: auto QA for ticket + human read when useful |
| v0.9.5 | 2026-08-04 | W4 locked; D25 auto-dispatch + secrets |
| v0.9.6 | 2026-08-04 | W5: single-repo v1; multi-repo later |
| v0.9.7 | 2026-08-04 | W2b: ready-to-merge list + board button; human authorizes |
| v0.9.8 | 2026-08-04 | D18e: host ship.rafaelgonzalezalbes.com (no paid domain) |
| v0.9.9 | 2026-08-04 | D23b testing1–3 slots; UX/infra/secrets change classes |
| v0.9.10 | 2026-08-04 | D25 secrets broker + role allowlist across tickets/workers |
| v0.9.11 | 2026-08-04 | D23c swappable bays; D23d URL vs checklist; D25c tmpfs inject |
| v0.9.12 | 2026-08-04 | D23g ship=infra / testing=apps; Docker auto-tests; plain D25b/d |
| v0.9.13 | 2026-08-04 | D26 waiting_on + server resource gates (Netdata/Kuma) |
| v0.9.14 | 2026-08-04 | Hardening backlog H1–H12 (state, slots, DoD, stuck, rollback, …) |
| v0.9.15 | 2026-08-04 | Plain deep-dive for H1–H5 (do-first plumbing) |
| v0.9.16 | 2026-08-04 | Plain deep-dive for H6–H12 (workers + close the loop) |
| v0.9.17 | 2026-08-04 | H1–H13 locked; D27 LLM cost bands (less/mid/more) in review pack |
| v0.9.18 | 2026-08-04 | H14–H20: freeze, conflict, re-agree, time band, learn, Kuma slot, playbooks |
| v0.9.19 | 2026-08-04 | H21–H28: away, shadow, branches, ship windows, viewer, incident, digest, UX evidence |
| v0.9.20 | 2026-08-04 | H29–H36: deps, blast-radius, wallet, failover, migration, external, soak, parking |
| v0.9.21 | 2026-08-04 | D27c FinOps + D27d price catalog refresh + ship UX layers (progressive disclosure) |
| v0.9.22 | 2026-08-04 | D23f Staging test feedback loop: Micro-Agreement Pack (diagnosis, fix plan, scope check, retry delta) before code fix |
| v0.9.23 | 2026-08-04 | Added hardening controls H2b/c (staging isolation/reclamation), H7c/d (DefectDojo triage/flake isolator), H8b/c (auto-rebase/Graphify warm-up), H9b/c (pre-flight health/auto-rollback 5xx), H18b (post-mortem debt collector) |
| v0.9.24 | 2026-08-05 | Open D37: park TencentDB Agent Memory as optional later eval (chat/persona); keep Graphify + Plane for now |
| v0.9.25 | 2026-08-05 | D38 + agent-patterns-borrow.md: steal list from TencentDB / Compound / Reasonix / gh-aw / Cypress / Kilo evals |
| v0.9.39 | 2026-08-06 | CI → Ship webhook: Woodpecker notify sets ci_url, advances waiting_on: ci → preview |
| v0.9.38 | 2026-08-06 | W1 Plane on agree — work items per task (+ parent when multi-task); install-ship-plane-key.sh |
| v0.9.37 | 2026-08-06 | Layer 4 agree forms v1 — board review pack (goal/tasks/bands), agree → queued tickets + receipts |
| v0.9.36 | 2026-08-06 | H9c post-ship soak + auto-rollback; scanSoakTickets() probes live URL for 3 min, auto-Done or auto-rollback |
| v0.9.35 | 2026-08-06 | H28 UX evidence: gate ux/app @ human_test; live PORTFOLIO-H28 exercise; /evidence/… receipts |
| v0.9.33 | 2026-08-06 | D19b OpenRouter coding worker (allowed_paths); wallet/402 fail-closed; install-ship-openrouter-key.sh |
| v0.9.32 | 2026-08-06 | D19b ship-worker docker poller (no paste); Woodpecker ship-worker workflow; H2c install script |
| v0.9.31 | 2026-08-05 | D25 staging inject/reveal; H9b preflight gate; D19b job queue + runner; H21 away; H28 evidence; H2c cron template |
| v0.9.30 | 2026-08-05 | Ship board hardening statuses: H1–H15/H22/H30/H31 (shipped/partial); W4 scan + D19b session + ship-work-t1 |
| v0.9.26 | 2026-08-05 | Borrow catalog: Microsoft Agent Framework (HITL/handoff/checkpoint/OTel); park SDK under D19b |
| v0.9.27 | 2026-08-05 | Borrow catalog: xpander.ai — skip product (ship overlap); steal graphs + governed connectors |
| v0.9.28 | 2026-08-05 | Borrow catalog: Testsigma skip; keep Playwright-first app E2E (§7) |
| v0.9.29 | 2026-08-05 | Borrow catalog: Shep — steal worktrees/CI-retry/feature graph for ship; don’t replace Forgejo spine |
Pointers for agents¶
- Ship on infra VPS;
testingNapps on apps VPS. - Before deploy/Docker: check server resources; if hot →
waiting_on: resources_*, don’t pile on. - Board must show why a ticket is waiting (human, CI, slot, resources, …).
- Test slots are swappable; wipe on release.
- Workers run Docker / auto tests before human gate.
- Staging test feedback (D23f): Minor in-scope fixes require a Micro-Agreement Pack (diagnosis, 1-3 fix points, scope check, retry budget delta) before applying code fixes to the branch.
- Before agree, always show concept + full ticket list/bodies + LLM cost band (less/mid/more, as of catalog date) + wallet awareness (~€30 D27c).
- Cost estimates use the price catalog (OpenRouter refresh + manual rows); never invent $/MTok from memory if catalog exists.
- Ship UX is layered: board first, then wallet/gates, advanced behind ticket detail — not 36 home buttons.
- Tickets: secret names only, never values.
- Staging: tmpfs on apps; reveal via ship later / password manager now.
- Worker LLM keys:
secrets/ship-workers.enc.env(SOPS → tmpfs). Cursor IDE ≠ worker API wallet. - Prefer hard caps (prepaid / workspace / OpenRouter guardrails); on 402/429 quota →
waiting_on: budget, no retry-burn. - No free evaluation tiers for proprietary repo/ticket content.
- Hardening H1–H36 are locked direction (spine → day-2 → planning/resilience).
- Material scope change mid-flight → re-agree (H16), do not silent-expand.
- v1: one agreement → one repo. Manual “work T1” until auto-dispatch.
- Merge: never silent auto-merge. One worker at a time.
- No production until user tested and authorized merge.
- Respect away (H21) and ship windows (H24) when notifying or shipping.
- Prefer H12 dry-run before building more ship UI.
- When designing workers / gated writes: apply D38 borrow patterns (agent-patterns-borrow.md) — especially safe outputs and read-only defaults — without installing foreign products.
- Park incomplete ideas (H36) instead of premature Plane tickets.