codebyplan 1.11.2 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +590 -405
- package/package.json +1 -1
- package/templates/hooks/README.md +1 -13
- package/templates/hooks/cbp-statusline.mjs +44 -0
- package/templates/hooks/cbp-statusline.py +24 -2
- package/templates/hooks/cbp-statusline.sh +22 -2
- package/templates/hooks/cbp-test-coverage-gate.sh +8 -0
- package/templates/hooks/cbp-test-hooks.sh +0 -42
- package/templates/hooks/hooks.json +0 -9
- package/templates/rules/README.md +8 -1
- package/templates/rules/supabase-branch-lifecycle.md +99 -0
- package/templates/settings.project.base.json +1 -2
- package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +1 -2
- package/templates/skills/cbp-checkpoint-create/SKILL.md +2 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +27 -5
- package/templates/skills/cbp-checkpoint-start/SKILL.md +2 -2
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +17 -1
- package/templates/skills/cbp-session-start/SKILL.md +28 -3
- package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/SKILL.md +1 -1
- package/templates/skills/cbp-setup-eslint/SKILL.md +199 -0
- package/templates/skills/cbp-setup-eslint/reference/base.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/cli.md +56 -0
- package/templates/skills/cbp-setup-eslint/reference/e2e.md +68 -0
- package/templates/skills/cbp-setup-eslint/reference/jest.md +59 -0
- package/templates/skills/cbp-setup-eslint/reference/nestjs.md +69 -0
- package/templates/skills/cbp-setup-eslint/reference/nextjs.md +63 -0
- package/templates/skills/cbp-setup-eslint/reference/node.md +74 -0
- package/templates/skills/cbp-setup-eslint/reference/react-native.md +60 -0
- package/templates/skills/cbp-setup-eslint/reference/react.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/tailwind.md +64 -0
- package/templates/skills/cbp-setup-eslint/reference/testing-react.md +57 -0
- package/templates/skills/cbp-setup-eslint/reference/vitest.md +62 -0
- package/templates/skills/cbp-ship-main/SKILL.md +13 -0
- package/templates/skills/cbp-supabase-branch-check/SKILL.md +12 -5
- package/templates/skills/cbp-supabase-migrate/SKILL.md +139 -9
- package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +1 -1
- package/templates/skills/cbp-supabase-setup/SKILL.md +13 -7
- package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +2 -2
- package/templates/skills/cbp-task-complete/SKILL.md +1 -3
- package/templates/skills/cbp-task-start/SKILL.md +5 -3
- package/templates/hooks/cbp-mcp-worktree-inject.sh +0 -76
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/maestro.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/playwright.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/tauri.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/vscode.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/xcuitest.md +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# react-native — React Native / Expo flat config
|
|
2
|
+
|
|
3
|
+
For Expo / React Native apps (the CBP `livebyplan` mobile app). **Gap stack — no CBP DB
|
|
4
|
+
preset.** Use Expo's official lint config.
|
|
5
|
+
|
|
6
|
+
> **Verified 2026-05-31.** `eslint-config-expo` is the official config and ships **flat config
|
|
7
|
+
> by default from Expo SDK 53** onward (SDK 52 and earlier use legacy `.eslintrc`).
|
|
8
|
+
|
|
9
|
+
## Packages
|
|
10
|
+
|
|
11
|
+
| Package | Latest | Purpose |
|
|
12
|
+
| ------- | ------ | ------- |
|
|
13
|
+
| `eslint-config-expo` | `56.0.4` | Expo's flat config (`/flat` subpath) |
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx expo lint # installs eslint + eslint-config-expo and scaffolds eslint.config.js
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`eslint-config-expo` bundles `eslint-plugin-expo`, `eslint-plugin-react`,
|
|
20
|
+
`eslint-plugin-react-hooks`, `eslint-plugin-import`, and `@typescript-eslint/*`. It does **not**
|
|
21
|
+
bundle `eslint-plugin-react-native` (that's a separate optional add-on, `@5.0.0`).
|
|
22
|
+
|
|
23
|
+
## Flat config
|
|
24
|
+
|
|
25
|
+
Expo's template is **CommonJS `eslint.config.js`** (not `.mjs`):
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
// eslint.config.js
|
|
29
|
+
const { defineConfig } = require("eslint/config");
|
|
30
|
+
const expoConfig = require("eslint-config-expo/flat");
|
|
31
|
+
const eslintPluginPrettierRecommended = require("eslint-plugin-prettier/recommended");
|
|
32
|
+
|
|
33
|
+
module.exports = defineConfig([
|
|
34
|
+
expoConfig,
|
|
35
|
+
eslintPluginPrettierRecommended,
|
|
36
|
+
{ ignores: ["dist/*"] },
|
|
37
|
+
]);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Minimal form (no Prettier): just `expoConfig` in the array.
|
|
41
|
+
|
|
42
|
+
## Gotchas
|
|
43
|
+
|
|
44
|
+
- RN platform support comes from RN global variables + platform file extensions
|
|
45
|
+
(`.android.ts`, `.ios.ts`, `.web.ts`) and `eslint-plugin-expo` — **not** from
|
|
46
|
+
`eslint-plugin-react-native`. Add `eslint-plugin-react-native@5.0.0` manually only if you
|
|
47
|
+
want RN-specific rules (`no-inline-styles`, `no-unused-styles`).
|
|
48
|
+
- Run linting with `npx expo lint` (it wires the config the first time).
|
|
49
|
+
- Expo apps test with **Jest** — add the [jest.md](jest.md) override.
|
|
50
|
+
|
|
51
|
+
## CBP preset divergence
|
|
52
|
+
|
|
53
|
+
There is **no** CBP `react-native`/`expo` DB preset, and the `react` preset `excludes`
|
|
54
|
+
nothing for RN but is browser-globals oriented. Use `eslint-config-expo/flat` directly; the
|
|
55
|
+
skill does not add a preset for this stack.
|
|
56
|
+
|
|
57
|
+
## Official docs
|
|
58
|
+
|
|
59
|
+
- Using ESLint in Expo: https://docs.expo.dev/guides/using-eslint/
|
|
60
|
+
- eslint-config-expo: https://github.com/expo/expo/tree/main/packages/eslint-config-expo
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# react — standalone React (Vite, Tauri) flat config
|
|
2
|
+
|
|
3
|
+
For React apps that are **not** Next.js (Vite SPA, Tauri desktop webview). Layers on
|
|
4
|
+
[base](base.md). Maps to the CBP **`react`** DB preset
|
|
5
|
+
(`tech_match.requires: ["React"]`, `excludes: ["Next.js"]`, `requires_capabilities: ["jsx"]`).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** **Do NOT install `eslint-plugin-react-compiler`** — it is
|
|
8
|
+
> superseded. React Compiler v1.0 (Oct 2025) merged the compiler lint rules into
|
|
9
|
+
> **`eslint-plugin-react-hooks@7`** under `configs.flat["recommended-latest"]`.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Purpose |
|
|
14
|
+
| ------- | ------ | ------- |
|
|
15
|
+
| `eslint-plugin-react` | `7.37.5` | React rules + JSX parsing (`configs.flat.*`) |
|
|
16
|
+
| `eslint-plugin-react-hooks` | `7.1.1` | hooks rules **+ bundled React Compiler rules** |
|
|
17
|
+
| `eslint-plugin-jsx-a11y` | `6.10.2` | accessibility (`flatConfigs.*` — note plural) |
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y globals
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Flat config
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// eslint.config.mjs
|
|
27
|
+
import { defineConfig } from "eslint/config";
|
|
28
|
+
import react from "eslint-plugin-react";
|
|
29
|
+
import reactHooks from "eslint-plugin-react-hooks";
|
|
30
|
+
import jsxA11y from "eslint-plugin-jsx-a11y";
|
|
31
|
+
import globals from "globals";
|
|
32
|
+
|
|
33
|
+
export default defineConfig([
|
|
34
|
+
react.configs.flat.recommended, // namespaced react/, enables JSX parsing
|
|
35
|
+
react.configs.flat["jsx-runtime"], // React 17+ automatic JSX transform
|
|
36
|
+
reactHooks.configs.flat["recommended-latest"], // hooks + React Compiler rules
|
|
37
|
+
jsxA11y.flatConfigs.strict, // or flatConfigs.recommended
|
|
38
|
+
{
|
|
39
|
+
files: ["**/*.{js,jsx,ts,tsx}"],
|
|
40
|
+
languageOptions: { globals: globals.browser },
|
|
41
|
+
settings: { react: { version: "detect" } },
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
|
|
48
|
+
- **`eslint-plugin-react` flat configs do not set `files` or globals** — add your own
|
|
49
|
+
`files`/`globals.browser`/`settings.react.version` object (shown above) or you'll get the
|
|
50
|
+
"React version not specified" warning and no JSX globals.
|
|
51
|
+
- **`eslint-plugin-react-hooks` v7 keys** live under `configs.flat.*`:
|
|
52
|
+
`recommended` (standard hooks) vs `recommended-latest` (hooks **+ compiler** rules — use
|
|
53
|
+
this for React 19 + the compiler).
|
|
54
|
+
- **`jsx-a11y` uses `flatConfigs` (plural)** — `jsxA11y.flatConfigs.strict`, a different
|
|
55
|
+
namespace from react's `configs.flat`.
|
|
56
|
+
|
|
57
|
+
## Storybook (bonus)
|
|
58
|
+
|
|
59
|
+
If the app uses Storybook, add `eslint-plugin-storybook@10.4.1`:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import storybook from "eslint-plugin-storybook";
|
|
63
|
+
// ...spread into the array:
|
|
64
|
+
...storybook.configs["flat/recommended"],
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The standalone plugin repo was archived (2025-11); it now lives in the Storybook monorepo but
|
|
68
|
+
the npm name `eslint-plugin-storybook` is unchanged.
|
|
69
|
+
|
|
70
|
+
## CBP preset divergence
|
|
71
|
+
|
|
72
|
+
CBP's `react` preset still depends on `eslint-plugin-react-compiler: ^19.0.0` and registers
|
|
73
|
+
`react-compiler/react-compiler`. The latest guidance removes that plugin and relies on
|
|
74
|
+
`eslint-plugin-react-hooks@7`'s `recommended-latest`. Adopt that when regenerating; the skill
|
|
75
|
+
does not modify the preset.
|
|
76
|
+
|
|
77
|
+
## Official docs
|
|
78
|
+
|
|
79
|
+
- eslint-plugin-react: https://github.com/jsx-eslint/eslint-plugin-react
|
|
80
|
+
- react-hooks: https://react.dev/reference/eslint-plugin-react-hooks
|
|
81
|
+
- React Compiler v1.0: https://react.dev/blog/2025/10/07/react-compiler-1
|
|
82
|
+
- jsx-a11y: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# tailwind — Tailwind CSS class linting
|
|
2
|
+
|
|
3
|
+
For apps using Tailwind CSS (the CBP `tarkur` repo uses Tailwind + shadcn/ui). **Gap stack —
|
|
4
|
+
no CBP DB preset.** Adds class-sorting / validation rules on top of the app's base config.
|
|
5
|
+
|
|
6
|
+
> **Verified 2026-05-31.** Use **`eslint-plugin-better-tailwindcss`** — it is the only plugin
|
|
7
|
+
> with first-class **Tailwind v4** + ESLint 9/10 flat-config support. The original
|
|
8
|
+
> `eslint-plugin-tailwindcss` only handles v4 on an unstable alpha — **avoid it for v4.**
|
|
9
|
+
|
|
10
|
+
## Packages
|
|
11
|
+
|
|
12
|
+
| Package | Latest | Tailwind v4? | Verdict |
|
|
13
|
+
| ------- | ------ | ------------ | ------- |
|
|
14
|
+
| `eslint-plugin-better-tailwindcss` | `4.5.0` | **yes (stable)** | **use this** |
|
|
15
|
+
| `eslint-plugin-tailwindcss` | `3.18.3` (v4 only on `4.0.0-alpha`) | beta/as-is | avoid for v4 |
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add -D eslint-plugin-better-tailwindcss
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Peer deps: `eslint ^7 || ^8 || ^9 || ^10`, `tailwindcss ^3.3.0 || ^4.1.17`. Node ≥ 20.19.
|
|
22
|
+
|
|
23
|
+
## Flat config
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// eslint.config.mjs
|
|
27
|
+
import { defineConfig } from "eslint/config";
|
|
28
|
+
import betterTailwind from "eslint-plugin-better-tailwindcss";
|
|
29
|
+
|
|
30
|
+
export default defineConfig([
|
|
31
|
+
{
|
|
32
|
+
extends: [betterTailwind.configs["recommended"]],
|
|
33
|
+
settings: {
|
|
34
|
+
"better-tailwindcss": {
|
|
35
|
+
// Tailwind v4: path to the CSS file with `@import "tailwindcss"`
|
|
36
|
+
entryPoint: "src/app/globals.css",
|
|
37
|
+
// Tailwind v3 ONLY (omit for v4):
|
|
38
|
+
// tailwindConfig: "tailwind.config.js",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
]);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Gotchas
|
|
46
|
+
|
|
47
|
+
- **`settings.entryPoint` is REQUIRED for Tailwind v4** — it points at the global CSS file
|
|
48
|
+
containing `@import "tailwindcss"` (v4 has no JS config file). For v3, use `tailwindConfig`
|
|
49
|
+
instead.
|
|
50
|
+
- **Monorepo**: set `settings["better-tailwindcss"].cwd` per file-group so the plugin resolves
|
|
51
|
+
`tailwindcss` + the config from the correct project dir when ESLint runs from the repo root.
|
|
52
|
+
- Config presets: `recommended`, `correctness` (errors), `stylistic` (warnings); severity
|
|
53
|
+
suffixes `-error` / `-warn`.
|
|
54
|
+
- Non-JSX file types (Svelte/Vue/Astro/HTML) need the matching `languageOptions.parser`.
|
|
55
|
+
|
|
56
|
+
## CBP preset divergence
|
|
57
|
+
|
|
58
|
+
There is **no** CBP `tailwind` DB preset — Tailwind linting is entirely manual. `tarkur`
|
|
59
|
+
currently has no Tailwind ESLint rules; add the block above to lint class order/validity.
|
|
60
|
+
|
|
61
|
+
## Official docs
|
|
62
|
+
|
|
63
|
+
- eslint-plugin-better-tailwindcss: https://github.com/schoero/eslint-plugin-better-tailwindcss
|
|
64
|
+
- Settings: https://github.com/schoero/eslint-plugin-better-tailwindcss/blob/main/docs/settings/settings.md
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# testing-react — Testing Library + jest-dom rules
|
|
2
|
+
|
|
3
|
+
For React component tests (Testing Library assertions). Layers a **test-scoped** override on
|
|
4
|
+
top of [base](base.md) + the test-runner doc ([vitest](vitest.md) or [jest](jest.md)). Maps to
|
|
5
|
+
the CBP **`testing-react`** DB preset
|
|
6
|
+
(`tech_match.requires: ["React", "Vitest"]`, `requires_capabilities: ["jsx"]`).
|
|
7
|
+
|
|
8
|
+
> **Verified 2026-05-31.** Both plugins use bracketed `configs['flat/...']` keys and each
|
|
9
|
+
> spreads its own plugin registration — keep them as **separate array entries**.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Purpose |
|
|
14
|
+
| ------- | ------ | ------- |
|
|
15
|
+
| `eslint-plugin-testing-library` | `7.16.2` | Testing Library best-practices |
|
|
16
|
+
| `eslint-plugin-jest-dom` | `5.5.0` | `@testing-library/jest-dom` matchers |
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add -D eslint-plugin-testing-library eslint-plugin-jest-dom
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Flat config
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
// eslint.config.mjs
|
|
26
|
+
import testingLibrary from "eslint-plugin-testing-library";
|
|
27
|
+
import jestDom from "eslint-plugin-jest-dom";
|
|
28
|
+
|
|
29
|
+
const TEST_GLOBS = ["**/*.{test,spec}.{ts,tsx,js,jsx}", "**/__tests__/**/*.{ts,tsx,js,jsx}"];
|
|
30
|
+
|
|
31
|
+
export default [
|
|
32
|
+
{ files: TEST_GLOBS, ...testingLibrary.configs["flat/react"] }, // 'flat/dom' for non-React
|
|
33
|
+
{ files: TEST_GLOBS, ...jestDom.configs["flat/recommended"] },
|
|
34
|
+
];
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Gotchas
|
|
38
|
+
|
|
39
|
+
- Keep the two as **separate array entries** — each `...config` spread re-declares its own
|
|
40
|
+
`plugins`. Merging them into one object means you must hand-combine `plugins` + `rules`.
|
|
41
|
+
- `eslint-plugin-testing-library` framework presets: `flat/react`, `flat/dom` (agnostic),
|
|
42
|
+
`flat/vue`, `flat/angular`, `flat/svelte`, `flat/marko` — pick **one**.
|
|
43
|
+
- Scope to the **same test globs** as your runner override so the rules don't bleed onto
|
|
44
|
+
production code.
|
|
45
|
+
- Don't let Playwright e2e specs hit `testing-library/*` rules (e.g.
|
|
46
|
+
`prefer-screen-queries` mis-fires on Playwright's `page.getByRole`) — scope to `src/**`
|
|
47
|
+
unit tests, not the e2e dir (see [e2e.md](e2e.md)).
|
|
48
|
+
|
|
49
|
+
## CBP preset divergence
|
|
50
|
+
|
|
51
|
+
The CBP `testing-react` preset matches this (`eslint-plugin-testing-library: ^7.0.0`,
|
|
52
|
+
`eslint-plugin-jest-dom: ^5.0.0`, `flat/react` + `flat/recommended`). No divergence.
|
|
53
|
+
|
|
54
|
+
## Official docs
|
|
55
|
+
|
|
56
|
+
- testing-library: https://github.com/testing-library/eslint-plugin-testing-library
|
|
57
|
+
- jest-dom: https://github.com/testing-library/eslint-plugin-jest-dom
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# vitest — Vitest test-file rules
|
|
2
|
+
|
|
3
|
+
For apps that test with Vitest (CBP web + CLI + most repos). Layers a **test-scoped** override
|
|
4
|
+
on top of [base](base.md). Maps to the CBP **`testing`** DB preset
|
|
5
|
+
(`tech_match.requires: ["Vitest"]`).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** The package was **renamed** to the scoped
|
|
8
|
+
> **`@vitest/eslint-plugin`** (the old `eslint-plugin-vitest` is the deprecated name). Its
|
|
9
|
+
> flat-config key is plain **`configs.recommended`** — there is **no `flat/` prefix**.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Purpose |
|
|
14
|
+
| ------- | ------ | ------- |
|
|
15
|
+
| `@vitest/eslint-plugin` | `1.6.18` | Vitest rules (scoped pkg) |
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add -D @vitest/eslint-plugin
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Flat config
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
// eslint.config.mjs
|
|
25
|
+
import vitest from "@vitest/eslint-plugin";
|
|
26
|
+
|
|
27
|
+
export default [
|
|
28
|
+
{
|
|
29
|
+
files: ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
|
|
30
|
+
plugins: { vitest },
|
|
31
|
+
rules: {
|
|
32
|
+
...vitest.configs.recommended.rules,
|
|
33
|
+
// tests are I/O-heavy + mock-heavy — relax type-safety on test files:
|
|
34
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
35
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
36
|
+
"@typescript-eslint/no-unsafe-member-access": "off",
|
|
37
|
+
"@typescript-eslint/no-unsafe-call": "off",
|
|
38
|
+
"@typescript-eslint/no-unsafe-argument": "off",
|
|
39
|
+
"@typescript-eslint/no-unsafe-return": "off",
|
|
40
|
+
},
|
|
41
|
+
settings: { vitest: { typecheck: true } }, // only if using Vitest type-testing
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
|
|
48
|
+
- The key is **`vitest.configs.recommended`** (plain) — NOT `configs['flat/recommended']`.
|
|
49
|
+
Other plugins use the bracketed `flat/` form; Vitest does not.
|
|
50
|
+
- When you spread only `.rules`, register `plugins: { vitest }` yourself. Alternatively spread
|
|
51
|
+
the whole `...vitest.configs.recommended` (carries the plugin registration).
|
|
52
|
+
- The `no-unsafe-*` / `no-explicit-any` opt-outs are CBP convention — production code keeps
|
|
53
|
+
them at `error`; test surfaces relax them because mocks produce `any`-typed values.
|
|
54
|
+
|
|
55
|
+
## CBP preset divergence
|
|
56
|
+
|
|
57
|
+
The CBP `testing` preset matches this (the six `no-unsafe-*`/`no-explicit-any` opt-outs,
|
|
58
|
+
`@vitest/eslint-plugin: ^1.0.0`). No divergence.
|
|
59
|
+
|
|
60
|
+
## Official docs
|
|
61
|
+
|
|
62
|
+
- @vitest/eslint-plugin: https://github.com/vitest-dev/eslint-plugin-vitest
|
|
@@ -52,6 +52,19 @@ Pass `--dry-run` through if the skill was invoked with a dry-run arg.
|
|
|
52
52
|
|
|
53
53
|
Parse JSON from Step 3. Report `pr_url`, `merge_commit`, `branch_deleted`. If `checks_failed: true`, surface `checks_failure_reason` and stop.
|
|
54
54
|
|
|
55
|
+
If `branch_deleted === true`, run a conditional Supabase preview-branch teardown for the feat branch that was just merged:
|
|
56
|
+
|
|
57
|
+
> Lifecycle contract: see [[supabase-branch-lifecycle]].
|
|
58
|
+
|
|
59
|
+
- Read `FEAT_BRANCH` from the `feat_branch` field in the Step 3 JSON output — NOT from `git branch --show-current`. By the time Step 4 runs, `codebyplan ship` has already checked out the base branch (unless `--keep-feat` was passed), so the live branch is the base, not the feat branch.
|
|
60
|
+
- Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
|
|
61
|
+
- Scan the returned list for an entry whose `name` exactly equals `$FEAT_BRANCH`.
|
|
62
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Report the Supabase delete outcome alongside `pr_url` / `merge_commit` / `branch_deleted`.
|
|
63
|
+
- If not found: no-op silently — the GitHub integration may have already removed the preview branch on PR close; not-found is success, NOT an error.
|
|
64
|
+
- If the `list_branches` call itself fails (network, auth, or a non-success response — distinct from a successful lookup that returns no match): emit a non-blocking warning that the Supabase preview branch for `$FEAT_BRANCH` may still exist and should be verified in the dashboard. Do not treat an API failure as a not-found success.
|
|
65
|
+
- Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
|
|
66
|
+
- This coordinates safely with `/cbp-checkpoint-end` — the existence-checked delete makes any second attempt a harmless no-op.
|
|
67
|
+
|
|
55
68
|
## Key Rules
|
|
56
69
|
|
|
57
70
|
- **Read branch names from config** — never hardcode "main"
|
|
@@ -62,10 +62,10 @@ Infer `TARGET` when absent:
|
|
|
62
62
|
|
|
63
63
|
## Step 1 — Read DB Paths Config
|
|
64
64
|
|
|
65
|
-
Read `.codebyplan.json` to obtain the configured DB path globs:
|
|
65
|
+
Read `.codebyplan/shipment.json` to obtain the configured DB path globs:
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
DB_PATHS=$(jq -r '.shipment.surfaces.supabase.db_paths[]? // empty' .codebyplan.json 2>/dev/null)
|
|
68
|
+
DB_PATHS=$(jq -r '.shipment.surfaces.supabase.db_paths[]? // empty' .codebyplan/shipment.json 2>/dev/null)
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
If `DB_PATHS` is empty, fall back to defaults:
|
|
@@ -80,11 +80,11 @@ Store each pattern as a separate entry for matching in Step 2.
|
|
|
80
80
|
|
|
81
81
|
## Step 2 — Detect DB-Path Changes
|
|
82
82
|
|
|
83
|
-
Resolve the BASE branch from `TARGET`. Read `.codebyplan.json`:
|
|
83
|
+
Resolve the BASE branch from `TARGET`. Read `.codebyplan/git.json`:
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
INTEGRATION=$(jq -r '.branch_config.integration // "development"' .codebyplan.json)
|
|
87
|
-
PRODUCTION=$(jq -r '.branch_config.production // "main"' .codebyplan.json)
|
|
86
|
+
INTEGRATION=$(jq -r '.branch_config.integration // "development"' .codebyplan/git.json)
|
|
87
|
+
PRODUCTION=$(jq -r '.branch_config.production // "main"' .codebyplan/git.json)
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
Set `BASE`:
|
|
@@ -156,6 +156,13 @@ Store as `PROJECT_REF`.
|
|
|
156
156
|
|
|
157
157
|
## Step 4 — Handle Missing project_ref
|
|
158
158
|
|
|
159
|
+
> **Note — Hybrid branch creation**: The preview branch may pre-exist as a CBP-created
|
|
160
|
+
> branch (named identically to the git branch, provisioned lazily by `cbp-supabase-migrate`
|
|
161
|
+
> on first DB change) rather than being auto-created by the GitHub integration on PR open.
|
|
162
|
+
> The by-name resolution in Step 3 works identically for both creation paths because both
|
|
163
|
+
> name the branch verbatim after the git branch. See [[supabase-branch-lifecycle]] for the
|
|
164
|
+
> full lifecycle contract.
|
|
165
|
+
|
|
159
166
|
If `PROJECT_REF` is empty after Step 3:
|
|
160
167
|
|
|
161
168
|
- `MODE=pre_pr_create`:
|
|
@@ -3,7 +3,7 @@ scope: org-shared
|
|
|
3
3
|
name: cbp-supabase-migrate
|
|
4
4
|
description: Scaffold or adopt a Supabase migration for the current PR branch, apply to the branch's preview DB, run advisor checks, regenerate TypeScript types. Includes a fresh-branch dry-run pre-flight that uses one persistent dry-run ephemeral branch per feature branch.
|
|
5
5
|
argument-hint: "[--new <name> | <path-to-sql>]"
|
|
6
|
-
allowed-tools: Read, Edit, Write, Bash(git *), Bash(supabase *), Bash(jq *), Bash(date *), Bash(which *), Bash(cp *), Bash(mv *), Bash(test *), Bash(ls *), mcp__supabase__apply_migration, mcp__supabase__list_migrations, mcp__supabase__get_advisors, mcp__supabase__generate_typescript_types, mcp__supabase__reset_branch, mcp__supabase__list_branches
|
|
6
|
+
allowed-tools: Read, Edit, Write, Bash(git *), Bash(supabase *), Bash(jq *), Bash(date *), Bash(which *), Bash(cp *), Bash(mv *), Bash(test *), Bash(ls *), mcp__supabase__apply_migration, mcp__supabase__list_migrations, mcp__supabase__get_advisors, mcp__supabase__generate_typescript_types, mcp__supabase__reset_branch, mcp__supabase__list_branches, mcp__supabase__create_branch, mcp__supabase__get_cost, mcp__supabase__confirm_cost, mcp__codebyplan__update_checkpoint, mcp__codebyplan__update_task
|
|
7
7
|
model: sonnet
|
|
8
8
|
effort: xhigh
|
|
9
9
|
---
|
|
@@ -61,11 +61,139 @@ Parse the output for:
|
|
|
61
61
|
- `POSTGRES_URL_NON_POOLING` — direct connection string for the preview DB
|
|
62
62
|
- `project_ref` — the Supabase project ref for this branch's environment
|
|
63
63
|
|
|
64
|
-
Capture both values. The `project_ref` is used
|
|
64
|
+
Capture both values. The `project_ref` is used from Step 3 onward; Step 2.3 may replace it with a `PREVIEW_PROJECT_REF` when it lazily provisions the branch. (Step 5.5 resolves its own separate dry-run branch `project_ref` — see [reference/preflight-dry-run.md](reference/preflight-dry-run.md).)
|
|
65
|
+
|
|
66
|
+
## Step 2.3 — Ensure Supabase Branch Exists
|
|
67
|
+
|
|
68
|
+
Couples the Supabase preview branch lifecycle to the git branch: when this skill runs on a
|
|
69
|
+
feat branch that touches the database, a Supabase branch named **exactly** the current git
|
|
70
|
+
branch is guaranteed to exist before any migration is applied. Naming it identically to the
|
|
71
|
+
git branch is the linchpin that lets the GitHub branching integration reconcile to the same
|
|
72
|
+
branch (no duplicate).
|
|
73
|
+
|
|
74
|
+
> Lifecycle contract: see [[supabase-branch-lifecycle]].
|
|
75
|
+
|
|
76
|
+
This step runs **before** Step 2.5: it lazily provisions the branch so that an empty
|
|
77
|
+
`project_ref` from Step 2 gets filled in. Step 2.5 then fires only when `project_ref` is
|
|
78
|
+
**still** empty after this step (i.e. this step was skipped or creation was declined).
|
|
79
|
+
|
|
80
|
+
### Guard 1 — feat-branch only
|
|
81
|
+
|
|
82
|
+
Read branch config from `.codebyplan/git.json`:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
PRODUCTION=$(jq -r '.branch_config.production // "main"' .codebyplan/git.json)
|
|
86
|
+
PROTECTED=$(jq -r '.branch_config.protected[]? // empty' .codebyplan/git.json)
|
|
87
|
+
INTEGRATION=$(jq -r '.branch_config.integration // empty' .codebyplan/git.json)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If `$BRANCH` equals `$PRODUCTION` or appears in `$PROTECTED`, skip this entire step — never
|
|
91
|
+
provision a Supabase branch for the production/protected branch. On `$PRODUCTION` the
|
|
92
|
+
`project_ref` from Step 2 is the parent project itself; Step 3's main-project guard handles
|
|
93
|
+
that case. (A standalone task pinned to the production branch is covered by this same check,
|
|
94
|
+
since its `$BRANCH` equals `$PRODUCTION`.)
|
|
95
|
+
|
|
96
|
+
If `$INTEGRATION` is non-empty and `$BRANCH` equals `$INTEGRATION`, skip this step — the
|
|
97
|
+
integration branch uses a persistent Supabase branch provisioned by `cbp-supabase-setup`,
|
|
98
|
+
not a lazy ephemeral one. Do NOT default or write `$INTEGRATION` to any value; only read and
|
|
99
|
+
skip.
|
|
100
|
+
|
|
101
|
+
### Guard 2 — DB-path / migration intent
|
|
102
|
+
|
|
103
|
+
Reuse the db_paths detection so the step proceeds only when this invocation actually touches
|
|
104
|
+
the database. Read the globs (default `supabase/**`, `apps/backend/**`, `packages/**/db/**`):
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
DB_PATHS=$(jq -r '.shipment.surfaces.supabase.db_paths[]? // empty' .codebyplan/shipment.json 2>/dev/null)
|
|
108
|
+
[ -z "$DB_PATHS" ] && DB_PATHS=$(printf '%s\n' 'supabase/**' 'apps/backend/**' 'packages/**/db/**')
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Proceed when **either**:
|
|
112
|
+
- the branch diff against `origin/$PRODUCTION` touches any `DB_PATHS` glob, **or**
|
|
113
|
+
- this invocation will create/adopt a migration — `$ARGUMENTS` is `--new <name>` or a `.sql`
|
|
114
|
+
path (the migration file may not exist on disk yet, so explicit migrate intent counts as a
|
|
115
|
+
DB change). The bare-picker case (Step 5 Case C) is treated as migrate intent.
|
|
116
|
+
|
|
117
|
+
If neither holds (no DB-path changes and no migrate intent), skip this step silently and let
|
|
118
|
+
Step 2.5 / the normal flow handle the empty `project_ref` — do not provision or prompt for
|
|
119
|
+
cost on a branch that touches no database paths.
|
|
120
|
+
|
|
121
|
+
### Already-provisioned reuse
|
|
122
|
+
|
|
123
|
+
If `project_ref` from Step 2 is already non-empty, the GitHub integration (or a prior run)
|
|
124
|
+
already provisioned the branch. Capture it as `PREVIEW_PROJECT_REF` and jump straight to
|
|
125
|
+
"Record connection" below — idempotent, no creation.
|
|
126
|
+
|
|
127
|
+
### Idempotency check (list before create)
|
|
128
|
+
|
|
129
|
+
Call `mcp__supabase__list_branches` with the parent `project_id` `rrvtrumtkhrsbhcyrwvf`. The
|
|
130
|
+
parent `project_id` for MCP calls is the same ref string stored in `.codebyplan/shipment.json`
|
|
131
|
+
`surfaces.supabase.project_ref` — Supabase uses that one ref as both the project identifier
|
|
132
|
+
and the branch target. Scan the returned list for an entry whose `name` exactly equals
|
|
133
|
+
`$BRANCH` (slashes included — `feat/CHK-144-...` is a valid Supabase branch name).
|
|
134
|
+
|
|
135
|
+
- **Match found**: capture its `project_ref` as `PREVIEW_PROJECT_REF`. Skip creation; proceed
|
|
136
|
+
to "Record connection". This is the idempotent reuse path (covers a branch the GitHub
|
|
137
|
+
integration auto-created between Step 2 and now).
|
|
138
|
+
- **No match**: proceed to "Cost confirmation and creation".
|
|
139
|
+
|
|
140
|
+
### Cost confirmation and creation
|
|
141
|
+
|
|
142
|
+
Cost confirmation is mandatory before creating a branch — never bypass it:
|
|
143
|
+
|
|
144
|
+
1. Call `mcp__supabase__get_cost` with `type: "branch"`. Display the returned estimate to the
|
|
145
|
+
user, capturing the returned `confirm_cost_id`.
|
|
146
|
+
2. Call `mcp__supabase__confirm_cost` with that `confirm_cost_id`.
|
|
147
|
+
3. On user cancellation or cost-confirm rejection: emit a warning and continue in
|
|
148
|
+
scaffold-only mode (jump to Step 5 write-only path; skip Steps 5.5 and 6). `project_ref`
|
|
149
|
+
stays empty.
|
|
150
|
+
|
|
151
|
+
After cost is confirmed, call `mcp__supabase__create_branch`:
|
|
152
|
+
- `project_id`: `rrvtrumtkhrsbhcyrwvf` (parent project ref)
|
|
153
|
+
- `name`: `$BRANCH` (verbatim — slashes included)
|
|
154
|
+
- `confirm_cost_id`: the same id from the `get_cost` response that was passed to `confirm_cost`
|
|
155
|
+
|
|
156
|
+
After the create call returns, poll `mcp__supabase__list_branches` every 10 s until an entry
|
|
157
|
+
with `name == $BRANCH` appears (up to 60 s / 6 polls). Capture its `project_ref` as
|
|
158
|
+
`PREVIEW_PROJECT_REF`. If polling times out:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
Supabase branch creation for <BRANCH> did not settle within 60 s.
|
|
162
|
+
Check the Supabase dashboard: Branches — then re-run /cbp-supabase-migrate.
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Stop.
|
|
166
|
+
|
|
167
|
+
### Record connection
|
|
168
|
+
|
|
169
|
+
Record the branch so cleanup (see `cbp-checkpoint-end`, `cbp-git-worktree-remove`) and other
|
|
170
|
+
skills can discover it. Phrase any context payload as prose — the MCP edge rejects raw
|
|
171
|
+
uppercase database keywords (Cloudflare WAF).
|
|
172
|
+
|
|
173
|
+
1. **Checkpoint / task context** — call `mcp__codebyplan__update_checkpoint` (or
|
|
174
|
+
`mcp__codebyplan__update_task` for a standalone task) to add to `context.discoveries`:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{ "topic": "supabase_preview_branch", "finding": "branch <BRANCH> -> project_ref <PREVIEW_PROJECT_REF>" }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
2. **`.codebyplan/shipment.json`** — read-merge-write (the `preview_branches` array may not
|
|
181
|
+
exist yet — create it if absent; never clobber the rest of the file). Under
|
|
182
|
+
`surfaces.supabase.preview_branches`, first check for an existing entry whose `branch`
|
|
183
|
+
equals `$BRANCH`: if present, update its `project_ref` only if it differs (no duplicate
|
|
184
|
+
append); if absent, append:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{ "branch": "<BRANCH>", "project_ref": "<PREVIEW_PROJECT_REF>", "created_at": "<ISO timestamp>" }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Set `project_ref = $PREVIEW_PROJECT_REF` so Steps 3 onward target this branch's project.
|
|
65
191
|
|
|
66
192
|
## Step 2.5 — Empty project_ref Handling
|
|
67
193
|
|
|
68
|
-
If `project_ref` is empty after Step 2
|
|
194
|
+
If `project_ref` is **still** empty after Step 2.3 (no branch was provisioned — e.g. no
|
|
195
|
+
DB-path changes / no migrate intent, or this is a protected branch, or cost confirmation was
|
|
196
|
+
declined), AskUserQuestion:
|
|
69
197
|
|
|
70
198
|
```
|
|
71
199
|
Could not resolve a Supabase project_ref for branch: <BRANCH>
|
|
@@ -88,12 +216,14 @@ On (C): stop silently.
|
|
|
88
216
|
|
|
89
217
|
## Step 3 — Main-Project Guard
|
|
90
218
|
|
|
91
|
-
If `project_ref` is empty
|
|
219
|
+
If `project_ref` is empty, skip Steps 3 and 4 entirely and jump directly to Step 5. (Normally
|
|
220
|
+
Step 2.3 has already populated `project_ref` for a feat branch, or scaffold-only mode was
|
|
221
|
+
chosen in Step 2.5; this remains a defensive guard for the scaffold-only path.)
|
|
92
222
|
|
|
93
|
-
Read `.codebyplan.json`:
|
|
223
|
+
Read `.codebyplan/shipment.json`:
|
|
94
224
|
|
|
95
225
|
```bash
|
|
96
|
-
MAIN_PROJECT_REF=$(jq -r '.shipment.surfaces.supabase.project_ref' .codebyplan.json)
|
|
226
|
+
MAIN_PROJECT_REF=$(jq -r '.shipment.surfaces.supabase.project_ref' .codebyplan/shipment.json)
|
|
97
227
|
```
|
|
98
228
|
|
|
99
229
|
`MAIN_PROJECT_REF` is consumed by Step 5.5's dry-run CLI calls (`branches create` and `branches get`) to pin those calls to the parent project rather than any linked preview branch.
|
|
@@ -274,16 +404,16 @@ severity level. Hard-block enforcement at ship time is owned by `cbp-supabase-br
|
|
|
274
404
|
|
|
275
405
|
## Step 8 — Regenerate TypeScript Types
|
|
276
406
|
|
|
277
|
-
Read the types output path from `.codebyplan.json`:
|
|
407
|
+
Read the types output path from `.codebyplan/shipment.json`:
|
|
278
408
|
|
|
279
409
|
```bash
|
|
280
|
-
jq -r '.shipment.surfaces.supabase.types_path' .codebyplan.json
|
|
410
|
+
jq -r '.shipment.surfaces.supabase.types_path' .codebyplan/shipment.json
|
|
281
411
|
```
|
|
282
412
|
|
|
283
413
|
If the field is missing or empty, AskUserQuestion:
|
|
284
414
|
|
|
285
415
|
```
|
|
286
|
-
types_path not found in .codebyplan.json under
|
|
416
|
+
types_path not found in .codebyplan/shipment.json under surfaces.supabase.types_path.
|
|
287
417
|
Enter the path where TypeScript types should be written (e.g., apps/web/src/lib/database.types.ts):
|
|
288
418
|
```
|
|
289
419
|
|
|
@@ -12,7 +12,7 @@ The dry-run uses ONE persistent branch per feature branch — created on first u
|
|
|
12
12
|
|
|
13
13
|
DRY_RUN_BRANCH="${BRANCH}-cbp-migrate-dryrun"
|
|
14
14
|
|
|
15
|
-
The CLI `branches` sub-commands act on the project the CLI is *linked* to — mid-development that is often a preview branch, not the parent project. Pin every `branches` call to the parent with `--project-ref "$MAIN_PROJECT_REF"`, where `MAIN_PROJECT_REF` is the parent `project_ref` SKILL.md Step 3 already resolves from `.codebyplan.json` (`.shipment.surfaces.supabase.project_ref`). `mcp__supabase__list_branches` and `reset_branch` need no such flag — the MCP server is already bound to the parent project.
|
|
15
|
+
The CLI `branches` sub-commands act on the project the CLI is *linked* to — mid-development that is often a preview branch, not the parent project. Pin every `branches` call to the parent with `--project-ref "$MAIN_PROJECT_REF"`, where `MAIN_PROJECT_REF` is the parent `project_ref` SKILL.md Step 3 already resolves from `.codebyplan/shipment.json` (`.shipment.surfaces.supabase.project_ref`). `mcp__supabase__list_branches` and `reset_branch` need no such flag — the MCP server is already bound to the parent project.
|
|
16
16
|
|
|
17
17
|
1. Call `mcp__supabase__list_branches`. Look for an entry whose name equals `DRY_RUN_BRANCH`. If found, capture its `id` field as `DRY_RUN_BRANCH_ID` — `reset_branch` and every status poll below act on the branch id, not the name.
|
|
18
18
|
2. **If absent** — run `supabase --experimental branches create "$DRY_RUN_BRANCH" --project-ref "$MAIN_PROJECT_REF" --yes`. The `--yes` flag is required: branch creation prompts for cost confirmation and the skill runs non-interactively, so the prompt would otherwise hang. The CLI create command is asynchronous and returns a human-readable message (not JSON with an `id`). After the CLI call, poll `mcp__supabase__list_branches` until an entry whose name equals `DRY_RUN_BRANCH` appears, then capture its `id` as `DRY_RUN_BRANCH_ID`. This poll both confirms the create succeeded and yields the id. Creation clones at `git_ref=main` and replays main's migration chain as a baseline — skip the reset in step 4 and go straight to step 5 (the initial provisioning already gave a main baseline).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
scope: org-shared
|
|
3
3
|
name: cbp-supabase-setup
|
|
4
|
-
description: Enable Supabase GitHub branching integration — GitHub app authorization, required-status-check enforcement on main + integration branch, persistent branch creation, and idempotency marker in .codebyplan.json.
|
|
4
|
+
description: Enable Supabase GitHub branching integration — GitHub app authorization, required-status-check enforcement on main + integration branch, persistent branch creation, and idempotency marker in .codebyplan/shipment.json.
|
|
5
5
|
argument-hint: "[--force]"
|
|
6
6
|
allowed-tools: Read, Edit, Bash(supabase *), Bash(jq *), Bash(mv *), Bash(date *), Bash(test *), Bash(which *)
|
|
7
7
|
effort: xhigh
|
|
@@ -41,13 +41,19 @@ first, then re-invoke /cbp-supabase-setup.
|
|
|
41
41
|
Read `supabase/config.toml` to extract the linked `project_id` (under `[api]` or the top-level
|
|
42
42
|
`project_id` field, depending on CLI version).
|
|
43
43
|
|
|
44
|
-
Read `.codebyplan.json`:
|
|
44
|
+
Read `.codebyplan/git.json` and `.codebyplan/shipment.json`:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
jq '.branch_config.integration // empty' .codebyplan.json
|
|
48
|
-
jq '.shipment.surfaces.supabase.branching_configured // empty' .codebyplan.json
|
|
47
|
+
jq '.branch_config.integration // empty' .codebyplan/git.json
|
|
48
|
+
jq '.shipment.surfaces.supabase.branching_configured // empty' .codebyplan/shipment.json
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
> **Note — Two distinct Supabase branching models**: This skill performs a ONE-TIME
|
|
52
|
+
> persistent setup of the GitHub branching integration (the OAuth link, required-status-check
|
|
53
|
+
> rules, and optional persistent integration branch). It is separate from the PER-FEATURE
|
|
54
|
+
> explicit Supabase branches that `cbp-supabase-migrate` creates lazily on first DB change
|
|
55
|
+
> for each feat branch. See [[supabase-branch-lifecycle]] for the per-feature lifecycle.
|
|
56
|
+
|
|
51
57
|
Track per-item done state:
|
|
52
58
|
- `github_app_installed` — true if `branching_configured.github_app_installed` is already true
|
|
53
59
|
- `required_check_enforced` — true if `branching_configured.required_check_enforced` is already true
|
|
@@ -82,7 +88,7 @@ Set `github_app_installed = true` in the idempotency tracker (persisted at Step
|
|
|
82
88
|
|
|
83
89
|
## Step 4 — GitHub repo: required status check (manual checklist)
|
|
84
90
|
|
|
85
|
-
Read `branch_config.integration` from `.codebyplan.json`. Determine branches to protect:
|
|
91
|
+
Read `branch_config.integration` from `.codebyplan/git.json`. Determine branches to protect:
|
|
86
92
|
|
|
87
93
|
- Always: `main`
|
|
88
94
|
- Also: `branch_config.integration` (when set and !== 'main')
|
|
@@ -193,7 +199,7 @@ sql_paths = ["./seed.sql"]
|
|
|
193
199
|
|
|
194
200
|
Reference: [reference/branching-setup.md § 4](reference/branching-setup.md)
|
|
195
201
|
|
|
196
|
-
## Step 7 — Write idempotency marker to `.codebyplan.json`
|
|
202
|
+
## Step 7 — Write idempotency marker to `.codebyplan/shipment.json`
|
|
197
203
|
|
|
198
204
|
Generate the ISO timestamp in the shell first (jq can't produce wall-clock time natively),
|
|
199
205
|
then merge the marker under `shipment.surfaces.supabase.branching_configured`:
|
|
@@ -204,7 +210,7 @@ jq --arg now "$NOW" '.shipment.surfaces.supabase.branching_configured = {
|
|
|
204
210
|
enabled_at: $now,
|
|
205
211
|
github_app_installed: true,
|
|
206
212
|
required_check_enforced: true
|
|
207
|
-
}' .codebyplan.json > .codebyplan.json.tmp && mv .codebyplan.json.tmp .codebyplan.json
|
|
213
|
+
}' .codebyplan/shipment.json > .codebyplan/shipment.json.tmp && mv .codebyplan/shipment.json.tmp .codebyplan/shipment.json
|
|
208
214
|
```
|
|
209
215
|
|
|
210
216
|
The three sub-fields:
|