|
18 | 18 |
|
19 | 19 | ## PR Workflow |
20 | 20 |
|
21 | | -1. **Routine Pre-PR Validation**: `pnpm check:full`, it wipes derived state and regenerates from scratch. If `ccc-dev/ccc/` has pending work, the wipe is skipped to prevent data loss — re-record or push CCC changes first for a clean validation |
| 21 | +1. **Routine Pre-PR Validation**: `pnpm check:full`, it wipes derived state and regenerates from scratch. If any fork clone has pending work, the wipe is skipped to prevent data loss — re-record or push fork changes first for a clean validation |
22 | 22 | 2. **Open a PR**: Run `pnpm changeset` to generate a changeset entry, then push the branch and present a clickable markdown link `[title](url)` where the URL is a GitHub compare URL (`quick_pull=1`). Base branch is `master`. Prefill "title" (concise, under 70 chars) and "body" (markdown with ## Why and ## Changes sections) |
23 | 23 | 3. **Fetch PR review comments**: Use the GitHub REST API via curl. Fetch all three comment types (issue comments, reviews, and inline comments). Categorize feedback by actionability (action required / informational), not by source (human / bot). Reviewers reply asynchronously — poll every minute until comments arrive |
24 | 24 |
|
25 | | -## CCC Local Development (ccc-dev/) |
| 25 | +## Fork Management (fork-scripts/ + *-fork/) |
26 | 26 |
|
27 | | -The `ccc-dev/` system uses a record/replay mechanism for deterministic builds of a local CCC fork: |
| 27 | +The `fork-scripts/` system uses a record/replay mechanism for deterministic builds of external repo forks. Each fork lives in a `<name>-fork/` directory with a `config.json` specifying upstream URL, fork URL, merge refs, and workspace config. Scripts in `fork-scripts/` are generic and accept the fork directory as their first argument. |
28 | 28 |
|
29 | | -- `ccc-dev/pins/` is **committed** to git (base SHAs, merge refs, conflict resolutions, local patches), regenerated by `pnpm ccc:record` |
30 | | -- `ccc-dev/ccc/` is **not in git** — it is rebuilt from pins on `pnpm install` |
31 | | -- The developer may have **pending work** in `ccc-dev/ccc/`. Run `pnpm ccc:status` (exit 0 = safe to wipe, exit 1 = has custom work) before any operation that would destroy it. `pnpm ccc:record`, `pnpm ccc:clean`, and `pnpm ccc:reset` already guard against this automatically |
32 | | -- `.pnpmfile.cjs` silently rewrites all `@ckb-ccc/*` dependencies to `workspace:*` when `ccc-dev/ccc/` exists. Local CCC packages override published ones without any visible change in package.json files |
33 | | -- `pnpm install` has a side effect: if `ccc-dev/pins/REFS` exists but `ccc-dev/ccc/` does not, it automatically runs `ccc-dev/replay.sh` to rebuild CCC from pins. This is intentional |
34 | | -- `ccc-dev/patch.sh` rewrites CCC package exports to point at `.ts` source instead of `.d.ts`, then creates a deterministic git commit (fixed author/date) so record and replay produce the same `pins/HEAD` hash. This is why imports from `@ckb-ccc/*` resolve to TypeScript source files inside `node_modules` — it is not a bug |
35 | | -- `ccc-dev/tsgo-filter.sh` is a bash wrapper around `tsgo` that filters out diagnostics originating from `ccc-dev/ccc/`. CCC source does not satisfy this repo's strict tsconfig (`verbatimModuleSyntax`, `noUncheckedIndexedAccess`, `noImplicitOverride`), so the wrapper suppresses those errors while still reporting errors in stack source |
| 29 | +### Per-fork directory structure |
36 | 30 |
|
37 | | -### Opening a CCC upstream PR |
| 31 | +Each `<name>-fork/` contains: |
| 32 | +- `config.json` — upstream URL, fork URL, refs to merge, cloneDir, workspace include/exclude |
| 33 | +- `pins/` — **committed** to git (manifest + counted resolutions + local patches), regenerated by `pnpm fork:record <name>-fork` |
| 34 | + - `pins/HEAD` — expected final SHA after full replay |
| 35 | + - `pins/manifest` — base SHA + merge refs (TSV, one per line) |
| 36 | + - `pins/res-N.resolution` — conflict resolution for merge step N (counted format: `--- path` file headers, `CONFLICT ours=N base=M theirs=K resolution=R` conflict headers followed by R resolution lines; parser is purely positional — reads counts and skips lines, never inspects content) |
| 37 | + - `pins/local-*.patch` — local development patches (applied after merges + patch.sh) |
| 38 | +- `<cloneDir>/` — **not in git** — rebuilt from pins on `pnpm install` |
38 | 39 |
|
39 | | -In `ccc-dev/ccc/`, branch off `origin/master` (or relevant branch), push to fork (`phroi/ccc`), open PR against `ckb-devrel/ccc`. Before pushing, run the CCC CI steps (`ccc-dev/ccc/.github/workflows/check.yaml`) with `CI=true`. |
| 40 | +### Key behaviors |
40 | 41 |
|
41 | | -Once the PR is open, replace the local patch with a merge ref: |
| 42 | +- The developer may have **pending work** in a fork clone. Run `pnpm fork:status <name>-fork` (exit 0 = safe to wipe, exit 1 = has custom work) before any operation that would destroy it. `fork:record`, `fork:clean`, and `fork:reset` already guard against this automatically |
| 43 | +- `.pnpmfile.cjs` scans all `*-fork/config.json` directories and silently rewrites matching dependencies to `workspace:*` when clones exist. Local fork packages override published ones without any visible change in package.json files |
| 44 | +- `pnpm install` has a side effect: if `<name>-fork/pins/manifest` exists but the clone does not, it automatically runs `fork-scripts/replay.sh` to rebuild from pins. This is intentional |
| 45 | +- `fork-scripts/patch.sh` rewrites fork package exports to point at `.ts` source instead of `.d.ts`, then creates a deterministic git commit (fixed author/date) so record and replay produce the same HEAD hash. This is why imports from fork packages resolve to TypeScript source files — it is not a bug |
| 46 | +- `fork-scripts/tsgo-filter.sh` is a bash wrapper around `tsgo` that filters out diagnostics originating from all `*-fork/` clone paths. Fork source may not satisfy this repo's strict tsconfig, so the wrapper suppresses those errors while still reporting errors in stack source |
| 47 | +- `pnpm fork:save <name>-fork [description]` captures local work as a patch in `pins/`. Patches survive re-records and replays |
| 48 | +- `pnpm fork:record` regenerates the fork workspace entries in `pnpm-workspace.yaml` (between `@generated` markers) from all `*-fork/config.json` files — manual edits to that section are overwritten on re-record |
42 | 49 |
|
43 | | -1. Delete the patch from `ccc-dev/pins/local/` |
44 | | -2. Add the PR number to `ccc:record` in `package.json` — order PRs by target branch from upstream to downstream, so each group merges cleanly onto its base before the next layer begins |
45 | | -3. Run `pnpm ccc:record` |
46 | | -4. Run `pnpm check:full` to verify the merge ref reproduces what the local patch achieved |
| 50 | +### CCC upstream contributions |
| 51 | +
|
| 52 | +Work locally via `ccc-fork/` first. Only push to the fork (`phroi/ccc`) when changes are validated against the stack. Do not open PRs against `ckb-devrel/ccc` prematurely — keep changes on the fork until they are production-ready and the maintainer decides to upstream. |
| 53 | +
|
| 54 | +1. Develop and test in `ccc-fork/ccc/` on the `wip` branch |
| 55 | +2. When ready, use `pnpm fork:push ccc-fork` to cherry-pick commits onto a PR branch |
| 56 | +3. Push the PR branch to `phroi/ccc` for review |
| 57 | +4. Add the PR number to `refs` in `ccc-fork/config.json` — order PRs by target branch from upstream to downstream, so each group merges cleanly onto its base before the next layer begins |
| 58 | +5. Run `pnpm fork:record ccc-fork` and `pnpm check:full` to verify |
| 59 | +6. Only open an upstream PR against `ckb-devrel/ccc` when the maintainer explicitly decides to upstream |
47 | 60 |
|
48 | 61 | ## Reference Repos |
49 | 62 |
|
|
0 commit comments