# OpenLife v1.18 — Changelog

**Branch:** `main`
**Predecessor:** v1.17.0 (tagged 2026-05-22)
**Released:** 2026-05-22

v1.18 closes the **v1.15→v1.18 SaaS Forge arc**. After this release the
full path from idea → SaaS-in-production exists as composable CLI
commands:

```bash
# 1. Bootstrap (v1.16)
openlife scaffold meu-app --template=nextjs-supabase-clerk-stripe

# 2. Pull a design system (v1.15)
openlife design pull stripe

# 3. Develop autonomously (v1.17)
openlife story execute 1.1

# 4. Ship + Deploy (v1.18 — THIS RELEASE)
openlife ship                           # vortex-delegated push + PR
openlife deploy --provider=vercel       # auto-detects from vercel.json
```

## What landed by phase

### Phase D1 — `openlife ship`

The escape hatch that lifts the v1.17 git-push prohibition for ONE
sanctioned call site. Authorizes the push via a try/finally pattern:

```ts
const release = GitOps._authorizePush();
try { await gitops.push({ setUpstream: true }); }
finally { release(); }
```

Outside the `try` block, push remains refused everywhere else.

**ShipCommand flow:**
1. Detect story (most-recent InReview, or `--story <id>` override)
2. Refuse if on a protected branch (main/master/develop/production)
3. Refuse if working tree is dirty
4. Authorize → push branch → release
5. Build PR title from story tag (`feat(1.1):`, `fix(1.1):`, etc.)
6. Build PR body from story description + AC checkboxes + File List
7. `gh pr create --body-file -` (body via stdin to avoid shell quoting)

**Flags:** `--story`, `--remote`, `--target`, `--no-pr`, `--dry-run`, `--json`.

### Phase D2 — `openlife deploy`

Pluggable adapter pattern matching v1.17's HostInvoker design.

| Adapter | CLI | Detect marker | Rollback |
|---|---|---|---|
| `VercelAdapter` | `vercel` | `vercel.json` or `.vercel/` | ✓ `vercel rollback` |
| `RailwayAdapter` | `railway` | `railway.toml` or `railway.json` | ✗ deferred to v1.18.1 |

**Auto-detection:** `DeployRegistry.autoDetect(cwd)` inspects filesystem
markers AND probes which CLI is on PATH. Returns first plausible match
or `null`.

**Preflight:** Each adapter runs project-link + env-var + config sanity
checks BEFORE deploying. Issues classified as `error` (block) or
`warning` (proceed). Vercel checks `.vercel/project.json` link state +
`vercel.json` validity. Railway checks `railway.toml` presence +
build-strategy declaration.

**Subcommands:** `openlife deploy [--preview]`, `openlife deploy rollback`,
`openlife deploy list`.

### Phase D3 — 4 SaaS skills

Markdown-only skills (no TS code — they're applied by the host CLI's
own file mutation tools per Host-Native Mode v1.10).

| Skill | What it wires |
|---|---|
| `clerk-wire` | Clerk auth: middleware + sign-in/sign-up routes + UserButton + server helpers + webhook |
| `stripe-billing-wire` | Stripe: SDK + plan defs + checkout + customer portal + subscription webhook + RLS-aware DB sync |
| `supabase-rls-wire` | Postgres: users + subscriptions + organizations + org_members tables with self-select RLS policies |
| `vercel-deploy-wire` | Deploy prep: vercel.json + env-var registration + webhook URL setup + custom domain |

Each skill includes pre-flight checks, file recipes (with copyable code),
required environment variables, post-install steps, and composition
notes ("requires X first, pairs with Y").

### Phase D4 — Tests + docs + ship

13 new test scenarios across 2 files — all green:

- `test_ship_command.ts` (5) — GitOps push authorization, protected
  branches refused, try/finally round-trip, ShipCommand exports, GitOps
  `_authorizePush` helper.
- `test_deploy_adapters.ts` (8) — registry defaults, auto-detect from
  markers, preflight issue surfacing (unlinked, invalid JSON, missing
  config), Railway rollback graceful not-supported message.

## Safety model

- **Push remains @vortex-exclusive.** ShipCommand is the ONE caller
  authorized via `GitOps._authorizePush()`. Authorization is
  module-scoped and released immediately. Any other caller hitting
  `gitops.push()` without the flag gets `gitops_refused: not_authorized`.
- **Protected-branch ban applies to ship.** Cannot ship from
  `main/master/develop/production` even with authorization.
- **Dirty tree refused.** Commit first.
- **Deploy adapters have 10min default timeout** with SIGKILL escalation.
- **Preflight by default.** `--skip-preflight` available for advanced users.
- **No automatic webhook configuration.** Skills document the steps but
  never call Clerk/Stripe APIs to register webhooks — that requires the
  user's explicit dashboard interaction.

## Composition map — the full SaaS Forge

```
┌─────────────────────────────────────────────────────────────┐
│                  v1.15 Design.md Hub                        │
│  openlife design extract <url>                              │
│  openlife design pull <brand>                               │
│  openlife design diff <a> <b>                               │
└─────────────────────────┬───────────────────────────────────┘
                          │  (informs styling tokens)
                          ▼
┌─────────────────────────────────────────────────────────────┐
│                  v1.16 SaaS Scaffold                        │
│  openlife scaffold meu-app --template=...                   │
│    → nextjs-supabase-clerk-stripe ready in 30 seconds       │
└─────────────────────────┬───────────────────────────────────┘
                          │  (produces a working baseline)
                          ▼
┌─────────────────────────────────────────────────────────────┐
│                  v1.17 Autonomous Story Loop                │
│  openlife story execute 1.1                                 │
│    → Loop runs personas, mutates story, commits locally     │
└──────────────────┬──────────────────────────────────────────┘
                   │
       ┌───────────┴──────────────┐
       ▼                          ▼
┌──────────────┐         ┌──────────────────┐
│ v1.18 SaaS   │         │ v1.18 Ship+Deploy│
│ Skills       │◀────────│ openlife ship    │
│ - clerk-wire │         │ openlife deploy  │
│ - stripe-…   │         │   --provider=…   │
│ - supabase-… │         │                  │
│ - vercel-…   │         │                  │
└──────────────┘         └──────────────────┘
       (applied during                 (push + PR + deploy)
        story execution
        or manually)
```

## Out of scope (deferred)

- **Cloudflare adapter** (`cloudflare-wire` skill + CloudflareAdapter) → v1.18.1
- **Fly.io adapter** → v1.18.1
- **Native Railway rollback** (`railway redeploy`) → v1.18.1
- **`openlife deploy --watch`** (live build log streaming) → v1.18.2
- **AI-driven preflight remediation** (auto-`vercel link`, etc.) → v1.19+
- **Multi-environment promote** (`openlife deploy --env=staging --then-prod`) → v1.19+
- **SvelteKit template** (v1.16.1) — independent track
- **Cross-machine bridge** (#9) — independent track

## Tarball impact

```
v1.17.0 → v1.18.0
package size:    1.95MB → 2.0MB  (+50KB)
unpacked size:   7.6MB → 7.8MB   (+200KB)
total files:     1218  → 1232    (+14)
```

The +14 files: 4 new TS source + 4 SaaS skills + 2 test files + 2 docs + 2 dist artifacts.

## Upgrade

```bash
openlife update --global

# Verify
openlife --version             # 1.18.0
openlife ship --help            # 6 flags
openlife deploy --help          # 5 flags + 2 subcommands
openlife deploy list            # vercel + railway adapter status
```

## File summary

**New (10):**
- `src/cli/ShipCommand.ts`
- `src/cli/DeployCommand.ts`
- `src/orchestrator/deploy/DeployAdapter.ts`
- `src/orchestrator/deploy/VercelAdapter.ts`
- `src/orchestrator/deploy/RailwayAdapter.ts`
- `.catalog/skills/clerk-wire/SKILL.md`
- `.catalog/skills/stripe-billing-wire/SKILL.md`
- `.catalog/skills/supabase-rls-wire/SKILL.md`
- `.catalog/skills/vercel-deploy-wire/SKILL.md`
- `docs/v1.18-changelog.md`

**Tests (2):** `test_ship_command.ts`, `test_deploy_adapters.ts`

**Modified (3):**
- `src/orchestrator/util/GitOps.ts` — adds `push()` + `_authorizePush()`
  helper. Module-level `_pushAuthorized` flag gates the args-level
  refusal.
- `src/index.ts` — registers ShipCommand + DeployCommand lazily.
- `package.json` — 3 new test scripts + chain into `test:all`,
  `docs/v1.18-changelog.md` in `files[]`, version 1.17.0 → 1.18.0.

**Catalog stats:** 46 squads, 57 → 61 skills (+4 SaaS skills).

## Roadmap after v1.18

The v1.15→v1.18 SaaS Forge arc is **closed**. Next-up:

- **v1.18.1** — Cloudflare + Fly adapters, Railway native rollback, SvelteKit template
- **v1.19.0** — Multi-environment promote, AI-driven preflight remediation
- **Issue #9** — Cross-machine bridge (independent track)

## Closing note

OpenLife now has a coherent end-to-end story: design → scaffold →
autonomous-implement → ship → deploy. Every step is a composable CLI
command. Every step has safety boundaries. Every step has tests.

Per the project ethos: **"Not a chat. A practice."**
