proteum 2.5.5 → 2.5.7

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.
@@ -81,7 +81,6 @@ Managed compact root routers must use trigger -> canonical instruction file refe
81
81
  - Before finishing, re-check touched files against root-level `CODING_STYLE.md` and any narrower area `AGENTS.md` that applied to the edit. Re-check against root-level `optimizations.md` only for touched client-side files. Re-check against root-level `diagnostics.md` only if the task involved an issue, diagnosis, runtime reproduction, or verification failure.
82
82
  - Before finishing a production code change, re-check root-level `DOCUMENTATION.md` update rules. If behavior changed, a bug was fixed, a decision changed, or an important route, auth/OAuth, or integration issue was addressed, update the relevant docs before committing or explicitly explain why no docs update was needed.
83
83
  - Run targeted tests and checks that match the changed surface before finishing each feature or change. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass and expand only when the selected plan is insufficient. Continue running tests after changes, but do not run coverage by default. Downstream app commit workflows run only `proteum refresh`, then targeted lint, typecheck, and test commands in parallel; framework-repo commit workflows skip this downstream app verification. Reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
84
- - Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
85
84
  - When you have finished your work, ask the user whether they want a commit message. After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
86
85
  `Explain in short minimalistic and few bullet points what we changed in this thread, like you would do to your grandma. Start with a verb in the past.`
87
86
 
@@ -67,7 +67,6 @@ Managed compact root routers must use trigger -> canonical instruction file refe
67
67
  - Before finishing a production code change, re-check root-level `DOCUMENTATION.md` update rules. If behavior changed, a bug was fixed, a decision changed, or an important route, auth/OAuth, or integration issue was addressed, update the relevant docs before committing or explicitly explain why no docs update was needed.
68
68
  - For production changes, always add or update focused unit tests and run the targeted unit or integration tests that match the changed behavior. Do not run coverage after every ordinary change by default. Reserve whole-project coverage for the repository's full `npm run check` gate during push workflows or when the user explicitly requests it; downstream app commit-only workflows run `proteum refresh`, then targeted lint, typecheck, and test commands in parallel unless the user explicitly requests more, while framework-repo commits skip this downstream app verification. Document any generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested as explicit exceptions.
69
69
  - Run targeted tests and checks that match the changed surface before finishing each feature or change. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass and expand only when the selected plan is insufficient. Continue running tests after changes, but do not run coverage by default. Downstream app commit workflows run only `proteum refresh`, then targeted lint, typecheck, and test commands in parallel; framework-repo commit workflows skip this downstream app verification. Reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
70
- - Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
71
70
  - When you have finished your work, ask the user whether they want a commit message. After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
72
71
  `Explain in short minimalistic and few bullet points what we changed in this thread, like you would do to your grandma. Start with a verb in the past.`
73
72
 
@@ -14,10 +14,12 @@ import { renderRows } from '../presentation/layout';
14
14
  import { isLikelyProteumAppRoot } from '../presentation/commands';
15
15
  import { renderStep, renderSuccess, renderTitle, renderWarning } from '../presentation/ink';
16
16
  import {
17
+ configureMonorepoProjectAgentInstructions,
17
18
  configureProjectAgentInstructions,
18
19
  findLikelyRepoRoot,
19
20
  isInsideDirectory,
20
21
  resolveCanonicalPath,
22
+ type TConfigureMonorepoProjectAgentInstructionsResult,
21
23
  type TConfigureProjectAgentInstructionsResult,
22
24
  } from '../utils/agents';
23
25
 
@@ -68,20 +70,22 @@ const promptMonorepoRoot = async ({
68
70
  return resolveCanonicalPath(String(response.value || defaultRoot || ''));
69
71
  };
70
72
 
71
- const promptBlockedOverwritePaths = async (blockedPaths: string[]) => {
72
- if (blockedPaths.length === 0) return [];
73
+ export const promptBlockedOverwritePaths = async (blockedPaths: string[]) => {
74
+ const uniqueBlockedPaths = [...new Set(blockedPaths)];
75
+
76
+ if (uniqueBlockedPaths.length === 0) return [];
73
77
 
74
78
  console.info(await renderWarning('Proteum found existing paths that block managed instruction updates.'));
75
79
  console.info(
76
80
  [
77
81
  'Choose whether to overwrite each path with a Proteum-managed instruction path:',
78
- ...blockedPaths.map((entry) => `- ${entry}`),
82
+ ...uniqueBlockedPaths.map((entry) => `- ${entry}`),
79
83
  ].join('\n'),
80
84
  );
81
85
 
82
86
  const overwriteBlockedPaths: string[] = [];
83
87
 
84
- for (const blockedPath of blockedPaths) {
88
+ for (const blockedPath of uniqueBlockedPaths) {
85
89
  const response = await prompts(
86
90
  {
87
91
  type: 'confirm',
@@ -133,6 +137,12 @@ const renderConfigureResultSections = (result: TConfigureProjectAgentInstruction
133
137
  return sections;
134
138
  };
135
139
 
140
+ const renderConfigureMonorepoResultSections = (result: TConfigureMonorepoProjectAgentInstructionsResult) =>
141
+ renderConfigureResultSections({
142
+ ...result,
143
+ appRoot: result.monorepoRoot,
144
+ });
145
+
136
146
  /*----------------------------------
137
147
  - COMMAND
138
148
  ----------------------------------*/
@@ -218,3 +228,52 @@ export const runConfigureAgentsWizard = async ({
218
228
 
219
229
  if (sections.length > 0) console.info(`\n${sections.join('\n\n')}`);
220
230
  };
231
+
232
+ export const runConfigureAgentsMonorepoWizard = async ({
233
+ appRoots,
234
+ coreRoot = cli.paths.core.root,
235
+ monorepoRoot,
236
+ }: {
237
+ appRoots: string[];
238
+ coreRoot?: string;
239
+ monorepoRoot: string;
240
+ }) => {
241
+ if (appRoots.length === 0) throw new UsageError(`No Proteum app roots were found under ${monorepoRoot}.`);
242
+ for (const appRoot of appRoots) assertProteumAppRoot(appRoot);
243
+
244
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
245
+ throw new UsageError('`proteum configure agents` is interactive and requires a TTY.');
246
+ }
247
+
248
+ console.info(
249
+ [
250
+ await renderTitle('PROTEUM CONFIGURE AGENTS', 'Configure monorepo Proteum instruction files and Claude aliases.'),
251
+ renderRows([
252
+ { label: 'monorepo root', value: monorepoRoot === process.cwd() ? '.' : monorepoRoot },
253
+ { label: 'apps', value: String(appRoots.length) },
254
+ ]),
255
+ ].join('\n\n'),
256
+ );
257
+
258
+ const preview = configureMonorepoProjectAgentInstructions({
259
+ appRoots,
260
+ coreRoot,
261
+ dryRun: true,
262
+ monorepoRoot,
263
+ });
264
+ const overwriteBlockedPaths = await promptBlockedOverwritePaths(preview.blocked);
265
+
266
+ console.info(await renderStep('[1/1]', 'Writing monorepo root and app instruction files and Claude aliases.'));
267
+
268
+ const result = configureMonorepoProjectAgentInstructions({
269
+ appRoots,
270
+ coreRoot,
271
+ monorepoRoot,
272
+ overwriteBlockedPaths,
273
+ });
274
+ const sections = renderConfigureMonorepoResultSections(result);
275
+
276
+ console.info(await renderSuccess('Proteum-managed monorepo instruction files and Claude aliases are configured.'));
277
+
278
+ if (sections.length > 0) console.info(`\n${sections.join('\n\n')}`);
279
+ };
package/cli/index.ts CHANGED
@@ -9,6 +9,7 @@ import { renderCliOverview, renderCommandHelp, resolveCustomHelpRequest } from '
9
9
  import { renderCliWelcomeBanner } from './presentation/welcome';
10
10
  import { normalizeHelpArgv, normalizeLegacyArgv } from './runtime/argv';
11
11
  import { createCli, registeredCommands } from './runtime/commands';
12
+ import { isMonorepoFanoutChild, maybeRunMonorepoCommand } from './runtime/monorepoCommands';
12
13
 
13
14
  const formatInvocation = (argv: string[]) => ['proteum', ...argv].join(' ').trim();
14
15
 
@@ -21,6 +22,7 @@ const shouldRenderSharedWelcomeBanner = ({
21
22
  argv: string[];
22
23
  helpRequestKind: 'none' | 'overview' | 'command';
23
24
  }) => {
25
+ if (isMonorepoFanoutChild()) return false;
24
26
  if (helpRequestKind !== 'none') return false;
25
27
  if (argv.length !== 1) return false;
26
28
 
@@ -32,27 +34,9 @@ const shouldRenderSharedWelcomeBanner = ({
32
34
  export const runCli = async (argv: string[] = process.argv.slice(2)) => {
33
35
  const normalizedArgv = normalizeHelpArgv(normalizeLegacyArgv(argv), proteumCommandNames);
34
36
  const version = String(cli.packageJson.version || '');
35
- const proteumInstall = resolveFrameworkInstallInfo({
36
- appRoot: cli.paths.appRoot,
37
- framework: cli.paths.framework,
38
- });
39
37
  const clipanion = createCli(version);
40
38
  const initAvailable = true;
41
39
  const helpRequest = resolveCustomHelpRequest(normalizedArgv);
42
- const shouldRenderWelcomeBanner = shouldRenderSharedWelcomeBanner({
43
- argv: normalizedArgv,
44
- helpRequestKind: helpRequest.kind,
45
- });
46
-
47
- if (shouldRenderWelcomeBanner) {
48
- process.stderr.write(
49
- `${await renderCliWelcomeBanner({
50
- command: formatInvocation(normalizedArgv),
51
- installSummary: proteumInstall.summary,
52
- version,
53
- })}\n\n`,
54
- );
55
- }
56
40
 
57
41
  if (helpRequest.kind === 'overview') {
58
42
  process.stdout.write(
@@ -77,6 +61,28 @@ export const runCli = async (argv: string[] = process.argv.slice(2)) => {
77
61
  return;
78
62
  }
79
63
 
64
+ if (await maybeRunMonorepoCommand(normalizedArgv)) return;
65
+
66
+ const shouldRenderWelcomeBanner = shouldRenderSharedWelcomeBanner({
67
+ argv: normalizedArgv,
68
+ helpRequestKind: helpRequest.kind,
69
+ });
70
+
71
+ if (shouldRenderWelcomeBanner) {
72
+ const proteumInstall = resolveFrameworkInstallInfo({
73
+ appRoot: cli.paths.appRoot,
74
+ framework: cli.paths.framework,
75
+ });
76
+
77
+ process.stderr.write(
78
+ `${await renderCliWelcomeBanner({
79
+ command: formatInvocation(normalizedArgv),
80
+ installSummary: proteumInstall.summary,
81
+ version,
82
+ })}\n\n`,
83
+ );
84
+ }
85
+
80
86
  await clipanion.runExit(normalizedArgv, Cli.defaultContext);
81
87
  };
82
88
 
@@ -130,6 +130,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
130
130
  'This command is interactive. It asks whether the current Proteum app belongs to a monorepo and, if so, which ancestor path should receive the reusable root instruction files.',
131
131
  'Standalone mode writes tracked instruction files into the current Proteum app root and creates `CLAUDE.md` symlinks beside each `AGENTS.md`.',
132
132
  'Monorepo mode writes reusable root documents such as `AGENTS.md`, `DOCUMENTATION.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root, then writes only app-root and area instruction files into the current Proteum app root.',
133
+ 'When run from a monorepo wrapper root that contains Proteum apps, configure writes the shared root documents once and app-root instruction files for every discovered app.',
133
134
  'Every generated `CLAUDE.md` is a sibling symlink pointing to `AGENTS.md`.',
134
135
  'Every managed instruction file contains a `# Proteum Instructions` section with the full embedded Proteum project instruction corpus.',
135
136
  'Existing content outside `# Proteum Instructions` is preserved. Directories and foreign symlinks are replaced only after confirmation.',
@@ -167,6 +168,8 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
167
168
  'Bootstrap writes `.proteum/worktree-bootstrap.json` with hashes, step timestamps, dependency status, runtime status, and Proteum version.',
168
169
  'When `.env` is missing, `--source` is required and must point to an app root with a readable `.env`.',
169
170
  'For monorepos with root tooling, bootstrap also ensures the workspace-root `.env` exists from the source root or source app env.',
171
+ 'When `worktree init` runs from a monorepo wrapper root, Proteum bootstraps every discovered app, matches source apps by relative path, and deduplicates dependency install by shared package-lock root.',
172
+ 'When `worktree create` runs from a source monorepo wrapper root, Proteum creates the Git worktree once and then bootstraps every matching target app.',
170
173
  'Guarded commands block inside `/.codex/worktrees/` until bootstrap is complete or explicitly bypassed with `PROTEUM_ALLOW_UNBOOTSTRAPPED_WORKTREE=1`.',
171
174
  '`worktree create` preserves the source app root path relative to the source repository root, so monorepo app roots are bootstrapped in the matching target location.',
172
175
  ],
@@ -207,13 +210,14 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
207
210
  },
208
211
  ],
209
212
  notes: [
210
- 'Use `--cwd` when the target Proteum app lives in another worktree or checkout and you do not want to `cd` first.',
213
+ 'From a monorepo wrapper root, eligible app-scoped commands run for every discovered Proteum app. Use an app root or `--cwd` when supported to target exactly one app.',
214
+ 'From a monorepo wrapper root, bare `proteum dev` supervises all discovered apps with app-local session files and unique router/HMR port pairs; `dev list` and `dev stop` aggregate every app.',
211
215
  'Proteum writes a machine-readable dev session file under `var/run/proteum/dev/<port>.json` by default; override it with `--session-file` when an agent needs a stable path.',
212
216
  'Before registering a new session, Proteum removes stale same-worktree session files and fails fast if another live tracked session remains.',
213
217
  'Before the dev loop starts, Proteum ensures tracked instruction files contain the current managed `# Proteum Instructions` section.',
214
218
  'Use `--replace-existing` only when retrying the exact requested session file.',
215
- '`proteum dev list` inspects tracked sessions for the current app root. Add `--stale` to show only orphaned or dead sessions.',
216
- '`proteum dev stop` targets the current session file by default. Add `--all` to stop every tracked session for the current app root.',
219
+ '`proteum dev list` inspects tracked sessions for the current app root, or every discovered app from a monorepo wrapper root. Add `--stale` to show only orphaned or dead sessions.',
220
+ '`proteum dev stop` targets the current session file by default. Add `--all` to stop every tracked session for the current app root, or run from a monorepo wrapper root to apply the stop command to every app.',
217
221
  '`proteum dev` clears the interactive terminal once at startup, then shows `CTRL+R` reload and `CTRL+C` shutdown hotkeys in the session banner.',
218
222
  'Legacy single-dash long options remain supported, for example `proteum dev -port 3001`.',
219
223
  ],
@@ -229,7 +233,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
229
233
  examples: [
230
234
  { description: 'Refresh generated contracts after source edits', command: 'proteum refresh' },
231
235
  ],
232
- notes: ['Use this when you need deterministic regeneration without starting the full dev loop.'],
236
+ notes: ['Use this when you need deterministic regeneration without starting the full dev loop.', 'From a monorepo wrapper root, refresh runs once per discovered Proteum app.'],
233
237
  status: 'stable',
234
238
  },
235
239
  build: {
@@ -257,6 +261,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
257
261
  '`--analyze-serve` switches the analyzer to HTTP server mode and keeps the process open until you stop it.',
258
262
  '`--analyze-host` and `--analyze-port` require `--analyze-serve`; use `auto` to let the OS assign a free port.',
259
263
  'Use `--strict` when the build must refresh generated typings and fail on any TypeScript error before compilation starts.',
264
+ 'From a monorepo wrapper root, build runs once per discovered Proteum app. `--analyze-serve` must be run from one app root because the analyzer server stays open.',
260
265
  'The production output is emitted under `bin/`.',
261
266
  ],
262
267
  status: 'stable',
@@ -270,7 +275,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
270
275
  examples: [
271
276
  { description: 'Typecheck every discovered client and server app tsconfig', command: 'proteum typecheck' },
272
277
  ],
273
- notes: ['Proteum refreshes generated typings before running TypeScript.'],
278
+ notes: ['Proteum refreshes generated typings before running TypeScript.', 'From a monorepo wrapper root, typecheck runs once per discovered Proteum app.'],
274
279
  status: 'stable',
275
280
  },
276
281
  lint: {
@@ -283,7 +288,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
283
288
  { description: 'Run ESLint in check mode', command: 'proteum lint' },
284
289
  { description: 'Apply fixable lint changes', command: 'proteum lint --fix' },
285
290
  ],
286
- notes: ['Legacy positional usage such as `proteum lint fix` remains supported.'],
291
+ notes: ['Legacy positional usage such as `proteum lint fix` remains supported.', 'From a monorepo wrapper root, lint runs once per discovered Proteum app.'],
287
292
  status: 'stable',
288
293
  },
289
294
  check: {
@@ -293,7 +298,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
293
298
  usage: 'proteum check',
294
299
  bestFor: 'One command before commits, pushes, or CI when you want the standard local validation path.',
295
300
  examples: [{ description: 'Run the full default validation pipeline', command: 'proteum check' }],
296
- notes: ['This command executes refresh, typecheck, then lint in that order.'],
301
+ notes: ['This command executes refresh, typecheck, then lint in that order.', 'From a monorepo wrapper root, check runs once per discovered Proteum app.'],
297
302
  status: 'stable',
298
303
  },
299
304
  e2e: {