@webpresso/agent-kit 0.21.5 → 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 +87 -124
- 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/pll/SKILL.md +1 -0
- package/catalog/base-kit/.github/workflows/ci.webpresso.yml.tmpl +33 -0
- package/catalog/base-kit/stryker.config.ts.tmpl +2 -2
- package/catalog/docs/templates/blueprint.md +1 -0
- package/catalog/docs/templates/blueprint.yaml +10 -12
- package/commands/blueprint.md +8 -43
- 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/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/lifecycle/audit.js +9 -2
- package/dist/esm/blueprint/lifecycle/local.js +15 -4
- package/dist/esm/blueprint/service/BlueprintCreationService.js +11 -6
- 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/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/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 +2 -0
- package/dist/esm/cli/commands/blueprint/router.js +11 -8
- 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/index.js +35 -1
- package/dist/esm/cli/commands/init/scaffold-base-kit.js +1 -1
- 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 +5 -20
- 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 +11 -2
- package/dist/esm/e2e/config.d.ts +56 -0
- package/dist/esm/e2e/config.js +114 -0
- package/dist/esm/e2e/execution.js +4 -0
- package/dist/esm/e2e/run-planner.js +1 -0
- package/dist/esm/e2e/types.d.ts +2 -0
- package/dist/esm/format/index.js +1 -3
- 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 +1 -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 +30 -26
- 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 +11 -0
- package/dist/esm/mcp/tools/e2e.d.ts +1 -1
- 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 +5 -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 +3 -0
- package/dist/esm/test/command-builder.js +22 -3
- package/dist/esm/tool-runtime/index.d.ts +2 -2
- package/dist/esm/tool-runtime/index.js +2 -1
- package/dist/esm/tool-runtime/resolve-runner.d.ts +3 -0
- package/dist/esm/tool-runtime/resolve-runner.js +7 -5
- 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 +67 -31
- package/skills/pll/SKILL.md +1 -0
|
@@ -23,6 +23,7 @@ import { openDb } from '#db/connection.js';
|
|
|
23
23
|
import { resolveBlueprintProjectionDbPath } from '#db/paths.js';
|
|
24
24
|
import { findTemplate } from '#db/templates.js';
|
|
25
25
|
import { resolveBlueprintRoot } from '#utils/blueprint-root.js';
|
|
26
|
+
import { getBlueprintDocumentPaths } from '#utils/document-paths.js';
|
|
26
27
|
import { evidenceListSchema, canonicalizeEvidenceList } from '#evidence.js';
|
|
27
28
|
import { checkFreshness, readCurrentHead, readProjectionMetadata } from '#freshness.js';
|
|
28
29
|
import { applyVerification, assertAllTasksHaveCanonicalPassingEvidence, readTaskVerification, } from '#verification.js';
|
|
@@ -251,10 +252,10 @@ async function reIngest(cwd) {
|
|
|
251
252
|
await reIngestProjection(cwd);
|
|
252
253
|
}
|
|
253
254
|
async function persistBlueprintMarkdown(input) {
|
|
254
|
-
const { projectCwd, slug,
|
|
255
|
-
mkdirSync(path.dirname(
|
|
255
|
+
const { projectCwd, slug, blueprintPath, markdown } = input;
|
|
256
|
+
mkdirSync(path.dirname(blueprintPath), { recursive: true });
|
|
256
257
|
parseBlueprint(markdown, slug);
|
|
257
|
-
writeFileSync(
|
|
258
|
+
writeFileSync(blueprintPath, markdown, 'utf8');
|
|
258
259
|
await reIngest(projectCwd);
|
|
259
260
|
const refreshed = getCurrentProjectBlueprint(projectCwd, slug);
|
|
260
261
|
if (!refreshed.blueprint) {
|
|
@@ -264,9 +265,11 @@ async function persistBlueprintMarkdown(input) {
|
|
|
264
265
|
}
|
|
265
266
|
function findBlueprintDir(blueprintRoot, slug, states) {
|
|
266
267
|
for (const state of states) {
|
|
267
|
-
const
|
|
268
|
-
if (existsSync(
|
|
269
|
-
return { dir:
|
|
268
|
+
const paths = getBlueprintDocumentPaths(blueprintRoot, state, slug);
|
|
269
|
+
if (existsSync(paths.flat))
|
|
270
|
+
return { dir: path.dirname(paths.flat), path: paths.flat, shape: 'flat', state };
|
|
271
|
+
if (existsSync(paths.directory))
|
|
272
|
+
return { dir: paths.directory, path: paths.folder, shape: 'folder', state };
|
|
270
273
|
}
|
|
271
274
|
return null;
|
|
272
275
|
}
|
|
@@ -557,7 +560,7 @@ async function handleNew(cwd, raw) {
|
|
|
557
560
|
}
|
|
558
561
|
const b = bytes(template);
|
|
559
562
|
const slug = titleToSlug(title);
|
|
560
|
-
const targetPath =
|
|
563
|
+
const targetPath = getBlueprintDocumentPaths(resolveBlueprintRoot(cwd), 'draft', slug).flat;
|
|
561
564
|
// Platform-first path: push event to register the blueprint before returning the scaffold.
|
|
562
565
|
// Iron rule: resolveSyncAdapter() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
|
|
563
566
|
const adapter = await resolveSyncAdapter(cwd);
|
|
@@ -886,7 +889,7 @@ async function handleTaskVerify(projectResolver, cwd, raw) {
|
|
|
886
889
|
if (!found) {
|
|
887
890
|
return err('wp_blueprint_task_verify failed', `Blueprint "${slug}" not found in any state directory`);
|
|
888
891
|
}
|
|
889
|
-
const filePath =
|
|
892
|
+
const filePath = found.path;
|
|
890
893
|
if (!existsSync(filePath)) {
|
|
891
894
|
return err('wp_blueprint_task_verify failed', `Blueprint overview not found at ${filePath}`);
|
|
892
895
|
}
|
|
@@ -981,8 +984,8 @@ async function handlePromote(projectResolver, cwd, raw) {
|
|
|
981
984
|
const found = findBlueprintDir(root, slug, ALL_STATES);
|
|
982
985
|
if (!found)
|
|
983
986
|
return err('wp_blueprint_promote failed', `Blueprint "${slug}" not found in any state directory`);
|
|
984
|
-
const {
|
|
985
|
-
const overviewPath = path
|
|
987
|
+
const { state: currentState } = found;
|
|
988
|
+
const overviewPath = found.path;
|
|
986
989
|
if (to_state === 'completed') {
|
|
987
990
|
try {
|
|
988
991
|
assertBlueprintCanComplete(overviewPath, slug);
|
|
@@ -1085,7 +1088,7 @@ async function handleFinalize(projectResolver, cwd, raw) {
|
|
|
1085
1088
|
return err('wp_blueprint_finalize failed', `Blueprint "${slug}" not found`);
|
|
1086
1089
|
}
|
|
1087
1090
|
try {
|
|
1088
|
-
assertBlueprintCanComplete(
|
|
1091
|
+
assertBlueprintCanComplete(found.path, slug);
|
|
1089
1092
|
}
|
|
1090
1093
|
catch (error) {
|
|
1091
1094
|
return err('wp_blueprint_finalize refused', toStr(error));
|
|
@@ -1807,14 +1810,14 @@ async function handleBlueprintPut(projectResolver, cwd, raw) {
|
|
|
1807
1810
|
return err('wp_blueprint_put refused', `New blueprint "${slug}" must start in "draft"; use wp_blueprint_transition for later lifecycle moves.`);
|
|
1808
1811
|
}
|
|
1809
1812
|
const overviewPath = found
|
|
1810
|
-
?
|
|
1811
|
-
:
|
|
1813
|
+
? found.path
|
|
1814
|
+
: getBlueprintDocumentPaths(root, document.status, slug).flat;
|
|
1812
1815
|
try {
|
|
1813
1816
|
const markdown = renderBlueprintMarkdownFromDocument(slug, document);
|
|
1814
1817
|
const blueprint = await persistBlueprintMarkdown({
|
|
1815
1818
|
projectCwd,
|
|
1816
1819
|
slug,
|
|
1817
|
-
overviewPath,
|
|
1820
|
+
blueprintPath: overviewPath,
|
|
1818
1821
|
markdown,
|
|
1819
1822
|
});
|
|
1820
1823
|
const payload = {
|
|
@@ -1904,7 +1907,7 @@ async function handleBlueprintTransition(projectResolver, cwd, raw) {
|
|
|
1904
1907
|
async function applyLocalBlueprintTransition(input) {
|
|
1905
1908
|
const { projectCwd, slug, to_state, found } = input;
|
|
1906
1909
|
const root = resolveBlueprintRoot(projectCwd);
|
|
1907
|
-
const overviewPath =
|
|
1910
|
+
const overviewPath = found.path;
|
|
1908
1911
|
const parsed = runValidate(overviewPath);
|
|
1909
1912
|
if (!parsed.valid) {
|
|
1910
1913
|
throw new Error(parsed.gaps.join('; '));
|
|
@@ -1918,13 +1921,15 @@ async function applyLocalBlueprintTransition(input) {
|
|
|
1918
1921
|
progress: formatBlueprintProgress(currentBlueprint.tasks.length, currentBlueprint.tasks.filter((task) => task.status === 'done').length, currentBlueprint.tasks.filter((task) => task.status === 'blocked').length),
|
|
1919
1922
|
});
|
|
1920
1923
|
parseBlueprint(updated, slug);
|
|
1921
|
-
const
|
|
1922
|
-
mkdirSync(path.dirname(
|
|
1924
|
+
const destination = getBlueprintDocumentPaths(root, to_state, slug);
|
|
1925
|
+
mkdirSync(path.dirname(found.shape === 'flat' ? destination.flat : destination.directory), {
|
|
1926
|
+
recursive: true,
|
|
1927
|
+
});
|
|
1923
1928
|
let finalOverviewPath = overviewPath;
|
|
1924
1929
|
if (found.state !== to_state) {
|
|
1925
1930
|
const { renameSync } = await import('node:fs');
|
|
1926
|
-
renameSync(found.dir,
|
|
1927
|
-
finalOverviewPath =
|
|
1931
|
+
renameSync(found.shape === 'flat' ? overviewPath : found.dir, found.shape === 'flat' ? destination.flat : destination.directory);
|
|
1932
|
+
finalOverviewPath = found.shape === 'flat' ? destination.flat : destination.folder;
|
|
1928
1933
|
}
|
|
1929
1934
|
writeFileSync(finalOverviewPath, updated, 'utf8');
|
|
1930
1935
|
await reIngest(projectCwd);
|
|
@@ -1960,10 +1965,9 @@ async function handleBlueprintCreate(projectResolver, cwd, raw) {
|
|
|
1960
1965
|
const today = new Date().toISOString().split('T')[0] ?? '';
|
|
1961
1966
|
const slug = titleToSlug(title);
|
|
1962
1967
|
const root = resolveBlueprintRoot(projectCwd);
|
|
1963
|
-
const
|
|
1964
|
-
const overviewPath = path.join(targetDir, '_overview.md');
|
|
1968
|
+
const overviewPath = getBlueprintDocumentPaths(root, 'draft', slug).flat;
|
|
1965
1969
|
try {
|
|
1966
|
-
mkdirSync(
|
|
1970
|
+
mkdirSync(path.dirname(overviewPath), { recursive: true });
|
|
1967
1971
|
const content = BLUEPRINT_TEMPLATE.replace(/{TITLE}/g, title)
|
|
1968
1972
|
.replace(/{COMPLEXITY}/g, complexity)
|
|
1969
1973
|
.replace(/{DATE}/g, today)
|
|
@@ -1971,7 +1975,7 @@ async function handleBlueprintCreate(projectResolver, cwd, raw) {
|
|
|
1971
1975
|
await persistBlueprintMarkdown({
|
|
1972
1976
|
projectCwd,
|
|
1973
1977
|
slug,
|
|
1974
|
-
overviewPath,
|
|
1978
|
+
blueprintPath: overviewPath,
|
|
1975
1979
|
markdown: content,
|
|
1976
1980
|
});
|
|
1977
1981
|
const b = bytes(content);
|
|
@@ -2083,12 +2087,12 @@ export async function registerBlueprintTools(registrar, cwd, projectResolver = c
|
|
|
2083
2087
|
next_action: nextActionOutputSchema,
|
|
2084
2088
|
},
|
|
2085
2089
|
}, (r) => handleBlueprintTransition(projectResolver, cwd, r), { title: 'Blueprint Transition', destructiveHint: false, openWorldHint: false });
|
|
2086
|
-
registrar.registerTool('wp_blueprint_validate', 'Validate _overview.md
|
|
2090
|
+
registrar.registerTool('wp_blueprint_validate', 'Validate canonical blueprint markdown structure (`<slug>.md` or `<slug>/_overview.md`). Returns { valid, gaps }. Must pass before wp_blueprint_promote.', { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] }, undefined, (r) => handleValidate(cwd, r), { title: 'Blueprint Validate', readOnlyHint: false, openWorldHint: false });
|
|
2087
2091
|
registrar.registerTool('wp_blueprint_task_next', 'Return the next ready task (all deps done). Accepts optional project_id for nested-workspace disambiguation. Returns { summary, task }.', {
|
|
2088
2092
|
type: 'object',
|
|
2089
2093
|
properties: { blueprint: { type: 'string' }, project_id: { type: 'string' } },
|
|
2090
2094
|
}, undefined, (r) => handleTaskNext(projectResolver, cwd, r), { title: 'Blueprint Task Next', readOnlyHint: true, openWorldHint: false });
|
|
2091
|
-
registrar.registerTool('wp_blueprint_task_advance', 'Advance task status. Edits
|
|
2095
|
+
registrar.registerTool('wp_blueprint_task_advance', 'Advance task status. Edits the canonical blueprint markdown and re-syncs DB. Accepts optional request_id for idempotent retries and optional head_at_ingest from wp_blueprint_get/wp_blueprint_list to reject stale writes. Returns { summary, old_status, new_status, idempotent }.', {
|
|
2092
2096
|
type: 'object',
|
|
2093
2097
|
properties: {
|
|
2094
2098
|
project_id: { type: 'string' },
|
|
@@ -2206,7 +2210,7 @@ export async function registerBlueprintTools(registrar, cwd, projectResolver = c
|
|
|
2206
2210
|
},
|
|
2207
2211
|
required: [...summaryEnvelopeOutputSchema.required, 'chunks', 'total_bytes', 'project_id'],
|
|
2208
2212
|
}, (r) => handleBlueprintContext(projectResolver, cwd, r), { title: 'Blueprint Context', readOnlyHint: true, openWorldHint: false });
|
|
2209
|
-
registrar.registerTool('wp_blueprint_create', 'Create a new blueprint markdown under blueprints/draft/<slug>/_overview.md and re-ingest. Accepts optional request_id for idempotent retries and optional head_at_ingest from wp_blueprint_projects/wp_blueprint_list to reject stale writes. Returns { slug, path, next_action, idempotent }.', {
|
|
2213
|
+
registrar.registerTool('wp_blueprint_create', 'Create a new blueprint markdown under blueprints/draft/<slug>.md by default (folder-shaped `<slug>/_overview.md` remains supported elsewhere) and re-ingest. Accepts optional request_id for idempotent retries and optional head_at_ingest from wp_blueprint_projects/wp_blueprint_list to reject stale writes. Returns { slug, path, next_action, idempotent }.', {
|
|
2210
2214
|
type: 'object',
|
|
2211
2215
|
properties: {
|
|
2212
2216
|
project_id: { type: 'string' },
|
package/dist/esm/mcp/cli.js
CHANGED
|
@@ -12,18 +12,26 @@ import { createServer } from './server.js';
|
|
|
12
12
|
export async function runStdioServer() {
|
|
13
13
|
const server = await createServer();
|
|
14
14
|
const transport = new StdioServerTransport();
|
|
15
|
+
const settle = Promise.withResolvers();
|
|
15
16
|
let shuttingDown = false;
|
|
16
17
|
const shutdown = async () => {
|
|
17
18
|
if (shuttingDown)
|
|
18
19
|
return;
|
|
19
20
|
shuttingDown = true;
|
|
20
21
|
deleteSentinel();
|
|
22
|
+
try {
|
|
23
|
+
await transport.close();
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
/* ignore transport close errors during shutdown */
|
|
27
|
+
}
|
|
21
28
|
try {
|
|
22
29
|
await server.close();
|
|
23
30
|
}
|
|
24
31
|
catch {
|
|
25
32
|
/* ignore close errors during shutdown */
|
|
26
33
|
}
|
|
34
|
+
settle.resolve();
|
|
27
35
|
};
|
|
28
36
|
process.on('SIGINT', () => {
|
|
29
37
|
void shutdown().then(() => process.exit(0));
|
|
@@ -31,8 +39,21 @@ export async function runStdioServer() {
|
|
|
31
39
|
process.on('SIGTERM', () => {
|
|
32
40
|
void shutdown().then(() => process.exit(0));
|
|
33
41
|
});
|
|
42
|
+
process.stdin.on('end', () => {
|
|
43
|
+
void shutdown();
|
|
44
|
+
});
|
|
45
|
+
process.stdin.on('close', () => {
|
|
46
|
+
void shutdown();
|
|
47
|
+
});
|
|
48
|
+
transport.onclose = () => {
|
|
49
|
+
void shutdown();
|
|
50
|
+
};
|
|
51
|
+
transport.onerror = () => {
|
|
52
|
+
void shutdown();
|
|
53
|
+
};
|
|
34
54
|
await server.connect(transport);
|
|
35
55
|
writeSentinel();
|
|
56
|
+
await settle.promise;
|
|
36
57
|
}
|
|
37
58
|
import { realpathSync } from 'node:fs';
|
|
38
59
|
import { fileURLToPath } from 'node:url';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { globSync } from 'glob';
|
|
4
|
+
import { getPackageScript, isRecursiveWpScript, packageUsesVitest } from '#cli/package-scripts.js';
|
|
4
5
|
import { isRunFailure, runCommand as runSharedCommand } from '#mcp/tools/_shared/run-command';
|
|
5
6
|
// Keep the runner's own deadline comfortably below common MCP client call
|
|
6
7
|
// ceilings so slow suites fail fast with a structured `timedOut` payload
|
|
@@ -55,6 +56,14 @@ export async function runTests(input) {
|
|
|
55
56
|
if (workspaceShardRuns && workspaceShardRuns.length > 0) {
|
|
56
57
|
return runScopedSequence(cwd, workspaceShardRuns, input, workspaceSharding);
|
|
57
58
|
}
|
|
59
|
+
if (shouldBypassWorkspaceTestScript(cwd)) {
|
|
60
|
+
const result = await runCommand('vp', ['exec', '--', 'vitest', 'run', '--reporter=json', '--no-color'], {
|
|
61
|
+
...input,
|
|
62
|
+
cwd,
|
|
63
|
+
timeoutMs: commandTimeoutMs,
|
|
64
|
+
});
|
|
65
|
+
return withFailureScope(result, 'workspace vitest command');
|
|
66
|
+
}
|
|
58
67
|
const result = await runCommand('vp', ['run', 'test'], {
|
|
59
68
|
...input,
|
|
60
69
|
cwd,
|
|
@@ -222,6 +231,12 @@ function hasRootVitestTestScript(cwd) {
|
|
|
222
231
|
const testScript = scripts.test;
|
|
223
232
|
return typeof testScript === 'string' && /\bvitest\b/.test(testScript);
|
|
224
233
|
}
|
|
234
|
+
function shouldBypassWorkspaceTestScript(cwd) {
|
|
235
|
+
const testScript = getPackageScript(cwd, 'test');
|
|
236
|
+
if (!testScript || !isRecursiveWpScript(testScript, 'test'))
|
|
237
|
+
return false;
|
|
238
|
+
return packageUsesVitest(cwd);
|
|
239
|
+
}
|
|
225
240
|
function discoverVitestFiles(cwd) {
|
|
226
241
|
return globSync(VITEST_DEFAULT_INCLUDE, {
|
|
227
242
|
cwd,
|
package/dist/esm/mcp/server.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* — no edits required here.
|
|
8
8
|
*/
|
|
9
9
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
|
+
export type ToolLoadMode = 'filesystem' | 'registry';
|
|
10
11
|
export interface CreateServerOptions {
|
|
11
12
|
/**
|
|
12
13
|
* Directory to scan for tool descriptors. Defaults to `./tools` relative to
|
|
@@ -14,6 +15,12 @@ export interface CreateServerOptions {
|
|
|
14
15
|
* `vp run build`.
|
|
15
16
|
*/
|
|
16
17
|
toolsDir?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Tool loading strategy. Use `registry` for compiled runtime execution where
|
|
20
|
+
* runtime directory scans are unsafe, and `filesystem` for dev/test disk
|
|
21
|
+
* discovery.
|
|
22
|
+
*/
|
|
23
|
+
toolLoadMode?: ToolLoadMode;
|
|
17
24
|
/**
|
|
18
25
|
* Repo working directory passed through to the blueprint structured-store
|
|
19
26
|
* registrar (Task 2.1). Defaults to `process.cwd()`. Tests inject a tmpdir.
|
package/dist/esm/mcp/server.js
CHANGED
|
@@ -8,42 +8,25 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
10
|
import { CallToolRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, RootsListChangedNotificationSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
12
11
|
import { dirname, join } from 'node:path';
|
|
13
12
|
import { fileURLToPath } from 'node:url';
|
|
14
|
-
import { discoverTools, } from './auto-discover.js';
|
|
13
|
+
import { discoverTools, registerToolDescriptors, } from './auto-discover.js';
|
|
15
14
|
import { registerBlueprintServer } from './blueprint-server.js';
|
|
15
|
+
import { COMPILED_TOOL_REGISTRY } from './tools/_registry.js';
|
|
16
|
+
import { readOwnedPackageVersion } from '#runtime/package-version.js';
|
|
16
17
|
const SERVER_NAME = 'webpresso';
|
|
17
|
-
|
|
18
|
-
// for both src/mcp/server.ts (dev) and dist/esm/mcp/server.js (built) without
|
|
19
|
-
// hardcoding asymmetric `../../..` counts.
|
|
20
|
-
const MAX_UPWARD_LEVELS = 8;
|
|
21
|
-
function readPackageVersion() {
|
|
22
|
-
let dir = dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
for (let i = 0; i < MAX_UPWARD_LEVELS; i++) {
|
|
24
|
-
const candidate = join(dir, 'package.json');
|
|
25
|
-
if (existsSync(candidate)) {
|
|
26
|
-
const pkg = JSON.parse(readFileSync(candidate, 'utf-8'));
|
|
27
|
-
// Some build outputs emit a marker `package.json` (e.g. `{ "type": "module" }`)
|
|
28
|
-
// without a version. Skip those and keep walking so we land on the real
|
|
29
|
-
// package root, instead of throwing the moment we see any package.json.
|
|
30
|
-
if (typeof pkg.version === 'string' && pkg.version.length > 0)
|
|
31
|
-
return pkg.version;
|
|
32
|
-
}
|
|
33
|
-
const parent = dirname(dir);
|
|
34
|
-
if (parent === dir)
|
|
35
|
-
break;
|
|
36
|
-
dir = parent;
|
|
37
|
-
}
|
|
38
|
-
throw new Error('Cannot locate a versioned package.json relative to webpresso MCP server module');
|
|
39
|
-
}
|
|
40
|
-
const SERVER_VERSION = readPackageVersion();
|
|
18
|
+
const SERVER_VERSION = readOwnedPackageVersion(import.meta.url);
|
|
41
19
|
function defaultToolsDir() {
|
|
42
20
|
// import.meta.url resolves to either src/mcp/server.ts (dev/test via vitest)
|
|
43
21
|
// or dist/esm/mcp/server.js (built). The tools directory is colocated.
|
|
44
22
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
45
23
|
return join(here, 'tools');
|
|
46
24
|
}
|
|
25
|
+
function resolveDefaultToolLoadMode() {
|
|
26
|
+
return process.env.WP_MCP_TOOL_MODE === 'registry' || process.env.WP_COMPILED_RUNTIME === '1'
|
|
27
|
+
? 'registry'
|
|
28
|
+
: 'filesystem';
|
|
29
|
+
}
|
|
47
30
|
export async function createServer(options = {}) {
|
|
48
31
|
const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, {
|
|
49
32
|
capabilities: {
|
|
@@ -60,7 +43,13 @@ export async function createServer(options = {}) {
|
|
|
60
43
|
tools.set(name, { name, description, inputSchema, outputSchema, handler, annotations });
|
|
61
44
|
},
|
|
62
45
|
};
|
|
63
|
-
|
|
46
|
+
const toolLoadMode = options.toolLoadMode ?? resolveDefaultToolLoadMode();
|
|
47
|
+
if (toolLoadMode === 'registry') {
|
|
48
|
+
registerToolDescriptors(registrar, COMPILED_TOOL_REGISTRY);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
await discoverTools(registrar, options.toolsDir ?? defaultToolsDir());
|
|
52
|
+
}
|
|
64
53
|
// Task 2.1: register the blueprint structured-store tools AFTER auto-discover
|
|
65
54
|
// so any tool-name collision surfaces here as a thrown error rather than
|
|
66
55
|
// silent shadowing. Roots are looked up lazily via `server.listRoots()`; the
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import audit from './audit.js';
|
|
2
|
+
import ciAct from './ci-act.js';
|
|
3
|
+
import e2e from './e2e.js';
|
|
4
|
+
import format from './format.js';
|
|
5
|
+
import lint from './lint.js';
|
|
6
|
+
import qa from './qa.js';
|
|
7
|
+
import test from './test.js';
|
|
8
|
+
import typecheck from './typecheck.js';
|
|
9
|
+
import workerTail from './worker-tail.js';
|
|
10
|
+
export const COMPILED_TOOL_REGISTRY = [
|
|
11
|
+
audit,
|
|
12
|
+
ciAct,
|
|
13
|
+
e2e,
|
|
14
|
+
format,
|
|
15
|
+
lint,
|
|
16
|
+
qa,
|
|
17
|
+
test,
|
|
18
|
+
typecheck,
|
|
19
|
+
workerTail,
|
|
20
|
+
];
|
|
21
|
+
//# sourceMappingURL=_registry.js.map
|
|
@@ -32,6 +32,7 @@ declare const inputSchema: z.ZodObject<{
|
|
|
32
32
|
"catalog-drift": "catalog-drift";
|
|
33
33
|
"package-surface": "package-surface";
|
|
34
34
|
"architecture-drift": "architecture-drift";
|
|
35
|
+
"cloudflare-deploy-contract": "cloudflare-deploy-contract";
|
|
35
36
|
"absolute-path-policy": "absolute-path-policy";
|
|
36
37
|
"ai-contracts": "ai-contracts";
|
|
37
38
|
}>;
|
|
@@ -28,6 +28,7 @@ const KINDS = [
|
|
|
28
28
|
'docs-frontmatter',
|
|
29
29
|
'blueprint-lifecycle',
|
|
30
30
|
'architecture-drift',
|
|
31
|
+
'cloudflare-deploy-contract',
|
|
31
32
|
'absolute-path-policy',
|
|
32
33
|
'roadmap-links',
|
|
33
34
|
'bundle-budget',
|
|
@@ -155,6 +156,16 @@ async function dispatch(input) {
|
|
|
155
156
|
details: auditResult,
|
|
156
157
|
};
|
|
157
158
|
}
|
|
159
|
+
case 'cloudflare-deploy-contract': {
|
|
160
|
+
const { auditCloudflareDeployContract } = await import('#audit/cloudflare-deploy-contract');
|
|
161
|
+
const auditResult = await auditCloudflareDeployContract(input.cwd ?? input.directory ?? process.cwd());
|
|
162
|
+
return {
|
|
163
|
+
passed: auditResult.ok,
|
|
164
|
+
summary: summarizeRepoAudit(kind, auditResult),
|
|
165
|
+
kind,
|
|
166
|
+
details: auditResult,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
158
169
|
case 'absolute-path-policy': {
|
|
159
170
|
const { auditAbsolutePathPolicy } = await import('#audit/absolute-path-policy');
|
|
160
171
|
const auditResult = auditAbsolutePathPolicy(input.cwd ?? input.directory ?? process.cwd());
|
|
@@ -12,8 +12,8 @@ declare const inputSchema: z.ZodObject<{
|
|
|
12
12
|
suite: z.ZodOptional<z.ZodString>;
|
|
13
13
|
runner: z.ZodOptional<z.ZodEnum<{
|
|
14
14
|
command: "command";
|
|
15
|
-
vitest: "vitest";
|
|
16
15
|
playwright: "playwright";
|
|
16
|
+
vitest: "vitest";
|
|
17
17
|
}>>;
|
|
18
18
|
config: z.ZodOptional<z.ZodString>;
|
|
19
19
|
files: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
@@ -14,6 +14,7 @@ import { join } from 'node:path';
|
|
|
14
14
|
import { globSync } from 'glob';
|
|
15
15
|
import { z } from 'zod';
|
|
16
16
|
import { applyOutputTransform } from '#output-transforms/index';
|
|
17
|
+
import { getManagedRunner } from '#tool-runtime';
|
|
17
18
|
import { resolveProjectRoot } from './_shared/project-root.js';
|
|
18
19
|
import { createSummaryOutputSchema, createSummaryResult } from './_shared/result.js';
|
|
19
20
|
import { isRunFailure, runCommand } from './_shared/run-command.js';
|
|
@@ -143,11 +144,12 @@ const tool = {
|
|
|
143
144
|
// current resolution treats each entry as a relative path either way.
|
|
144
145
|
const workspaceGlobs = targets ? readWorkspaceGlobs(cwd) : null;
|
|
145
146
|
const runs = [];
|
|
147
|
+
const resolution = getManagedRunner('tsc', { outputPolicy: 'structured' });
|
|
146
148
|
if (targets) {
|
|
147
149
|
for (const pkg of targets) {
|
|
148
150
|
const resolvedTarget = resolveTypecheckTarget(cwd, pkg, workspaceGlobs);
|
|
149
151
|
const tsconfig = join(resolvedTarget, 'tsconfig.json');
|
|
150
|
-
const outcome = await runCommand(
|
|
152
|
+
const outcome = await runCommand(resolution.command, [...resolution.args, '--noEmit', '-p', tsconfig], runOptions);
|
|
151
153
|
if (isRunFailure(outcome)) {
|
|
152
154
|
throw outcome.error;
|
|
153
155
|
}
|
|
@@ -155,7 +157,7 @@ const tool = {
|
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
159
|
else {
|
|
158
|
-
const outcome = await runCommand(
|
|
160
|
+
const outcome = await runCommand(resolution.command, [...resolution.args, '--noEmit'], runOptions);
|
|
159
161
|
if (isRunFailure(outcome)) {
|
|
160
162
|
throw outcome.error;
|
|
161
163
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Stryker only on packages changed vs. the base branch.
|
|
3
|
+
* Returns 0 on success, 1 if any package fails its break threshold.
|
|
4
|
+
*
|
|
5
|
+
* Reads GITHUB_BASE_REF (set by GitHub Actions on pull_request events) to
|
|
6
|
+
* determine the base branch; falls back to "main".
|
|
7
|
+
*/
|
|
8
|
+
export declare function runAffectedMutation(): 0 | 1;
|
|
9
|
+
//# sourceMappingURL=affected.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Run Stryker only on packages changed vs. the base branch.
|
|
4
|
+
* Returns 0 on success, 1 if any package fails its break threshold.
|
|
5
|
+
*
|
|
6
|
+
* Reads GITHUB_BASE_REF (set by GitHub Actions on pull_request events) to
|
|
7
|
+
* determine the base branch; falls back to "main".
|
|
8
|
+
*/
|
|
9
|
+
export function runAffectedMutation() {
|
|
10
|
+
const base = process.env.GITHUB_BASE_REF ?? 'main';
|
|
11
|
+
const changed = execSync(`git diff --name-only origin/${base}...HEAD`)
|
|
12
|
+
.toString()
|
|
13
|
+
.trim()
|
|
14
|
+
.split('\n')
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
const affectedPkgs = new Set();
|
|
17
|
+
for (const file of changed) {
|
|
18
|
+
const match = file.match(/^(apps\/[^/]+|packages\/[^/]+)\//);
|
|
19
|
+
if (match)
|
|
20
|
+
affectedPkgs.add(match[1]);
|
|
21
|
+
}
|
|
22
|
+
if (affectedPkgs.size === 0) {
|
|
23
|
+
console.log('No affected packages — skipping mutation.');
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
for (const pkg of affectedPkgs) {
|
|
27
|
+
try {
|
|
28
|
+
execSync(`pnpm --filter ./${pkg} mutation --if-present`, { stdio: 'inherit' });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=affected.js.map
|
package/dist/esm/package.json
CHANGED
|
@@ -51,6 +51,11 @@
|
|
|
51
51
|
"#tool-runtime": "./tool-runtime/index.js",
|
|
52
52
|
"#tool-runtime/*.js": "./tool-runtime/*.js",
|
|
53
53
|
"#tool-runtime/*": "./tool-runtime/*.js",
|
|
54
|
+
"#wp-extension": "./wp-extension/index.js",
|
|
55
|
+
"#wp-extension/*.js": "./wp-extension/*.js",
|
|
56
|
+
"#wp-extension/*": "./wp-extension/*.js",
|
|
57
|
+
"#runtime/*.js": "./runtime/*.js",
|
|
58
|
+
"#runtime/*": "./runtime/*.js",
|
|
54
59
|
"#output-transforms/*.js": "./output-transforms/*.js",
|
|
55
60
|
"#output-transforms/*": "./output-transforms/*.js",
|
|
56
61
|
"#lint/*.js": "./lint/*.js",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const ACCEPTED_PACKAGE_PREFIXES = ['@webpresso/agent-kit', 'webpresso'];
|
|
5
|
+
const MAX_UPWARD_LEVELS = 8;
|
|
6
|
+
function matchesOwnedPackageName(name) {
|
|
7
|
+
return (typeof name === 'string' &&
|
|
8
|
+
ACCEPTED_PACKAGE_PREFIXES.some((prefix) => name === prefix || name.startsWith(`${prefix}-`)));
|
|
9
|
+
}
|
|
10
|
+
function readVersionFromDir(startDir) {
|
|
11
|
+
let dir = path.resolve(startDir);
|
|
12
|
+
for (let i = 0; i < MAX_UPWARD_LEVELS; i++) {
|
|
13
|
+
const candidate = path.join(dir, 'package.json');
|
|
14
|
+
if (existsSync(candidate)) {
|
|
15
|
+
try {
|
|
16
|
+
const parsed = JSON.parse(readFileSync(candidate, 'utf8'));
|
|
17
|
+
if (matchesOwnedPackageName(parsed.name) && typeof parsed.version === 'string') {
|
|
18
|
+
return parsed.version;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// keep walking
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const parent = path.dirname(dir);
|
|
26
|
+
if (parent === dir)
|
|
27
|
+
break;
|
|
28
|
+
dir = parent;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
export function readOwnedPackageVersion(moduleUrl) {
|
|
33
|
+
const fromModule = readVersionFromDir(path.dirname(fileURLToPath(moduleUrl)));
|
|
34
|
+
if (fromModule)
|
|
35
|
+
return fromModule;
|
|
36
|
+
if (process.execPath) {
|
|
37
|
+
const fromExec = readVersionFromDir(path.dirname(process.execPath));
|
|
38
|
+
if (fromExec)
|
|
39
|
+
return fromExec;
|
|
40
|
+
}
|
|
41
|
+
return '0.0.0';
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResolvedTestTarget } from './target-resolver.js';
|
|
2
|
+
import { type ManagedRunnerOutputPolicy } from '#tool-runtime';
|
|
2
3
|
export interface CommandConfig {
|
|
3
4
|
command: string;
|
|
4
5
|
args: string[];
|
|
@@ -6,6 +7,7 @@ export interface CommandConfig {
|
|
|
6
7
|
}
|
|
7
8
|
export type VpRunLogMode = 'interleaved' | 'labeled' | 'grouped';
|
|
8
9
|
export interface TestCommandOptions {
|
|
10
|
+
cwd?: string;
|
|
9
11
|
watch?: boolean;
|
|
10
12
|
coverage?: boolean;
|
|
11
13
|
testNamePattern?: string;
|
|
@@ -18,6 +20,7 @@ export interface TestCommandOptions {
|
|
|
18
20
|
log?: VpRunLogMode;
|
|
19
21
|
passthrough?: readonly string[];
|
|
20
22
|
filterOutput?: boolean;
|
|
23
|
+
outputPolicy?: ManagedRunnerOutputPolicy;
|
|
21
24
|
}
|
|
22
25
|
export declare function buildTestCommand(target: ResolvedTestTarget, options?: TestCommandOptions): CommandConfig;
|
|
23
26
|
export declare function buildVpTestCommand(filters: readonly string[], options?: TestCommandOptions): CommandConfig;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { getManagedRunner } from '#tool-runtime';
|
|
2
|
+
import { getPackageScript, isRecursiveWpScript, packageUsesVitest } from '#cli/package-scripts.js';
|
|
2
3
|
export function buildTestCommand(target, options = {}) {
|
|
4
|
+
if (target.type === 'all' && shouldBypassRecursiveWpTest(options.cwd ?? process.cwd())) {
|
|
5
|
+
return buildVitestCommand([], options);
|
|
6
|
+
}
|
|
3
7
|
if (target.type === 'file') {
|
|
4
8
|
return buildVitestCommand(target.values, options);
|
|
5
9
|
}
|
|
@@ -8,7 +12,7 @@ export function buildTestCommand(target, options = {}) {
|
|
|
8
12
|
export function buildVpTestCommand(filters, options = {}) {
|
|
9
13
|
const task = getVpTestTask(options);
|
|
10
14
|
const resolvedFilters = filters.map((filter) => formatVpRunFilter(filter, task));
|
|
11
|
-
const explicitTargets = resolvedFilters.every(isExplicitVpTaskTarget);
|
|
15
|
+
const explicitTargets = resolvedFilters.length > 0 && resolvedFilters.every(isExplicitVpTaskTarget);
|
|
12
16
|
const args = ['run', ...resolvedFilters];
|
|
13
17
|
appendVpRunOptions(args, options);
|
|
14
18
|
if (!explicitTargets) {
|
|
@@ -18,7 +22,9 @@ export function buildVpTestCommand(filters, options = {}) {
|
|
|
18
22
|
if (passthrough.length > 0) {
|
|
19
23
|
args.push('--', ...passthrough);
|
|
20
24
|
}
|
|
21
|
-
const resolution = getManagedRunner('vp', {
|
|
25
|
+
const resolution = getManagedRunner('vp', {
|
|
26
|
+
outputPolicy: resolveOutputPolicy(options.outputPolicy, options.filterOutput),
|
|
27
|
+
});
|
|
22
28
|
const env = buildVpRunEnv(options);
|
|
23
29
|
const mergedArgs = [...resolution.args, ...args];
|
|
24
30
|
return env
|
|
@@ -45,7 +51,9 @@ export function buildVitestCommand(files, options = {}) {
|
|
|
45
51
|
args.push('--config', configFile);
|
|
46
52
|
}
|
|
47
53
|
args.push(...buildVitestPassthrough(options), ...testFiles);
|
|
48
|
-
const resolution = getManagedRunner('vitest', {
|
|
54
|
+
const resolution = getManagedRunner('vitest', {
|
|
55
|
+
outputPolicy: resolveOutputPolicy(options.outputPolicy, options.filterOutput),
|
|
56
|
+
});
|
|
49
57
|
return { command: resolution.command, args: [...resolution.args, ...args] };
|
|
50
58
|
}
|
|
51
59
|
export function getVpTestTask(options) {
|
|
@@ -101,4 +109,15 @@ function buildVitestPassthrough(options) {
|
|
|
101
109
|
function isVitestConfigFile(file) {
|
|
102
110
|
return /^vitest(?:\.[\w-]+)?\.config\.(?:ts|mts|cts|js|mjs|cjs)$/u.test(file);
|
|
103
111
|
}
|
|
112
|
+
function resolveOutputPolicy(outputPolicy, filterOutput) {
|
|
113
|
+
if (outputPolicy)
|
|
114
|
+
return outputPolicy;
|
|
115
|
+
return filterOutput === false ? 'structured' : 'rtk-filtered';
|
|
116
|
+
}
|
|
117
|
+
function shouldBypassRecursiveWpTest(cwd) {
|
|
118
|
+
const testScript = getPackageScript(cwd, 'test');
|
|
119
|
+
if (!testScript || !isRecursiveWpScript(testScript, 'test'))
|
|
120
|
+
return false;
|
|
121
|
+
return packageUsesVitest(cwd);
|
|
122
|
+
}
|
|
104
123
|
//# sourceMappingURL=command-builder.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ManagedRunnerResolution, type ResolveRunnerOptions } from './resolve-runner.js';
|
|
1
|
+
import { type ManagedRunnerResolution, type ResolveRunnerOptions, type ManagedRunnerOutputPolicy } from './resolve-runner.js';
|
|
2
2
|
export declare function getManagedRunner(tool: string, options?: ResolveRunnerOptions): ManagedRunnerResolution;
|
|
3
3
|
export declare function clearManagedRunnerCache(): void;
|
|
4
|
-
export type { ManagedRunnerResolution, ResolveRunnerOptions };
|
|
4
|
+
export type { ManagedRunnerOutputPolicy, ManagedRunnerResolution, ResolveRunnerOptions };
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|