Skip to content

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

  1. Keep designing the workflow (discovery → agree → tickets → workers → live Done).
  2. Principal near-term UI: orchestrator status board — see ideas, tickets, workflow step, deploy/live.
  3. Each ticket reaches Done only when live-tested and working.
  4. Daily token budget bounds autonomous loops.
  5. 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 ship85.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):

  1. Concept — what we are building (goal, out of scope, what “done” looks like). Visual/summary of the idea.
  2. Ticket list — every ticket that will be created, with the full information inside each (title, acceptance, repo/surface, UX?, checks).
  3. Order — T1 → T2 → …
  4. 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)
  5. Time band (H17) — rough soon / days / longer calendar effort next to cost
  6. Blast radius (H30) — primary: docs | app | infra | secrets
  7. 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)

  1. One active ticket at a time per initiative.
  2. Next ticket only after previous Done (or you skip).
  3. You can pause anytime.
  4. No production before your test on a testingN slot (or approved infra checklist).
  5. 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
testing1testing3 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/3apps

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)

  1. Prefer questions/options over jumping to code.
  2. Propose a task list when work emerges.
  3. Before agree: concept + full ticket contents (review pack).
  4. Wait for agree before Plane + workers.
  5. Status: mode + one next action.
  6. 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:

  1. Read status → if resources_*, set stage waiting + reason; backoff; ping board/you.
  2. When pressure drops, resume same step (no silent parallel second deploy).
  3. Coder may still write code locally while waiting on resources_apps for deploy — but must not push a deploy that piles on.
  4. Board MVP should surface waiting reason as a first-class column (status board priority).

Rules

  1. Only 1 worker runs at a time (v1).
  2. That worker walks one ticket through steps 6→11 (plane/dispatch may be conductor/orchestrator).
  3. Do not start step N+1 until step N exit criteria pass (or human override).
  4. Human steps (agree, 8b test) never get auto-skipped.
  5. When we add worker #2, decide: second ticket in parallel vs specialized parallel roles (D17 / D24b).
  6. 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-apply
  • inject_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:

  1. Ticket/worker asks by name + role + slot (e.g. testing2).
  2. Broker checks role allowlist + ticket claim on that slot.
  3. Broker loads from the right vault (staging vs prod).
  4. Injects into tmpfs / process env / compose env for that step — not into Plane or chat.
  5. Worker sees env vars in the target process, or gets a short-lived handle; it must not echo values into logs, PRs, or Discord.
  6. 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):

  1. On claim, broker creates a slot-scoped staging bundle (generate random passwords or copy from a staging SOPS blob — never from prod).
  2. Writes values only to tmpfs on the Apps VPS (where testingN runs), e.g. /run/testing-slots/testing1.env (mode 600, deploy user only).
  3. Compose / Traefik on apps for that slot uses env_file: pointing at that tmpfs path (or Docker secrets).
  4. Worker (worker-test-deploy) triggers deploy from ship/CI — it does not cat the file into chat.
  5. You learn staging login via D25d (ship “show password” later; password manager / private path now) — never Plane.
  6. 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)

  1. No plain API keys / passwords in git, chat, Plane, PR bodies, Discord.
  2. Decrypt only into tmpfs / process env (same idea as /run/infra-secrets).
  3. Staging ≠ prod — different values always; testing slots never get prod passwords.
  4. Least privilege per role — execute cannot prod-apply; ship cannot run until you authorize.
  5. Fail closed — missing vault / wrong role → stop; ping human.
  6. Audit names only on ship board.
  7. Cursor-manual phase: your local Cursor keys stay local; do not copy into the repo “for later.”
  8. 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: testing1testing3 slots 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

  1. Board first for visibility — see stages while we finish the workflow design.
  2. Workflow: review pack → agree → tickets → worker → CI → QA/review → testingN (you) → prod → live Done.
  3. Spine underneath = Plane + Forgejo + Woodpecker + VPS/IONOS.
  4. Human agree (concept + tickets) before Plane + workers.
  5. Done = live-tested on production per ticket.
  6. Budget-bounded autonomy.
  7. Agree/QA rules grow over time (D22).
  8. Chat/dispatch on orchestrator is end-state, not blocking board MVP.
  9. 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 = testing1testing3.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 testing13 (“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:

  1. claim — “ticket X owns testing2 now” (fail if already owned)
  2. deploy — put this app into that bay (Traefik points testing2 at it)
  3. 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

  1. €0 idle — many provider accounts OK if unused and no base subscription / PTU / paid APIM.
  2. Hard spend stops where the platform supports them (prepaid, workspace caps, OpenRouter guardrails) — soft billing emails alone are not enough for autonomous loops.
  3. Server-side keys only — never in browser, Plane, PRs, or Discord.
  4. Cursor ≠ worker wallet — IDE subscription is separate from VPS worker API spend.
  5. 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.

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 closedwaiting_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_test while 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: cipreview
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; testingN apps 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.