docs(lanes): document ccam lanes sync-base (E2)

This commit is contained in:
2026-08-05 10:59:02 +07:00
parent 5a127df709
commit ed884c6961
3 changed files with 27 additions and 6 deletions
+4 -5
View File
@@ -83,8 +83,7 @@ Do NOT jump to code. Understand the requirement first.
### 2 — Pre-push CI gates + dev preflight (on the feature branch) ### 2 — Pre-push CI gates + dev preflight (on the feature branch)
- `ccam lanes hook ci-gate` — runs the profile's CI gate (lint / test / contract checks) against an isolated per-lane test DB. On failure: read the output, fix on the feature branch, commit, re-run. Loop until green. - `ccam lanes hook ci-gate` — runs the profile's CI gate (lint / test / contract checks) against an isolated per-lane test DB. On failure: read the output, fix on the feature branch, commit, re-run. Loop until green.
- `ccam lanes sync-base --check feat/<slug>` — the dev preflight: fetches and checks the branch against the CURRENT `origin/development` without merging anything. **This command is a LATER task, not yet built as of this skill's authoring** — until it exists, skip this preflight check and rely on Stage 12's conflict handling to catch a divergence at merge time; note this gap explicitly in your Stage 2 evidence (`ccam stage gates --evidence "sync-base preflight unavailable, skipped"`). - `ccam lanes sync-base --check feat/<slug>` — the dev preflight: fetches and checks the branch against the CURRENT `origin/development` without merging anything. Exit 5 on a migration-number collision: rename the printed file to the suggested number on the feature branch (`git mv`, update any in-file references), then re-run Stage 2. Exit 0 with `DEV_DELTA:`/`DEV_OVERLAP:` output otherwise — informational, you do NOT sync the branch for it (GitHub merges non-conflicting histories fine); a large overlapping delta is a heads-up that post-merge behavior may differ from what you test locally.
- Once built, its contract is: exit 5 on a migration-number collision (print the exact rename, do it on the feature branch, re-run Stage 2); informational `DEV_DELTA:`/`DEV_OVERLAP:` output otherwise (you do NOT sync the branch for it — GitHub merges non-conflicting histories fine).
### 3 — E2E on the feature branch ### 3 — E2E on the feature branch
The e2e hook doesn't run migrations itself — it tests the already-running stack. To exercise the feature's code and any new schema, boot the lane stack with the feature branch first: The e2e hook doesn't run migrations itself — it tests the already-running stack. To exercise the feature's code and any new schema, boot the lane stack with the feature branch first:
@@ -124,7 +123,7 @@ The e2e hook doesn't run migrations itself — it tests the already-running stac
### 8 — Publish: push branch + open/update PR *(GATED — only on GO)* ### 8 — Publish: push branch + open/update PR *(GATED — only on GO)*
- `ccam stage publishing --status running` - `ccam stage publishing --status running`
- Re-run the preflight if `ccam lanes sync-base` exists by the time you read this — development may have moved while you were in QC. If it doesn't exist yet, skip straight to the push (same gap noted in Stage 2). - Re-run the preflight: `ccam lanes sync-base --check feat/<slug>` — development may have moved while you were in QC. A migration collision here (exit 5) sends you back to Stage 2 with the rename; a clean result (exit 0) proceeds to the push.
- `git push -u origin feat/<slug>` — first push of the feature branch to remote. All gates have passed before this point; the PR is finalized before reviewers see it. - `git push -u origin feat/<slug>` — first push of the feature branch to remote. All gates have passed before this point; the PR is finalized before reviewers see it.
- Open or update the PR **based on and targeting `development`**: `gh pr create --base development --fill` (or `gh pr edit` / the push itself if a prior run already created it). Capture the URL. - Open or update the PR **based on and targeting `development`**: `gh pr create --base development --fill` (or `gh pr edit` / the push itself if a prior run already created it). Capture the URL.
- `ccam stage pr-open --evidence "<pr-url>"` — the dashboard shows the PR link from here (via `--evidence` in `ccam feature show`/`ccam lanes`). - `ccam stage pr-open --evidence "<pr-url>"` — the dashboard shows the PR link from here (via `--evidence` in `ccam feature show`/`ccam lanes`).
@@ -152,8 +151,8 @@ The e2e hook doesn't run migrations itself — it tests the already-running stac
- `MERGED` → a human merged it: go to **Stage 13** (post-merge verification). - `MERGED` → a human merged it: go to **Stage 13** (post-merge verification).
- `CLOSED` (unmerged) → the human rejected/abandoned it: `ccam stage done --status passed --note "PR closed unmerged by human"` → STOP. - `CLOSED` (unmerged) → the human rejected/abandoned it: `ccam stage done --status passed --note "PR closed unmerged by human"` → STOP.
- `CONFLICTING` → the feature branch conflicts with `development`. Resolve it as real work: - `CONFLICTING` → the feature branch conflicts with `development`. Resolve it as real work:
- If `ccam lanes sync-base` exists by now: `ccam lanes sync-base feat/<slug>` (merges the latest `origin/development` INTO the feature branch — the only sanctioned merge). Resolve every conflict thoughtfully — keep `development`'s behavior for code unrelated to this feature, preserve the feature's intent where they overlap; when genuinely ambiguous, STOP and escalate (`--status blocked`, note the files) rather than guess. `git add` ONLY the conflicted files, `git commit --no-edit`. - `ccam lanes sync-base feat/<slug>` (merges the latest `origin/development` INTO the feature branch — the only sanctioned merge). A migration-number collision (exit 5) means nothing was merged — rename the printed file on the feature branch, re-run Stage 2, then retry this step.
- If it doesn't exist yet: `git fetch origin && git merge origin/development` directly on the feature branch, resolve conflicts the same way, commit. - **Exit 4 — merge conflict, left in place on purpose.** Resolve every conflict thoughtfully on the feature branch — keep `development`'s behavior for code unrelated to this feature, preserve the feature's intent where they overlap; when genuinely ambiguous, STOP and escalate (`--status blocked`, note the files) rather than guess. Never hand-merge a generated contract/client file listed in the profile's `GENERATED_MERGE_PATHS` — the keep-ours driver + regen own them. `git add` ONLY the conflicted files, `git commit --no-edit`, then `ccam lanes sync-base --continue feat/<slug>` (folds any regenerated artifacts into a follow-up commit).
- Re-enter the pipeline **from Stage 2 through Stage 8** (the push updates the PR), then return here and keep watching. - Re-enter the pipeline **from Stage 2 through Stage 8** (the push updates the PR), then return here and keep watching.
- For each new PR comment (list with `gh pr view <pr_url> --json comments`, tracking which you've already handled by comment id in your own notes), triage AND **always reply on its thread** (every comment gets a response — no silent handling, so reviewers see it was considered): - For each new PR comment (list with `gh pr view <pr_url> --json comments`, tracking which you've already handled by comment id in your own notes), triage AND **always reply on its thread** (every comment gets a response — no silent handling, so reviewers see it was considered):
- **Worth fixing** (reviewer-requested change, real bug, test/doc gap): this is a NEW CHANGE — apply it on the feature branch and re-enter the pipeline **from Stage 2 through Stage 8** (+ Stage 10 CI watch). The full process applies; no shortcuts because "it's just review feedback". **After the fix is pushed, reply to the comment** confirming resolution — what changed + the commit/PR ref — by writing the reply to a file and posting `gh pr comment <pr_url> --body-file <path>` referencing the comment. **Never inline `--body "..."`** — bodies carry backticks/`file:line`/`$(...)` that bash reads as command substitution inside double quotes, which corrupts the comment and trips an approval prompt. Then come back here and keep watching. - **Worth fixing** (reviewer-requested change, real bug, test/doc gap): this is a NEW CHANGE — apply it on the feature branch and re-enter the pipeline **from Stage 2 through Stage 8** (+ Stage 10 CI watch). The full process applies; no shortcuts because "it's just review feedback". **After the fix is pushed, reply to the comment** confirming resolution — what changed + the commit/PR ref — by writing the reply to a file and posting `gh pr comment <pr_url> --body-file <path>` referencing the comment. **Never inline `--body "..."`** — bodies carry backticks/`file:line`/`$(...)` that bash reads as command substitution inside double quotes, which corrupts the comment and trips an approval prompt. Then come back here and keep watching.
+22
View File
@@ -1013,6 +1013,28 @@ QC_BOOT_ENV="MOCK_PAYMENTS=1 STUB_EMAIL=1"
These environment variables are passed to the profile's `boot` hook during `ccam lanes up --qc`, ensuring QC test runs are deterministic. These environment variables are passed to the profile's `boot` hook during `ccam lanes up --qc`, ensuring QC test runs are deterministic.
### Dev preflight and merge safety: sync-base
`ccam lanes sync-base` is the ONE sanctioned merge in the pipeline — `origin/development` into a feature branch — used at Stages 2, 8, and 12. Three modes:
```bash
ccam lanes sync-base --check feat/<slug> # read-only preflight: fetch + collision check + DEV_DELTA/DEV_OVERLAP
ccam lanes sync-base feat/<slug> # merge origin/development into the feature branch
ccam lanes sync-base --continue feat/<slug> # finish after a manually resolved conflict
```
Exit codes: `0` clean, `4` merge conflict (left in place — resolve, commit, then `--continue`), `5` migration-number collision (nothing merged — rename the printed file, re-run).
Two profile declarations control it, both empty (off) by default:
```bash
# .ccam/profile/profile.env
MIGRATIONS_DIR="db/migrations"
GENERATED_MERGE_PATHS="api/openapi.json api/client.ts"
```
`MIGRATIONS_DIR` enables the collision preflight against a numbered-migrations directory. `GENERATED_MERGE_PATHS` gives the listed files a keep-ours merge driver (never hand-merged) and folds the profile's `regen` hook output into the sync commit — the single most common cross-lane conflict, for a repo that generates an API contract/client.
### Pipeline template: ship-feature (16 node stages) ### Pipeline template: ship-feature (16 node stages)
The skill uses the `ship-feature` pipeline template, which defines the following 16 stages (node IDs): The skill uses the `ship-feature` pipeline template, which defines the following 16 stages (node IDs):
@@ -279,7 +279,7 @@ with `LOCK_MAX_HOLD=1`; release from a non-holder is refused and leaves the lock
**Goal:** port Shipyard's driving skill and its five agents. Needs A2·B·C·D. **Goal:** port Shipyard's driving skill and its five agents. Needs A2·B·C·D.
**Progress:** pipeline template + skill text (E1) done 2026-08-04 — see `docs/superpowers/specs/2026-08-04-ship-feature-skill-design.md`. Agents, `sync-base`, and F's integrations remain. **Progress:** pipeline template + skill text (E1) done 2026-08-04 — see `docs/superpowers/specs/2026-08-04-ship-feature-skill-design.md`. `sync-base` (E2) done 2026-08-05 — see `docs/superpowers/specs/2026-08-05-sync-base-design.md`. Agents and F's integrations remain.
**This is where "CCAM does not orchestrate" is preserved by construction:** the **This is where "CCAM does not orchestrate" is preserved by construction:** the
skill runs in the session and calls `ccam` commands; the dashboard still only skill runs in the session and calls `ccam` commands; the dashboard still only