@webpresso/agent-kit 0.21.5 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +87 -124
  4. package/bin/_run.js +143 -1
  5. package/bin/runtime-manifest.json +40 -0
  6. package/catalog/AGENTS.md.tpl +7 -6
  7. package/catalog/agent/commands/plan-refine.md +3 -3
  8. package/catalog/agent/commands/pll.md +2 -0
  9. package/catalog/agent/guides/parallel-execution.md +2 -0
  10. package/catalog/agent/rules/extraction-parity.md +27 -1
  11. package/catalog/agent/rules/public-package-safety.md +24 -1
  12. package/catalog/agent/skills/pll/SKILL.md +1 -0
  13. package/catalog/base-kit/.github/workflows/ci.webpresso.yml.tmpl +33 -0
  14. package/catalog/base-kit/stryker.config.ts.tmpl +2 -2
  15. package/catalog/docs/templates/blueprint.md +1 -0
  16. package/catalog/docs/templates/blueprint.yaml +10 -12
  17. package/commands/blueprint.md +8 -43
  18. package/dist/esm/audit/blueprint-db-consistency.d.ts +1 -1
  19. package/dist/esm/audit/blueprint-db-consistency.js +6 -8
  20. package/dist/esm/audit/blueprint-lifecycle-sql.js +10 -3
  21. package/dist/esm/audit/cloudflare-deploy-contract.d.ts +3 -0
  22. package/dist/esm/audit/cloudflare-deploy-contract.js +80 -0
  23. package/dist/esm/audit/no-legacy-cli-bin.d.ts +3 -0
  24. package/dist/esm/audit/no-legacy-cli-bin.js +100 -0
  25. package/dist/esm/audit/package-surface.js +14 -1
  26. package/dist/esm/audit/repo-guardrails.js +40 -13
  27. package/dist/esm/audit/roadmap-links.js +23 -10
  28. package/dist/esm/blueprint/core/schema.d.ts +8 -8
  29. package/dist/esm/blueprint/core/schema.js +2 -2
  30. package/dist/esm/blueprint/db/enums.d.ts +1 -1
  31. package/dist/esm/blueprint/db/ingester.js +18 -10
  32. package/dist/esm/blueprint/lifecycle/audit.js +9 -2
  33. package/dist/esm/blueprint/lifecycle/local.js +15 -4
  34. package/dist/esm/blueprint/service/BlueprintCreationService.js +11 -6
  35. package/dist/esm/blueprint/service/BlueprintService.js +37 -19
  36. package/dist/esm/blueprint/service/scanner.js +73 -9
  37. package/dist/esm/blueprint/tracked-document/schema.d.ts +2 -2
  38. package/dist/esm/blueprint/utils/document-paths.d.ts +23 -0
  39. package/dist/esm/blueprint/utils/document-paths.js +91 -0
  40. package/dist/esm/build/package-manifest.js +7 -0
  41. package/dist/esm/build/release-policy.d.ts +27 -0
  42. package/dist/esm/build/release-policy.js +29 -0
  43. package/dist/esm/build/runtime-targets.d.ts +13 -0
  44. package/dist/esm/build/runtime-targets.js +48 -0
  45. package/dist/esm/cli/auto-update/detect-pm.d.ts +15 -0
  46. package/dist/esm/cli/auto-update/detect-pm.js +24 -9
  47. package/dist/esm/cli/auto-update/skip.js +9 -1
  48. package/dist/esm/cli/bundle/agent-command-inventory.d.ts +120 -0
  49. package/dist/esm/cli/bundle/agent-command-inventory.js +100 -0
  50. package/dist/esm/cli/bundle/index.d.ts +17 -0
  51. package/dist/esm/cli/bundle/index.js +15 -0
  52. package/dist/esm/cli/cli.d.ts +1 -1
  53. package/dist/esm/cli/cli.js +49 -5
  54. package/dist/esm/cli/commands/audit-core.d.ts +1 -1
  55. package/dist/esm/cli/commands/audit.js +2 -0
  56. package/dist/esm/cli/commands/blueprint/router.js +11 -8
  57. package/dist/esm/cli/commands/hook.d.ts +8 -0
  58. package/dist/esm/cli/commands/hook.js +47 -0
  59. package/dist/esm/cli/commands/init/index.js +35 -1
  60. package/dist/esm/cli/commands/init/scaffold-base-kit.js +1 -1
  61. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-ownership.js +9 -1
  62. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +130 -20
  63. package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.d.ts +65 -0
  64. package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +64 -0
  65. package/dist/esm/cli/commands/package-manager.d.ts +15 -0
  66. package/dist/esm/cli/commands/package-manager.js +42 -0
  67. package/dist/esm/cli/commands/test.d.ts +1 -0
  68. package/dist/esm/cli/commands/test.js +2 -1
  69. package/dist/esm/cli/commands/typecheck.js +5 -20
  70. package/dist/esm/cli/package-scripts.d.ts +12 -0
  71. package/dist/esm/cli/package-scripts.js +59 -0
  72. package/dist/esm/cli/utils.js +3 -22
  73. package/dist/esm/cli/wp-extensions.d.ts +14 -0
  74. package/dist/esm/cli/wp-extensions.js +34 -0
  75. package/dist/esm/config/docs-lint/schemas/common.d.ts +1 -1
  76. package/dist/esm/config/docs-lint/schemas/implementation-plan.d.ts +2 -2
  77. package/dist/esm/config/docs-lint/schemas/parent-roadmap.d.ts +1 -1
  78. package/dist/esm/config/stryker/index.d.ts +85 -0
  79. package/dist/esm/config/stryker/index.js +31 -0
  80. package/dist/esm/e2e/command-builder.js +11 -2
  81. package/dist/esm/e2e/config.d.ts +65 -0
  82. package/dist/esm/e2e/config.js +126 -0
  83. package/dist/esm/e2e/execution.js +4 -0
  84. package/dist/esm/e2e/load-host-adapter.d.ts +6 -1
  85. package/dist/esm/e2e/load-host-adapter.js +27 -9
  86. package/dist/esm/e2e/run-planner.js +1 -0
  87. package/dist/esm/e2e/types.d.ts +2 -0
  88. package/dist/esm/format/index.js +1 -3
  89. package/dist/esm/hooks/guard-switch/index.d.ts +1 -1
  90. package/dist/esm/hooks/guard-switch/index.js +22 -14
  91. package/dist/esm/hooks/post-tool/lint-after-edit.d.ts +1 -0
  92. package/dist/esm/hooks/post-tool/lint-after-edit.js +5 -2
  93. package/dist/esm/hooks/pretool-guard/validators/file-conventions.js +1 -1
  94. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.d.ts +6 -0
  95. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +27 -2
  96. package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +2 -1
  97. package/dist/esm/hooks/pretool-guard/validators/path-contract.js +59 -34
  98. package/dist/esm/hooks/pretool-guard/validators/plan-frontmatter.js +3 -3
  99. package/dist/esm/hooks/shared/routing-block.js +18 -4
  100. package/dist/esm/hooks/shared/validators/blueprint.js +3 -0
  101. package/dist/esm/hooks/stop/qa-changed-files.d.ts +1 -0
  102. package/dist/esm/hooks/stop/qa-changed-files.js +5 -2
  103. package/dist/esm/lint/index.js +1 -1
  104. package/dist/esm/mcp/auto-discover.d.ts +2 -0
  105. package/dist/esm/mcp/auto-discover.js +14 -6
  106. package/dist/esm/mcp/blueprint-server.js +30 -26
  107. package/dist/esm/mcp/cli.js +21 -0
  108. package/dist/esm/mcp/runners/test.js +15 -0
  109. package/dist/esm/mcp/server.d.ts +7 -0
  110. package/dist/esm/mcp/server.js +16 -27
  111. package/dist/esm/mcp/tools/_registry.d.ts +3 -0
  112. package/dist/esm/mcp/tools/_registry.js +21 -0
  113. package/dist/esm/mcp/tools/audit.d.ts +1 -0
  114. package/dist/esm/mcp/tools/audit.js +11 -0
  115. package/dist/esm/mcp/tools/e2e.d.ts +1 -1
  116. package/dist/esm/mcp/tools/typecheck.js +4 -2
  117. package/dist/esm/mutation/affected.d.ts +9 -0
  118. package/dist/esm/mutation/affected.js +36 -0
  119. package/dist/esm/package.json +5 -0
  120. package/dist/esm/runtime/package-version.d.ts +2 -0
  121. package/dist/esm/runtime/package-version.js +43 -0
  122. package/dist/esm/test/command-builder.d.ts +3 -0
  123. package/dist/esm/test/command-builder.js +22 -3
  124. package/dist/esm/tool-runtime/index.d.ts +2 -2
  125. package/dist/esm/tool-runtime/index.js +2 -1
  126. package/dist/esm/tool-runtime/resolve-runner.d.ts +3 -0
  127. package/dist/esm/tool-runtime/resolve-runner.js +7 -5
  128. package/dist/esm/typecheck/index.js +4 -2
  129. package/dist/esm/wp-extension/index.d.ts +50 -0
  130. package/dist/esm/wp-extension/index.js +268 -0
  131. package/package.json +67 -31
  132. package/skills/pll/SKILL.md +1 -0
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `agent-kit-global` self-update scaffolder.
3
+ *
4
+ * Keeps the ONE globally-distributed `@webpresso/agent-kit` binary fresh on
5
+ * every `wp setup`, mirroring how omx / omc / codex / claude self-update their
6
+ * own global installs. The PATH `wp`, the Claude plugin MCP, and the agent
7
+ * hooks all resolve to this single global binary, so refreshing it here means
8
+ * the next invocation everywhere runs the latest published release.
9
+ *
10
+ * Uses the exact same command the auto-update installer infers
11
+ * (`buildVpGlobalInstallCommand` — single source of truth), so there is no
12
+ * second place that can drift on the install incantation.
13
+ *
14
+ * Skipped (no-op, non-fatal) when:
15
+ * - `--dry-run` (no writes anywhere),
16
+ * - `WP_SKIP_AUTO_INSTALL=1` (the documented opt-out, surfaced in the update
17
+ * banner),
18
+ * - the running binary resolves into a webpresso source/git clone — a global
19
+ * install would clobber the developer's working clone with a published
20
+ * tarball (`detectGitInstall`),
21
+ * - `vp` is not on PATH (nothing to install with).
22
+ *
23
+ * A failed refresh is reported but NEVER fails consumer setup: keeping the
24
+ * global tool current is ancillary to scaffolding the consumer repo (same
25
+ * warn-only contract as the codex-cli scaffolder).
26
+ */
27
+ import { spawnSync } from 'node:child_process';
28
+ import { makeNoopSpinnerFactory } from '#cli/commands/init/scaffolders/spinner';
29
+ import { buildVpGlobalInstallCommand, detectGitInstall, PUBLIC_PACKAGE_NAME, } from '#cli/auto-update/detect-pm.js';
30
+ const NO_VP_HINT = 'vp (vite-plus) is not on PATH; cannot refresh the global ' +
31
+ `${PUBLIC_PACKAGE_NAME}. Install vite-plus, then re-run \`wp setup\`.`;
32
+ /**
33
+ * Refresh the single global `@webpresso/agent-kit` install via `vp install -g`.
34
+ */
35
+ export function ensureAgentKitGlobal(input) {
36
+ if (input.options.dryRun)
37
+ return { kind: 'agent-kit-global-skipped-dry-run' };
38
+ const env = input.env ?? process.env;
39
+ if (env.WP_SKIP_AUTO_INSTALL === '1') {
40
+ return { kind: 'agent-kit-global-skipped-opt-out' };
41
+ }
42
+ const argv1 = input.argv1 ?? process.argv[1] ?? '';
43
+ const detectGit = input.detectGit ?? detectGitInstall;
44
+ const sourceCloneRoot = argv1.length > 0 ? detectGit(argv1) : null;
45
+ if (sourceCloneRoot !== null) {
46
+ return { kind: 'agent-kit-global-skipped-source-clone', repoRoot: sourceCloneRoot };
47
+ }
48
+ const spawn = input.spawn ?? spawnSync;
49
+ const spinner = (input.spinnerFactory ?? makeNoopSpinnerFactory())('agent-kit-global');
50
+ const probe = spawn('vp', ['--version'], { encoding: 'utf8' });
51
+ if (probe.error || (probe.status !== null && probe.status !== 0)) {
52
+ return { kind: 'agent-kit-global-skipped-no-vp', hint: NO_VP_HINT };
53
+ }
54
+ const command = buildVpGlobalInstallCommand();
55
+ spinner.start();
56
+ const install = spawn(command[0], command.slice(1), { stdio: 'inherit' });
57
+ if (install.status !== 0) {
58
+ spinner.fail('agent-kit global refresh failed');
59
+ return { kind: 'agent-kit-global-failed', exitCode: install.status ?? -1, command };
60
+ }
61
+ spinner.succeed('agent-kit global up to date');
62
+ return { kind: 'agent-kit-global-updated', command };
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,15 @@
1
+ import type { CAC } from 'cac';
2
+ import type { SpawnSyncReturns } from 'node:child_process';
3
+ export declare const PACKAGE_MANAGER_VERBS: readonly ["install", "add", "remove", "update", "exec", "run"];
4
+ export type PackageManagerVerb = (typeof PACKAGE_MANAGER_VERBS)[number];
5
+ export interface PackageManagerCommandConfig {
6
+ readonly command: string;
7
+ readonly args: readonly string[];
8
+ }
9
+ export interface PackageManagerCommandDeps {
10
+ readonly run?: (command: string, args: readonly string[]) => SpawnSyncReturns<string>;
11
+ }
12
+ export declare function registerPackageManagerCommand(cli: CAC, verb: PackageManagerVerb): void;
13
+ export declare function buildPackageManagerCommand(verb: PackageManagerVerb, argv?: readonly string[]): PackageManagerCommandConfig;
14
+ export declare function runPackageManagerCommand(verb: PackageManagerVerb, deps?: PackageManagerCommandDeps): number;
15
+ //# sourceMappingURL=package-manager.d.ts.map
@@ -0,0 +1,42 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { getManagedRunner } from '#tool-runtime';
3
+ export const PACKAGE_MANAGER_VERBS = ['install', 'add', 'remove', 'update', 'exec', 'run'];
4
+ const HELP_BY_VERB = {
5
+ install: 'Install dependencies through the managed vp facade.',
6
+ add: 'Add dependencies through the managed vp facade.',
7
+ remove: 'Remove dependencies through the managed vp facade.',
8
+ update: 'Update dependencies through the managed vp facade.',
9
+ exec: 'Run a binary through the managed vp facade.',
10
+ run: 'Run a package script through the managed vp facade.',
11
+ };
12
+ export function registerPackageManagerCommand(cli, verb) {
13
+ cli
14
+ .command(`${verb} [...args]`, HELP_BY_VERB[verb])
15
+ .allowUnknownOptions()
16
+ .action(() => runPackageManagerCommand(verb));
17
+ }
18
+ export function buildPackageManagerCommand(verb, argv = process.argv) {
19
+ const resolution = getManagedRunner('vp', { outputPolicy: 'structured' });
20
+ return {
21
+ command: resolution.command,
22
+ args: [...resolution.args, verb, ...extractVerbArgs(verb, argv)],
23
+ };
24
+ }
25
+ export function runPackageManagerCommand(verb, deps = {}) {
26
+ const command = buildPackageManagerCommand(verb);
27
+ const result = (deps.run ?? defaultRun)(command.command, command.args);
28
+ return typeof result.status === 'number' ? result.status : 1;
29
+ }
30
+ function extractVerbArgs(verb, argv) {
31
+ const verbIndex = argv.findIndex((arg, index) => index >= 2 && arg === verb);
32
+ return verbIndex === -1 ? [] : argv.slice(verbIndex + 1);
33
+ }
34
+ function defaultRun(command, args) {
35
+ return spawnSync(command, [...args], {
36
+ encoding: 'utf8',
37
+ env: process.env,
38
+ stdio: 'inherit',
39
+ windowsHide: true,
40
+ });
41
+ }
42
+ //# sourceMappingURL=package-manager.js.map
@@ -2,6 +2,7 @@ import type { CommandConfig, TestCommandOptions } from '#test';
2
2
  import type { CAC } from 'cac';
3
3
  export declare const TEST_COMMAND_HELP: string;
4
4
  export interface AkTestCommandInput extends TestCommandOptions {
5
+ cwd?: string;
5
6
  package?: readonly string[] | string;
6
7
  file?: readonly string[] | string;
7
8
  targets?: readonly string[] | string;
@@ -14,7 +14,7 @@ export function createAkTestCommandConfig(input) {
14
14
  file: toArray(input.file),
15
15
  positional: toArray(input.targets),
16
16
  });
17
- return buildTestCommand(target, input);
17
+ return buildTestCommand(target, { ...input, cwd: input.cwd });
18
18
  }
19
19
  export function registerTestCommand(cli) {
20
20
  cli
@@ -35,6 +35,7 @@ export function registerTestCommand(cli) {
35
35
  .action((targets, flags) => {
36
36
  const rawArgv = process.argv.slice(2);
37
37
  const command = createAkTestCommandConfig({
38
+ cwd: process.cwd(),
38
39
  package: flags.package,
39
40
  file: flags.file,
40
41
  targets: targets ?? [],
@@ -1,7 +1,6 @@
1
1
  import { getManagedRunner } from '#tool-runtime';
2
+ import { getPackageScript, isRecursiveWpScript } from '#cli/package-scripts.js';
2
3
  import { spawnSync } from 'node:child_process';
3
- import { existsSync, readFileSync } from 'node:fs';
4
- import { join } from 'node:path';
5
4
  export const TYPECHECK_COMMAND_HELP = [
6
5
  'Typecheck the current workspace through the portable wp surface.',
7
6
  '',
@@ -17,17 +16,15 @@ export function registerTypecheckCommand(cli) {
17
16
  }
18
17
  export function buildTypecheckCommand(options = {}) {
19
18
  const cwd = options.cwd ?? process.cwd();
20
- if (hasCheckTypesScript(cwd)) {
21
- const resolution = getManagedRunner('vp');
19
+ const checkTypesScript = getPackageScript(cwd, 'check-types');
20
+ if (checkTypesScript && !isRecursiveWpScript(checkTypesScript, 'typecheck')) {
21
+ const resolution = getManagedRunner('vp', { outputPolicy: 'structured' });
22
22
  return {
23
23
  command: resolution.command,
24
24
  args: [...resolution.args, 'run', 'check-types'],
25
25
  };
26
26
  }
27
- const resolution = getManagedRunner('tsc', {
28
- fallbackCommand: 'tsc',
29
- fallbackArgs: [],
30
- });
27
+ const resolution = getManagedRunner('tsc', { outputPolicy: 'structured' });
31
28
  return {
32
29
  command: resolution.command,
33
30
  args: [...resolution.args, '--noEmit', ...(options.pretty ? [] : ['--pretty', 'false'])],
@@ -48,16 +45,4 @@ function defaultRun(command, args) {
48
45
  windowsHide: true,
49
46
  });
50
47
  }
51
- function hasCheckTypesScript(cwd) {
52
- const packageJsonPath = join(cwd, 'package.json');
53
- if (!existsSync(packageJsonPath))
54
- return false;
55
- try {
56
- const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
57
- return typeof parsed.scripts?.['check-types'] === 'string';
58
- }
59
- catch {
60
- return false;
61
- }
62
- }
63
48
  //# sourceMappingURL=typecheck.js.map
@@ -0,0 +1,12 @@
1
+ export interface PackageJsonLike {
2
+ readonly scripts?: Record<string, unknown>;
3
+ readonly dependencies?: Record<string, unknown>;
4
+ readonly devDependencies?: Record<string, unknown>;
5
+ readonly optionalDependencies?: Record<string, unknown>;
6
+ }
7
+ export declare function readPackageJson(cwd: string): PackageJsonLike | undefined;
8
+ export declare function getPackageScript(cwd: string, name: string): string | undefined;
9
+ export declare function packageHasDependency(cwd: string, dependencyName: string): boolean;
10
+ export declare function packageUsesVitest(cwd: string): boolean;
11
+ export declare function isRecursiveWpScript(script: string, verb: string): boolean;
12
+ //# sourceMappingURL=package-scripts.d.ts.map
@@ -0,0 +1,59 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ export function readPackageJson(cwd) {
4
+ const packageJsonPath = join(cwd, 'package.json');
5
+ if (!existsSync(packageJsonPath))
6
+ return;
7
+ try {
8
+ const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
9
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
10
+ return;
11
+ return parsed;
12
+ }
13
+ catch {
14
+ return;
15
+ }
16
+ }
17
+ export function getPackageScript(cwd, name) {
18
+ const parsed = readPackageJson(cwd);
19
+ const candidate = parsed?.scripts?.[name];
20
+ return typeof candidate === 'string' ? candidate : undefined;
21
+ }
22
+ export function packageHasDependency(cwd, dependencyName) {
23
+ const parsed = readPackageJson(cwd);
24
+ if (!parsed)
25
+ return false;
26
+ return ['dependencies', 'devDependencies', 'optionalDependencies'].some((section) => {
27
+ const dependencies = parsed[section];
28
+ return Boolean(dependencies &&
29
+ typeof dependencies === 'object' &&
30
+ !Array.isArray(dependencies) &&
31
+ dependencyName in dependencies);
32
+ });
33
+ }
34
+ export function packageUsesVitest(cwd) {
35
+ return packageHasDependency(cwd, 'vitest');
36
+ }
37
+ export function isRecursiveWpScript(script, verb) {
38
+ const normalized = stripLeadingEnvAssignments(script.trim());
39
+ if (!normalized)
40
+ return false;
41
+ const patterns = [
42
+ new RegExp(`^(?:vp\\s+exec\\s+)?wp\\s+${escapeRegExp(verb)}(?:\\s|$)`),
43
+ new RegExp(`^(?:bunx?|npx)\\s+(?:--yes\\s+)?(?:@webpresso/agent-kit\\s+)?wp\\s+${escapeRegExp(verb)}(?:\\s|$)`),
44
+ ];
45
+ return patterns.some((pattern) => pattern.test(normalized));
46
+ }
47
+ function stripLeadingEnvAssignments(input) {
48
+ let remaining = input.replace(/^env\s+/u, '');
49
+ while (true) {
50
+ const next = remaining.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S+)\s+)/u, '');
51
+ if (next === remaining)
52
+ return remaining.trim();
53
+ remaining = next;
54
+ }
55
+ }
56
+ function escapeRegExp(value) {
57
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
58
+ }
59
+ //# sourceMappingURL=package-scripts.js.map
@@ -5,8 +5,9 @@
5
5
  * unknown-command formatting) and webpresso/packages/cli/cli-utils
6
6
  * (getProjectRoot) so this package has no @webpresso/* runtime dependencies.
7
7
  */
8
- import { existsSync, readFileSync } from 'node:fs';
9
8
  import path from 'node:path';
9
+ import { existsSync } from 'node:fs';
10
+ import { readOwnedPackageVersion } from '#runtime/package-version.js';
10
11
  // ---------------------------------------------------------------------------
11
12
  // Project root resolution
12
13
  // ---------------------------------------------------------------------------
@@ -131,26 +132,6 @@ export function formatUnknownCommandError(input, commands, binName = 'wp') {
131
132
  * having to know how many `..` segments to append.
132
133
  */
133
134
  export function readPackageVersion(metaUrl) {
134
- const url = new URL(metaUrl);
135
- let dir = path.dirname(url.pathname);
136
- for (let i = 0; i < 6; i++) {
137
- const candidate = path.join(dir, 'package.json');
138
- if (existsSync(candidate)) {
139
- try {
140
- const parsed = JSON.parse(readFileSync(candidate, 'utf-8'));
141
- if (parsed.name === 'webpresso') {
142
- return parsed.version ?? '0.0.0';
143
- }
144
- }
145
- catch {
146
- // keep walking
147
- }
148
- }
149
- const parent = path.dirname(dir);
150
- if (parent === dir)
151
- break;
152
- dir = parent;
153
- }
154
- return '0.0.0';
135
+ return readOwnedPackageVersion(metaUrl);
155
136
  }
156
137
  //# sourceMappingURL=utils.js.map
@@ -0,0 +1,14 @@
1
+ import type { CAC } from 'cac';
2
+ import { type LoadWpExtensionsOptions, type WpExtensionAliasV1 } from '#wp-extension';
3
+ export interface RegisterWpExtensionsOptions extends LoadWpExtensionsOptions {
4
+ readonly cli: CAC;
5
+ readonly baseCommands: readonly string[];
6
+ }
7
+ export interface RegisteredWpExtensions {
8
+ readonly aliasMap: ReadonlyMap<string, WpExtensionAliasV1>;
9
+ readonly warnings: readonly string[];
10
+ readonly commandNames: readonly string[];
11
+ }
12
+ export declare function registerWpExtensions(options: RegisterWpExtensionsOptions): Promise<RegisteredWpExtensions>;
13
+ export declare function resolveWpCommandAlias(command: string | undefined, aliasMap: ReadonlyMap<string, WpExtensionAliasV1>): string | undefined;
14
+ //# sourceMappingURL=wp-extensions.d.ts.map
@@ -0,0 +1,34 @@
1
+ import { loadWpExtensions, resolveAcceptedExtensionAliases, } from '#wp-extension';
2
+ export async function registerWpExtensions(options) {
3
+ const loaded = await loadWpExtensions(options);
4
+ const warnings = loaded.flatMap((entry) => entry.warnings);
5
+ const commandNames = [];
6
+ const blockedCommandNames = new Set(options.baseCommands);
7
+ const registeredCommandNames = new Set();
8
+ for (const extension of loaded) {
9
+ if (!extension.extension || !extension.compatible || !extension.detected)
10
+ continue;
11
+ for (const command of extension.extension.commands) {
12
+ if (blockedCommandNames.has(command.name)) {
13
+ warnings.push(`${extension.packageName}: skipped command "${command.name}" because it collides with an existing command`);
14
+ continue;
15
+ }
16
+ command.register(options.cli);
17
+ commandNames.push(command.name);
18
+ blockedCommandNames.add(command.name);
19
+ registeredCommandNames.add(command.name);
20
+ }
21
+ }
22
+ const aliasResolution = resolveAcceptedExtensionAliases(loaded, options.baseCommands, registeredCommandNames);
23
+ return {
24
+ aliasMap: aliasResolution.aliases,
25
+ warnings: [...warnings, ...aliasResolution.warnings],
26
+ commandNames,
27
+ };
28
+ }
29
+ export function resolveWpCommandAlias(command, aliasMap) {
30
+ if (!command)
31
+ return command;
32
+ return aliasMap.get(command)?.commandName ?? command;
33
+ }
34
+ //# sourceMappingURL=wp-extensions.js.map
@@ -46,8 +46,8 @@ export declare const implementationStatus: z.ZodEnum<{
46
46
  completed: "completed";
47
47
  draft: "draft";
48
48
  planned: "planned";
49
- "in-progress": "in-progress";
50
49
  parked: "parked";
50
+ "in-progress": "in-progress";
51
51
  archived: "archived";
52
52
  current: "current";
53
53
  complete: "complete";
@@ -15,8 +15,8 @@ export declare const implementationPlanFrontmatter: z.ZodObject<{
15
15
  completed: "completed";
16
16
  draft: "draft";
17
17
  planned: "planned";
18
- "in-progress": "in-progress";
19
18
  parked: "parked";
19
+ "in-progress": "in-progress";
20
20
  archived: "archived";
21
21
  current: "current";
22
22
  complete: "complete";
@@ -40,8 +40,8 @@ export declare const implementationPlanFrontmatter: z.ZodObject<{
40
40
  completed: "completed";
41
41
  draft: "draft";
42
42
  planned: "planned";
43
- "in-progress": "in-progress";
44
43
  parked: "parked";
44
+ "in-progress": "in-progress";
45
45
  archived: "archived";
46
46
  current: "current";
47
47
  complete: "complete";
@@ -14,8 +14,8 @@ export declare const parentRoadmapFrontmatter: z.ZodObject<{
14
14
  completed: "completed";
15
15
  draft: "draft";
16
16
  planned: "planned";
17
- "in-progress": "in-progress";
18
17
  parked: "parked";
18
+ "in-progress": "in-progress";
19
19
  archived: "archived";
20
20
  current: "current";
21
21
  complete: "complete";
@@ -40,5 +40,90 @@ export declare const baseConfig: {
40
40
  incremental: boolean;
41
41
  incrementalFile: string;
42
42
  };
43
+ /**
44
+ * Extends baseConfig with TypeScript checker defaults.
45
+ * Use this in any TypeScript package instead of baseConfig directly.
46
+ *
47
+ * @example
48
+ * import { typescriptBaseConfig } from '@webpresso/agent-kit/stryker'
49
+ *
50
+ * export default { ...typescriptBaseConfig }
51
+ * // or, for packages with a CF-pool vitest config:
52
+ * export default { ...typescriptBaseConfig, vitest: { configFile: 'vitest.stryker.config.ts' } }
53
+ */
54
+ export declare const typescriptBaseConfig: {
55
+ checkers: string[];
56
+ tsconfigFile: string;
57
+ packageManager: string;
58
+ testRunner: string;
59
+ plugins: string[];
60
+ ignorePatterns: string[];
61
+ mutate: string[];
62
+ concurrency: number;
63
+ timeoutMS: number;
64
+ dryRunTimeoutMinutes: number;
65
+ ignoreStatic: boolean;
66
+ thresholds: {
67
+ high: number;
68
+ low: number;
69
+ break: number;
70
+ };
71
+ mutator: {
72
+ excludedMutations: string[];
73
+ };
74
+ reporters: string[];
75
+ htmlReporter: {
76
+ fileName: string;
77
+ };
78
+ jsonReporter: {
79
+ fileName: string;
80
+ };
81
+ incremental: boolean;
82
+ incrementalFile: string;
83
+ };
84
+ /**
85
+ * Extends typescriptBaseConfig for Cloudflare Workers packages whose vitest config
86
+ * uses @cloudflare/vitest-pool-workers (incompatible with Stryker's pool injection).
87
+ * Points to a per-package vitest.stryker.config.ts that uses the standard forks pool
88
+ * and excludes any tests that require CF runtime globals (cloudflare:test).
89
+ *
90
+ * @example
91
+ * import { typescriptWorkersBaseConfig } from '@webpresso/agent-kit/stryker'
92
+ *
93
+ * export default { ...typescriptWorkersBaseConfig }
94
+ */
95
+ export declare const typescriptWorkersBaseConfig: {
96
+ vitest: {
97
+ configFile: string;
98
+ };
99
+ checkers: string[];
100
+ tsconfigFile: string;
101
+ packageManager: string;
102
+ testRunner: string;
103
+ plugins: string[];
104
+ ignorePatterns: string[];
105
+ mutate: string[];
106
+ concurrency: number;
107
+ timeoutMS: number;
108
+ dryRunTimeoutMinutes: number;
109
+ ignoreStatic: boolean;
110
+ thresholds: {
111
+ high: number;
112
+ low: number;
113
+ break: number;
114
+ };
115
+ mutator: {
116
+ excludedMutations: string[];
117
+ };
118
+ reporters: string[];
119
+ htmlReporter: {
120
+ fileName: string;
121
+ };
122
+ jsonReporter: {
123
+ fileName: string;
124
+ };
125
+ incremental: boolean;
126
+ incrementalFile: string;
127
+ };
43
128
  export default baseConfig;
44
129
  //# sourceMappingURL=index.d.ts.map
@@ -75,5 +75,36 @@ export const baseConfig = {
75
75
  incremental: true,
76
76
  incrementalFile: 'reports/stryker-incremental.json',
77
77
  };
78
+ /**
79
+ * Extends baseConfig with TypeScript checker defaults.
80
+ * Use this in any TypeScript package instead of baseConfig directly.
81
+ *
82
+ * @example
83
+ * import { typescriptBaseConfig } from '@webpresso/agent-kit/stryker'
84
+ *
85
+ * export default { ...typescriptBaseConfig }
86
+ * // or, for packages with a CF-pool vitest config:
87
+ * export default { ...typescriptBaseConfig, vitest: { configFile: 'vitest.stryker.config.ts' } }
88
+ */
89
+ export const typescriptBaseConfig = {
90
+ ...baseConfig,
91
+ checkers: ['typescript'],
92
+ tsconfigFile: 'tsconfig.json',
93
+ };
94
+ /**
95
+ * Extends typescriptBaseConfig for Cloudflare Workers packages whose vitest config
96
+ * uses @cloudflare/vitest-pool-workers (incompatible with Stryker's pool injection).
97
+ * Points to a per-package vitest.stryker.config.ts that uses the standard forks pool
98
+ * and excludes any tests that require CF runtime globals (cloudflare:test).
99
+ *
100
+ * @example
101
+ * import { typescriptWorkersBaseConfig } from '@webpresso/agent-kit/stryker'
102
+ *
103
+ * export default { ...typescriptWorkersBaseConfig }
104
+ */
105
+ export const typescriptWorkersBaseConfig = {
106
+ ...typescriptBaseConfig,
107
+ vitest: { configFile: 'vitest.stryker.config.ts' },
108
+ };
78
109
  export default baseConfig;
79
110
  //# sourceMappingURL=index.js.map
@@ -16,7 +16,9 @@ function buildPlaywrightCommand(options) {
16
16
  throw new Error(`Step ${step.logName} uses runner "playwright" but does not define configPath.`);
17
17
  }
18
18
  const { baseDir, configArg, files } = resolveRunnerPaths(step.configPath, options.files ?? []);
19
- const resolution = withBaseDir(getManagedRunner('playwright', { filterOutput: options.filterOutput }), baseDir);
19
+ const resolution = withBaseDir(getManagedRunner('playwright', {
20
+ outputPolicy: resolveOutputPolicy(options.outputPolicy, options.filterOutput),
21
+ }), baseDir);
20
22
  const args = [...resolution.args, 'test', '--config', configArg];
21
23
  appendPlaywrightFlags(args, options);
22
24
  args.push(...(step.fixedArgs ?? []), ...files, ...(options.passthrough ?? []));
@@ -28,7 +30,9 @@ function buildVitestE2eCommand(options) {
28
30
  throw new Error(`Step ${step.logName} uses runner "vitest" but does not define configPath.`);
29
31
  }
30
32
  const { baseDir, configArg, files } = resolveRunnerPaths(step.configPath, options.files ?? []);
31
- const resolution = withBaseDir(getManagedRunner('vitest', { filterOutput: options.filterOutput }), baseDir);
33
+ const resolution = withBaseDir(getManagedRunner('vitest', {
34
+ outputPolicy: resolveOutputPolicy(options.outputPolicy, options.filterOutput),
35
+ }), baseDir);
32
36
  const args = [...resolution.args, 'run', '--config', configArg];
33
37
  if (options.workers !== undefined) {
34
38
  args.push('--poolOptions.threads.maxThreads', String(options.workers));
@@ -114,4 +118,9 @@ function withBaseDir(resolution, baseDir) {
114
118
  }
115
119
  return { command: resolution.command, args: [...resolution.args] };
116
120
  }
121
+ function resolveOutputPolicy(outputPolicy, filterOutput) {
122
+ if (outputPolicy)
123
+ return outputPolicy;
124
+ return filterOutput === false ? 'structured' : 'rtk-filtered';
125
+ }
117
126
  //# sourceMappingURL=command-builder.js.map
@@ -1,11 +1,76 @@
1
1
  import { z } from 'zod';
2
2
  export declare const WEBPRESSO_CONFIG_FILE_NAME = "webpresso.config.ts";
3
3
  export declare const WEBPRESSO_CONFIG_EXPORT_NAME = "webpressoConfig";
4
+ export declare const AGENT_KIT_CONFIG_FILE_NAME = "agent-kit.config.ts";
5
+ export declare const AGENT_KIT_CONFIG_EXPORT_NAME = "agentKitConfig";
6
+ export declare const WEBPRESSO_CONFIG_CANDIDATES: readonly [{
7
+ readonly fileName: "agent-kit.config.ts";
8
+ readonly exportName: "agentKitConfig";
9
+ }, {
10
+ readonly fileName: "webpresso.config.ts";
11
+ readonly exportName: "webpressoConfig";
12
+ }];
4
13
  declare const webpressoConfigSchema: z.ZodObject<{
5
14
  e2e: z.ZodOptional<z.ZodObject<{
6
15
  hostAdapterModule: z.ZodString;
7
16
  hostAdapterExport: z.ZodOptional<z.ZodString>;
8
17
  }, z.core.$strict>>;
18
+ deploy: z.ZodOptional<z.ZodObject<{
19
+ cloudflare: z.ZodOptional<z.ZodObject<{
20
+ lanes: z.ZodObject<{
21
+ dev: z.ZodObject<{
22
+ wranglerEnvName: z.ZodString;
23
+ }, z.core.$strict>;
24
+ preview_main: z.ZodObject<{
25
+ wranglerEnvName: z.ZodString;
26
+ }, z.core.$strict>;
27
+ preview_pr: z.ZodObject<{
28
+ wranglerEnvNamePattern: z.ZodString;
29
+ }, z.core.$strict>;
30
+ prd: z.ZodObject<{
31
+ wranglerEnvName: z.ZodString & z.ZodType<"production", string, z.core.$ZodTypeInternals<"production", string>>;
32
+ deployedWorkerNameMode: z.ZodLiteral<"top_level_name">;
33
+ }, z.core.$strict>;
34
+ }, z.core.$strict>;
35
+ production: z.ZodObject<{
36
+ metadataPath: z.ZodLiteral<"infra/release-metadata.production.json">;
37
+ }, z.core.$strict>;
38
+ targets: z.ZodArray<z.ZodObject<{
39
+ id: z.ZodString;
40
+ type: z.ZodEnum<{
41
+ single_worker: "single_worker";
42
+ worker_plus_assets: "worker_plus_assets";
43
+ monorepo_multi_target: "monorepo_multi_target";
44
+ }>;
45
+ topLevelWorkerName: z.ZodString;
46
+ previewTransport: z.ZodEnum<{
47
+ custom_domain_env: "custom_domain_env";
48
+ workers_dev_env: "workers_dev_env";
49
+ }>;
50
+ routeSpec: z.ZodOptional<z.ZodObject<{
51
+ pattern: z.ZodString;
52
+ }, z.core.$strict>>;
53
+ durableObjectBindings: z.ZodOptional<z.ZodArray<z.ZodObject<{
54
+ name: z.ZodString;
55
+ className: z.ZodString;
56
+ scriptName: z.ZodOptional<z.ZodString>;
57
+ }, z.core.$strict>>>;
58
+ vars: z.ZodRecord<z.ZodString, z.ZodUnknown>;
59
+ requiredSecrets: z.ZodArray<z.ZodString>;
60
+ storageMode: z.ZodEnum<{
61
+ isolated: "isolated";
62
+ shared_via_script_name: "shared_via_script_name";
63
+ }>;
64
+ destroyMode: z.ZodLiteral<"wrangler_delete_env">;
65
+ repoCleanupHook: z.ZodOptional<z.ZodString>;
66
+ blastRadiusDoc: z.ZodOptional<z.ZodString>;
67
+ productionStrategyDefault: z.ZodEnum<{
68
+ direct: "direct";
69
+ gradual: "gradual";
70
+ }>;
71
+ }, z.core.$strict>>;
72
+ }, z.core.$strict>>;
73
+ }, z.core.$strict>>;
9
74
  }, z.core.$strict>;
10
75
  export type WebpressoConfig = z.infer<typeof webpressoConfigSchema>;
11
76
  export type WebpressoE2eConfig = NonNullable<WebpressoConfig['e2e']>;