@icebreakers/monorepo-templates 2.0.7 → 2.2.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 +1 -1
- package/README.zh-CN.md +1 -1
- package/assets/.agents/skills/repoctl/SKILL.md +4 -2
- package/assets/.agents/skills/repoctl/references/commands.md +224 -13
- package/assets/.agents/skills/repoctl/references/config.md +70 -6
- package/assets/.agents/skills/repoctl/references/dependencies.md +37 -0
- package/assets/.agents/skills/repoctl/references/knip.md +34 -0
- package/assets/.agents/skills/repoctl/references/templates.md +26 -2
- package/assets/.github/workflows/ci.yml +10 -14
- package/assets/package.json +8 -16
- package/assets/pnpm-workspace.yaml +4 -1
- package/assets/repoctl.config.ts +1 -1
- package/assets/turbo.json +12 -4
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +281 -1
- package/dist/index.mjs +1138 -75
- package/dist/{prepare-BapI8ioj.mjs → prepare-BYNSxvoB.mjs} +96 -4
- package/package.json +2 -1
- package/template-data.mjs +32 -0
- package/templates/client/package.json +2 -2
- package/templates/next/README.md +31 -0
- package/templates/next/eslint.config.js +5 -0
- package/templates/next/gitignore +7 -0
- package/templates/next/next.config.ts +5 -0
- package/templates/next/package.json +36 -0
- package/templates/next/src/app/api/health/route.ts +5 -0
- package/templates/next/src/app/counter.tsx +19 -0
- package/templates/next/src/app/favicon.ico +0 -0
- package/templates/next/src/app/globals.css +109 -0
- package/templates/next/src/app/layout.tsx +17 -0
- package/templates/next/src/app/page.tsx +16 -0
- package/templates/next/stylelint.config.js +3 -0
- package/templates/next/test/counter.test.tsx +22 -0
- package/templates/next/tsconfig.json +40 -0
- package/templates/next/turbo.json +24 -0
- package/templates/next/vitest.config.js +9 -0
- package/templates/nimbus/AGENTS.md +12 -0
- package/templates/nimbus/LICENSE +21 -0
- package/templates/nimbus/README.md +17 -0
- package/templates/nimbus/UPSTREAM.md +16 -0
- package/templates/nimbus/astro.config.ts +28 -0
- package/templates/nimbus/eslint.config.js +25 -0
- package/templates/nimbus/gitignore +5 -0
- package/templates/nimbus/nimbus.json +4 -0
- package/templates/nimbus/package.json +34 -0
- package/templates/nimbus/public/favicon.svg +1 -0
- package/templates/nimbus/scripts/check-locales.mjs +11 -0
- package/templates/nimbus/src/components/aside.astro +9 -0
- package/templates/nimbus/src/components/head.astro +43 -0
- package/templates/nimbus/src/components/search/client.ts +62 -0
- package/templates/nimbus/src/components/search/index.astro +26 -0
- package/templates/nimbus/src/components/sidebar.astro +26 -0
- package/templates/nimbus/src/components.ts +3 -0
- package/templates/nimbus/src/content/docs/get-started.mdx +36 -0
- package/templates/nimbus/src/content/docs/index.mdx +16 -0
- package/templates/nimbus/src/content/docs/writing.mdx +35 -0
- package/templates/nimbus/src/content/docs/zh/get-started.mdx +36 -0
- package/templates/nimbus/src/content/docs/zh/index.mdx +16 -0
- package/templates/nimbus/src/content/docs/zh/writing.mdx +35 -0
- package/templates/nimbus/src/content.config.ts +6 -0
- package/templates/nimbus/src/env.d.ts +6 -0
- package/templates/nimbus/src/layouts/docs.astro +70 -0
- package/templates/nimbus/src/lib/locale.ts +50 -0
- package/templates/nimbus/src/pages/[...slug]/index.md.ts +4 -0
- package/templates/nimbus/src/pages/[...slug]/index.mdx.ts +4 -0
- package/templates/nimbus/src/pages/[...slug].astro +36 -0
- package/templates/nimbus/src/pages/[section]/llms.txt.ts +4 -0
- package/templates/nimbus/src/pages/llms-full.txt.ts +4 -0
- package/templates/nimbus/src/pages/llms.txt.ts +4 -0
- package/templates/nimbus/src/pages/robots.txt.ts +18 -0
- package/templates/nimbus/src/styles/base.css +121 -0
- package/templates/nimbus/src/styles/site.css +186 -0
- package/templates/nimbus/stylelint.config.js +3 -0
- package/templates/nimbus/tsconfig.json +10 -0
- package/templates/react-lib/LICENSE +21 -0
- package/templates/react-lib/README.md +52 -0
- package/templates/react-lib/eslint.config.js +5 -0
- package/templates/react-lib/gitignore +4 -0
- package/templates/react-lib/package.json +48 -0
- package/templates/react-lib/src/counter.tsx +28 -0
- package/templates/react-lib/src/index.ts +2 -0
- package/templates/react-lib/src/style.css +36 -0
- package/templates/react-lib/stylelint.config.js +3 -0
- package/templates/react-lib/test/counter.test.tsx +28 -0
- package/templates/react-lib/test-d/index.test-d.ts +11 -0
- package/templates/react-lib/tsconfig.app.json +15 -0
- package/templates/react-lib/tsconfig.build.json +12 -0
- package/templates/react-lib/tsconfig.json +4 -0
- package/templates/react-lib/tsconfig.node.json +11 -0
- package/templates/react-lib/vite.config.ts +22 -0
- package/templates/react-lib/vitest.config.ts +5 -0
- package/templates/react-vite/README.md +27 -0
- package/templates/react-vite/eslint.config.js +5 -0
- package/templates/react-vite/gitignore +6 -0
- package/templates/react-vite/index.html +13 -0
- package/templates/react-vite/package.json +36 -0
- package/templates/react-vite/src/app.tsx +22 -0
- package/templates/react-vite/src/main.tsx +15 -0
- package/templates/react-vite/src/style.css +95 -0
- package/templates/react-vite/stylelint.config.js +3 -0
- package/templates/react-vite/test/app.test.tsx +22 -0
- package/templates/react-vite/tsconfig.app.json +26 -0
- package/templates/react-vite/tsconfig.json +11 -0
- package/templates/react-vite/tsconfig.node.json +18 -0
- package/templates/react-vite/vite.config.ts +6 -0
- package/templates/react-vite/vitest.config.ts +9 -0
- package/templates/server/package.json +1 -1
- package/templates/vitepress/.vitepress/config.ts +4 -5
- package/templates/vitepress/.vitepress/home/content.ts +2 -2
- package/templates/vitepress/.vitepress/home/faq.ts +16 -0
- package/templates/vitepress/.vitepress/mermaid/markdown.ts +18 -0
- package/templates/vitepress/.vitepress/mermaid/mermaid.vue +66 -0
- package/templates/vitepress/.vitepress/mermaid/render.ts +37 -0
- package/templates/vitepress/.vitepress/navigation/routes.ts +7 -0
- package/templates/vitepress/.vitepress/seo.ts +12 -1
- package/templates/vitepress/.vitepress/theme/components/HomePage.vue +2 -16
- package/templates/vitepress/.vitepress/theme/index.ts +3 -1
- package/templates/vitepress/ai/create.md +1 -1
- package/templates/vitepress/package.json +4 -8
- package/templates/vitepress/reference/artifacts.md +51 -0
- package/templates/vitepress/reference/commands.md +152 -3
- package/templates/vitepress/reference/config.md +101 -7
- package/templates/vitepress/reference/dependencies.md +116 -0
- package/templates/vitepress/reference/dependency-admission.md +67 -0
- package/templates/vitepress/reference/devcontainer.md +25 -0
- package/templates/vitepress/reference/index.md +1 -0
- package/templates/vitepress/reference/install-security.md +51 -0
- package/templates/vitepress/reference/knip.md +55 -0
- package/templates/vitepress/reference/move.md +39 -0
- package/templates/vitepress/reference/organization-presets.md +89 -0
- package/templates/vitepress/reference/removal.md +42 -0
- package/templates/vitepress/reference/template-assets.md +40 -1
- package/templates/vitepress/reference/templates.md +376 -9
- package/templates/vitepress/start/diagnose.md +19 -2
- package/templates/vitepress/tasks/checks.md +149 -1
- package/templates/vitepress/tasks/ci.md +93 -1
- package/templates/vitepress/tasks/index.md +1 -1
- package/templates/vitepress/tasks/release.md +72 -6
- package/templates/vitepress/test/mermaid.test.ts +39 -0
- package/templates/vitepress/test/render.test.ts +48 -0
- package/templates/vitepress/test/seo.test.ts +19 -0
- package/templates/vitepress/tsconfig.json +8 -8
- package/templates/vitepress/vitest.config.ts +8 -0
- package/templates/vitepress/zh/ai/create.md +1 -1
- package/templates/vitepress/zh/learn/monorepo/manage.md +1 -1
- package/templates/vitepress/zh/reference/artifacts.md +51 -0
- package/templates/vitepress/zh/reference/commands.md +151 -3
- package/templates/vitepress/zh/reference/config.md +94 -2
- package/templates/vitepress/zh/reference/dependencies.md +116 -0
- package/templates/vitepress/zh/reference/dependency-admission.md +67 -0
- package/templates/vitepress/zh/reference/devcontainer.md +25 -0
- package/templates/vitepress/zh/reference/execution-model.md +1 -1
- package/templates/vitepress/zh/reference/index.md +1 -0
- package/templates/vitepress/zh/reference/install-security.md +51 -0
- package/templates/vitepress/zh/reference/knip.md +55 -0
- package/templates/vitepress/zh/reference/move.md +39 -0
- package/templates/vitepress/zh/reference/organization-presets.md +89 -0
- package/templates/vitepress/zh/reference/removal.md +42 -0
- package/templates/vitepress/zh/reference/template-assets.md +22 -6
- package/templates/vitepress/zh/reference/templates.md +356 -9
- package/templates/vitepress/zh/start/diagnose.md +24 -13
- package/templates/vitepress/zh/tasks/checks.md +150 -0
- package/templates/vitepress/zh/tasks/ci.md +93 -1
- package/templates/vitepress/zh/tasks/index.md +1 -1
- package/templates/vitepress/zh/tasks/release.md +72 -6
- package/templates/vitepress/zh/tasks/reports.md +1 -1
- package/templates/vue-lib/package.json +1 -1
|
@@ -2,22 +2,11 @@
|
|
|
2
2
|
import type { DocsLocale } from '../../navigation/routes'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
4
|
import { homeContent } from '../../home/content'
|
|
5
|
+
import { faqContent } from '../../home/faq'
|
|
5
6
|
|
|
6
7
|
const props = defineProps<{ locale: DocsLocale }>()
|
|
7
8
|
const content = computed(() => homeContent[props.locale])
|
|
8
|
-
const faq = computed(() => props.locale
|
|
9
|
-
? [
|
|
10
|
-
['repoctl 是什么?', 'repoctl 是面向 pnpm 与 Turborepo monorepo 的任务型 CLI,用于初始化、诊断、创建、校验和发布工作区。'],
|
|
11
|
-
['如何安装 repoctl?', '在项目中运行 pnpm add -D repoctl,然后使用 pnpm exec repo init 和 pnpm exec repo doctor。'],
|
|
12
|
-
['repoctl 与 pnpm、Turborepo 是什么关系?', 'pnpm 和 Turborepo 负责包管理与任务编排,repoctl 负责把团队约定、检查和日常操作组织成可复用任务。'],
|
|
13
|
-
['repo doctor 与 repo check 有什么区别?', 'repo doctor 诊断仓库健康状况,repo check 规划并执行 lint、类型、构建和测试校验。'],
|
|
14
|
-
]
|
|
15
|
-
: [
|
|
16
|
-
['What is repoctl?', 'repoctl is a task-first CLI for initializing, diagnosing, creating, checking, and releasing pnpm and Turborepo monorepos.'],
|
|
17
|
-
['How do I install repoctl?', 'Run pnpm add -D repoctl, then use pnpm exec repo init and pnpm exec repo doctor.'],
|
|
18
|
-
['How does repoctl relate to pnpm and Turborepo?', 'pnpm and Turborepo provide package management and task orchestration; repoctl turns repository conventions and checks into reusable tasks.'],
|
|
19
|
-
['What is the difference between repo doctor and repo check?', 'repo doctor diagnoses repository health, while repo check plans and runs lint, type, build, and test checks.'],
|
|
20
|
-
])
|
|
9
|
+
const faq = computed(() => faqContent[props.locale])
|
|
21
10
|
</script>
|
|
22
11
|
|
|
23
12
|
<template>
|
|
@@ -129,9 +118,6 @@ const faq = computed(() => props.locale === 'zh'
|
|
|
129
118
|
<summary>{{ item[0] }}</summary>
|
|
130
119
|
<p>{{ item[1] }}</p>
|
|
131
120
|
</details>
|
|
132
|
-
<script type="application/ld+json">
|
|
133
|
-
{{ JSON.stringify({ '@context': 'https://schema.org', '@type': 'FAQPage', "mainEntity": faq.map(item => ({ '@type': 'Question', "name": item[0], "acceptedAnswer": { '@type': 'Answer', "text": item[1] } })) }) }}
|
|
134
|
-
</script>
|
|
135
121
|
</section>
|
|
136
122
|
</main>
|
|
137
123
|
</template>
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { EnhanceAppContext, Theme } from 'vitepress'
|
|
2
2
|
import DefaultTheme from 'vitepress/theme'
|
|
3
|
+
import Mermaid from '../mermaid/mermaid.vue'
|
|
3
4
|
import HomePage from './components/HomePage.vue'
|
|
4
5
|
import Layout from './Layout.vue'
|
|
5
6
|
import './tailwind.css'
|
|
6
7
|
import './home/index.css'
|
|
7
8
|
|
|
8
9
|
export default {
|
|
9
|
-
|
|
10
|
+
extends: DefaultTheme,
|
|
10
11
|
Layout,
|
|
11
12
|
enhanceApp({ app }: EnhanceAppContext) {
|
|
12
13
|
app.component('HomePage', HomePage)
|
|
14
|
+
app.component('Mermaid', Mermaid)
|
|
13
15
|
},
|
|
14
16
|
} satisfies Theme
|
|
@@ -35,7 +35,7 @@ pnpm exec repo doctor
|
|
|
35
35
|
| API / Hono service | `hono-server` |
|
|
36
36
|
| TypeScript library / SDK | `tsdown` |
|
|
37
37
|
| Vue component library | `vue-lib` |
|
|
38
|
-
| Documentation site | `
|
|
38
|
+
| Documentation site | `nimbus` |
|
|
39
39
|
| CLI | `cli` |
|
|
40
40
|
|
|
41
41
|
Omit `--templates` when the intent is unclear. After init, create a package with:
|
|
@@ -34,23 +34,19 @@
|
|
|
34
34
|
"deploy:dry-run": "wrangler deploy --dry-run",
|
|
35
35
|
"lint": "eslint .",
|
|
36
36
|
"lint:fix": "eslint . --fix",
|
|
37
|
-
"typecheck": "vue-tsc -p tsconfig.json --noEmit"
|
|
37
|
+
"typecheck": "vue-tsc -p tsconfig.json --noEmit",
|
|
38
|
+
"test": "vitest run"
|
|
38
39
|
},
|
|
39
40
|
"dependencies": {
|
|
40
41
|
"vue": "^3.5.43"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@braintree/sanitize-url": "^7.1.2",
|
|
44
44
|
"@tailwindcss/vite": "^4.3.3",
|
|
45
|
-
"cytoscape": "^3.34.3",
|
|
46
|
-
"cytoscape-cose-bilkent": "^4.1.0",
|
|
47
|
-
"dayjs": "^1.11.23",
|
|
48
|
-
"debug": "^4.4.3",
|
|
49
45
|
"mermaid": "^12.0.0",
|
|
50
46
|
"tailwindcss": "^4.3.3",
|
|
51
|
-
"vitepress": "
|
|
47
|
+
"vitepress": "2.0.0-alpha.20",
|
|
52
48
|
"vitepress-plugin-llms": "^1.14.0",
|
|
53
|
-
"
|
|
49
|
+
"vitest": "~5.0.3",
|
|
54
50
|
"vue-tsc": "^3.3.11",
|
|
55
51
|
"wrangler": "^4.135.0"
|
|
56
52
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Prepare build and production artifacts
|
|
2
|
+
|
|
3
|
+
`repo workspace prepare` previews one exact package. `prune` invokes locally installed Turbo 2 to produce a partial monorepo and pruned lockfile. `deploy` invokes the exact pnpm version pinned in the root `packageManager` to prepare a production directory. It prepares local files; it does not run the application, build an image or contact a deployment platform.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
# Build inputs and runtime entrypoints explicitly first.
|
|
7
|
+
pnpm build
|
|
8
|
+
repo workspace prepare @acme/service --mode prune --out ../service-build --json > ../prune-plan.json
|
|
9
|
+
repo workspace prepare --apply ../prune-plan.json
|
|
10
|
+
|
|
11
|
+
# Split Turbo's output into full/json Docker cache layers.
|
|
12
|
+
repo workspace prepare ./apps/service --mode prune --docker --out ../docker-context --json
|
|
13
|
+
|
|
14
|
+
# Production workspace dependencies; use only packages already in the local store.
|
|
15
|
+
repo workspace prepare @acme/service --mode deploy --entry dist/server.js --offline --out ../service-runtime --json > ../deploy-plan.json
|
|
16
|
+
repo workspace prepare --apply ../deploy-plan.json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Preview is always read-only, including `--dry-run`; native version, capability and path-setting probes do not install tools. Save the JSON plan outside the source workspace. Applying requires a separate `--apply` command and cannot be combined with preview selections or `--dry-run`.
|
|
20
|
+
|
|
21
|
+
## Native behavior and prerequisites
|
|
22
|
+
|
|
23
|
+
Both modes require a pnpm workspace and existing `pnpm-lock.yaml`. Select one uniquely named non-root package by exact npm name or `./directory`; globs, multiple matches and dependency selectors are rejected. The output must be outside the source workspace under an existing directory. Linked, overlapping and unrelated nonempty targets are rejected; there is no force flag.
|
|
24
|
+
|
|
25
|
+
Prune supports locally installed stable Turbo 2 and keeps native build dependency selection. `manifestCandidates` only explains manifest relationships; Turbo decides what is retained. Native task-dependency and global-file behavior follows the selected Turbo version and configuration. `--docker` retains its native `full`, `json` and lockfile layout.
|
|
26
|
+
|
|
27
|
+
Deploy supports pinned stable pnpm 10, 11 and 12 when their native command exposes the supported options. It uses `--prod`, `--ignore-scripts`, `--frozen-lockfile` and disables pnpmfile hooks. `--legacy` explicitly selects native legacy behavior, whose production layout may omit a root lockfile; only prune requires that output file. Since pnpm 12.2, native deploy supports non-injected workspace dependencies; earlier versions may require `injectWorkspacePackages` or legacy mode. Peer ambiguity and other native errors remain failures with their native diagnostic code. repoctl does not resolve or rewrite dependency graphs or lockfiles itself.
|
|
28
|
+
|
|
29
|
+
Deploy checks an existing built runtime file: explicit `--entry`, `package.main`, or a single `bin`. If native `files`/ignore rules omit it, preparation fails. Arbitrary `start` scripts are not interpreted or executed. Native dependency lifecycle scripts stay disabled, so prepare required native binaries explicitly before deployment; artifact preparation does not certify arbitrary application behavior.
|
|
30
|
+
|
|
31
|
+
## Source and output boundaries
|
|
32
|
+
|
|
33
|
+
Native tools run against an isolated source copy, without source `node_modules`, `.git`, `.turbo` or `.repoctl` storage. Real `.env`/`.env.*`, `.npmrc`, `.netrc`, `_netrc`, Yarn authentication configuration, `.aws`, `.ssh` and `.gnupg` paths are excluded before copying. Public `.env.example` and `.env.sample` files remain. The output is checked again for these paths. This is a named-file policy, not a general secret detector; use public placeholders in example files and provide deployment credentials separately.
|
|
34
|
+
|
|
35
|
+
The source copy retains built files even if Git ignores them; native prune/package file rules still control final inclusion. Source symlinks and special files are rejected. Input and output inventories are bounded to 100,000 entries and 1 GiB. Use native tools directly when a workspace needs different copy or storage policies.
|
|
36
|
+
|
|
37
|
+
Effective pnpm store/cache/state/module/lockfile paths are inspected without dumping credential-bearing configuration. Paths that would write back into the source workspace are rejected before deploy, and module/lockfile storage must remain relative to the artifact. Staging itself must be outside the source workspace. Native global stores outside the workspace remain under pnpm's control.
|
|
38
|
+
|
|
39
|
+
Output links must resolve inside the artifact. Relative links are preserved; Windows directory junctions are recreated against the final artifact directory. When transferring a Windows artifact, use a copy/archive method that materializes junction contents. Integration tests copy the directory, remove the source and original artifact, then execute the production entry independently.
|
|
40
|
+
|
|
41
|
+
## Review, recovery and repeated application
|
|
42
|
+
|
|
43
|
+
Plans fingerprint source files, modes, tool/version evidence, relevant path settings and options. Apply reconstructs the plan and rejects changes. Source inputs are rechecked after copying, after native execution, during publication and before completion. Concurrent source edits are preserved.
|
|
44
|
+
|
|
45
|
+
Native output is staged first. Publication creates files exclusively, records their ownership and written contents, and commits `.repoctl-artifact.json` last. Files may be visible before the receipt commits; do not consume an incomplete directory. Failures remove only unchanged operation-owned output and retain concurrent edits with their exact paths in the error. Cleanup failure after successful publication returns `cleanupPending` rather than claiming rollback.
|
|
46
|
+
|
|
47
|
+
Reapplying an unchanged plan returns `unchanged` only if its complete receipt and file inventory still match. Unknown or modified nonempty output is never overwritten. The `.repoctl/workspace-artifacts.lock` covers replay checks through native execution, publication and cleanup. After a crash, confirm no writer remains, inspect incomplete output and retained staging paths, and recover them before removing the lock.
|
|
48
|
+
|
|
49
|
+
Public APIs: `planWorkspaceArtifact(cwd, options)` and `applyWorkspaceArtifactPlan(cwd, plan, { signal, timeoutMs })`; JSON schema version is 1. Native execution defaults to a two-minute timeout, configurable up to ten minutes through the API.
|
|
50
|
+
|
|
51
|
+
References: [Turbo prune](https://turborepo.com/docs/reference/prune) and [pnpm deploy](https://pnpm.io/cli/deploy).
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Command Reference
|
|
2
2
|
|
|
3
|
+
Use [`repo workspace move`](./move.md) with `--to`, `--name`, or both to preview workspace refactoring. Review the JSON plan and located source tasks, then explicitly apply it with `--apply`.
|
|
4
|
+
|
|
5
|
+
Use [`repo workspace prepare`](./artifacts.md) to preview a native Turbo prune build context or pinned pnpm deploy production directory, then explicitly apply a reviewed JSON plan. Select one exact package and an empty output outside the workspace.
|
|
6
|
+
|
|
3
7
|
This page focuses on high-value repoctl commands and options.
|
|
4
8
|
|
|
5
9
|
## Main Entry
|
|
@@ -46,6 +50,41 @@ Use it to check root workspace files, Node compatibility, CLI dependency presenc
|
|
|
46
50
|
|
|
47
51
|
`--strict` treats warnings as failures. `--redact` removes local absolute paths from shareable reports.
|
|
48
52
|
|
|
53
|
+
```bash
|
|
54
|
+
repo doctor --list-rules
|
|
55
|
+
repo doctor --rules root-scripts,package-manager --strict
|
|
56
|
+
repo doctor --rules root-scripts --fix --out plans/doctor-fix.json
|
|
57
|
+
repo doctor --apply plans/doctor-fix.json --json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`--rules` selects exact stable check IDs before execution; unknown IDs fail and list the available rules. The CLI replaces `commands.doctor.rules`; omitted rules run all checks, while an explicit empty config array runs none. Shared discovery and rule prerequisites still run. `manifest-health` is an aggregate over the static manifest checks. Workspace boundaries and dependency admission use stable `boundary-*` / `admission-*` IDs; selecting only `boundary-policy` or `admission-policy` preserves the actual aggregate failure status, and prerequisite configuration failures remain visible. Custom policy names appear only in diagnostic details.
|
|
61
|
+
|
|
62
|
+
Configure reasoned waivers under `commands.doctor.suppressions`. Each item needs `id` and a nonempty `reason`; optional `path` matches an exact workspace-relative finding path. Optional `expires` is an inclusive UTC date (`YYYY-MM-DD`). JSON retains the original finding status, `suppression`, `rawSummary`, and every waiver with its matched count. Only active waivers are excluded from effective `summary` and strict exit status; expired and unmatched waivers remain visible.
|
|
63
|
+
|
|
64
|
+
`--fix` previews JSON without modifying project files. Only missing `repo:init`, `repo:new`, `repo:check`, and `repo:doctor` keys in the root `package.json` are supported. Existing values, including empty/custom scripts, are preserved for manual review. An actively suppressed or unselected rule produces no fix. Review the additions, complete before/after content, hashes, risk, and diff before using `--apply`. Plans contain original manifest content and cannot be redacted or rendered as Markdown for execution.
|
|
65
|
+
|
|
66
|
+
Apply checks the canonical workspace and original file contents, rejects links and modified operations, reuses the staged file transaction with rollback, and reruns the root-script check without suppression. A changed input stops the fix; regenerate the plan. Reapplying an already applied plan is unchanged. Textual `fix` suggestions are never executed, and dependency installation or release workflow modification is outside this fixer.
|
|
67
|
+
|
|
68
|
+
Doctor fix application holds `.repoctl/doctor-fix.lock` from input validation through verification, rollback and cleanup, preventing overlapping writers from undoing a successful fix. After a crash, verify no writer remains and reconcile any retained backups before manually removing the lock.
|
|
69
|
+
|
|
70
|
+
## `repo env check`
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
repo env check
|
|
74
|
+
repo env check build test --json --strict
|
|
75
|
+
repo env check --markdown --no-framework-inference
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This read-only check compares static `process.env.NAME`, `import.meta.env.NAME`, literal property reads and destructuring with Turbo environment declarations. It checks `build` by default and includes private packages. Each package/task report separates hashed variables, passthrough variables, inferred framework prefixes, framework built-ins, missing declarations and unresolved dynamic reads, with source locations. Comments and ordinary strings do not become references. Actual `.env*` and `.dev.vars*` contents are never read; example files contribute key names only. No values or source snippets appear in JSON, text or Markdown.
|
|
79
|
+
|
|
80
|
+
Root and package `turbo.json`/`turbo.jsonc` configurations support package-qualified tasks, ordered package inheritance, array replacement, `$TURBO_EXTENDS$` and task inheritance exclusions. Wildcards and negations follow Turbo environment syntax. Unsupported advanced `global` configuration and object-form inputs fail validation instead of guessing coverage. Environment files are checked against `globalDependencies`, task `inputs`, `$TURBO_ROOT$`, explicit exclusions and Git's default non-ignored paths. Merely finding an env file does not establish hash coverage. `passThroughEnv` makes a variable available without hashing its value; it is reported for review rather than automatically moved into `globalEnv`. A global `*` declaration receives a scope warning.
|
|
81
|
+
|
|
82
|
+
Configure `commands.env` in `repoctl.config`: `tasks`, package-relative `include`/`exclude` globs, `frameworkInference`, and `suppressions`. Each suppression requires a stable `rule` and nonempty `reason`, with optional `package`, `task`, `variable` and repository-relative `path` glob selectors. Suppressed findings remain visible, and unused suppressions produce a warning. Configuration failures exit 1; `--strict` also fails on warnings. `--dry-run` documents the always-read-only behavior. APIs are `checkEnvironmentCache(cwd, options)` and `formatEnvironmentCache(report, markdown?)`.
|
|
83
|
+
|
|
84
|
+
Static references are task candidates, not proof that a script executes that source. Scanning covers JS/TS and Vue/Svelte script blocks, skips links and files above 2 MiB, and does not resolve aliases, shadowed globals, templates, generated code or direct cross-package source imports. Framework inference is estimated from package dependencies; runtime flags, custom prefixes and variables introduced by shell scripts require review. Existing executable repoctl configuration must itself avoid side effects. The command does not run tasks, load real environment values, rewrite Turbo config or widen global cache inputs.
|
|
85
|
+
|
|
86
|
+
References: [Turbo environment variables](https://turborepo.com/docs/crafting-your-repository/using-environment-variables), [configuration](https://turborepo.com/docs/reference/configuration), and [package inheritance](https://turborepo.com/docs/reference/package-configurations).
|
|
87
|
+
|
|
49
88
|
## `repo templates`
|
|
50
89
|
|
|
51
90
|
```bash
|
|
@@ -64,15 +103,33 @@ Use it to discover built-in template keys, inspect metadata, verify template hea
|
|
|
64
103
|
```bash
|
|
65
104
|
repo new
|
|
66
105
|
repo new sdk --template tsdown
|
|
67
|
-
repo new docs --template
|
|
68
|
-
repo new docs --template
|
|
69
|
-
repo new docs --template
|
|
106
|
+
repo new docs --template nimbus
|
|
107
|
+
repo new docs --template nimbus --dry-run
|
|
108
|
+
repo new docs --template nimbus --json --out plans/docs.json
|
|
70
109
|
```
|
|
71
110
|
|
|
72
111
|
Use it to create packages and apps. Explicit template keys are validated first; invalid keys fail with suggestions instead of silently falling back.
|
|
73
112
|
|
|
113
|
+
## `repo package check`
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
repo package check
|
|
117
|
+
repo package check --filter '@scope/*' --strict
|
|
118
|
+
repo package check --filter my-library --keep-temp --json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Build the selected workspace packages and their dependencies in dependency order, then validate real `pnpm pack` tarballs with publint 0.3.25 and ATTW 0.18.5. Build failure prevents all packing. Local development prerequisites are included in the build; private prerequisites can build without being packed or checked. Private packages are reported as skipped unless `--include-private` is supplied. Repeat `--filter` to combine pnpm selectors; `--build-script` changes the default `build` script. Packages without that script are treated as already authored artifacts.
|
|
122
|
+
|
|
123
|
+
Independent temporary consumers install the tarballs and their local runtime dependency tarballs, then exercise declared Node ESM/CJS entrypoints and TypeScript NodeNext consumption. TypeScript consumption uses ATTW's pinned TypeScript 5.6.1-rc. Undeclared module formats are not required. Browser-only and non-JavaScript asset exports receive manifest/type analysis rather than Node execution; JavaScript bins receive syntax checks, without invoking application commands. Installation can contact the registry, while dependency install scripts are disabled. Workspace build and pack lifecycle scripts run normally.
|
|
124
|
+
|
|
125
|
+
JSON contains each package's file list, stable diagnostic source/code, original upstream details, and subprocess argument arrays. `--strict` also fails on warnings. `--keep-temp` preserves the tarballs, consumer manifests and command working directories for reproduction; otherwise temporary files are removed even after failure. The command never publishes, changes package versions, or writes release state.
|
|
126
|
+
|
|
127
|
+
To use it as a release gate, add a package script such as `"package:check": "repoctl package check --strict"` and reference `package:check` in `commands.release.hooks.verify`. Do not put this command in a build/prepack script, since it runs those stages itself.
|
|
128
|
+
|
|
74
129
|
## `repo check`
|
|
75
130
|
|
|
131
|
+
For explicitly enabled unused-code and dependency analysis, see [`repo check knip`](./knip.md).
|
|
132
|
+
|
|
76
133
|
```bash
|
|
77
134
|
repo check
|
|
78
135
|
repo check --staged
|
|
@@ -87,6 +144,10 @@ Use it to preview or run the recommended local verification flow. `--staged` is
|
|
|
87
144
|
|
|
88
145
|
## `repo upgrade`
|
|
89
146
|
|
|
147
|
+
For third-party dependency declarations, use `repo deps check`, create an explicit
|
|
148
|
+
read-only plan with `repo deps plan`, then apply reviewed JSON with `repo deps apply`.
|
|
149
|
+
See [Dependency consistency](./dependencies.md) for protocols, version groups and recovery.
|
|
150
|
+
|
|
90
151
|
```bash
|
|
91
152
|
repo upgrade
|
|
92
153
|
repo upgrade --yes
|
|
@@ -95,12 +156,65 @@ repo upgrade --no-overwrite
|
|
|
95
156
|
repo upgrade --core
|
|
96
157
|
repo upgrade -i
|
|
97
158
|
repo upgrade -s
|
|
159
|
+
repo upgrade --dry-run
|
|
160
|
+
repo upgrade --json > upgrade-plan.json
|
|
161
|
+
repo upgrade --markdown
|
|
162
|
+
repo upgrade --apply upgrade-plan.json
|
|
98
163
|
```
|
|
99
164
|
|
|
100
165
|
Use it to sync standard assets and scripts. `--core` skips GitHub-related assets. `--no-overwrite` preserves changed files.
|
|
101
166
|
|
|
167
|
+
`--dry-run`, `--json` and `--markdown` always preview without writes or prompts. Every selected asset has an `add`, `modify`, `delete`, `identical`, `skip` or `conflict` status and a reason. Package scripts/dependencies, workspace settings, AGENTS sections, gitignore rules, tooling references and legacy versioning migration all use the same plan. Text and Markdown show per-file unified diffs; binary files and text larger than 256 KiB combined are explicitly marked without a fabricated diff.
|
|
168
|
+
|
|
169
|
+
`--apply` applies every actionable entry in a reviewed JSON plan, using its exact bytes. The ordinary command retains interactive selection for semantic migrations; safe merges against a recorded upstream baseline and approved additions can run non-interactively. All approvals happen before the first write. `--no-overwrite` and `-s` also preserve legacy metadata. Custom release workflows remain protected unless `--overwrite-release` is explicit; existing licenses are preserved. A prerelease lane migration and its metadata deletion form one indivisible selection group. Unknown prerelease state stays on disk for manual migration.
|
|
170
|
+
|
|
171
|
+
Root managed assets use three-way merging: the previous upstream content, the current local file, and the newly installed template. Independent edits merge automatically; overlapping edits expose base/local/upstream regions and line positions in the plan. Binary divergence and text over 1 MiB combined remain conflicts. Existing semantic strategies for package/workspace configuration, AGENTS and gitignore stay in place. This does not upgrade generated app/package directories or run historical template code.
|
|
172
|
+
|
|
173
|
+
Baselines live in `.repoctl/baselines/root/<path-sha256>.json`; commit this directory to preserve upgrade history across clones. Each record contains the asset path, template package/version, source SHA-256, and upstream bytes/hash, never a customized merged output. Hashes check integrity and identify the locally installed source; they are not publisher signatures. A saved plan is the reviewed write payload: editing its contents and recalculating hashes creates a new payload to review, rather than proof of its author. A differing old file without a baseline is a `baseline-missing` conflict: review and use `--overwrite` to explicitly adopt the new template. `--yes` alone does not resolve conflicts. Identical files can safely acquire a baseline without rewriting the asset. Removing this directory loses historical merge information and returns the next upgrade to this conservative first-run behavior.
|
|
174
|
+
|
|
175
|
+
Locally deleted tracked files remain deleted, even with `--overwrite`; restore them manually to resume upgrades. Upstream deletion removes only an unchanged owned file, while customized files remain conflicts. A selected file and its reviewed baseline update share one transaction, including rollback and retry checks. JSON file entries include optional `baseline` operations with before/after hashes and exact content; partial selection never advances other baselines. Older saved plans without this field still apply without creating unreviewed records. Conflict files are never applied, and CLI preview/apply returns exit code 1 while any remain; API apply results list unresolved paths in `conflicts` even when other selected files were successfully applied.
|
|
176
|
+
|
|
177
|
+
Versioned migrations appear in the plan's `migrations` report with stable IDs, version boundaries, selection reasons and affected files. The built-in `changesets-to-pnpm-versioning` migration crosses template version `1.1.0`, the release that introduced pnpm native versioning. The target is the exact installed template package version. If a repository has no history, `--from-version 1.0.15` can attest its exact previous template version; dependency ranges such as `^1.0.0` never establish that version. Unknown versions only adopt recognized legacy formats and report `adopt-detected-legacy-format`; malformed metadata and downgrades are blocked. Fresh projects without legacy metadata do not run or initialize old migrations.
|
|
178
|
+
|
|
179
|
+
Commit `.repoctl/migrations/ledger.json` once created. Its `evaluatedVersion` is a migration cursor, not a claim that every managed asset uses that template version. Dry runs write nothing. The completed ledger is reviewed as a normal file diff, while JSON includes the exact intermediate pending/failed contents. Migration files form an indivisible selection group; unselected or failed steps never advance the cursor. The pending record is saved before changes, and completed is written last in the migration transaction. A failure to write completed rolls back that transaction and records failed; if recording failure also fails, the pending journal remains for recovery. Independent selected assets apply after the migration group, so a later independent failure does not erase a completed migration.
|
|
180
|
+
|
|
181
|
+
After interruption, preview again. The journal retains reviewed outputs and before/after hashes; recovery shows which files already match the output and which still need writing. Any third state blocks recovery and preserves local edits plus original `*.repoctl-upgrade-<attempt-id>.bak` files for review. Recovery requires the original installed template version and unchanged other recorded inputs; it never executes historical scripts or performs network/publish actions. An exclusive local process lock prevents concurrent applications. A force-terminated process can leave `.repoctl/upgrade.lock`; confirm no writer is active and inspect pending backups before removing it, then preview again. Locks are not stolen by age, and normal cleanup verifies both the caller's token and filesystem identity. Older plans without migration metadata do not create unreviewed ledger records.
|
|
182
|
+
|
|
183
|
+
Plans record the original target, asset and local configuration hashes. Application holds `.repoctl/upgrade.lock` through input checks, no-op detection, writes, rollback and cleanup. It rejects concurrent writers or a changed workspace package set and treats a fully applied plan as a no-op. It creates original `.repoctl-upgrade-*.bak` backups before replacing files and rolls back a failed operation. Recovery files and created directories are removed only while their filesystem identity still belongs to the transaction; changed recovery bytes and colliding files are retained. When a concurrent edit prevents rollback, the error identifies retained originals. After a process interruption, verify that no writer is active, inspect backups and temporary files, restore originals as needed, then remove the lock and generate a new plan. Unrelated files and Git refs/index are untouched.
|
|
184
|
+
|
|
185
|
+
Each preview refreshes configuration entries, inherited configs and statically resolved local imports, including literal dynamic imports, in memory. These files join the input checks; module-relative paths remain intact. Installed packages, computed imports, environment variables and arbitrary filesystem/network reads are outside this tracked module set, so regenerate the plan when those runtime inputs change. Executable configuration must itself avoid side effects for a read-only preview.
|
|
186
|
+
|
|
187
|
+
Preview never generates missing template assets. An `assets-not-prepared` blocker means the package installation must be repaired first; source contributors can run `pnpm --filter @icebreakers/monorepo-templates sync:assets` explicitly. Plans belong to the same working directory, output directory and installed asset location. Public APIs are `planUpgrade(options)`, `formatUpgradePlan(plan, 'text' | 'markdown')`, `applyUpgradePlan(cwd, plan, { files? })` and `upgradeMonorepo({ dryRun: true })`; `UpgradePlan` includes base64 payloads for exact application. `repo workspace upgrade` and `repo ws up` share these options.
|
|
188
|
+
|
|
189
|
+
## Workspace Dependencies
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
repo workspace graph
|
|
193
|
+
repo workspace graph --json --redact
|
|
194
|
+
repo workspace graph --mermaid
|
|
195
|
+
repo workspace graph --package @acme/shared --type dependencies
|
|
196
|
+
repo workspace why @acme/web @acme/shared --json
|
|
197
|
+
repo workspace impact @acme/shared --direct --json
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
These read-only queries share a manifest dependency graph. Private apps are included by default; `--exclude-private` excludes them and `--include-root` adds the root package. Edges point from a consumer to its dependency. `--type` accepts `dependencies`, `devDependencies`, `peerDependencies`, or `optionalDependencies` and can be repeated. With no type filter, all four fields are included.
|
|
201
|
+
|
|
202
|
+
`graph --package <name-or-directory>` shows the selected packages and their direct incoming/outgoing relationships; repeat it to select several packages. `why <from> <to>` returns one deterministic shortest dependency path, including both endpoints; no path is a successful query with `found: false`. `impact <package>` returns direct and transitive consumers with minimum distance and one path per consumer. `--direct` limits it to immediate consumers. Cycles are safe and the target itself is excluded from its impact result.
|
|
203
|
+
|
|
204
|
+
Selectors accept exact package names or workspace-relative directories such as `./packages/shared`. Duplicate names produce diagnostics, and queries using an ambiguous name fail; use an explicit directory to disambiguate. Unnamed packages remain queryable by directory. Missing, ambiguous, invalid, and version-incompatible forced local references are included in `diagnostics` instead of becoming guessed edges.
|
|
205
|
+
|
|
206
|
+
The graph understands workspace ranges, workspace aliases (`workspace:@acme/shared@^1`), relative workspace paths, and local `link:`/`file:` directories. Every edge records `resolution`: `workspace` and `local` are explicit local references, while `semver` marks a matching local candidate for an ordinary range or `npm:` alias. These are manifest relationships, not proof of what a lockfile installed: registry tags, catalogs, remote URLs and source imports are not resolved. Catalog references and unsupported specifiers with a same-name local candidate produce `unresolved_specifier` diagnostics. Consumers must inspect diagnostics before treating the graph as complete; affected checks can fall back conservatively. Filtering private/root packages can also leave forced references unresolved.
|
|
207
|
+
|
|
208
|
+
JSON uses schema version `1`, directory-based node IDs and stable sorting; field names and diagnostic codes do not change with `--lang`. Mermaid uses the same nodes and edges, including isolated packages. Queries write only to stdout, so shell redirection can save an export. `--json` and `--mermaid` are mutually exclusive.
|
|
209
|
+
|
|
210
|
+
Programmatic users can call `getWorkspaceGraph(cwd, options)`, `filterWorkspaceGraph(graph, options)`, `whyWorkspaceDependency(graph, from, to, options)` and `getWorkspaceImpact(graph, package, options)`. Discovery refreshes its cache for each graph read. Query APIs accept the same public graph model without exposing pnpm implementation types.
|
|
211
|
+
|
|
102
212
|
## Grouped Commands
|
|
103
213
|
|
|
214
|
+
For an optional root development environment, see the [Dev Container preset](./devcontainer.md): `repo tooling devcontainer --json --out ../plan.json`, then `repo tooling devcontainer --apply ../plan.json` after review.
|
|
215
|
+
|
|
216
|
+
Use [`repo workspace remove`](./removal.md) to preview removal of one exact package, inspect consumers and manual reference candidates, then explicitly apply a reviewed JSON plan. Preview does not delete anything; dependencies block removal unless their exact manifest fields are included with `--remove-references`.
|
|
217
|
+
|
|
104
218
|
```bash
|
|
105
219
|
repo ws ls
|
|
106
220
|
repo ws ls --json --out reports/workspaces.json
|
|
@@ -118,3 +232,38 @@ repo skills sync --codex
|
|
|
118
232
|
- [Add checks to CI](/tasks/ci)
|
|
119
233
|
- [Troubleshoot](/tasks/troubleshooting)
|
|
120
234
|
- [Command Aliases](./aliases.md)
|
|
235
|
+
|
|
236
|
+
### Public API baselines
|
|
237
|
+
|
|
238
|
+
`repoctl package api check [--package <selectors...>] [--json]` compares built public declarations with explicitly configured API Extractor reports. Set `tooling.apiReports` with package-relative declaration entries and workspace-relative `.api.md` baselines; install a local stable `@microsoft/api-extractor >=7.52.12 <8` and build first. `package api update --json` only previews; review its output, then pass it to `package api update --apply <plan.json>`. Updates revalidate inputs and use guarded transactions. Signature diffs and pending change intents are advisory; no complete SemVer inference or release is performed.
|
|
239
|
+
|
|
240
|
+
## `repo tooling references`
|
|
241
|
+
|
|
242
|
+
`check --json` checks existing references without opt-in. `plan` and `sync --dry-run` preview deterministic JSON without writes. With `tooling.projectReferences.enabled: true`, use `sync` or `apply <plan.json>` to maintain only registered references. Existing manual references and TypeScript/Vue validation scripts are preserved; incompatible compiler options, cycles, missing targets and stale plans block application. See [configuration](./config#typescript-project-references) for discovery, explicit compilation relationships, ownership and recovery.
|
|
243
|
+
|
|
244
|
+
### Incremental Playwright capability
|
|
245
|
+
|
|
246
|
+
Add browser tests to an existing Vue/React Vite application with `build` and `preview` scripts:
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
repo tooling capability list --json
|
|
250
|
+
repo tooling capability plan playwright --target web --route / --role button --name Increment --expect-text 'Count: 1' --json > e2e-plan.json
|
|
251
|
+
repo tooling capability apply e2e-plan.json --json
|
|
252
|
+
pnpm install
|
|
253
|
+
pnpm --filter @repoctl-e2e/web test:e2e:install
|
|
254
|
+
pnpm test:e2e
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Use `--test-id` instead of `--role`/`--name` for a test-id locator. The route, click and expected text describe a real interaction in your application. The plan shows file diffs, dependencies, scripts, conflicts and next steps, without installing anything. Apply uses those exact reviewed bytes, rejects stale inputs and conflicts, and rolls back failed writes. A repeated unchanged apply has no effect. Choose an empty destination (`--directory`) for the new E2E workspace. Existing application sources and differing generated files are protected.
|
|
258
|
+
|
|
259
|
+
The capability creates an independent E2E workspace, headless Chromium tests, Turbo build dependencies, a dedicated CI workflow, HTML reports and failure traces. Browser installation is explicit. `--port` and `--ci-port` set distinct local and CI ports. CI never reuses a running service. `--reuse-existing-server` opts into local reuse; Playwright cleans up its own service after success, failure or interruption, and leaves a borrowed service running. Commit the lockfile after installation.
|
|
260
|
+
|
|
261
|
+
Public APIs: `listToolingCapabilities()`, `planToolingCapability(cwd, options)` and `applyToolingCapability(plan)`. JSON uses schema version 1 and stable English keys regardless of CLI language.
|
|
262
|
+
|
|
263
|
+
### Optional Storybook for a component library
|
|
264
|
+
|
|
265
|
+
`repo tooling capability plan storybook --target <exact-workspace> --framework vue|react --component <named-export> --example example.json --json` previews a separate `stories/<slug>` workspace. Apply the reviewed JSON with `repo tooling capability apply plan.json`. The first version supports Vue 3 and React 18/19 libraries with a build script, public entry and an explicit runtime version range. Install dependencies after applying and commit the resulting lockfile. Discovery and planning do not install Storybook or a browser.
|
|
266
|
+
|
|
267
|
+
A Vue prop-update example is `{"kind":"prop-update","prop":"msg","initial":"Hello Storybook","updated":"Updated component"}`. For a React counter use `{"kind":"click","args":{"initialCount":0},"alternateArgs":{"initialCount":4},"click":{"role":"button","name":"Increase"},"expectText":"1"}`. Component props must be JSON primitives; interaction assertions exercise the selected component. `Default`, `Alternate` and `Interaction` stories provide two states and a play test.
|
|
268
|
+
|
|
269
|
+
Run `pnpm build:storybook` for the static site, then `pnpm --filter @repoctl-stories/<slug> test:storybook:install` and `pnpm test:storybook` for headless Chromium tests. Turbo builds library dependencies first and records `storybook-static/**`; play tests run without caching and write a JUnit report. Use the generated workspace's `storybook` script for local development. Its independent Vitest and Vite configurations leave the library's existing tests, package exports, runtime dependencies and tarball contents unchanged. Existing stories and configuration are preserved; differing generated files block application and require a new review. No hosted visual testing service is enabled.
|
|
@@ -51,19 +51,113 @@ export default defineMonorepoConfig({
|
|
|
51
51
|
})
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
| Option | Purpose
|
|
55
|
-
| --------------------------------- |
|
|
56
|
-
| `commands.init.preset` | Default setup preset
|
|
57
|
-
| `commands.create.defaultTemplate` | Default template for `repo new <name>`
|
|
58
|
-
| `commands.clean.autoConfirm` |
|
|
59
|
-
| `commands.
|
|
54
|
+
| Option | Purpose |
|
|
55
|
+
| --------------------------------- | -------------------------------------------------------- |
|
|
56
|
+
| `commands.init.preset` | Default setup preset |
|
|
57
|
+
| `commands.create.defaultTemplate` | Default template for `repo new <name>` |
|
|
58
|
+
| `commands.clean.autoConfirm` | Select all eligible packages without prompting |
|
|
59
|
+
| `commands.clean.dryRun` | Preview deletions and dependency changes without writing |
|
|
60
|
+
| `commands.upgrade.skipOverwrite` | Whether upgrade preserves changed managed files |
|
|
60
61
|
|
|
61
62
|
## Inspect Config
|
|
62
63
|
|
|
64
|
+
Share fixed configuration across repositories with [organization preset packages](./organization-presets.md). They contribute JSON configuration, templates, capability recommendations and explicitly managed engineering assets.
|
|
65
|
+
|
|
63
66
|
```bash
|
|
64
67
|
repo config inspect
|
|
65
68
|
repo cfg i --json --out reports/config.json
|
|
66
69
|
repo cfg i --markdown --redact --out reports/config.md
|
|
70
|
+
repo config validate --json
|
|
71
|
+
repo config inspect --command ai --set 'format="json"' --set 'force=false' --json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Runtime loading validates repoctl-owned fields before CLI actions and before config-consuming APIs write files. Unknown fields, wrong types, invalid enums and conflicting overwrite policies fail with stable diagnostic IDs and field paths. Omit optional fields instead of setting them to `null`. Native ESLint, Stylelint, Commitlint and Vitest overrides, plugin functions and lint-staged callbacks retain their extension boundary. C12 config factories, inherited configurations and environment layers remain supported.
|
|
75
|
+
|
|
76
|
+
`config validate` is read-only and exits with code 1 on failure. JSON includes `schemaVersion`, `valid`, `file` and `diagnostics`; each diagnostic has `id`, `path`, `actualType`, `expected` and `suggestion`. Evaluation/import failures use `config.load-failed` and do not include arbitrary thrown values. Config files are trusted JavaScript and are evaluated to load them; this command does not sandbox their own code.
|
|
77
|
+
|
|
78
|
+
`inspect --command` supports `ai`, `clean`, `create`, `deps`, `doctor`, `init`, `mirror`, `release` and `upgrade`. It uses the same option resolver as command execution and adds `effective.values` and per-field `effective.origins` (`default`, `project`, `cli`). Repeated `--set field=JSON` previews config-field overrides without executing the command. Arrays replace the previous array; explicit `false` and empty arrays are retained. These values explain command configuration; use the command's own plan for discovered files, selected packages and runtime-only flags such as `--all`.
|
|
79
|
+
|
|
80
|
+
Config CLI reports always hide environment maps, scripts, native tool payloads and sensitive keys. `--redact` additionally replaces cwd, config directory and home paths. The programmatic `explainMonorepoConfig` and `validateConfigFile` APIs return safe reports; `loadMonorepoConfigDetails` and the existing `inspectMonorepoConfig` retain runtime objects for code that consumes callbacks. Avoid serializing those raw objects for support reports.
|
|
81
|
+
|
|
82
|
+
Older generated configs may use `tooling.lintStaged.monorepoCommand`; replace that field with `tooling.lintStaged.repoCommand`. The old name was ignored by the runtime and is now diagnosed instead of silently falling back.
|
|
83
|
+
|
|
84
|
+
## Cleaning workspace packages
|
|
85
|
+
|
|
86
|
+
Use `repo workspace clean --dry-run` to select packages and preview the changes.
|
|
87
|
+
For automation, `repo workspace clean --yes --dry-run` previews all eligible
|
|
88
|
+
packages. Remove `--dry-run` to execute. Interactive choices start unchecked;
|
|
89
|
+
empty selection or cancellation writes nothing. `--yes` respects `ignorePackages`
|
|
90
|
+
and `includePrivate`; it never adds repository docs, `.qoder`, or global skills.
|
|
91
|
+
Configuration is read from the workspace root even when invoked inside a package.
|
|
92
|
+
|
|
93
|
+
The JSON preview lists removed directories in `deletions` and root `package.json`
|
|
94
|
+
dependency changes with before/after values in `metadata`. Only a nonempty
|
|
95
|
+
selection may migrate `devDependencies.@icebreakers/monorepo` and ensure
|
|
96
|
+
`devDependencies.repoctl`. Existing repoctl versions are retained unless
|
|
97
|
+
`--pinned-version` overrides them; a missing version defaults to `latest`.
|
|
98
|
+
An already-correct manifest is not rewritten.
|
|
99
|
+
|
|
100
|
+
Outside paths, symbolic-link targets or parent paths, linked root manifests,
|
|
101
|
+
and deletion of unselected nested packages fail validation before any writes.
|
|
102
|
+
The command does not update consumer dependency declarations.
|
|
103
|
+
|
|
104
|
+
The `init` inspection context describes the top-level CLI: its default preset is `standard`, while project configuration and explicit CLI options take precedence. The public `init()` API and `workspace init` retain their metadata-only defaults. Origin paths escape dots and backslashes in dynamic keys with a backslash. Commands that load repoctl configuration validate all repoctl-owned blocks before execution, including blocks unrelated to the selected command.
|
|
105
|
+
|
|
106
|
+
## `commands.doctor`
|
|
107
|
+
|
|
108
|
+
Doctor first validates the schema of the whole configuration, then executes only the selected rules. Unselected policies can contain violations without contributing findings, but malformed configuration is always rejected. Omit `rules` to run all rules; use `rules: []` to run none. `config inspect --command doctor` explains the same workspace-root policy that doctor executes, including when invoked from a package directory; explicit CLI selection overrides that policy.
|
|
109
|
+
|
|
110
|
+
Configure reasoned waivers under `commands.doctor.suppressions`. Each item needs `id` and a nonempty `reason`; optional `path` matches an exact workspace-relative finding path. Optional `expires` is an inclusive UTC date (`YYYY-MM-DD`). JSON retains the original finding status, `suppression`, `rawSummary`, and every waiver with its matched count. Only active waivers are excluded from effective `summary` and strict exit status; expired and unmatched waivers remain visible.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
export default defineMonorepoConfig({
|
|
114
|
+
commands: {
|
|
115
|
+
doctor: {
|
|
116
|
+
rules: ['root-scripts', 'commit-hooks'],
|
|
117
|
+
suppressions: [{
|
|
118
|
+
id: 'commit-hooks',
|
|
119
|
+
reason: 'CI validates commits while the hooks migration is scheduled',
|
|
120
|
+
expires: '2026-12-31',
|
|
121
|
+
}],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## TypeScript project references
|
|
128
|
+
|
|
129
|
+
Check an existing reference graph without enabling writes:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
repo tooling references check --json
|
|
133
|
+
repo tooling references plan > references-plan.json
|
|
134
|
+
repo tooling references sync --dry-run
|
|
135
|
+
repo tooling references apply references-plan.json
|
|
136
|
+
repo tooling references sync
|
|
67
137
|
```
|
|
68
138
|
|
|
69
|
-
|
|
139
|
+
`check` exits with 1 for diagnostics or pending managed changes. All commands emit versioned JSON. `check`, `plan` and `sync --dry-run` never write. `apply` and `sync` require explicit `tooling.projectReferences.enabled: true`:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
export default defineMonorepoConfig({
|
|
143
|
+
tooling: {
|
|
144
|
+
projectReferences: {
|
|
145
|
+
enabled: true,
|
|
146
|
+
root: 'tsconfig.json',
|
|
147
|
+
projects: ['packages/*/tsconfig.json', 'apps/*/tsconfig.build.json'],
|
|
148
|
+
exclude: ['packages/legacy/tsconfig.json'],
|
|
149
|
+
relations: [
|
|
150
|
+
{ source: 'packages/app/tsconfig.json', target: 'packages/shared/tsconfig.json' },
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The root solution and selected configs must already exist. Without `projects`, discovery selects `tsconfig.json` in each actual pnpm workspace package, including private packages; non-TS packages are skipped. Patterns are workspace-relative and can select multiple configs per package. Exclusions affect managed discovery, not existing manual references. Configs outside workspace packages are not automatically selected. The source workspace's references are never copied into generated projects.
|
|
158
|
+
|
|
159
|
+
The root aggregates selected projects. Only explicit `relations` add compilation dependencies between them: npm dependencies do not imply a TypeScript reference. TypeScript must be installed in the target workspace. Its compiler reads inherited settings and checks missing targets, reference cycles, `composite`, declaration output and `noEmit` compatibility before writes. repoctl never enables composite, changes compiler options, creates tsconfigs or replaces scripts. The plan lists validation commands, preserving each package's existing `typecheck` script (including `vue-tsc`); run them after synchronization to check actual source files. Planning validates configuration, not a full source compilation.
|
|
160
|
+
|
|
161
|
+
Existing references remain manually owned. Only newly added entries are recorded in `.repoctl/typescript-references.json`; commit that registry alongside the tsconfigs. Removing or excluding a project removes only entries recorded there. Editing/removing an owned entry blocks synchronization: restore it, or deliberately remove its registry entry to return ownership to the user. JSONC content outside the `references` value, BOM and line endings are preserved. Root aggregation and explicit edges produce stable relative config-file paths.
|
|
162
|
+
|
|
163
|
+
Saved plans include input fingerprints and exact diffs. Applying a stale or edited plan fails before writes; reapplying an already completed plan is a no-op. A process lock at `.repoctl/typescript-references.lock` covers revalidation, writing, verification, rollback and cleanup. Changes stage together with backups and roll back on failure. If concurrent edits prevent safe rollback, the error names retained recovery files: preserve them, reconcile the business edit with the original backup, restore the ownership registry consistently and generate a new plan. A killed process can also leave `.repoctl-references-*.bak`/`.tmp` files; verify no writer remains, reconcile matching backups and the registry, then remove the stale lock. No recovery action overwrites a concurrent edit automatically.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Dependency consistency
|
|
3
|
+
description: Compare workspace dependency declarations and apply reviewed fixes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dependency consistency
|
|
7
|
+
|
|
8
|
+
`repo deps check` reads root and workspace manifests, including private packages. It groups each dependency by its declaration section and configured version cohort. It does not query a registry or choose the newest version.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm exec repo deps check
|
|
12
|
+
pnpm exec repo deps check --json
|
|
13
|
+
pnpm exec repo deps plan typescript --section devDependencies --to '^5.7.0' --json > deps-plan.json
|
|
14
|
+
pnpm exec repo deps apply deps-plan.json
|
|
15
|
+
pnpm install --lockfile-only
|
|
16
|
+
pnpm install --frozen-lockfile
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`deps fix` is an alias for `deps plan`. Planning is always a dry run, including without `--dry-run`. Only `deps apply` changes manifests. Review the JSON before applying it; lockfile updates and installation are separate, explicit pnpm steps.
|
|
20
|
+
|
|
21
|
+
## Reading the report
|
|
22
|
+
|
|
23
|
+
| Status | Meaning |
|
|
24
|
+
| -------------- | ----------------------------------------------------------- |
|
|
25
|
+
| `consistent` | Identical declarations with a known source and range. |
|
|
26
|
+
| `equivalent` | Different text permits the same versions. |
|
|
27
|
+
| `compatible` | Different ranges have a common allowed version. |
|
|
28
|
+
| `conflict` | There is no version allowed by every declaration. |
|
|
29
|
+
| `uncomparable` | The protocol, source or range cannot be compared reliably. |
|
|
30
|
+
| `managed` | Workspace references belong to workspace and release rules. |
|
|
31
|
+
| `exception` | An explicit policy exception includes its reason. |
|
|
32
|
+
|
|
33
|
+
The report includes every manifest path, workspace directory, original specifier, dependency section, protocol and resolved semver range. Check exits with status 1 for equivalent-text drift, compatible drift or conflicts; exceptions and uncomparable declarations remain visible in the report. JSON keys and status values are stable across locales.
|
|
34
|
+
|
|
35
|
+
`dependencies`, `devDependencies`, `peerDependencies` and `optionalDependencies` are independent. npm aliases retain their source package; aliases targeting different packages are uncomparable. Default and named catalogs are resolved for comparison, but fixes do not replace catalog references. Workspace, file, link, URL, Git and unknown declarations are report-only. Numeric prereleases follow semver's prerelease rules.
|
|
36
|
+
|
|
37
|
+
## Intentional version groups
|
|
38
|
+
|
|
39
|
+
Configure groups in the workspace root's `repoctl.config.ts`, even when invoking the command from a child package:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { defineMonorepoConfig } from 'repoctl'
|
|
43
|
+
|
|
44
|
+
export default defineMonorepoConfig({
|
|
45
|
+
commands: {
|
|
46
|
+
deps: {
|
|
47
|
+
groups: [
|
|
48
|
+
{
|
|
49
|
+
name: 'vue2-adapter',
|
|
50
|
+
workspaces: ['packages/legacy-adapter'],
|
|
51
|
+
dependencies: ['vue'],
|
|
52
|
+
sections: ['dependencies', 'peerDependencies'],
|
|
53
|
+
reason: 'The adapter still supports Vue 2 consumers',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'canary',
|
|
57
|
+
workspaces: ['examples/canary'],
|
|
58
|
+
dependencies: ['vue'],
|
|
59
|
+
reason: 'Upstream compatibility experiment',
|
|
60
|
+
ignore: true,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Workspace selectors are exact relative directories (`.` selects the root), not package-name patterns. Dependencies are exact names. Omit `sections` to match all sections while continuing to compare them independently. Every group needs a unique name and a nonempty reason. Overlapping matches are errors; unmatched occurrences belong to `default`. An ignored group cannot be fixed. Select another cohort with `--group vue2-adapter`.
|
|
69
|
+
|
|
70
|
+
## Applying and recovering
|
|
71
|
+
|
|
72
|
+
A plan requires a dependency name, section and explicit target. It accepts compatible plain semver declarations or npm aliases with the same source and protocol. The target must share a common allowed version with the entire selected cohort. Conflicts, unknown protocols and exceptions block planning; split intentional cohorts or perform a separately reviewed incompatible upgrade. No version or major upgrade is selected automatically.
|
|
73
|
+
|
|
74
|
+
Plans contain exact before/after values, file hashes and hashes of all discovered manifests, workspace settings and local repoctl configuration files. Applying re-discovers the workspace and regenerates the proposed changes. A changed input, new package, tampered diff, linked manifest or partially applied plan is rejected before any new replacement. Plans are bound to the original workspace path.
|
|
75
|
+
|
|
76
|
+
Only planned manifests are replaced; unrelated fields and dependency sections are retained. An already-applied plan is a no-op. Replacements are staged with original backups and failures roll back completed replacements. If rollback cannot safely overwrite a concurrent edit, the error lists retained `.repoctl-deps-*.bak` files. After a process interruption, inspect those backups beside each manifest, restore originals as needed, remove leftover `.tmp` files, and regenerate the plan. Doctor and pnpm installation can then validate the resulting workspace.
|
|
77
|
+
|
|
78
|
+
Public APIs are `checkDependencies(cwd)`, `planDependencyFix(cwd, options)` and `applyDependencyFixPlan(cwd, plan)`, exported from `repoctl` with their report, configuration and plan types.
|
|
79
|
+
|
|
80
|
+
## Peer compatibility
|
|
81
|
+
|
|
82
|
+
Run `repoctl deps peers --json` to compare each workspace peer promise with its explicit `devDependencies` test declaration. Private packages and the root are included. Required peers without a test declaration fail; absent optional peers are skipped. An optional peer with a test declaration is checked normally. This does not alter pnpm auto-install or strict-peer policies.
|
|
83
|
+
|
|
84
|
+
The report distinguishes `declared_range`, `declared_version`, `lockfile_version`, and `workspace_version` evidence. A declared range fully contained in the peer range is compatible as a declaration; partial overlap remains `unknown` until an exact supported pnpm lockfile version or workspace version establishes a result. Stale/unsupported lockfiles and unknown protocols are never treated as passed. Named/default catalogs, same-source npm aliases, internal workspace aliases, prereleases and compound semver ranges are supported. Missing development peers are not silently replaced by auto-installed peers.
|
|
85
|
+
|
|
86
|
+
JSON includes stable codes, package/path, peer and test declarations, resolved ranges/version, optional status, and pnpm policy values from workspace configuration. A single tested or locked version does not establish compatibility across the whole advertised range; lockfile evidence does not verify installed state. No installs or writes occur, and release workspace-protocol rules remain separate. Failures exit nonzero; `--strict` also fails on unknown results. The public API is `checkPeerDependencies(cwd)`.
|
|
87
|
+
|
|
88
|
+
## Third-party admission
|
|
89
|
+
|
|
90
|
+
Use [dependency admission policies](./dependency-admission) to allow or deny direct third-party dependencies per workspace, review exceptions and compare CI baselines.
|
|
91
|
+
|
|
92
|
+
## pnpm catalog inspection and migration
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pnpm exec repo deps catalog check --json
|
|
96
|
+
pnpm exec repo deps catalog check --catalog legacy --json
|
|
97
|
+
pnpm exec repo deps catalog plan typescript --section devDependencies --json > catalog-plan.json
|
|
98
|
+
pnpm exec repo deps catalog plan react --section dependencies --group react18 --catalog react18 --to '^18.3.0' --json
|
|
99
|
+
pnpm exec repo deps catalog apply catalog-plan.json --json
|
|
100
|
+
pnpm install --lockfile-only
|
|
101
|
+
pnpm install --frozen-lockfile
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`catalog check` inspects every default and named catalog, root/private workspace consumer, missing catalog or entry, and unused entry. `catalog:` and `catalog:default` are equivalent. The default catalog may live at `catalog` or `catalogs.default`; declaring both is a pnpm configuration error. `--catalog` chooses the policy used to report direct-version bypasses and migration candidates; reference integrity is always checked across all catalogs. Direct peer ranges and explicit ignored version groups are exempt from bypass findings.
|
|
105
|
+
|
|
106
|
+
The versioned JSON includes exact manifest paths, dependency sections, package names, original specifiers, catalog entries, consumers and stable finding codes. `missing_catalog`, `missing_entry` and `direct_declaration` make check exit with code 1. `unused_entry` and `uncomparable_entry` are informational; an unused entry is never automatically deleted. Simple `overrides` consumers, including version-qualified package selectors, are counted. Nested override selectors are reported as `unresolved_selector`, with possibly referenced entries marked `usage_unknown` instead of claiming they are unused.
|
|
107
|
+
|
|
108
|
+
Migration reuses dependency consistency cohorts from `commands.deps.groups`; sections remain separate. Identical or semver-equivalent declarations can propose one entry automatically. Compatible but different ranges return `needs_target`: provide `--to` with a range that is a **subset of every selected declaration**, so migration cannot widen allowed versions or introduce a major upgrade. Mutually incompatible versions require explicit cohorts and separate named catalogs, or no migration. No registry is queried and no newest version is chosen.
|
|
109
|
+
|
|
110
|
+
Only plain semver ranges and same-source npm aliases can migrate. An alias keeps its complete `npm:source@range` in the catalog. Workspace/file/link/Git/URL/tag and unknown declarations stay unchanged. Direct `peerDependencies` are report-only and cannot be migrated by this command. Existing catalog references are preserved; a cohort mixing references to other catalogs requires explicit grouping. Existing entries are never overwritten, including when `--to` differs: choose a new named catalog or separately review an entry change affecting all its consumers.
|
|
111
|
+
|
|
112
|
+
`catalog plan` is always read-only, with or without `--dry-run`. Its JSON contains complete before/after YAML and consumer-manifest contents, file hashes, every discovered input hash and the normalized selection. Review the linked changes before `catalog apply`. YAML AST editing preserves unrelated configuration and comments; an edited catalog mapping shared through YAML anchors/aliases is rejected rather than changing unrelated alias consumers. Existing default/named catalog locations are retained. Lockfile generation remains a separate explicit pnpm action.
|
|
113
|
+
|
|
114
|
+
Apply is bound to the same workspace and full input set. Stale YAML, changed manifests/policies, new packages, linked files, partial application and modified plan contents are rejected before writes. It uses the same staged replacements, backups and rollback as dependency fixes, across both YAML and JSON. A fully applied plan and a repeated migration are no-ops. If recovery cannot safely replace a concurrent edit, inspect the listed `.repoctl-deps-*.bak` originals, restore reviewed files, remove stale temporary files and generate a fresh plan; the concurrent edit is preserved.
|
|
115
|
+
|
|
116
|
+
Public APIs are `checkCatalogs(cwd, options?)`, `planCatalogMigration(cwd, options)` and `applyCatalogMigrationPlan(cwd, plan)`. See [pnpm catalogs](https://pnpm.io/catalogs) for protocol semantics and [Syncpack](https://syncpack.dev/) for intentional version-group policy patterns.
|