codebyplan 1.12.0 → 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.
Files changed (30) hide show
  1. package/dist/cli.js +50 -71
  2. package/package.json +1 -1
  3. package/templates/hooks/README.md +1 -13
  4. package/templates/hooks/cbp-test-coverage-gate.sh +8 -0
  5. package/templates/hooks/cbp-test-hooks.sh +0 -42
  6. package/templates/hooks/hooks.json +0 -9
  7. package/templates/skills/cbp-checkpoint-start/SKILL.md +2 -2
  8. package/templates/skills/cbp-session-start/SKILL.md +1 -1
  9. package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/SKILL.md +1 -1
  10. package/templates/skills/cbp-setup-eslint/SKILL.md +199 -0
  11. package/templates/skills/cbp-setup-eslint/reference/base.md +82 -0
  12. package/templates/skills/cbp-setup-eslint/reference/cli.md +56 -0
  13. package/templates/skills/cbp-setup-eslint/reference/e2e.md +68 -0
  14. package/templates/skills/cbp-setup-eslint/reference/jest.md +59 -0
  15. package/templates/skills/cbp-setup-eslint/reference/nestjs.md +69 -0
  16. package/templates/skills/cbp-setup-eslint/reference/nextjs.md +63 -0
  17. package/templates/skills/cbp-setup-eslint/reference/node.md +74 -0
  18. package/templates/skills/cbp-setup-eslint/reference/react-native.md +60 -0
  19. package/templates/skills/cbp-setup-eslint/reference/react.md +82 -0
  20. package/templates/skills/cbp-setup-eslint/reference/tailwind.md +64 -0
  21. package/templates/skills/cbp-setup-eslint/reference/testing-react.md +57 -0
  22. package/templates/skills/cbp-setup-eslint/reference/vitest.md +62 -0
  23. package/templates/skills/cbp-task-complete/SKILL.md +1 -3
  24. package/templates/skills/cbp-task-start/SKILL.md +3 -3
  25. package/templates/hooks/cbp-mcp-worktree-inject.sh +0 -76
  26. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/maestro.md +0 -0
  27. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/playwright.md +0 -0
  28. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/tauri.md +0 -0
  29. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/vscode.md +0 -0
  30. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/xcuitest.md +0 -0
@@ -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
@@ -137,9 +137,7 @@ Skip the push only when nothing was committed in Step 5 AND `/cbp-merge-main` re
137
137
 
138
138
  ### Step 7: Complete Task
139
139
 
140
- If `CALLER_WT` is non-empty, call `complete_task(task_id, caller_worktree_id: CALLER_WT)`. Otherwise call `complete_task(task_id)` with no worktree id the pre-guard is skipped (backwards-compat).
141
-
142
- **When calling `complete_task`**: pass `caller_worktree_id` resolved from `npx codebyplan resolve-worktree`. The MCP server's pre-guard rejects mutations from non-matching worktrees; supplying `caller_worktree_id` ensures legitimate completion succeeds. The server auto-clears `assigned_user_id` + `assigned_worktree_id` on the task; if this was the last sibling task, it also clears the parent checkpoint's assignment. (Per CHK-104 TASK-2 hard-lock.)
140
+ Call `complete_task(task_id)`. The server resolves the caller's worktree identity from the JWT/ctx and enforces the mutate-lock (CHK-140 TASK-3 — `caller_worktree_id` input field removed). The server auto-clears `assigned_user_id` + `assigned_worktree_id` on the task; if this was the last sibling task, it also clears the parent checkpoint's assignment. (Per CHK-104 hard-lock.)
143
141
 
144
142
  ### Step 7.5: Standalone Task Branch Merge
145
143
 
@@ -160,9 +160,9 @@ See `dependency-vulnerability-fixes.md` "Audit Sweep at Task Start" for the sour
160
160
 
161
161
  ### Step 3.5: Worktree-Match Verification
162
162
 
163
- Before activating the task, verify the caller's worktree matches the assigned worktree on the target row. (Per CHK-104 TASK-2 — DB-level hard-lock prevents cross-worktree mutations.)
163
+ Before activating the task, verify the caller's worktree matches the assigned worktree on the target row. (Per CHK-104 — DB-level hard-lock prevents cross-worktree mutations; the server resolves caller identity from the JWT/ctx.)
164
164
 
165
- 1. Read caller worktree: `CALLER_WT=$(npx codebyplan resolve-worktree 2>/dev/null)`. If empty, the `caller_worktree_id` parameter is omitted from the MCP call entirely — the pre-guard is skipped and the update proceeds without a worktree check (backwards-compat).
165
+ 1. Read caller worktree: `CALLER_WT=$(npx codebyplan resolve-worktree 2>/dev/null)`.
166
166
  2. Determine target worktree:
167
167
  - **Checkpoint-bound tasks**: `TARGET_WT = checkpoint.worktree_id` (read from MCP `get_checkpoints`). Note: checkpoint-bound tasks may have a NULL `task.assigned_worktree_id` because the lock lives on the parent checkpoint — fall through to `checkpoint.worktree_id`.
168
168
  - **Standalone tasks**: `TARGET_WT = task.assigned_worktree_id`.
@@ -222,7 +222,7 @@ Display context summary:
222
222
 
223
223
  Use MCP `update_task(task_id, status: "in_progress")`.
224
224
 
225
- If worktree_id present, include `claim_worktree_id` to auto-claim the checkpoint AND `caller_worktree_id: CALLER_WT` so the MCP server's pre-guard accepts the call (CHK-104 TASK-2 hard-lock).
225
+ If worktree_id present, include `claim_worktree_id` to auto-claim the checkpoint. The server resolves the caller's worktree identity from the JWT/ctx (CHK-140 TASK-3 — `caller_worktree_id` input field removed).
226
226
 
227
227
  ### Step 6: Auto-trigger Round Start
228
228
 
@@ -1,76 +0,0 @@
1
- #!/bin/bash
2
- # @scope: org-shared
3
- # Hook: PreToolUse mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)
4
- # Purpose: Auto-inject caller_worktree_id into MCP mutation calls when not already
5
- # present. Uses the PreToolUse hookSpecificOutput.updatedInput contract
6
- # (Claude Code v2.1 — see hooks.md "PreToolUse decision control"):
7
- # - Output JSON with hookSpecificOutput.permissionDecision="allow" and
8
- # hookSpecificOutput.updatedInput containing the full modified tool_input.
9
- # This hook NEVER exits non-zero — it is a no-op on all failure paths.
10
- #
11
- # Fallback chain:
12
- # 1. caller_worktree_id already present in tool_input → passthrough (no-op)
13
- # 2. Primary: npx codebyplan resolve-worktree → UUID found → inject
14
- # 3. Secondary: npx codebyplan resolve-worktree --fallback-from-branch → UUID found → inject
15
- # 4. Both empty → passthrough (server pre-guard skips when absent)
16
- #
17
- # NEVER exit non-zero — backwards-compat passthrough when resolver is broken.
18
-
19
- INPUT=$(cat)
20
-
21
- TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
22
-
23
- # Only intercept matching MCP mutation tools
24
- case "$TOOL_NAME" in
25
- mcp__codebyplan__update_task|\
26
- mcp__codebyplan__complete_task|\
27
- mcp__codebyplan__complete_round|\
28
- mcp__codebyplan__update_checkpoint) ;;
29
- *) exit 0 ;;
30
- esac
31
-
32
- # If caller_worktree_id is already present, pass through unchanged
33
- EXISTING=$(echo "$INPUT" | jq -r '.tool_input.caller_worktree_id // empty' 2>/dev/null)
34
- if [ -n "$EXISTING" ]; then
35
- exit 0
36
- fi
37
-
38
- # Try primary resolver
39
- UUID=$(npx --yes codebyplan resolve-worktree 2>/dev/null)
40
-
41
- # Try fallback if primary returned empty
42
- if [ -z "$UUID" ]; then
43
- UUID=$(npx --yes codebyplan resolve-worktree --fallback-from-branch 2>/dev/null)
44
- fi
45
-
46
- # If no UUID resolved, passthrough unchanged
47
- if [ -z "$UUID" ]; then
48
- exit 0
49
- fi
50
-
51
- # Extract tool_input and guard against null before merging
52
- TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input' 2>/dev/null)
53
- if [ -z "$TOOL_INPUT" ] || [ "$TOOL_INPUT" = "null" ]; then
54
- # No tool_input to mutate — output original input unchanged
55
- echo "$INPUT"
56
- exit 0
57
- fi
58
-
59
- MERGED_TOOL_INPUT=$(echo "$TOOL_INPUT" | jq -c --arg uuid "$UUID" '. + {caller_worktree_id: $uuid}' 2>/dev/null)
60
- if [ -z "$MERGED_TOOL_INPUT" ] || [ "$MERGED_TOOL_INPUT" = "null" ]; then
61
- echo "$INPUT"
62
- exit 0
63
- fi
64
-
65
- # Output PreToolUse hookSpecificOutput with updatedInput
66
- jq -n \
67
- --argjson updated "$MERGED_TOOL_INPUT" \
68
- '{
69
- hookSpecificOutput: {
70
- hookEventName: "PreToolUse",
71
- permissionDecision: "allow",
72
- updatedInput: $updated
73
- }
74
- }'
75
-
76
- exit 0