codebyplan 1.5.0 → 1.8.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/README.md +48 -5
- package/dist/cli.js +4578 -2709
- package/package.json +5 -1
- package/templates/.gitkeep +0 -0
- package/templates/README.md +20 -0
- package/templates/agents/cbp-cc-executor.md +213 -0
- package/templates/agents/cbp-database-agent.md +229 -0
- package/templates/agents/cbp-improve-claude.md +245 -0
- package/templates/agents/cbp-improve-round.md +284 -0
- package/templates/agents/cbp-mechanical-edits.md +111 -0
- package/templates/agents/cbp-research.md +282 -0
- package/templates/agents/cbp-round-executor.md +604 -0
- package/templates/agents/cbp-security-agent.md +134 -0
- package/templates/agents/cbp-task-check.md +213 -0
- package/templates/agents/cbp-task-planner.md +582 -0
- package/templates/agents/cbp-test-e2e-agent.md +363 -0
- package/templates/agents/cbp-testing-qa-agent.md +400 -0
- package/templates/context/mcp-docs.md +139 -0
- package/templates/hooks/README.md +236 -0
- package/templates/hooks/cbp-auto-test-hooks.sh +44 -0
- package/templates/hooks/cbp-lint-format-on-edit.sh +159 -0
- package/templates/hooks/cbp-maestro-yaml-validate.sh +100 -0
- package/templates/hooks/cbp-mcp-migration-guard.sh +32 -0
- package/templates/hooks/cbp-mcp-round-sync.sh +79 -0
- package/templates/hooks/cbp-mcp-worktree-inject.sh +76 -0
- package/templates/hooks/cbp-notify.sh +68 -0
- package/templates/hooks/cbp-plugin-dispatch.sh +29 -0
- package/templates/hooks/cbp-pre-commit-quality-gate.sh +204 -0
- package/templates/hooks/cbp-statusline.sh +347 -0
- package/templates/hooks/cbp-subagent-statusline.sh +182 -0
- package/templates/hooks/cbp-test-coverage-gate.sh +144 -0
- package/templates/hooks/cbp-test-hooks.sh +320 -0
- package/templates/hooks/hooks.json +85 -0
- package/templates/hooks/validate-context-usage.sh +59 -0
- package/templates/hooks/validate-git-commit.sh +78 -0
- package/templates/hooks/validate-git-stash-deny.sh +32 -0
- package/templates/hooks/validate-structure-lengths.sh +57 -0
- package/templates/hooks/validate-structure-lib.sh +104 -0
- package/templates/hooks/validate-structure-patterns.sh +54 -0
- package/templates/hooks/validate-structure-scope.sh +33 -0
- package/templates/hooks/validate-structure-smoke.sh +95 -0
- package/templates/hooks/validate-structure-templates.sh +34 -0
- package/templates/hooks/validate-structure.sh +69 -0
- package/templates/rules/.gitkeep +0 -0
- package/templates/rules/README.md +47 -0
- package/templates/rules/context-file-loading.md +52 -0
- package/templates/rules/scope-vocabulary.md +64 -0
- package/templates/rules/todo-backend.md +109 -0
- package/templates/settings.project.base.json +55 -0
- package/templates/settings.user.base.json +25 -0
- package/templates/skills/cbp-build-cc-agent/SKILL.md +139 -0
- package/templates/skills/cbp-build-cc-agent/examples/read-only-reviewer.md +32 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-hooks.md +41 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-skills-preload.md +25 -0
- package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +153 -0
- package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +37 -0
- package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +18 -0
- package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +67 -0
- package/templates/skills/cbp-build-cc-agent/templates/agent.md +66 -0
- package/templates/skills/cbp-build-cc-claude-file/SKILL.md +178 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/minimal-project.md +33 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/monorepo-with-imports.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/imports.md +72 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/what-belongs.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/project-claude-md.md +48 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/user-claude-md.md +22 -0
- package/templates/skills/cbp-build-cc-memory/SKILL.md +201 -0
- package/templates/skills/cbp-build-cc-memory/examples/feedback-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/project-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/reference-memory.md +13 -0
- package/templates/skills/cbp-build-cc-memory/examples/user-memory.md +14 -0
- package/templates/skills/cbp-build-cc-memory/reference/memory-types.md +59 -0
- package/templates/skills/cbp-build-cc-memory/reference/when-to-save.md +62 -0
- package/templates/skills/cbp-build-cc-memory/templates/MEMORY-index.md +4 -0
- package/templates/skills/cbp-build-cc-memory/templates/memory-entry.md +15 -0
- package/templates/skills/cbp-build-cc-mode/SKILL.md +99 -0
- package/templates/skills/cbp-build-cc-rule/SKILL.md +176 -0
- package/templates/skills/cbp-build-cc-rule/examples/global-rule.md +19 -0
- package/templates/skills/cbp-build-cc-rule/examples/scoped-rule.md +41 -0
- package/templates/skills/cbp-build-cc-rule/reference/paths-patterns.md +48 -0
- package/templates/skills/cbp-build-cc-rule/templates/rule.md +32 -0
- package/templates/skills/cbp-build-cc-settings/SKILL.md +220 -0
- package/templates/skills/cbp-build-cc-settings/examples/hooks-config.json +64 -0
- package/templates/skills/cbp-build-cc-settings/examples/permissions-config.json +34 -0
- package/templates/skills/cbp-build-cc-settings/examples/sandbox-config.json +42 -0
- package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +104 -0
- package/templates/skills/cbp-build-cc-settings/reference/permission-rules.md +61 -0
- package/templates/skills/cbp-build-cc-settings/reference/scope-precedence.md +73 -0
- package/templates/skills/cbp-build-cc-settings/reference/settings-fields.md +166 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.json +23 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.local.json +10 -0
- package/templates/skills/cbp-build-cc-skill/SKILL.md +154 -0
- package/templates/skills/cbp-build-cc-skill/examples/dynamic-context.md +31 -0
- package/templates/skills/cbp-build-cc-skill/examples/fork-skill.md +22 -0
- package/templates/skills/cbp-build-cc-skill/examples/knowledge-skill.md +25 -0
- package/templates/skills/cbp-build-cc-skill/examples/task-skill.md +29 -0
- package/templates/skills/cbp-build-cc-skill/reference/cbp-quality.md +157 -0
- package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +35 -0
- package/templates/skills/cbp-build-cc-skill/reference/string-substitutions.md +60 -0
- package/templates/skills/cbp-build-cc-skill/scripts/validate-skill.sh +90 -0
- package/templates/skills/cbp-build-cc-skill/templates/skill.md +51 -0
- package/templates/skills/cbp-checkpoint-check/SKILL.md +156 -0
- package/templates/skills/cbp-checkpoint-complete/SKILL.md +109 -0
- package/templates/skills/cbp-checkpoint-create/SKILL.md +287 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +241 -0
- package/templates/skills/cbp-checkpoint-update/SKILL.md +115 -0
- package/templates/skills/cbp-frontend-a11y/SKILL.md +109 -0
- package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +130 -0
- package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +122 -0
- package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +154 -0
- package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +111 -0
- package/templates/skills/cbp-frontend-design/SKILL.md +145 -0
- package/templates/skills/cbp-frontend-design/reference/nextjs-scss.md +118 -0
- package/templates/skills/cbp-frontend-design/reference/rn-expo.md +101 -0
- package/templates/skills/cbp-frontend-design/reference/tauri-react.md +82 -0
- package/templates/skills/cbp-frontend-ui/SKILL.md +262 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-label-maps.md +42 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-layout-patterns.md +105 -0
- package/templates/skills/cbp-frontend-ui/reference/variant-defaults.md +149 -0
- package/templates/skills/cbp-frontend-ux/SKILL.md +181 -0
- package/templates/skills/cbp-git-branch-feat-create/SKILL.md +115 -0
- package/templates/skills/cbp-git-commit/SKILL.md +278 -0
- package/templates/skills/cbp-git-worktree-create/SKILL.md +226 -0
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +145 -0
- package/templates/skills/cbp-merge-main/SKILL.md +228 -0
- package/templates/skills/cbp-round-check/SKILL.md +104 -0
- package/templates/skills/cbp-round-end/SKILL.md +183 -0
- package/templates/skills/cbp-round-end/reference/findings-presentation.md +44 -0
- package/templates/skills/cbp-round-end/reference/inline-fallback.md +35 -0
- package/templates/skills/cbp-round-execute/SKILL.md +211 -0
- package/templates/skills/cbp-round-execute/reference/inline-fallback.md +59 -0
- package/templates/skills/cbp-round-input/SKILL.md +165 -0
- package/templates/skills/cbp-round-start/SKILL.md +222 -0
- package/templates/skills/cbp-round-update/SKILL.md +163 -0
- package/templates/skills/cbp-session-end/SKILL.md +187 -0
- package/templates/skills/cbp-session-start/SKILL.md +155 -0
- package/templates/skills/cbp-ship/SKILL.md +332 -0
- package/templates/skills/cbp-ship/reference/changesets-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/eas-cli-overview.md +60 -0
- package/templates/skills/cbp-ship/reference/gh-cli-overview.md +135 -0
- package/templates/skills/cbp-ship/reference/gh-cli-shipment-commands.md +283 -0
- package/templates/skills/cbp-ship/reference/npm-publish-monorepo.md +252 -0
- package/templates/skills/cbp-ship/reference/npm-publish-oidc-trusted.md +157 -0
- package/templates/skills/cbp-ship/reference/npm-publish-overview.md +171 -0
- package/templates/skills/cbp-ship/reference/preflight-checklist.md +88 -0
- package/templates/skills/cbp-ship/reference/railway-nestjs-deployment.md +169 -0
- package/templates/skills/cbp-ship/reference/railway-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/railway-troubleshooting.md +168 -0
- package/templates/skills/cbp-ship/reference/release-please-overview.md +99 -0
- package/templates/skills/cbp-ship/reference/surface-expo-eas.md +155 -0
- package/templates/skills/cbp-ship/reference/surface-npm.md +180 -0
- package/templates/skills/cbp-ship/reference/surface-railway.md +152 -0
- package/templates/skills/cbp-ship/reference/surface-supabase.md +178 -0
- package/templates/skills/cbp-ship/reference/surface-tauri.md +138 -0
- package/templates/skills/cbp-ship/reference/surface-vercel.md +124 -0
- package/templates/skills/cbp-ship/reference/surface-vscode-ext.md +144 -0
- package/templates/skills/cbp-ship/reference/surfaces.md +60 -0
- package/templates/skills/cbp-ship/reference/testflight-automation.md +215 -0
- package/templates/skills/cbp-ship/reference/testflight-internal-vs-external.md +69 -0
- package/templates/skills/cbp-ship/reference/testflight-overview.md +98 -0
- package/templates/skills/cbp-ship/reference/versioning.md +116 -0
- package/templates/skills/cbp-ship/scripts/detect-surfaces.sh +217 -0
- package/templates/skills/cbp-ship/scripts/verify-expo-eas.sh +35 -0
- package/templates/skills/cbp-ship/scripts/verify-npm.sh +21 -0
- package/templates/skills/cbp-ship/scripts/verify-railway.sh +41 -0
- package/templates/skills/cbp-ship/scripts/verify-supabase.sh +19 -0
- package/templates/skills/cbp-ship/scripts/verify-tauri.sh +24 -0
- package/templates/skills/cbp-ship/scripts/verify-vercel.sh +32 -0
- package/templates/skills/cbp-ship/scripts/verify-vscode-ext.sh +25 -0
- package/templates/skills/cbp-ship/templates/eas.json +66 -0
- package/templates/skills/cbp-ship/templates/railway.toml +15 -0
- package/templates/skills/cbp-ship/templates/release-please-config.json +17 -0
- package/templates/skills/cbp-ship/templates/vercel.json +19 -0
- package/templates/skills/cbp-ship/templates/vscodeignore +21 -0
- package/templates/skills/cbp-ship/templates/workflow-changesets.yml +41 -0
- package/templates/skills/cbp-ship/templates/workflow-eas-submit.yml +53 -0
- package/templates/skills/cbp-ship/templates/workflow-npm-publish.yml +36 -0
- package/templates/skills/cbp-ship/templates/workflow-release-please.yml +21 -0
- package/templates/skills/cbp-ship/templates/workflow-tauri-release.yml +69 -0
- package/templates/skills/cbp-ship/templates/workflow-vsce-publish.yml +31 -0
- package/templates/skills/cbp-ship-configure/SKILL.md +296 -0
- package/templates/skills/cbp-ship-configure/reference/expo-mobile.md +204 -0
- package/templates/skills/cbp-ship-configure/reference/npm-package.md +165 -0
- package/templates/skills/cbp-ship-configure/reference/railway-backend.md +199 -0
- package/templates/skills/cbp-ship-configure/reference/supabase.md +200 -0
- package/templates/skills/cbp-ship-configure/reference/tauri-desktop.md +181 -0
- package/templates/skills/cbp-ship-configure/reference/vercel.md +117 -0
- package/templates/skills/cbp-ship-configure/reference/vscode-ext.md +155 -0
- package/templates/skills/cbp-ship-main/SKILL.md +65 -0
- package/templates/skills/cbp-supabase-branch-check/SKILL.md +337 -0
- package/templates/skills/cbp-supabase-branch-check/reference/dag-steps.md +29 -0
- package/templates/skills/cbp-supabase-migrate/SKILL.md +314 -0
- package/templates/skills/cbp-supabase-migrate/reference/advisor-triage.md +70 -0
- package/templates/skills/cbp-supabase-migrate/reference/cli-fallback.md +87 -0
- package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +58 -0
- package/templates/skills/cbp-supabase-setup/SKILL.md +239 -0
- package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +121 -0
- package/templates/skills/cbp-supabase-setup/reference/cli-fallback.md +109 -0
- package/templates/skills/cbp-task-check/SKILL.md +166 -0
- package/templates/skills/cbp-task-complete/SKILL.md +206 -0
- package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +48 -0
- package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +56 -0
- package/templates/skills/cbp-task-create/SKILL.md +167 -0
- package/templates/skills/cbp-task-start/SKILL.md +239 -0
- package/templates/skills/cbp-task-testing/SKILL.md +277 -0
- package/templates/skills/cbp-todo/SKILL.md +97 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Monorepo Publishing — pnpm Workspaces
|
|
2
|
+
|
|
3
|
+
Publishing one or more packages from a pnpm workspace. Workspace layout, `pnpm publish` vs `npm publish`, per-package `publishConfig`, version-management tools (changesets vs release-please), public/private separation, pre-publish gates.
|
|
4
|
+
|
|
5
|
+
## Workspace Layout
|
|
6
|
+
|
|
7
|
+
A typical pnpm monorepo with mixed published and internal packages:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
repo/
|
|
11
|
+
├── pnpm-workspace.yaml
|
|
12
|
+
├── package.json # private: true; root tooling only
|
|
13
|
+
├── packages/
|
|
14
|
+
│ ├── published/
|
|
15
|
+
│ │ ├── cli/ # @codebyplan/cli — published
|
|
16
|
+
│ │ ├── design-tokens/
|
|
17
|
+
│ │ └── auth/
|
|
18
|
+
│ └── internal/
|
|
19
|
+
│ ├── eslint-config/ # @codebyplan/eslint-config — private
|
|
20
|
+
│ └── tsconfig/
|
|
21
|
+
└── apps/
|
|
22
|
+
├── web/ # not published
|
|
23
|
+
└── backend/
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`pnpm-workspace.yaml`:
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
packages:
|
|
30
|
+
- "packages/*/*"
|
|
31
|
+
- "apps/*"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`packages/published/*` vs `packages/internal/*` is **organisational**. What keeps internal packages off the registry is `"private": true` in their `package.json` — pnpm refuses to publish private packages and skips them silently in `pnpm -r publish`.
|
|
35
|
+
|
|
36
|
+
## Root `package.json`
|
|
37
|
+
|
|
38
|
+
Always private at the root — never accidentally publish the workspace meta-package:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"name": "codebyplan-monorepo",
|
|
43
|
+
"private": true,
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "turbo run build",
|
|
46
|
+
"test": "turbo run test",
|
|
47
|
+
"lint:packages": "turbo run lint:package",
|
|
48
|
+
"release": "changeset publish"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Per-Package `package.json`
|
|
54
|
+
|
|
55
|
+
A published workspace package needs `publishConfig`:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"name": "@codebyplan/cli",
|
|
60
|
+
"version": "1.4.2",
|
|
61
|
+
"type": "module",
|
|
62
|
+
"exports": {
|
|
63
|
+
".": {
|
|
64
|
+
"types": "./dist/index.d.ts",
|
|
65
|
+
"default": "./dist/index.js"
|
|
66
|
+
},
|
|
67
|
+
"./package.json": "./package.json"
|
|
68
|
+
},
|
|
69
|
+
"bin": { "codebyplan": "./dist/cli.js" },
|
|
70
|
+
"files": ["dist", "README.md"],
|
|
71
|
+
"engines": { "node": ">=20" },
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public",
|
|
74
|
+
"provenance": true
|
|
75
|
+
},
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "git+https://github.com/codebyplan/codebyplan.git",
|
|
79
|
+
"directory": "packages/published/cli"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Notes:
|
|
85
|
+
|
|
86
|
+
- `repository.directory` tells the registry which subfolder this package lives in. Required for provenance attestations to validate.
|
|
87
|
+
- `publishConfig.access: "public"` is required for scoped packages (`@codebyplan/*`). Without it the first publish fails with `402 Payment Required`.
|
|
88
|
+
- `publishConfig.provenance: true` is the package.json equivalent of `--provenance` on the CLI.
|
|
89
|
+
|
|
90
|
+
An internal package just sets `"private": true`:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"name": "@codebyplan/eslint-config",
|
|
95
|
+
"version": "0.0.0",
|
|
96
|
+
"private": true,
|
|
97
|
+
"main": "./index.js"
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## `pnpm publish` vs `npm publish`
|
|
102
|
+
|
|
103
|
+
| Capability | `pnpm publish` | `npm publish` |
|
|
104
|
+
|------------|----------------|----------------|
|
|
105
|
+
| Recursive (`-r`) — publish all changed packages | Yes | No |
|
|
106
|
+
| `--filter` to scope to a subset | Yes | No |
|
|
107
|
+
| Auto-includes workspace root `LICENSE` | Yes | No |
|
|
108
|
+
| Rewrites `workspace:*` deps to actual versions in tarball | Yes — automatic | No |
|
|
109
|
+
| `--no-git-checks` | Yes | No |
|
|
110
|
+
| OIDC trusted publishing | Yes (npm CLI underneath) | Yes |
|
|
111
|
+
|
|
112
|
+
For a pnpm monorepo, **always use `pnpm publish`** — `npm publish` will leak `workspace:*` protocol strings into the published tarball and consumers will get install errors.
|
|
113
|
+
|
|
114
|
+
`pnpm publish -r` only publishes packages whose `version` is not already on the registry — safe to run repeatedly.
|
|
115
|
+
|
|
116
|
+
## Version Management — Changesets vs release-please
|
|
117
|
+
|
|
118
|
+
Two dominant tools. Both work with pnpm + GitHub Actions OIDC.
|
|
119
|
+
|
|
120
|
+
### Changesets
|
|
121
|
+
|
|
122
|
+
Maintainer-friendly — every PR adds a `.changeset/*.md` file declaring intent:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
.changeset/funky-tigers-dance.md
|
|
126
|
+
---
|
|
127
|
+
"@codebyplan/cli": minor
|
|
128
|
+
"@codebyplan/auth": patch
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
Added --provenance flag to publish command. Auth payload now includes scope.
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Workflow:
|
|
135
|
+
|
|
136
|
+
1. `pnpm changeset` while authoring a PR. Pick affected packages and bump types.
|
|
137
|
+
2. PR merges to main. Changesets GitHub Action opens (or updates) a "Version Packages" PR that consumes pending changesets, bumps versions, regenerates CHANGELOGs.
|
|
138
|
+
3. Merging the Version Packages PR triggers `pnpm changeset publish` → calls `pnpm publish -r` for every bumped package.
|
|
139
|
+
|
|
140
|
+
`.changeset/config.json` essentials:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"changelog": "@changesets/cli/changelog",
|
|
145
|
+
"commit": false,
|
|
146
|
+
"fixed": [],
|
|
147
|
+
"linked": [],
|
|
148
|
+
"access": "public",
|
|
149
|
+
"baseBranch": "main",
|
|
150
|
+
"updateInternalDependencies": "patch",
|
|
151
|
+
"ignore": ["@codebyplan/web", "@codebyplan/backend"]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`ignore` excludes apps that are deployed but never published.
|
|
156
|
+
|
|
157
|
+
Strengths: explicit intent per change; supports linked/fixed package groups; rich CHANGELOG output. Weaknesses: every PR must remember to add a changeset (the bot enforces this).
|
|
158
|
+
|
|
159
|
+
### release-please
|
|
160
|
+
|
|
161
|
+
Conventional-commit-driven — version is inferred from commit messages (`feat:` → minor, `fix:` → patch, `feat!:` or `BREAKING CHANGE:` → major):
|
|
162
|
+
|
|
163
|
+
1. Developer writes conventional-commit messages.
|
|
164
|
+
2. release-please GitHub Action watches main, opens a release PR per package summarising commits since the last tag.
|
|
165
|
+
3. Merging the release PR creates a git tag, GitHub release, and triggers a separate publish workflow.
|
|
166
|
+
|
|
167
|
+
`release-please-config.json`:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"packages": {
|
|
172
|
+
"packages/published/cli": { "release-type": "node" },
|
|
173
|
+
"packages/published/auth": { "release-type": "node" }
|
|
174
|
+
},
|
|
175
|
+
"plugins": ["node-workspace"]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The `node-workspace` plugin keeps `workspace:*` deps in sync across the bump.
|
|
180
|
+
|
|
181
|
+
Strengths: zero per-PR ceremony when commit hygiene is enforced. Weaknesses: monorepo config is more involved; granular bump control is harder.
|
|
182
|
+
|
|
183
|
+
### Picking one
|
|
184
|
+
|
|
185
|
+
- Conventional commits enforced → release-please.
|
|
186
|
+
- Want explicit per-PR intent and rich CHANGELOGs → Changesets.
|
|
187
|
+
- OSS / mixed contributors → Changesets (the bot reminds people).
|
|
188
|
+
|
|
189
|
+
CodeByPlan uses Changesets for `packages/published/*`.
|
|
190
|
+
|
|
191
|
+
## Pre-Publish Gates
|
|
192
|
+
|
|
193
|
+
Run these in CI before `pnpm publish -r`:
|
|
194
|
+
|
|
195
|
+
| # | Gate | Command |
|
|
196
|
+
|---|------|---------|
|
|
197
|
+
| 1 | Build | `pnpm -r --filter "./packages/published/*" build` |
|
|
198
|
+
| 2 | Test | `pnpm -r --filter "./packages/published/*" test` |
|
|
199
|
+
| 3 | publint | `pnpm -r --filter "./packages/published/*" exec publint` |
|
|
200
|
+
| 4 | attw | `pnpm -r --filter "./packages/published/*" exec attw --pack .` |
|
|
201
|
+
| 5 | Dry-run pack | `pnpm -r --filter "./packages/published/*" publish --dry-run` |
|
|
202
|
+
|
|
203
|
+
[publint](https://publint.dev) catches missing `exports`, broken `main` pointers, type-definition exclusion, ESM/CJS misalignment. [Are The Types Wrong](https://arethetypeswrong.github.io/) validates that the published tarball resolves correctly under both CJS and ESM consumers across conditional-export combinations.
|
|
204
|
+
|
|
205
|
+
The dry-run output lists every file that would be in the tarball plus total size. Compare against `files` in `package.json` — anything outside `files` means the glob is wrong (or `.npmignore` is interfering).
|
|
206
|
+
|
|
207
|
+
`pnpm publish -r` skips already-published versions automatically, but for clarity:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
pnpm -r --filter "./packages/published/*" exec sh -c \
|
|
211
|
+
'npm view "$npm_package_name@$npm_package_version" version 2>/dev/null \
|
|
212
|
+
&& echo "ALREADY PUBLISHED" && exit 1 || true'
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Wire gates 3-4 as a turbo task in each package's `package.json`:
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"scripts": {
|
|
220
|
+
"lint:package": "publint && attw --pack ."
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Then in CI before publish: `pnpm turbo run lint:package`.
|
|
226
|
+
|
|
227
|
+
## Public / Private Separation Recap
|
|
228
|
+
|
|
229
|
+
| Layer | Mechanism | Purpose |
|
|
230
|
+
|-------|-----------|---------|
|
|
231
|
+
| Folder convention | `packages/published/*` vs `packages/internal/*` | Human signal |
|
|
232
|
+
| `private: true` | `package.json` per internal package | Hard block — pnpm refuses to publish |
|
|
233
|
+
| Changesets `ignore` | `.changeset/config.json` | Keeps deployed apps off the version PR |
|
|
234
|
+
| Workspace dep protocol | `"@codebyplan/foo": "workspace:*"` | Internal deps stay internal; pnpm rewrites at publish time |
|
|
235
|
+
|
|
236
|
+
When an internal package is published by mistake:
|
|
237
|
+
|
|
238
|
+
1. `npm unpublish @scope/pkg@x.y.z` within 72 hours, OR
|
|
239
|
+
2. `npm deprecate @scope/pkg@"<= x.y.z" "Internal package — do not use"` after that.
|
|
240
|
+
|
|
241
|
+
Then add `"private": true` and ship.
|
|
242
|
+
|
|
243
|
+
## Sources
|
|
244
|
+
|
|
245
|
+
- [pnpm — publish](https://pnpm.io/cli/publish)
|
|
246
|
+
- [pnpm — workspaces](https://pnpm.io/workspaces)
|
|
247
|
+
- [npm Docs — package.json](https://docs.npmjs.com/cli/v10/configuring-npm/package-json)
|
|
248
|
+
- [Changesets](https://github.com/changesets/changesets)
|
|
249
|
+
- [release-please](https://github.com/googleapis/release-please)
|
|
250
|
+
- [publint](https://publint.dev/)
|
|
251
|
+
- [Are The Types Wrong](https://arethetypeswrong.github.io/)
|
|
252
|
+
- [npm CLI source](https://github.com/npm/cli)
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# npm OIDC Trusted Publishing
|
|
2
|
+
|
|
3
|
+
Modern publish flow: no NPM_TOKEN, no leak risk. npm trusts a short-lived OIDC token issued by your CI provider. Provenance attestations are generated automatically and recorded in a public transparency ledger (Sigstore).
|
|
4
|
+
|
|
5
|
+
This is the **default publish path for `/cbp-ship`** when the npm-package surface is in play — it's the publish path the orchestrator should reach for first.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
1. CI job starts. The CI provider (GitHub Actions, GitLab CI, CircleCI) mints a short-lived OIDC ID token signed with its public key.
|
|
10
|
+
2. `npm publish` reads the OIDC token from the runner and exchanges it with the npm registry for a one-shot publish credential.
|
|
11
|
+
3. npm validates the OIDC token's claims — `repository`, `workflow`, `ref`, `aud` — against the trusted-publisher rule registered for the package.
|
|
12
|
+
4. If the claims match, the publish is accepted. If not, the publish is rejected with `403`.
|
|
13
|
+
5. (GitHub Actions / GitLab only) npm automatically generates a Sigstore provenance attestation linking the published tarball to the exact commit, workflow file, and runner image that built it. The attestation is logged to the [Rekor transparency ledger](https://search.sigstore.dev/).
|
|
14
|
+
|
|
15
|
+
The OIDC token's lifetime is measured in minutes; it is bound to the workflow run; it cannot be replayed. There is nothing for an attacker to exfiltrate from the runner that survives the job.
|
|
16
|
+
|
|
17
|
+
## Supported Providers
|
|
18
|
+
|
|
19
|
+
| Provider | OIDC | Auto-provenance |
|
|
20
|
+
|----------|------|-----------------|
|
|
21
|
+
| GitHub Actions (GitHub-hosted runners) | Yes | Yes |
|
|
22
|
+
| GitLab CI/CD (GitLab.com shared runners) | Yes | Yes |
|
|
23
|
+
| CircleCI cloud | Yes | No (must pass `--provenance` manually with extra setup) |
|
|
24
|
+
| Self-hosted runners (any provider) | Not supported | Not supported |
|
|
25
|
+
|
|
26
|
+
Self-hosted runners cannot use trusted publishing today — the npm registry does not yet validate signing certificates from non-cloud OIDC issuers.
|
|
27
|
+
|
|
28
|
+
## Setup — GitHub Actions
|
|
29
|
+
|
|
30
|
+
### Step 1 — Register the trusted publisher on npmjs.com
|
|
31
|
+
|
|
32
|
+
1. Sign in at https://www.npmjs.com.
|
|
33
|
+
2. Navigate to your package: `npmjs.com/package/<your-pkg>`.
|
|
34
|
+
3. Settings → **Trusted Publishers** → **Add publisher**.
|
|
35
|
+
4. Select **GitHub Actions**, then fill in:
|
|
36
|
+
- **Organization or user**: e.g. `codebyplan`
|
|
37
|
+
- **Repository**: e.g. `codebyplan`
|
|
38
|
+
- **Workflow filename**: e.g. `release.yml` (just the filename, not the full path)
|
|
39
|
+
- **Environment** (optional): e.g. `production` — restricts to runs scoped to a GitHub Actions environment
|
|
40
|
+
|
|
41
|
+
If the package does not yet exist on the registry, you must publish it once with a classic token before you can register a trusted publisher (npm requires the package to exist to attach a trust rule).
|
|
42
|
+
|
|
43
|
+
### Step 2 — Update the workflow
|
|
44
|
+
|
|
45
|
+
Add `id-token: write` to the job's permissions and use a recent npm CLI (≥9.5.0; npm 10+ is recommended).
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
name: Release
|
|
49
|
+
|
|
50
|
+
on:
|
|
51
|
+
push:
|
|
52
|
+
tags:
|
|
53
|
+
- "v*"
|
|
54
|
+
|
|
55
|
+
jobs:
|
|
56
|
+
publish:
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
|
|
59
|
+
permissions:
|
|
60
|
+
contents: read # checkout
|
|
61
|
+
id-token: write # OIDC — required for trusted publishing
|
|
62
|
+
attestations: write # required for provenance attestations
|
|
63
|
+
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
|
|
67
|
+
- uses: actions/setup-node@v4
|
|
68
|
+
with:
|
|
69
|
+
node-version: "20"
|
|
70
|
+
registry-url: "https://registry.npmjs.org"
|
|
71
|
+
|
|
72
|
+
- uses: pnpm/action-setup@v4
|
|
73
|
+
with:
|
|
74
|
+
version: 10
|
|
75
|
+
|
|
76
|
+
- run: pnpm install --frozen-lockfile
|
|
77
|
+
|
|
78
|
+
- run: pnpm build
|
|
79
|
+
|
|
80
|
+
- run: pnpm test
|
|
81
|
+
|
|
82
|
+
- name: Verify publish (dry run)
|
|
83
|
+
run: pnpm publish --dry-run --access public
|
|
84
|
+
|
|
85
|
+
- name: Lint package shape
|
|
86
|
+
run: |
|
|
87
|
+
pnpm dlx publint
|
|
88
|
+
pnpm dlx @arethetypeswrong/cli --pack
|
|
89
|
+
|
|
90
|
+
- name: Publish to npm
|
|
91
|
+
run: pnpm publish --access public --provenance --no-git-checks
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Notes:
|
|
95
|
+
|
|
96
|
+
- **No `NODE_AUTH_TOKEN` env var.** That's the entire point — there is no token to leak. The `setup-node` action wires up `.npmrc` to the registry URL; OIDC handshake happens inside `npm publish`.
|
|
97
|
+
- `--provenance` is **automatic** on GitHub Actions OIDC publishes (npm enables it implicitly), but passing the flag is harmless and makes intent explicit. `publishConfig.provenance: true` in `package.json` is the third equivalent.
|
|
98
|
+
- `--no-git-checks` (pnpm-only) bypasses the "current branch must be the publish branch, working tree must be clean" check. Safe in CI where the runner has a fresh clone at a tag.
|
|
99
|
+
|
|
100
|
+
## Provenance Attestations
|
|
101
|
+
|
|
102
|
+
A provenance attestation is a JSON document signed by Sigstore that describes:
|
|
103
|
+
|
|
104
|
+
- The source repository URL and the exact commit SHA that was built.
|
|
105
|
+
- The workflow file path and the run ID.
|
|
106
|
+
- The builder identity (e.g. `https://github.com/actions/runner`).
|
|
107
|
+
- The npm package name, version, and tarball SHA.
|
|
108
|
+
|
|
109
|
+
After publish, the npm registry shows a "Provenance" badge on the package page linking to the Sigstore record.
|
|
110
|
+
|
|
111
|
+
### Verifying attestations as a consumer
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm audit signatures
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This walks every dependency in the current project, checks the registry signature on each tarball, and validates any provenance attestations. A failure means either the package was tampered with after publish or its signing identity changed unexpectedly.
|
|
118
|
+
|
|
119
|
+
For a single package without installing it:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npm view <pkg> --json | jq '.dist.attestations'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Returns the URL of the attestation bundle on the registry; the bundle is a Sigstore-format JSON that can be verified with `cosign` or the `sigstore-js` library.
|
|
126
|
+
|
|
127
|
+
## Comparison vs Classic NPM_TOKEN
|
|
128
|
+
|
|
129
|
+
| Aspect | Classic NPM_TOKEN | OIDC Trusted Publishing |
|
|
130
|
+
|--------|-------------------|--------------------------|
|
|
131
|
+
| Secret stored in CI | Yes — long-lived token | No |
|
|
132
|
+
| Rotation burden | Manual; forgotten tokens are common | None — every publish mints a fresh credential |
|
|
133
|
+
| Leak blast radius | Token works from anywhere until revoked | Credential expires in minutes; bound to one workflow run |
|
|
134
|
+
| Provenance | Manual `--provenance` + extra setup | Automatic on GitHub Actions / GitLab |
|
|
135
|
+
| Setup complexity | Generate token, paste into CI secrets | One-time npm web UI registration |
|
|
136
|
+
| Works on self-hosted runners | Yes | No (today) |
|
|
137
|
+
| Works locally | Yes | No (no OIDC issuer) |
|
|
138
|
+
|
|
139
|
+
Classic tokens still have a place: local release machines, self-hosted runners, providers npm doesn't trust yet. For everything else, OIDC is the default in 2026.
|
|
140
|
+
|
|
141
|
+
## Failure Modes
|
|
142
|
+
|
|
143
|
+
| Symptom | Cause | Fix |
|
|
144
|
+
|---------|-------|-----|
|
|
145
|
+
| `403 Forbidden — OIDC publish requires id-token: write` | Workflow missing the permission | Add `permissions.id-token: write` to the job |
|
|
146
|
+
| `403 — trusted publisher mismatch` | Workflow filename, repo, or org doesn't match the rule | Re-check the trusted-publisher rule on npmjs.com matches `${{ github.repository }}` and `${{ github.workflow_ref }}` exactly |
|
|
147
|
+
| `Provenance generation failed: repository field mismatch` | `package.json` `repository.url` doesn't match the GitHub repo URL | Set `"repository": { "type": "git", "url": "git+https://github.com/<org>/<repo>.git" }` (case-sensitive) |
|
|
148
|
+
| Attestations missing on the registry page | Used CircleCI without manual provenance setup | Either accept (CircleCI limitation) or migrate to GitHub Actions / GitLab |
|
|
149
|
+
| `OIDC token unavailable` from a self-hosted runner | Trusted publishing not supported there | Fall back to a granular token, or move the publish job to a GitHub-hosted runner |
|
|
150
|
+
|
|
151
|
+
## Sources
|
|
152
|
+
|
|
153
|
+
- [npm Docs — Trusted publishers](https://docs.npmjs.com/trusted-publishers)
|
|
154
|
+
- [npm Docs — Generating provenance statements](https://docs.npmjs.com/generating-provenance-statements)
|
|
155
|
+
- [npm Docs — npm audit signatures](https://docs.npmjs.com/cli/v10/commands/npm-audit)
|
|
156
|
+
- [Sigstore](https://www.sigstore.dev/) — signing infrastructure
|
|
157
|
+
- [npm CLI source](https://github.com/npm/cli)
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# npm Publish — Overview
|
|
2
|
+
|
|
3
|
+
Reference for the `/cbp-ship` orchestrator's `npm-package` surface. Covers what `npm publish` does, registry types, 2FA tiers, package metadata that affects publish output, and `latest` dist-tag semantics.
|
|
4
|
+
|
|
5
|
+
## What `npm publish` Does
|
|
6
|
+
|
|
7
|
+
`npm publish` packs the current package into a tarball and uploads it to a registry, registering the version under the package name. Once a version is published it is **immutable** — you cannot republish the same `name@version` (you can only `npm unpublish` within 72 hours, and only if no other public package depends on it).
|
|
8
|
+
|
|
9
|
+
Pack rules:
|
|
10
|
+
|
|
11
|
+
1. CLI computes the file list from (in order): `files` field in `package.json`, `.npmignore`, `.gitignore`. Always-included: `package.json`, `README*`, `LICENSE*`, the file at `main`/`bin`/`exports`. Always-excluded: `node_modules`, `.git`, `.npmrc`, `package-lock.json`.
|
|
12
|
+
2. CLI runs lifecycle scripts: `prepublishOnly` → `prepack` → tarball write → `postpack` → `publish` → `postpublish`.
|
|
13
|
+
3. Tarball uploaded to registry with auth (token or OIDC); registry assigns the `latest` dist-tag unless `--tag <name>` overrides.
|
|
14
|
+
|
|
15
|
+
`npm publish --dry-run` runs all the above except the upload — use it to preview the file list and lifecycle execution.
|
|
16
|
+
|
|
17
|
+
## Registry Types
|
|
18
|
+
|
|
19
|
+
| Registry | Purpose | URL |
|
|
20
|
+
|----------|---------|-----|
|
|
21
|
+
| Public registry | Default; what `npm install <pkg>` hits | `https://registry.npmjs.org` |
|
|
22
|
+
| GitHub Packages | npm packages scoped to a GitHub org | `https://npm.pkg.github.com` |
|
|
23
|
+
| Private registry | Verdaccio, Nexus, JFrog Artifactory, Bytesafe, Cloudsmith | self-hosted or vendor URL |
|
|
24
|
+
|
|
25
|
+
Registry selection comes from (highest precedence first):
|
|
26
|
+
|
|
27
|
+
1. `publishConfig.registry` in `package.json`
|
|
28
|
+
2. `--registry <url>` on the CLI
|
|
29
|
+
3. `npm_config_registry` env var
|
|
30
|
+
4. `registry=` line in `.npmrc` (project, then user, then global)
|
|
31
|
+
5. Default — `https://registry.npmjs.org`
|
|
32
|
+
|
|
33
|
+
Scoped packages (`@scope/name`) can route by scope: `@cbp-registry=https://npm.pkg.github.com` in `.npmrc` sends only that scope to GH Packages.
|
|
34
|
+
|
|
35
|
+
## 2FA Tiers
|
|
36
|
+
|
|
37
|
+
npm offers two 2FA modes (set with `npm profile enable-2fa <mode>`):
|
|
38
|
+
|
|
39
|
+
| Mode | Covers | Use case |
|
|
40
|
+
|------|--------|----------|
|
|
41
|
+
| `auth-only` | Login, profile changes | Convenience — publishes work with token alone |
|
|
42
|
+
| `auth-and-writes` | Login + every publish, `dist-tag`, `unpublish`, `access` change | Hardened — publish requires fresh OTP |
|
|
43
|
+
|
|
44
|
+
Publishing requires **one** of:
|
|
45
|
+
|
|
46
|
+
- 2FA enabled on the account (any mode), OR
|
|
47
|
+
- A **granular access token** with "bypass 2FA" enabled (legacy automation tokens are deprecated; granular is the modern equivalent).
|
|
48
|
+
|
|
49
|
+
For CI flows the modern recommendation is **OIDC trusted publishing** (no token at all) — see [npm-publish-oidc-trusted.md](./npm-publish-oidc-trusted.md). Granular tokens with bypass-2FA remain valid for non-CI release machines.
|
|
50
|
+
|
|
51
|
+
## Package Metadata That Matters at Publish Time
|
|
52
|
+
|
|
53
|
+
### `exports`
|
|
54
|
+
|
|
55
|
+
Modern entry-point map. Replaces `main` for resolvers that honour it (Node ≥12.20, all modern bundlers). Conditional exports let you ship CJS + ESM + types from one package:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"exports": {
|
|
60
|
+
".": {
|
|
61
|
+
"types": "./dist/index.d.ts",
|
|
62
|
+
"import": "./dist/index.mjs",
|
|
63
|
+
"require": "./dist/index.cjs"
|
|
64
|
+
},
|
|
65
|
+
"./package.json": "./package.json"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Always export `./package.json` — toolchains (`publint`, `attw`) and some bundlers expect it. If `exports` is set, `main` becomes a fallback only for legacy resolvers.
|
|
71
|
+
|
|
72
|
+
### `files`
|
|
73
|
+
|
|
74
|
+
Allowlist of paths to include in the tarball. Prefer `files` over `.npmignore` — allowlists fail closed (forgetting to ignore a build artefact never leaks a secret):
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"files": ["dist", "README.md", "LICENSE"]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`package.json`, `README*`, `LICENSE*` are always included regardless. `test/`, `__tests__/`, `*.test.*` are excluded automatically.
|
|
83
|
+
|
|
84
|
+
### `publishConfig`
|
|
85
|
+
|
|
86
|
+
Per-package override of registry config, applied only at publish time. Common keys:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"publishConfig": {
|
|
91
|
+
"access": "public",
|
|
92
|
+
"registry": "https://registry.npmjs.org",
|
|
93
|
+
"tag": "next",
|
|
94
|
+
"provenance": true
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `access: "public"` is required when first publishing a scoped package (`@scope/name`); otherwise registry assumes private and rejects free-tier accounts.
|
|
100
|
+
- `tag: "next"` (or any non-`latest`) keeps the version off the default install pointer — useful for prereleases.
|
|
101
|
+
- `provenance: true` is the package.json equivalent of `--provenance` (see [npm-publish-oidc-trusted.md](./npm-publish-oidc-trusted.md)).
|
|
102
|
+
|
|
103
|
+
### `engines`
|
|
104
|
+
|
|
105
|
+
Declares Node/npm version compatibility:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"engines": { "node": ">=20.0.0", "pnpm": ">=10.0.0" }
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
By default `engines` is advisory (warns, does not fail). `engine-strict=true` in `.npmrc` makes it a hard error on install.
|
|
114
|
+
|
|
115
|
+
### `bin`
|
|
116
|
+
|
|
117
|
+
Maps CLI command names to file paths. The published tarball will mark these executable; the install will create symlinks in `node_modules/.bin`:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"bin": { "codebyplan": "./dist/cli.js" }
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The target file must have a shebang (`#!/usr/bin/env node`).
|
|
126
|
+
|
|
127
|
+
## `latest` Dist-Tag Semantics
|
|
128
|
+
|
|
129
|
+
When a user runs `npm install <pkg>` without a version specifier, npm resolves to whatever the `latest` dist-tag points at. Implications:
|
|
130
|
+
|
|
131
|
+
- The first publish of a package always becomes `latest`.
|
|
132
|
+
- Subsequent publishes become `latest` **unless** `--tag <name>` is passed (or `publishConfig.tag` is set to something other than `latest`).
|
|
133
|
+
- Publishing a hotfix to an older major (e.g. `1.5.3` after `2.0.0` is already `latest`) will overwrite `latest` to point back at `1.5.3` — almost always a mistake. Use `npm publish --tag legacy` for hotfixes on old majors, then `npm dist-tag add <pkg>@1.5.3 v1-legacy` to give consumers an explicit pointer.
|
|
134
|
+
|
|
135
|
+
Common dist-tag conventions:
|
|
136
|
+
|
|
137
|
+
| Tag | Convention |
|
|
138
|
+
|-----|-----------|
|
|
139
|
+
| `latest` | Default install target — stable releases only |
|
|
140
|
+
| `next` | Upcoming version (often release candidates) |
|
|
141
|
+
| `beta` / `alpha` | Prereleases — opt-in via `npm install pkg@beta` |
|
|
142
|
+
| `canary` / `nightly` | Auto-published from main branch |
|
|
143
|
+
|
|
144
|
+
Manage tags after publish:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm dist-tag ls <pkg> # list all tags
|
|
148
|
+
npm dist-tag add <pkg>@<ver> next # promote a version to a tag
|
|
149
|
+
npm dist-tag rm <pkg> beta # remove a tag (does not unpublish)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Tags must not parse as valid semver ranges — `v1.4` is rejected, `v1-legacy` is fine.
|
|
153
|
+
|
|
154
|
+
## Pre-Publish Checklist
|
|
155
|
+
|
|
156
|
+
For a clean publish via `/cbp-ship`:
|
|
157
|
+
|
|
158
|
+
1. `npm whoami` (or OIDC trust verified) — confirm auth context.
|
|
159
|
+
2. `npm publish --dry-run` — review the file list; nothing surprising.
|
|
160
|
+
3. `npx publint` — lint package.json shape.
|
|
161
|
+
4. `npx @arethetypeswrong/cli --pack` — verify type resolution across CJS/ESM.
|
|
162
|
+
5. Version bump committed and tagged in git (release-please or changesets handles this).
|
|
163
|
+
6. CI green on the commit being published.
|
|
164
|
+
|
|
165
|
+
## Sources
|
|
166
|
+
|
|
167
|
+
- [npm Docs — package.json](https://docs.npmjs.com/cli/v10/configuring-npm/package-json)
|
|
168
|
+
- [npm Docs — npm publish](https://docs.npmjs.com/cli/v10/commands/npm-publish)
|
|
169
|
+
- [npm Docs — npm dist-tag](https://docs.npmjs.com/cli/v10/commands/npm-dist-tag)
|
|
170
|
+
- [npm Docs — Configuring 2FA](https://docs.npmjs.com/configuring-two-factor-authentication)
|
|
171
|
+
- [npm CLI source](https://github.com/npm/cli)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Pre-flight Checklist
|
|
2
|
+
|
|
3
|
+
Run before invoking `/cbp-ship`. The orchestrator's Step 1 detection runs this implicitly; this file documents what it checks and what to do when a check fails.
|
|
4
|
+
|
|
5
|
+
## Universal pre-flight (every shipment)
|
|
6
|
+
|
|
7
|
+
| # | Check | Why | If fails |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| 1 | `gh auth status` succeeds | gh CLI is needed for tag push, release verification | `gh auth login` |
|
|
10
|
+
| 2 | Working tree is clean (no uncommitted changes) | Shipping uncommitted code = ghosts | Commit or stash; do NOT proceed |
|
|
11
|
+
| 3 | Current branch matches expected post-promotion branch | Caller (`/cbp-checkpoint-end`) just merged into PRODUCTION | If wrong, `git checkout` correct branch |
|
|
12
|
+
| 4 | `.codebyplan/` files are parseable | All config reads from per-concern files | Fix JSON; or run `npx codebyplan config` |
|
|
13
|
+
| 5 | Active checkpoint exists in DB | Shipment is per-checkpoint | Run `/cbp-todo` to find/create checkpoint |
|
|
14
|
+
| 6 | `checkpoint.context.check_results` exists | Checkpoint check must pass before shipment | Run `/cbp-checkpoint-check` first |
|
|
15
|
+
|
|
16
|
+
## Per-surface pre-flight
|
|
17
|
+
|
|
18
|
+
The detection script (`scripts/detect-surfaces.sh`) emits `configured: false` with a `reason` when a surface fails its pre-flight. Rather than duplicating those reasons here, see each surface's `## Configured indicators` section in its reference file.
|
|
19
|
+
|
|
20
|
+
Quick reference:
|
|
21
|
+
|
|
22
|
+
| Surface | Critical pre-flight check |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `vercel-web` | `vercel whoami` succeeds AND `.vercel/project.json` exists |
|
|
25
|
+
| `expo-mobile` | `eas whoami` succeeds AND `eas.json` parseable AND credentials valid (`eas credentials` audit) |
|
|
26
|
+
| `tauri-desktop` | All 9 GH secrets present in repo (`gh secret list`) |
|
|
27
|
+
| `npm-package` | `npm whoami` succeeds AND 2FA enabled AND local version > registry version |
|
|
28
|
+
| `vscode-ext` | `vsce verify-pat <publisher>` succeeds |
|
|
29
|
+
| `railway-backend` | `railway whoami` succeeds AND service is linked AND env vars set |
|
|
30
|
+
| `supabase` | `supabase projects list` succeeds AND project ref matches |
|
|
31
|
+
|
|
32
|
+
## Recommended pre-flight when adding a new surface
|
|
33
|
+
|
|
34
|
+
If you're configuring a surface for the first time (via `/cbp-ship-configure`), run these once:
|
|
35
|
+
|
|
36
|
+
1. **For Vercel**:
|
|
37
|
+
- Verify build works locally: `pnpm build`
|
|
38
|
+
- Verify env vars are documented: `cat .env.example`
|
|
39
|
+
- Verify domain DNS is healthy if using custom domain
|
|
40
|
+
|
|
41
|
+
2. **For Expo / mobile**:
|
|
42
|
+
- Verify Apple Developer account is enrolled (paid)
|
|
43
|
+
- Verify ASC API key is generated and `.p8` file is readable
|
|
44
|
+
- Verify EAS project is created: `eas project:info`
|
|
45
|
+
- Run a development build first: `eas build --profile development --platform ios`
|
|
46
|
+
|
|
47
|
+
3. **For Tauri desktop**:
|
|
48
|
+
- Generate signing key: `npx tauri signer generate -w ~/.tauri/{app}.key`
|
|
49
|
+
- Export Apple Developer ID cert as `.p12`
|
|
50
|
+
- Upload all 9 GH secrets per architecture doc
|
|
51
|
+
- Test the workflow on a non-production tag first (e.g., `v0.0.0-test`)
|
|
52
|
+
|
|
53
|
+
4. **For npm package**:
|
|
54
|
+
- Verify `package.json` has `name`, `version`, `description`, `keywords`, `repository`, `license`, `author`
|
|
55
|
+
- Run `npm pack --dry-run` and verify the tarball contains the right files
|
|
56
|
+
- Run `pnpm publint` to catch metadata issues
|
|
57
|
+
- Run `pnpm attw --pack` to verify TS types resolve correctly
|
|
58
|
+
|
|
59
|
+
5. **For VS Code extension**:
|
|
60
|
+
- Create a publisher account at https://aka.ms/vscode-create-publisher
|
|
61
|
+
- Generate PAT with "Marketplace → Manage" scope
|
|
62
|
+
- Run `vsce verify-pat <publisher>` — succeeds = good
|
|
63
|
+
- Verify `package.json` has `displayName`, `description`, `categories`, `icon` (≥128×128 PNG)
|
|
64
|
+
|
|
65
|
+
6. **For Railway**:
|
|
66
|
+
- Create project: `railway init`
|
|
67
|
+
- Link service: `railway link`
|
|
68
|
+
- Add env vars: `railway variables set KEY=VALUE`
|
|
69
|
+
- Configure health endpoint in service code (`/health` returning 200)
|
|
70
|
+
- Test deploy: `railway up`
|
|
71
|
+
|
|
72
|
+
7. **For Supabase**:
|
|
73
|
+
- Verify migrations directory is initialized: `ls supabase/migrations/`
|
|
74
|
+
- Link project: `supabase link --project-ref <ref>`
|
|
75
|
+
- Generate baseline migration if existing schema: `supabase db dump > supabase/migrations/0000_baseline.sql`
|
|
76
|
+
- Verify types path: `supabase gen types typescript --project-id <ref> > types.ts`
|
|
77
|
+
|
|
78
|
+
## When pre-flight fails mid-shipment
|
|
79
|
+
|
|
80
|
+
If `/cbp-ship` is mid-shipment and a per-surface pre-flight fails:
|
|
81
|
+
|
|
82
|
+
1. Mark that surface failed
|
|
83
|
+
2. Continue with remaining surfaces (don't halt the whole shipment unless `supabase` failed)
|
|
84
|
+
3. Surface the failure in the final report
|
|
85
|
+
4. Suggest the user run `/cbp-ship-configure --surface=<id>` to fix
|
|
86
|
+
5. After fix, re-run `/cbp-ship` — it picks up where it left off (verified surfaces are skipped)
|
|
87
|
+
|
|
88
|
+
The shipment record (`checkpoint.context.shipment`) tracks per-surface status, so partial re-runs are safe.
|