@webpresso/agent-kit 0.21.4 → 0.23.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +93 -66
- package/bin/_run.js +143 -1
- package/bin/runtime-manifest.json +40 -0
- package/catalog/AGENTS.md.tpl +7 -6
- package/catalog/agent/commands/plan-refine.md +3 -3
- package/catalog/agent/commands/pll.md +2 -0
- package/catalog/agent/guides/parallel-execution.md +2 -0
- package/catalog/agent/rules/extraction-parity.md +27 -1
- package/catalog/agent/rules/public-package-safety.md +24 -1
- package/catalog/agent/skills/plan-refine/SKILL.md +5 -4
- package/catalog/agent/skills/pll/SKILL.md +1 -0
- package/catalog/base-kit/.github/workflows/ci.webpresso.yml.tmpl +33 -0
- package/catalog/base-kit/commitlint.config.ts.tmpl +1 -3
- package/catalog/base-kit/e2e/fixtures/smoke.html.tmpl +13 -0
- package/catalog/base-kit/e2e/smoke.spec.ts.tmpl +13 -0
- package/catalog/base-kit/oxlint.config.ts.tmpl +26 -0
- package/catalog/base-kit/playwright.config.ts.tmpl +10 -0
- package/catalog/base-kit/src/quality-sample.test.ts.tmpl +19 -0
- package/catalog/base-kit/src/quality-sample.ts.tmpl +11 -0
- package/catalog/base-kit/stryker.config.ts.tmpl +14 -0
- package/catalog/base-kit/tsconfig.json.tmpl +9 -0
- package/catalog/base-kit/vitest.config.ts.tmpl +10 -0
- package/catalog/docs/templates/adr.md +1 -1
- package/catalog/docs/templates/blueprint.md +2 -0
- package/catalog/docs/templates/blueprint.yaml +16 -15
- package/catalog/docs/templates/guide.md +1 -1
- package/catalog/docs/templates/postmortem.md +1 -1
- package/catalog/docs/templates/research.md +1 -1
- package/catalog/docs/templates/runbook.md +1 -1
- package/catalog/docs/templates/system.md +12 -3
- package/catalog/docs/templates/tech-debt.md +1 -0
- package/commands/blueprint.md +10 -12
- package/dist/esm/audit/blueprint-db-consistency.d.ts +1 -1
- package/dist/esm/audit/blueprint-db-consistency.js +6 -8
- package/dist/esm/audit/blueprint-lifecycle-sql.js +10 -3
- package/dist/esm/audit/cloudflare-deploy-contract.d.ts +3 -0
- package/dist/esm/audit/cloudflare-deploy-contract.js +64 -0
- package/dist/esm/audit/no-legacy-cli-bin.d.ts +3 -0
- package/dist/esm/audit/no-legacy-cli-bin.js +100 -0
- package/dist/esm/audit/package-surface.js +14 -1
- package/dist/esm/audit/repo-guardrails.js +40 -13
- package/dist/esm/audit/resolve-audit-script.d.ts +24 -0
- package/dist/esm/audit/resolve-audit-script.js +27 -0
- package/dist/esm/audit/roadmap-links.js +23 -10
- package/dist/esm/blueprint/core/schema.d.ts +8 -8
- package/dist/esm/blueprint/core/schema.js +2 -2
- package/dist/esm/blueprint/db/enums.d.ts +1 -1
- package/dist/esm/blueprint/db/ingester.js +18 -10
- package/dist/esm/blueprint/index.d.ts +0 -1
- package/dist/esm/blueprint/index.js +0 -2
- package/dist/esm/blueprint/lifecycle/audit.js +9 -2
- package/dist/esm/blueprint/lifecycle/local.js +15 -4
- package/dist/esm/blueprint/local.d.ts +0 -3
- package/dist/esm/blueprint/local.js +0 -2
- package/dist/esm/blueprint/service/BlueprintCreationService.js +16 -8
- package/dist/esm/blueprint/service/BlueprintService.js +37 -19
- package/dist/esm/blueprint/service/scanner.js +73 -9
- package/dist/esm/blueprint/tracked-document/schema.d.ts +2 -2
- package/dist/esm/blueprint/utils/document-paths.d.ts +23 -0
- package/dist/esm/blueprint/utils/document-paths.js +91 -0
- package/dist/esm/blueprint/utils/package-assets.d.ts +11 -0
- package/dist/esm/blueprint/utils/package-assets.js +33 -4
- package/dist/esm/build/package-manifest.js +7 -0
- package/dist/esm/build/release-policy.d.ts +27 -0
- package/dist/esm/build/release-policy.js +29 -0
- package/dist/esm/build/runtime-targets.d.ts +13 -0
- package/dist/esm/build/runtime-targets.js +48 -0
- package/dist/esm/build/sync-catalog-doc-templates.d.ts +23 -0
- package/dist/esm/build/sync-catalog-doc-templates.js +93 -0
- package/dist/esm/cli/auto-update/detect-pm.d.ts +15 -0
- package/dist/esm/cli/auto-update/detect-pm.js +24 -9
- package/dist/esm/cli/auto-update/skip.js +9 -1
- package/dist/esm/cli/bundle/agent-command-inventory.d.ts +120 -0
- package/dist/esm/cli/bundle/agent-command-inventory.js +100 -0
- package/dist/esm/cli/bundle/index.d.ts +17 -0
- package/dist/esm/cli/bundle/index.js +15 -0
- package/dist/esm/cli/cli.d.ts +1 -1
- package/dist/esm/cli/cli.js +49 -5
- package/dist/esm/cli/commands/audit-core.d.ts +1 -1
- package/dist/esm/cli/commands/audit.js +4 -7
- package/dist/esm/cli/commands/blueprint/router.js +16 -10
- package/dist/esm/cli/commands/blueprint/template-resolver.js +8 -4
- package/dist/esm/cli/commands/hook.d.ts +8 -0
- package/dist/esm/cli/commands/hook.js +47 -0
- package/dist/esm/cli/commands/init/host-visibility.js +4 -2
- package/dist/esm/cli/commands/init/index.js +80 -7
- package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +12 -0
- package/dist/esm/cli/commands/init/scaffold-base-kit.js +142 -7
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-ownership.js +9 -1
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +130 -20
- package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.d.ts +65 -0
- package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +64 -0
- package/dist/esm/cli/commands/package-manager.d.ts +15 -0
- package/dist/esm/cli/commands/package-manager.js +42 -0
- package/dist/esm/cli/commands/test.d.ts +1 -0
- package/dist/esm/cli/commands/test.js +2 -1
- package/dist/esm/cli/commands/typecheck.js +10 -19
- package/dist/esm/cli/package-scripts.d.ts +12 -0
- package/dist/esm/cli/package-scripts.js +59 -0
- package/dist/esm/cli/utils.js +3 -22
- package/dist/esm/cli/wp-extensions.d.ts +14 -0
- package/dist/esm/cli/wp-extensions.js +34 -0
- package/dist/esm/config/docs-lint/schemas/common.d.ts +1 -1
- package/dist/esm/config/docs-lint/schemas/implementation-plan.d.ts +2 -2
- package/dist/esm/config/docs-lint/schemas/parent-roadmap.d.ts +1 -1
- package/dist/esm/config/stryker/index.d.ts +85 -0
- package/dist/esm/config/stryker/index.js +31 -0
- package/dist/esm/e2e/command-builder.js +35 -7
- package/dist/esm/e2e/config.d.ts +56 -0
- package/dist/esm/e2e/config.js +114 -0
- package/dist/esm/e2e/execution.js +8 -0
- package/dist/esm/e2e/run-planner.js +2 -0
- package/dist/esm/e2e/types.d.ts +3 -0
- package/dist/esm/format/index.js +5 -1
- package/dist/esm/hooks/guard-switch/index.d.ts +1 -1
- package/dist/esm/hooks/guard-switch/index.js +22 -14
- package/dist/esm/hooks/post-tool/lint-after-edit.d.ts +1 -0
- package/dist/esm/hooks/post-tool/lint-after-edit.js +5 -2
- package/dist/esm/hooks/pretool-guard/validators/file-conventions.js +1 -1
- package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.d.ts +6 -0
- package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +27 -2
- package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +2 -1
- package/dist/esm/hooks/pretool-guard/validators/path-contract.js +59 -34
- package/dist/esm/hooks/pretool-guard/validators/plan-frontmatter.js +3 -3
- package/dist/esm/hooks/shared/routing-block.js +18 -4
- package/dist/esm/hooks/shared/validators/blueprint.js +3 -0
- package/dist/esm/hooks/stop/qa-changed-files.d.ts +1 -0
- package/dist/esm/hooks/stop/qa-changed-files.js +5 -2
- package/dist/esm/lint/index.js +3 -1
- package/dist/esm/mcp/auto-discover.d.ts +2 -0
- package/dist/esm/mcp/auto-discover.js +14 -6
- package/dist/esm/mcp/blueprint-server.js +379 -80
- package/dist/esm/mcp/cli.js +21 -0
- package/dist/esm/mcp/runners/test.js +15 -0
- package/dist/esm/mcp/server.d.ts +7 -0
- package/dist/esm/mcp/server.js +16 -27
- package/dist/esm/mcp/tools/_registry.d.ts +3 -0
- package/dist/esm/mcp/tools/_registry.js +21 -0
- package/dist/esm/mcp/tools/audit.d.ts +1 -0
- package/dist/esm/mcp/tools/audit.js +13 -8
- package/dist/esm/mcp/tools/typecheck.js +4 -2
- package/dist/esm/mutation/affected.d.ts +9 -0
- package/dist/esm/mutation/affected.js +36 -0
- package/dist/esm/package.json +8 -0
- package/dist/esm/runtime/package-version.d.ts +2 -0
- package/dist/esm/runtime/package-version.js +43 -0
- package/dist/esm/test/command-builder.d.ts +4 -0
- package/dist/esm/test/command-builder.js +28 -3
- package/dist/esm/test-helpers/hermetic-env.d.ts +25 -0
- package/dist/esm/test-helpers/hermetic-env.js +31 -0
- package/dist/esm/tool-runtime/index.d.ts +5 -0
- package/dist/esm/tool-runtime/index.js +24 -0
- package/dist/esm/tool-runtime/resolve-runner.d.ts +16 -0
- package/dist/esm/tool-runtime/resolve-runner.js +42 -0
- package/dist/esm/typecheck/index.js +4 -2
- package/dist/esm/wp-extension/index.d.ts +50 -0
- package/dist/esm/wp-extension/index.js +268 -0
- package/package.json +75 -46
- package/skills/plan-refine/SKILL.md +5 -4
- package/skills/pll/SKILL.md +1 -0
- package/dist/esm/blueprint/dag/cycle-detector.d.ts +0 -12
- package/dist/esm/blueprint/dag/cycle-detector.js +0 -46
- package/dist/esm/blueprint/dag/executor.d.ts +0 -140
- package/dist/esm/blueprint/dag/executor.js +0 -292
- package/dist/esm/blueprint/dag/index.d.ts +0 -20
- package/dist/esm/blueprint/dag/index.js +0 -17
- package/dist/esm/blueprint/dag/interfaces.d.ts +0 -56
- package/dist/esm/blueprint/dag/interfaces.js +0 -13
- package/dist/esm/blueprint/dag/local/independence.d.ts +0 -107
- package/dist/esm/blueprint/dag/local/independence.js +0 -231
- package/dist/esm/blueprint/dag/local/index.d.ts +0 -14
- package/dist/esm/blueprint/dag/local/index.js +0 -14
- package/dist/esm/blueprint/dag/local/package-graph.d.ts +0 -66
- package/dist/esm/blueprint/dag/local/package-graph.js +0 -148
- package/dist/esm/blueprint/dag/plan-parser.d.ts +0 -54
- package/dist/esm/blueprint/dag/plan-parser.js +0 -236
- package/dist/esm/blueprint/dag/task-graph-algorithms.d.ts +0 -13
- package/dist/esm/blueprint/dag/task-graph-algorithms.js +0 -236
- package/dist/esm/blueprint/dag/task-graph.d.ts +0 -171
- package/dist/esm/blueprint/dag/task-graph.js +0 -370
- package/dist/esm/blueprint/dag/types.d.ts +0 -17
- package/dist/esm/blueprint/dag/types.js +0 -2
- package/dist/esm/blueprint/graph/index.d.ts +0 -5
- package/dist/esm/blueprint/graph/index.js +0 -5
- package/dist/esm/blueprint/graph/mermaid-parser.d.ts +0 -3
- package/dist/esm/blueprint/graph/mermaid-parser.js +0 -93
- package/dist/esm/blueprint/graph/mermaid-serializer.d.ts +0 -3
- package/dist/esm/blueprint/graph/mermaid-serializer.js +0 -20
- package/dist/esm/blueprint/graph/schema.d.ts +0 -89
- package/dist/esm/blueprint/graph/schema.js +0 -104
- package/dist/esm/blueprint/graph/task-graph-adapter.d.ts +0 -6
- package/dist/esm/blueprint/graph/task-graph-adapter.js +0 -30
|
@@ -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
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getManagedRunner } from '#tool-runtime';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
export function buildE2eCommand(options) {
|
|
3
4
|
switch (options.step.runner) {
|
|
@@ -15,10 +16,13 @@ function buildPlaywrightCommand(options) {
|
|
|
15
16
|
throw new Error(`Step ${step.logName} uses runner "playwright" but does not define configPath.`);
|
|
16
17
|
}
|
|
17
18
|
const { baseDir, configArg, files } = resolveRunnerPaths(step.configPath, options.files ?? []);
|
|
18
|
-
const
|
|
19
|
+
const resolution = withBaseDir(getManagedRunner('playwright', {
|
|
20
|
+
outputPolicy: resolveOutputPolicy(options.outputPolicy, options.filterOutput),
|
|
21
|
+
}), baseDir);
|
|
22
|
+
const args = [...resolution.args, 'test', '--config', configArg];
|
|
19
23
|
appendPlaywrightFlags(args, options);
|
|
20
24
|
args.push(...(step.fixedArgs ?? []), ...files, ...(options.passthrough ?? []));
|
|
21
|
-
return { command:
|
|
25
|
+
return { command: resolution.command, args };
|
|
22
26
|
}
|
|
23
27
|
function buildVitestE2eCommand(options) {
|
|
24
28
|
const { step } = options;
|
|
@@ -26,12 +30,15 @@ function buildVitestE2eCommand(options) {
|
|
|
26
30
|
throw new Error(`Step ${step.logName} uses runner "vitest" but does not define configPath.`);
|
|
27
31
|
}
|
|
28
32
|
const { baseDir, configArg, files } = resolveRunnerPaths(step.configPath, options.files ?? []);
|
|
29
|
-
const
|
|
33
|
+
const resolution = withBaseDir(getManagedRunner('vitest', {
|
|
34
|
+
outputPolicy: resolveOutputPolicy(options.outputPolicy, options.filterOutput),
|
|
35
|
+
}), baseDir);
|
|
36
|
+
const args = [...resolution.args, 'run', '--config', configArg];
|
|
30
37
|
if (options.workers !== undefined) {
|
|
31
38
|
args.push('--poolOptions.threads.maxThreads', String(options.workers));
|
|
32
39
|
}
|
|
33
40
|
args.push(...(step.fixedArgs ?? []), ...files, ...(options.passthrough ?? []));
|
|
34
|
-
return { command:
|
|
41
|
+
return { command: resolution.command, args };
|
|
35
42
|
}
|
|
36
43
|
function buildCustomCommand(options) {
|
|
37
44
|
const { step } = options;
|
|
@@ -69,9 +76,6 @@ function appendPlaywrightFlags(args, options) {
|
|
|
69
76
|
args.push('--test-list', options.testList);
|
|
70
77
|
}
|
|
71
78
|
}
|
|
72
|
-
function buildPnpmExecPrefix(baseDir) {
|
|
73
|
-
return baseDir === '.' ? ['exec'] : ['--dir', baseDir, 'exec'];
|
|
74
|
-
}
|
|
75
79
|
function resolveRunnerPaths(configPath, files) {
|
|
76
80
|
const normalizedConfigPath = configPath.replace(/\\/gu, '/');
|
|
77
81
|
const baseDir = path.posix.dirname(normalizedConfigPath);
|
|
@@ -95,4 +99,28 @@ function resolveRunnerPaths(configPath, files) {
|
|
|
95
99
|
}),
|
|
96
100
|
};
|
|
97
101
|
}
|
|
102
|
+
function withBaseDir(resolution, baseDir) {
|
|
103
|
+
if (baseDir === '.') {
|
|
104
|
+
return { command: resolution.command, args: [...resolution.args] };
|
|
105
|
+
}
|
|
106
|
+
if (resolution.command === 'vp') {
|
|
107
|
+
return {
|
|
108
|
+
command: resolution.command,
|
|
109
|
+
args: ['--dir', baseDir, ...resolution.args],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const [wrappedCommand, ...wrappedArgs] = resolution.args;
|
|
113
|
+
if (resolution.command === 'rtk' && wrappedCommand === 'vp') {
|
|
114
|
+
return {
|
|
115
|
+
command: resolution.command,
|
|
116
|
+
args: ['vp', '--dir', baseDir, ...wrappedArgs],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return { command: resolution.command, args: [...resolution.args] };
|
|
120
|
+
}
|
|
121
|
+
function resolveOutputPolicy(outputPolicy, filterOutput) {
|
|
122
|
+
if (outputPolicy)
|
|
123
|
+
return outputPolicy;
|
|
124
|
+
return filterOutput === false ? 'structured' : 'rtk-filtered';
|
|
125
|
+
}
|
|
98
126
|
//# sourceMappingURL=command-builder.js.map
|
package/dist/esm/e2e/config.d.ts
CHANGED
|
@@ -6,6 +6,62 @@ declare const webpressoConfigSchema: z.ZodObject<{
|
|
|
6
6
|
hostAdapterModule: z.ZodString;
|
|
7
7
|
hostAdapterExport: z.ZodOptional<z.ZodString>;
|
|
8
8
|
}, z.core.$strict>>;
|
|
9
|
+
deploy: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
cloudflare: z.ZodOptional<z.ZodObject<{
|
|
11
|
+
lanes: z.ZodObject<{
|
|
12
|
+
dev: z.ZodObject<{
|
|
13
|
+
wranglerEnvName: z.ZodString;
|
|
14
|
+
}, z.core.$strict>;
|
|
15
|
+
preview_main: z.ZodObject<{
|
|
16
|
+
wranglerEnvName: z.ZodString;
|
|
17
|
+
}, z.core.$strict>;
|
|
18
|
+
preview_pr: z.ZodObject<{
|
|
19
|
+
wranglerEnvNamePattern: z.ZodString;
|
|
20
|
+
}, z.core.$strict>;
|
|
21
|
+
prd: z.ZodObject<{
|
|
22
|
+
wranglerEnvName: z.ZodString & z.ZodType<"production", string, z.core.$ZodTypeInternals<"production", string>>;
|
|
23
|
+
deployedWorkerNameMode: z.ZodLiteral<"top_level_name">;
|
|
24
|
+
}, z.core.$strict>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
production: z.ZodObject<{
|
|
27
|
+
metadataPath: z.ZodLiteral<"infra/release-metadata.production.json">;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
targets: z.ZodArray<z.ZodObject<{
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
type: z.ZodEnum<{
|
|
32
|
+
single_worker: "single_worker";
|
|
33
|
+
worker_plus_assets: "worker_plus_assets";
|
|
34
|
+
monorepo_multi_target: "monorepo_multi_target";
|
|
35
|
+
}>;
|
|
36
|
+
topLevelWorkerName: z.ZodString;
|
|
37
|
+
previewTransport: z.ZodEnum<{
|
|
38
|
+
custom_domain_env: "custom_domain_env";
|
|
39
|
+
workers_dev_env: "workers_dev_env";
|
|
40
|
+
}>;
|
|
41
|
+
routeSpec: z.ZodOptional<z.ZodObject<{
|
|
42
|
+
pattern: z.ZodString;
|
|
43
|
+
}, z.core.$strict>>;
|
|
44
|
+
durableObjectBindings: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
45
|
+
name: z.ZodString;
|
|
46
|
+
className: z.ZodString;
|
|
47
|
+
scriptName: z.ZodOptional<z.ZodString>;
|
|
48
|
+
}, z.core.$strict>>>;
|
|
49
|
+
vars: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
50
|
+
requiredSecrets: z.ZodArray<z.ZodString>;
|
|
51
|
+
storageMode: z.ZodEnum<{
|
|
52
|
+
isolated: "isolated";
|
|
53
|
+
shared_via_script_name: "shared_via_script_name";
|
|
54
|
+
}>;
|
|
55
|
+
destroyMode: z.ZodLiteral<"wrangler_delete_env">;
|
|
56
|
+
repoCleanupHook: z.ZodOptional<z.ZodString>;
|
|
57
|
+
blastRadiusDoc: z.ZodOptional<z.ZodString>;
|
|
58
|
+
productionStrategyDefault: z.ZodEnum<{
|
|
59
|
+
direct: "direct";
|
|
60
|
+
gradual: "gradual";
|
|
61
|
+
}>;
|
|
62
|
+
}, z.core.$strict>>;
|
|
63
|
+
}, z.core.$strict>>;
|
|
64
|
+
}, z.core.$strict>>;
|
|
9
65
|
}, z.core.$strict>;
|
|
10
66
|
export type WebpressoConfig = z.infer<typeof webpressoConfigSchema>;
|
|
11
67
|
export type WebpressoE2eConfig = NonNullable<WebpressoConfig['e2e']>;
|
package/dist/esm/e2e/config.js
CHANGED
|
@@ -1,15 +1,129 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export const WEBPRESSO_CONFIG_FILE_NAME = 'webpresso.config.ts';
|
|
3
3
|
export const WEBPRESSO_CONFIG_EXPORT_NAME = 'webpressoConfig';
|
|
4
|
+
const wranglerEnvNameSchema = z
|
|
5
|
+
.string()
|
|
6
|
+
.min(1, 'wranglerEnvName must not be empty.')
|
|
7
|
+
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'wranglerEnvName must be dash-safe lowercase letters, numbers, and hyphens only.');
|
|
4
8
|
const e2eWebpressoConfigSchema = z
|
|
5
9
|
.object({
|
|
6
10
|
hostAdapterModule: z.string().min(1, 'e2e.hostAdapterModule must not be empty.'),
|
|
7
11
|
hostAdapterExport: z.string().min(1, 'e2e.hostAdapterExport must not be empty.').optional(),
|
|
8
12
|
})
|
|
9
13
|
.strict();
|
|
14
|
+
const cloudflareDeployLaneSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
wranglerEnvName: wranglerEnvNameSchema,
|
|
17
|
+
})
|
|
18
|
+
.strict();
|
|
19
|
+
const previewPrCloudflareDeployLaneSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
wranglerEnvNamePattern: z
|
|
22
|
+
.string()
|
|
23
|
+
.min(1, 'wranglerEnvNamePattern must not be empty.')
|
|
24
|
+
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*-<n>$/, 'wranglerEnvNamePattern must be dash-safe and end with -<n>.'),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
27
|
+
const productionCloudflareDeployLaneSchema = cloudflareDeployLaneSchema.extend({
|
|
28
|
+
wranglerEnvName: wranglerEnvNameSchema.refine((value) => value === 'production', {
|
|
29
|
+
message: 'deploy.cloudflare.lanes.prd.wranglerEnvName must be "production".',
|
|
30
|
+
}),
|
|
31
|
+
deployedWorkerNameMode: z.literal('top_level_name'),
|
|
32
|
+
});
|
|
33
|
+
const cloudflareRouteSpecSchema = z
|
|
34
|
+
.object({
|
|
35
|
+
pattern: z.string().min(1, 'routeSpec.pattern must not be empty.'),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
const cloudflareDurableObjectBindingSchema = z
|
|
39
|
+
.object({
|
|
40
|
+
name: z.string().min(1, 'durableObjectBindings[].name must not be empty.'),
|
|
41
|
+
className: z.string().min(1, 'durableObjectBindings[].className must not be empty.'),
|
|
42
|
+
scriptName: z.string().min(1, 'durableObjectBindings[].scriptName must not be empty.').optional(),
|
|
43
|
+
})
|
|
44
|
+
.strict();
|
|
45
|
+
const cloudflareTargetSchema = z
|
|
46
|
+
.object({
|
|
47
|
+
id: z.string().min(1, 'deploy.cloudflare.targets[].id must not be empty.'),
|
|
48
|
+
type: z.enum(['single_worker', 'worker_plus_assets', 'monorepo_multi_target']),
|
|
49
|
+
topLevelWorkerName: z.string().min(1, 'topLevelWorkerName must not be empty.'),
|
|
50
|
+
previewTransport: z.enum(['custom_domain_env', 'workers_dev_env']),
|
|
51
|
+
routeSpec: cloudflareRouteSpecSchema.optional(),
|
|
52
|
+
durableObjectBindings: z.array(cloudflareDurableObjectBindingSchema).optional(),
|
|
53
|
+
vars: z.record(z.string(), z.unknown()),
|
|
54
|
+
requiredSecrets: z.array(z.string().min(1, 'requiredSecrets[] must not be empty.')),
|
|
55
|
+
storageMode: z.enum(['isolated', 'shared_via_script_name']),
|
|
56
|
+
destroyMode: z.literal('wrangler_delete_env'),
|
|
57
|
+
repoCleanupHook: z.string().min(1, 'repoCleanupHook must not be empty.').optional(),
|
|
58
|
+
blastRadiusDoc: z.string().min(1, 'blastRadiusDoc must not be empty.').optional(),
|
|
59
|
+
productionStrategyDefault: z.enum(['direct', 'gradual']),
|
|
60
|
+
})
|
|
61
|
+
.strict()
|
|
62
|
+
.superRefine((target, ctx) => {
|
|
63
|
+
const isDurableObjectTarget = (target.durableObjectBindings?.length ?? 0) > 0;
|
|
64
|
+
if (target.previewTransport === 'custom_domain_env' && !target.routeSpec) {
|
|
65
|
+
ctx.addIssue({
|
|
66
|
+
code: z.ZodIssueCode.custom,
|
|
67
|
+
path: ['routeSpec'],
|
|
68
|
+
message: 'routeSpec is required when previewTransport is "custom_domain_env".',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (isDurableObjectTarget && target.previewTransport !== 'custom_domain_env') {
|
|
72
|
+
ctx.addIssue({
|
|
73
|
+
code: z.ZodIssueCode.custom,
|
|
74
|
+
path: ['previewTransport'],
|
|
75
|
+
message: 'Durable Object targets must use previewTransport "custom_domain_env" unless a future explicit exception contract is introduced.',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (isDurableObjectTarget && Object.keys(target.vars).length === 0) {
|
|
79
|
+
ctx.addIssue({
|
|
80
|
+
code: z.ZodIssueCode.custom,
|
|
81
|
+
path: ['vars'],
|
|
82
|
+
message: 'Durable Object targets must declare at least one env-specific var.',
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (isDurableObjectTarget && target.requiredSecrets.length === 0) {
|
|
86
|
+
ctx.addIssue({
|
|
87
|
+
code: z.ZodIssueCode.custom,
|
|
88
|
+
path: ['requiredSecrets'],
|
|
89
|
+
message: 'Durable Object targets must declare at least one required secret name.',
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (target.storageMode === 'shared_via_script_name' && !target.blastRadiusDoc) {
|
|
93
|
+
ctx.addIssue({
|
|
94
|
+
code: z.ZodIssueCode.custom,
|
|
95
|
+
path: ['blastRadiusDoc'],
|
|
96
|
+
message: 'blastRadiusDoc is required when storageMode is "shared_via_script_name".',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const cloudflareDeployConfigSchema = z
|
|
101
|
+
.object({
|
|
102
|
+
lanes: z
|
|
103
|
+
.object({
|
|
104
|
+
dev: cloudflareDeployLaneSchema,
|
|
105
|
+
preview_main: cloudflareDeployLaneSchema,
|
|
106
|
+
preview_pr: previewPrCloudflareDeployLaneSchema,
|
|
107
|
+
prd: productionCloudflareDeployLaneSchema,
|
|
108
|
+
})
|
|
109
|
+
.strict(),
|
|
110
|
+
production: z
|
|
111
|
+
.object({
|
|
112
|
+
metadataPath: z.literal('infra/release-metadata.production.json'),
|
|
113
|
+
})
|
|
114
|
+
.strict(),
|
|
115
|
+
targets: z.array(cloudflareTargetSchema),
|
|
116
|
+
})
|
|
117
|
+
.strict();
|
|
118
|
+
const deployWebpressoConfigSchema = z
|
|
119
|
+
.object({
|
|
120
|
+
cloudflare: cloudflareDeployConfigSchema.optional(),
|
|
121
|
+
})
|
|
122
|
+
.strict();
|
|
10
123
|
const webpressoConfigSchema = z
|
|
11
124
|
.object({
|
|
12
125
|
e2e: e2eWebpressoConfigSchema.optional(),
|
|
126
|
+
deploy: deployWebpressoConfigSchema.optional(),
|
|
13
127
|
})
|
|
14
128
|
.strict();
|
|
15
129
|
export class WebpressoConfigValidationError extends Error {
|
|
@@ -18,6 +18,8 @@ export async function createE2eExecutionPlan(input, cwd = process.cwd()) {
|
|
|
18
18
|
workers: input.workers,
|
|
19
19
|
testList: input.testList,
|
|
20
20
|
passthrough: input.passthrough,
|
|
21
|
+
outputPolicy: input.outputPolicy,
|
|
22
|
+
filterOutput: input.filterOutput,
|
|
21
23
|
});
|
|
22
24
|
}
|
|
23
25
|
const hostAdapter = await loadConfiguredHostAdapter(cwd);
|
|
@@ -35,6 +37,8 @@ export async function createE2eExecutionPlan(input, cwd = process.cwd()) {
|
|
|
35
37
|
workers: input.workers,
|
|
36
38
|
testList: input.testList,
|
|
37
39
|
passthrough: input.passthrough,
|
|
40
|
+
outputPolicy: input.outputPolicy,
|
|
41
|
+
filterOutput: input.filterOutput,
|
|
38
42
|
});
|
|
39
43
|
}
|
|
40
44
|
if (hostAdapter.adapter.buildExecutionPlan) {
|
|
@@ -49,6 +53,8 @@ export async function createE2eExecutionPlan(input, cwd = process.cwd()) {
|
|
|
49
53
|
workers: input.workers,
|
|
50
54
|
testList: input.testList,
|
|
51
55
|
passthrough: input.passthrough,
|
|
56
|
+
outputPolicy: input.outputPolicy,
|
|
57
|
+
filterOutput: input.filterOutput,
|
|
52
58
|
});
|
|
53
59
|
}
|
|
54
60
|
return planE2eRun({
|
|
@@ -60,6 +66,8 @@ export async function createE2eExecutionPlan(input, cwd = process.cwd()) {
|
|
|
60
66
|
workers: input.workers,
|
|
61
67
|
testList: input.testList,
|
|
62
68
|
passthrough: input.passthrough,
|
|
69
|
+
outputPolicy: input.outputPolicy,
|
|
70
|
+
filterOutput: input.filterOutput,
|
|
63
71
|
});
|
|
64
72
|
}
|
|
65
73
|
export function plannedGroupsToCommandConfigs(groups) {
|
|
@@ -76,6 +76,8 @@ function planE2eRunsFromSuites(options) {
|
|
|
76
76
|
workers: options.request.workers,
|
|
77
77
|
testList: options.request.testList,
|
|
78
78
|
passthrough: options.request.passthrough,
|
|
79
|
+
outputPolicy: options.request.outputPolicy,
|
|
80
|
+
filterOutput: options.request.filterOutput,
|
|
79
81
|
});
|
|
80
82
|
runs.push({
|
|
81
83
|
suiteId: suite.id,
|
package/dist/esm/e2e/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ManagedRunnerOutputPolicy } from '#tool-runtime';
|
|
1
2
|
export type E2eRunnerKind = 'playwright' | 'vitest' | 'command';
|
|
2
3
|
export interface CommandConfig {
|
|
3
4
|
command: string;
|
|
@@ -48,6 +49,8 @@ export interface E2eCommandRequest {
|
|
|
48
49
|
workers?: number | string;
|
|
49
50
|
testList?: string;
|
|
50
51
|
passthrough?: readonly string[];
|
|
52
|
+
filterOutput?: boolean;
|
|
53
|
+
outputPolicy?: ManagedRunnerOutputPolicy;
|
|
51
54
|
}
|
|
52
55
|
export interface E2eExecutionRequest extends E2eCommandRequest {
|
|
53
56
|
suite?: string;
|
package/dist/esm/format/index.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { isMissingBinary, isRunFailure, runCommand } from '#mcp/tools/_shared/run-command';
|
|
10
10
|
import { resolveProjectRoot } from '#mcp/tools/_shared/project-root';
|
|
11
|
+
import { getManagedRunner } from '#tool-runtime';
|
|
11
12
|
const DEFAULT_FORMAT_TIMEOUT_MS = 5 * 60 * 1_000;
|
|
12
13
|
/**
|
|
13
14
|
* Run formatter and return a structured result. Throws a clear error when
|
|
@@ -33,7 +34,10 @@ export async function runFormat(options = {}) {
|
|
|
33
34
|
args.push('--ignore-path', '.gitignore');
|
|
34
35
|
if (options.files && options.files.length > 0)
|
|
35
36
|
args.push(...options.files);
|
|
36
|
-
const
|
|
37
|
+
const resolution = getManagedRunner('oxfmt', {
|
|
38
|
+
outputPolicy: 'structured',
|
|
39
|
+
});
|
|
40
|
+
const outcome = await runCommand(resolution.command, [...resolution.args, ...args], runOptions);
|
|
37
41
|
if (isRunFailure(outcome)) {
|
|
38
42
|
if (isMissingBinary(outcome)) {
|
|
39
43
|
throw new Error("oxfmt binary not found on PATH. Install it as a devDependency: 'vp install -D oxfmt'");
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { runHook } from '#hooks/shared/hook-bootstrap';
|
|
3
|
+
import { realpathSync } from 'node:fs';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
3
5
|
import { setGuardEnabled } from './state.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
export async function main() {
|
|
7
|
+
runHook((input) => {
|
|
8
|
+
const normalized = (input.prompt ?? '').toLowerCase().trim();
|
|
9
|
+
if (normalized === 'guard off') {
|
|
10
|
+
setGuardEnabled(false);
|
|
11
|
+
console.error('🛡️ Guard disabled — pretool validators will be skipped');
|
|
12
|
+
process.exit(2);
|
|
13
|
+
}
|
|
14
|
+
if (normalized === 'guard on') {
|
|
15
|
+
setGuardEnabled(true);
|
|
16
|
+
console.error('🛡️ Guard enabled — pretool validators active');
|
|
17
|
+
process.exit(2);
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}, () => '{}');
|
|
21
|
+
}
|
|
22
|
+
if (process.argv[1] &&
|
|
23
|
+
realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])) {
|
|
24
|
+
void main();
|
|
25
|
+
}
|
|
18
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -14,4 +14,5 @@ export declare function shouldLintFile(input: ToolInput): boolean;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function lintFile(filePath: string, _projectDir: string): boolean;
|
|
16
16
|
export declare function processPostToolUse(input: ToolInput, projectDir: string): boolean;
|
|
17
|
+
export declare function main(): Promise<void>;
|
|
17
18
|
//# sourceMappingURL=lint-after-edit.d.ts.map
|
|
@@ -46,12 +46,15 @@ export function processPostToolUse(input, projectDir) {
|
|
|
46
46
|
const filePath = input.tool_input.file_path;
|
|
47
47
|
return lintFile(filePath, projectDir);
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])) {
|
|
49
|
+
export async function main() {
|
|
51
50
|
runHook((input) => {
|
|
52
51
|
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
53
52
|
processPostToolUse(input, projectDir);
|
|
54
53
|
return null;
|
|
55
54
|
}, () => '{}');
|
|
56
55
|
}
|
|
56
|
+
if (process.argv[1] &&
|
|
57
|
+
realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])) {
|
|
58
|
+
void main();
|
|
59
|
+
}
|
|
57
60
|
//# sourceMappingURL=lint-after-edit.js.map
|
|
@@ -46,7 +46,7 @@ export function validateFileConventions(input) {
|
|
|
46
46
|
if (nonCanonicalPlanningViolation) {
|
|
47
47
|
return { validator: 'file-conventions', passed: false, message: nonCanonicalPlanningViolation };
|
|
48
48
|
}
|
|
49
|
-
const blueprintPathViolation = getBlueprintPathViolation(normalized);
|
|
49
|
+
const blueprintPathViolation = getBlueprintPathViolation(normalized, undefined, input.cwd);
|
|
50
50
|
if (blueprintPathViolation) {
|
|
51
51
|
return { validator: 'file-conventions', passed: false, message: blueprintPathViolation };
|
|
52
52
|
}
|
|
@@ -29,6 +29,11 @@ interface BlockedScriptSpec {
|
|
|
29
29
|
category: CommandCategory;
|
|
30
30
|
suggestion: string;
|
|
31
31
|
}
|
|
32
|
+
interface BlockedRawNodeModulesToolSpec {
|
|
33
|
+
modulePath: string;
|
|
34
|
+
category: CommandCategory;
|
|
35
|
+
suggestion: string;
|
|
36
|
+
}
|
|
32
37
|
interface RedirectOptions {
|
|
33
38
|
mcpReady?: boolean;
|
|
34
39
|
mcp?: MCPRedirectConfig;
|
|
@@ -39,6 +44,7 @@ export declare const AUDIT_MODE_ENV = "FORBIDDEN_COMMANDS_AUDIT";
|
|
|
39
44
|
export declare const DOCS_REF = "AGENTS.md \"Forbidden Commands (CRITICAL)\" section";
|
|
40
45
|
export declare const BLOCKED_TOOLS: BlockedToolSpec[];
|
|
41
46
|
export declare const BLOCKED_SCRIPTS: BlockedScriptSpec[];
|
|
47
|
+
export declare const BLOCKED_RAW_NODE_MODULE_TOOLS: BlockedRawNodeModulesToolSpec[];
|
|
42
48
|
export declare function generateRules(): CommandRule[];
|
|
43
49
|
export declare const COMMAND_RULES: CommandRule[];
|
|
44
50
|
export declare const SUGGESTION_MODIFIERS: SuggestionModifier[];
|
|
@@ -19,8 +19,18 @@ const TYPECHECK_HINT = 'wp_typecheck MCP tool with package/file scope';
|
|
|
19
19
|
const E2E_HINT = 'wp_e2e MCP tool';
|
|
20
20
|
const ENV_HINT = 'Use the repo-approved environment wrapper for secret-bearing commands';
|
|
21
21
|
const TASK_TARGET_HINT = 'Use the repo-approved vp facade or MCP tool instead of raw execution';
|
|
22
|
-
const EXEC_RUNNERS = [
|
|
23
|
-
|
|
22
|
+
const EXEC_RUNNERS = [
|
|
23
|
+
'vp exec',
|
|
24
|
+
'pnpm exec',
|
|
25
|
+
'npm exec',
|
|
26
|
+
'npm exec --',
|
|
27
|
+
'npx',
|
|
28
|
+
'pnpx',
|
|
29
|
+
'yarn exec',
|
|
30
|
+
'yarn dlx',
|
|
31
|
+
'bunx',
|
|
32
|
+
];
|
|
33
|
+
const DIRECT_RUNNERS = ['vp', 'pnpm', 'yarn', 'yarnpkg'];
|
|
24
34
|
const SCRIPT_RUNNERS = ['vp run', 'vp', 'pnpm', 'pnpm run', 'just'];
|
|
25
35
|
export const BLOCKED_TOOLS = [
|
|
26
36
|
{
|
|
@@ -59,6 +69,11 @@ export const BLOCKED_SCRIPTS = [
|
|
|
59
69
|
{ script: 'e2e', category: 'e2e', suggestion: E2E_HINT },
|
|
60
70
|
{ script: 'qa', category: 'unknown', suggestion: QA_HINT },
|
|
61
71
|
];
|
|
72
|
+
export const BLOCKED_RAW_NODE_MODULE_TOOLS = [
|
|
73
|
+
{ modulePath: 'vitest/vitest.mjs', category: 'test', suggestion: TEST_HINT },
|
|
74
|
+
{ modulePath: 'typescript/bin/tsc', category: 'typecheck', suggestion: TYPECHECK_HINT },
|
|
75
|
+
{ modulePath: 'oxlint/bin/oxlint', category: 'lint', suggestion: LINT_HINT },
|
|
76
|
+
];
|
|
62
77
|
function escapeRegex(s) {
|
|
63
78
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
64
79
|
}
|
|
@@ -66,6 +81,9 @@ function buildToolPattern(prefix, tool) {
|
|
|
66
81
|
const escaped = prefix ? `${escapeRegex(prefix)} ${escapeRegex(tool)}` : escapeRegex(tool);
|
|
67
82
|
return new RegExp(`^${escaped}(\\s|$)`);
|
|
68
83
|
}
|
|
84
|
+
function buildRawNodeModulesToolPattern(modulePath) {
|
|
85
|
+
return new RegExp(`^node\\s+(?:\\.\\/)?node_modules\\/${escapeRegex(modulePath)}(?:\\s|$)`);
|
|
86
|
+
}
|
|
69
87
|
export function generateRules() {
|
|
70
88
|
const rules = [];
|
|
71
89
|
for (const spec of BLOCKED_TOOLS) {
|
|
@@ -104,6 +122,13 @@ export function generateRules() {
|
|
|
104
122
|
});
|
|
105
123
|
}
|
|
106
124
|
}
|
|
125
|
+
for (const spec of BLOCKED_RAW_NODE_MODULE_TOOLS) {
|
|
126
|
+
rules.push({
|
|
127
|
+
pattern: buildRawNodeModulesToolPattern(spec.modulePath),
|
|
128
|
+
category: spec.category,
|
|
129
|
+
suggestion: spec.suggestion,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
107
132
|
rules.push({
|
|
108
133
|
pattern: /^vp exec markdownlint-cli2\b/,
|
|
109
134
|
category: 'unknown',
|