@webpresso/agent-kit 0.21.3 → 0.21.5

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 (99) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +105 -41
  4. package/catalog/AGENTS.md.tpl +3 -1
  5. package/catalog/agent/rules/changeset-release.md +13 -16
  6. package/catalog/agent/skills/plan-refine/SKILL.md +5 -4
  7. package/catalog/base-kit/commitlint.config.ts.tmpl +1 -3
  8. package/catalog/base-kit/e2e/fixtures/smoke.html.tmpl +13 -0
  9. package/catalog/base-kit/e2e/smoke.spec.ts.tmpl +13 -0
  10. package/catalog/base-kit/oxlint.config.ts.tmpl +26 -0
  11. package/catalog/base-kit/playwright.config.ts.tmpl +10 -0
  12. package/catalog/base-kit/src/quality-sample.test.ts.tmpl +19 -0
  13. package/catalog/base-kit/src/quality-sample.ts.tmpl +11 -0
  14. package/catalog/base-kit/stryker.config.ts.tmpl +14 -0
  15. package/catalog/base-kit/tsconfig.json.tmpl +9 -0
  16. package/catalog/base-kit/vitest.config.ts.tmpl +10 -0
  17. package/catalog/docs/templates/adr.md +1 -1
  18. package/catalog/docs/templates/blueprint.md +1 -0
  19. package/catalog/docs/templates/blueprint.yaml +6 -3
  20. package/catalog/docs/templates/guide.md +1 -1
  21. package/catalog/docs/templates/postmortem.md +1 -1
  22. package/catalog/docs/templates/research.md +1 -1
  23. package/catalog/docs/templates/runbook.md +1 -1
  24. package/catalog/docs/templates/system.md +12 -3
  25. package/catalog/docs/templates/tech-debt.md +1 -0
  26. package/commands/blueprint.md +37 -4
  27. package/dist/esm/audit/resolve-audit-script.d.ts +24 -0
  28. package/dist/esm/audit/resolve-audit-script.js +27 -0
  29. package/dist/esm/blueprint/db/enums.d.ts +1 -1
  30. package/dist/esm/blueprint/index.d.ts +0 -1
  31. package/dist/esm/blueprint/index.js +0 -2
  32. package/dist/esm/blueprint/local.d.ts +0 -3
  33. package/dist/esm/blueprint/local.js +0 -2
  34. package/dist/esm/blueprint/service/BlueprintCreationService.js +5 -2
  35. package/dist/esm/blueprint/utils/package-assets.d.ts +11 -0
  36. package/dist/esm/blueprint/utils/package-assets.js +33 -4
  37. package/dist/esm/build/sync-catalog-doc-templates.d.ts +23 -0
  38. package/dist/esm/build/sync-catalog-doc-templates.js +93 -0
  39. package/dist/esm/cli/commands/audit.js +2 -7
  40. package/dist/esm/cli/commands/blueprint/router.js +5 -2
  41. package/dist/esm/cli/commands/blueprint/template-resolver.js +8 -4
  42. package/dist/esm/cli/commands/init/host-visibility.js +4 -2
  43. package/dist/esm/cli/commands/init/index.js +46 -7
  44. package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +12 -0
  45. package/dist/esm/cli/commands/init/scaffold-base-kit.js +141 -6
  46. package/dist/esm/cli/commands/typecheck.js +10 -4
  47. package/dist/esm/e2e/command-builder.js +26 -7
  48. package/dist/esm/e2e/execution.js +4 -0
  49. package/dist/esm/e2e/run-planner.js +1 -0
  50. package/dist/esm/e2e/types.d.ts +1 -0
  51. package/dist/esm/format/index.js +7 -1
  52. package/dist/esm/lint/index.js +3 -1
  53. package/dist/esm/mcp/blueprint-server.js +361 -66
  54. package/dist/esm/mcp/tools/audit.js +2 -8
  55. package/dist/esm/mcp/tools/e2e.d.ts +1 -1
  56. package/dist/esm/package.json +3 -0
  57. package/dist/esm/secret-gate/runner.js +4 -0
  58. package/dist/esm/test/command-builder.d.ts +1 -0
  59. package/dist/esm/test/command-builder.js +8 -2
  60. package/dist/esm/test-helpers/hermetic-env.d.ts +25 -0
  61. package/dist/esm/test-helpers/hermetic-env.js +31 -0
  62. package/dist/esm/tool-runtime/index.d.ts +5 -0
  63. package/dist/esm/tool-runtime/index.js +23 -0
  64. package/dist/esm/tool-runtime/resolve-runner.d.ts +13 -0
  65. package/dist/esm/tool-runtime/resolve-runner.js +40 -0
  66. package/package.json +12 -18
  67. package/skills/plan-refine/SKILL.md +5 -4
  68. package/dist/esm/blueprint/dag/cycle-detector.d.ts +0 -12
  69. package/dist/esm/blueprint/dag/cycle-detector.js +0 -46
  70. package/dist/esm/blueprint/dag/executor.d.ts +0 -140
  71. package/dist/esm/blueprint/dag/executor.js +0 -292
  72. package/dist/esm/blueprint/dag/index.d.ts +0 -20
  73. package/dist/esm/blueprint/dag/index.js +0 -17
  74. package/dist/esm/blueprint/dag/interfaces.d.ts +0 -56
  75. package/dist/esm/blueprint/dag/interfaces.js +0 -13
  76. package/dist/esm/blueprint/dag/local/independence.d.ts +0 -107
  77. package/dist/esm/blueprint/dag/local/independence.js +0 -231
  78. package/dist/esm/blueprint/dag/local/index.d.ts +0 -14
  79. package/dist/esm/blueprint/dag/local/index.js +0 -14
  80. package/dist/esm/blueprint/dag/local/package-graph.d.ts +0 -66
  81. package/dist/esm/blueprint/dag/local/package-graph.js +0 -148
  82. package/dist/esm/blueprint/dag/plan-parser.d.ts +0 -54
  83. package/dist/esm/blueprint/dag/plan-parser.js +0 -236
  84. package/dist/esm/blueprint/dag/task-graph-algorithms.d.ts +0 -13
  85. package/dist/esm/blueprint/dag/task-graph-algorithms.js +0 -236
  86. package/dist/esm/blueprint/dag/task-graph.d.ts +0 -171
  87. package/dist/esm/blueprint/dag/task-graph.js +0 -370
  88. package/dist/esm/blueprint/dag/types.d.ts +0 -17
  89. package/dist/esm/blueprint/dag/types.js +0 -2
  90. package/dist/esm/blueprint/graph/index.d.ts +0 -5
  91. package/dist/esm/blueprint/graph/index.js +0 -5
  92. package/dist/esm/blueprint/graph/mermaid-parser.d.ts +0 -3
  93. package/dist/esm/blueprint/graph/mermaid-parser.js +0 -93
  94. package/dist/esm/blueprint/graph/mermaid-serializer.d.ts +0 -3
  95. package/dist/esm/blueprint/graph/mermaid-serializer.js +0 -20
  96. package/dist/esm/blueprint/graph/schema.d.ts +0 -89
  97. package/dist/esm/blueprint/graph/schema.js +0 -104
  98. package/dist/esm/blueprint/graph/task-graph-adapter.d.ts +0 -6
  99. package/dist/esm/blueprint/graph/task-graph-adapter.js +0 -30
@@ -0,0 +1,27 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ /**
4
+ * Resolve the absolute path of a Bun audit script (`audit-tph.ts`,
5
+ * `audit-tph-e2e.ts`) living in the sibling `audit/` directory two levels up
6
+ * from the caller.
7
+ *
8
+ * `../../audit/` is correct relative to the caller in BOTH layouts:
9
+ * - dev: `src/{cli,mcp}/.../audit.ts` → `src/audit/`
10
+ * - published: `dist/esm/{cli,mcp}/.../audit.js` → `dist/esm/audit/`
11
+ *
12
+ * The npm tarball ships only `dist/` (never `src/`), so the dev `.ts` source is
13
+ * absent there — fall back to the compiled `.js` sibling the build emits. The
14
+ * previous CLI resolver instead hand-rolled a `<bundle>/src/audit/<name>.ts`
15
+ * path that does not exist in dist, which made `bun` fail with
16
+ * "Module not found"; the MCP twin reached for the unshipped `src/audit/` via
17
+ * `resolvePackageAsset` and failed the same way.
18
+ */
19
+ export function resolveAuditScriptPath(name, { moduleUrl, exists = existsSync }) {
20
+ const sourceUrl = new URL(`../../audit/${name}`, moduleUrl);
21
+ if (exists(sourceUrl)) {
22
+ return fileURLToPath(sourceUrl);
23
+ }
24
+ const compiledUrl = new URL(`../../audit/${name.replace(/\.ts$/, '.js')}`, moduleUrl);
25
+ return fileURLToPath(compiledUrl);
26
+ }
27
+ //# sourceMappingURL=resolve-audit-script.js.map
@@ -65,8 +65,8 @@ export declare const reviewCadenceSchema: z.ZodEnum<{
65
65
  quarterly: "quarterly";
66
66
  }>;
67
67
  export declare const visibilitySchema: z.ZodEnum<{
68
- private: "private";
69
68
  public: "public";
69
+ private: "private";
70
70
  }>;
71
71
  export declare const taskFileOpSchema: z.ZodEnum<{
72
72
  create: "create";
@@ -16,7 +16,6 @@ export { validatePlanTemplate } from './core/validation/template.js';
16
16
  export { type BlueprintDiff, type DiffChange, type DiffFieldChange, formatDiffForDisplay, generateBlueprintDiff, } from './history/diff.js';
17
17
  export { checkAllCheckboxes, checkFirstCheckbox, extractCodeBlocks, extractTaskSection, updateBlockedReason, updateTaskStatus, } from './markdown/helpers.js';
18
18
  export { applyBlueprintLifecycle, type BlueprintLifecycleIntent, type BlueprintLifecycleResult, type LifecycleTaskStatus, } from './lifecycle/engine.js';
19
- export { type GraphEdge, type GraphEdgeType, type GraphLayout, type GraphNode, type GraphNodeType, type NormalizedGraph, parseMermaidToGraph, serializeGraphToMermaid, taskGraphToNormalizedGraph, } from './graph/index.js';
20
19
  export type { BlueprintQueryFilters, BlueprintQueryResult, BlueprintQuerySummary, BlueprintRecord, BlueprintSortField, BlueprintSortOptions, Complexity, SortDirection, TaskStatus, } from './query/types.js';
21
20
  export { isBlueprintStatus, isComplexity, isTaskStatus } from './query/types.js';
22
21
  export { BlueprintNotFoundError } from './utils/errors.js';
@@ -17,8 +17,6 @@ export { formatDiffForDisplay, generateBlueprintDiff, } from './history/diff.js'
17
17
  // Markdown helpers (pure functions)
18
18
  export { checkAllCheckboxes, checkFirstCheckbox, extractCodeBlocks, extractTaskSection, updateBlockedReason, updateTaskStatus, } from './markdown/helpers.js';
19
19
  export { applyBlueprintLifecycle, } from './lifecycle/engine.js';
20
- // Graph model + Mermaid integration
21
- export { parseMermaidToGraph, serializeGraphToMermaid, taskGraphToNormalizedGraph, } from './graph/index.js';
22
20
  export { isBlueprintStatus, isComplexity, isTaskStatus } from './query/types.js';
23
21
  export { BlueprintNotFoundError } from './utils/errors.js';
24
22
  // Evidence Contract (F10) — pin per-kind evidence rules at zod parse time.
@@ -4,9 +4,6 @@
4
4
  * These exports use Node.js APIs (fs, simple-git) and are NOT compatible with Cloudflare Workers.
5
5
  * For Workers-safe functions, use the main 'webpresso/blueprint' entry point.
6
6
  */
7
- export type { FalseDependency, ParallelizeResult, TaskFiles, TaskPairAnalysis, } from './dag/local/independence.js';
8
- export { createMockPackageGraph, IndependenceDetector } from './dag/local/independence.js';
9
- export { createMockFileSystem, PackageGraph, realFileSystem } from './dag/local/package-graph.js';
10
7
  export { type AcceptanceCriteria, type Blueprint, buildRoadmapModel, buildBlueprintProgressBridgeState, type BlueprintStatus, type BlueprintTaskStatus, checkAcceptanceCriteria, checkAllCheckboxes, checkChangelog, checkFirstCheckbox, complexitySchema, type CriteriaResult, extractTaskSection, formatDiffForDisplay, generateBlueprintDiff, isBlueprintStatus, isComplexity, isTaskStatus, lifecycleBlueprintStatusSchema, normalizeOmxTeamTaskSnapshot, type OmxTeamTaskSnapshot, type Phase, parseBlueprint, type PlanComplexity, type PlanFrontmatter, planStatusSchema, projectBlueprintLifecycleFromRuntime, resolveBlueprintProgressBridgePath, type RoadmapModel, type RoadmapNode, type RoadmapRollup, type RoadmapLike, serializeBlueprint, type Task, taskStatusSchema, type TaskStatusValue, updateBlockedReason, updateTaskStatus, type ValidationResult, validateEmbeddedPhases, validatePlanLinks, validatePlanState, validatePlanTemplate, } from './index.js';
11
8
  export { BlueprintCreationService, type BlueprintCreationServiceOptions, type BlueprintDraft, type CreateBlueprintInput, type CreatedBlueprint, } from './service/BlueprintCreationService.js';
12
9
  export { type BlueprintQueryOptions, BlueprintService, type BlueprintSummary, } from './service/BlueprintService.js';
@@ -4,8 +4,6 @@
4
4
  * These exports use Node.js APIs (fs, simple-git) and are NOT compatible with Cloudflare Workers.
5
5
  * For Workers-safe functions, use the main 'webpresso/blueprint' entry point.
6
6
  */
7
- export { createMockPackageGraph, IndependenceDetector } from './dag/local/independence.js';
8
- export { createMockFileSystem, PackageGraph, realFileSystem } from './dag/local/package-graph.js';
9
7
  // Workers-safe exports for convenience (explicit re-export to avoid wildcard)
10
8
  export { buildRoadmapModel, buildBlueprintProgressBridgeState, checkAcceptanceCriteria, checkAllCheckboxes, checkChangelog, checkFirstCheckbox, complexitySchema, extractTaskSection, formatDiffForDisplay, generateBlueprintDiff, isBlueprintStatus, isComplexity, isTaskStatus, lifecycleBlueprintStatusSchema, normalizeOmxTeamTaskSnapshot, parseBlueprint, planStatusSchema, projectBlueprintLifecycleFromRuntime, resolveBlueprintProgressBridgePath, serializeBlueprint, taskStatusSchema, updateBlockedReason, updateTaskStatus, validateEmbeddedPhases, validatePlanLinks, validatePlanState, validatePlanTemplate, } from './index.js';
11
9
  // Services (require filesystem/git)
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import { parseBlueprint } from '#core/parser';
5
5
  import { scanBlueprintDirectory } from '#service/scanner';
6
6
  import { resolveBlueprintRoot } from '#utils/blueprint-root';
7
- import { resolvePackageAsset } from '#utils/package-assets';
7
+ import { resolvePackageAssetPreferred } from '#utils/package-assets';
8
8
  const RESERVED_BLUEPRINT_SLUGS = new Set([
9
9
  'draft',
10
10
  'planned',
@@ -13,7 +13,10 @@ const RESERVED_BLUEPRINT_SLUGS = new Set([
13
13
  'completed',
14
14
  'archived',
15
15
  ]);
16
- const DEFAULT_TEMPLATE_PATH = resolvePackageAsset('docs/templates/blueprint.md');
16
+ const DEFAULT_TEMPLATE_PATH = resolvePackageAssetPreferred([
17
+ 'docs/templates/blueprint.md',
18
+ 'catalog/docs/templates/blueprint.md',
19
+ ]);
17
20
  function formatDate(date) {
18
21
  return date.toISOString().split('T')[0] ?? date.toISOString();
19
22
  }
@@ -3,4 +3,15 @@
3
3
  * package root) is found. Works whether running from src/ or dist/esm/.
4
4
  */
5
5
  export declare function resolvePackageAsset(relativeFromRoot: string): string;
6
+ /**
7
+ * Resolve the first existing candidate, in priority order. Use when an asset
8
+ * lives at one path in the source checkout but a different path in the
9
+ * published tarball — e.g. templates authored under repo-root `docs/templates/`
10
+ * but shipped under `catalog/docs/templates/` because the npm `files` list
11
+ * includes `catalog/` and not `docs/`. Prefers the dev/source location and
12
+ * falls back to the shipped one, mirroring `bin/_run.js`'s source→built path
13
+ * translation. Falls back to cwd-relative on the first candidate when none
14
+ * exist, matching `resolvePackageAsset`'s last-resort behavior.
15
+ */
16
+ export declare function resolvePackageAssetPreferred(candidates: readonly string[]): string;
6
17
  //# sourceMappingURL=package-assets.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  /**
4
- * Walk up from this file's location until the given path (relative to the
5
- * package root) is found. Works whether running from src/ or dist/esm/.
4
+ * Walk up from this file's location looking for `relativeFromRoot`. Returns the
5
+ * first existing match, or `null` if none is found within the ancestor budget.
6
6
  */
7
- export function resolvePackageAsset(relativeFromRoot) {
7
+ function findPackageAsset(relativeFromRoot) {
8
8
  let dir = path.dirname(new URL(import.meta.url).pathname);
9
9
  for (let i = 0; i < 8; i++) {
10
10
  const candidate = path.join(dir, relativeFromRoot);
@@ -15,6 +15,35 @@ export function resolvePackageAsset(relativeFromRoot) {
15
15
  break;
16
16
  dir = parent;
17
17
  }
18
- return path.join(process.cwd(), relativeFromRoot);
18
+ return null;
19
+ }
20
+ /**
21
+ * Walk up from this file's location until the given path (relative to the
22
+ * package root) is found. Works whether running from src/ or dist/esm/.
23
+ */
24
+ export function resolvePackageAsset(relativeFromRoot) {
25
+ return findPackageAsset(relativeFromRoot) ?? path.join(process.cwd(), relativeFromRoot);
26
+ }
27
+ /**
28
+ * Resolve the first existing candidate, in priority order. Use when an asset
29
+ * lives at one path in the source checkout but a different path in the
30
+ * published tarball — e.g. templates authored under repo-root `docs/templates/`
31
+ * but shipped under `catalog/docs/templates/` because the npm `files` list
32
+ * includes `catalog/` and not `docs/`. Prefers the dev/source location and
33
+ * falls back to the shipped one, mirroring `bin/_run.js`'s source→built path
34
+ * translation. Falls back to cwd-relative on the first candidate when none
35
+ * exist, matching `resolvePackageAsset`'s last-resort behavior.
36
+ */
37
+ export function resolvePackageAssetPreferred(candidates) {
38
+ for (const relativeFromRoot of candidates) {
39
+ const found = findPackageAsset(relativeFromRoot);
40
+ if (found)
41
+ return found;
42
+ }
43
+ const primary = candidates[0];
44
+ if (primary === undefined) {
45
+ throw new Error('resolvePackageAssetPreferred requires at least one candidate path');
46
+ }
47
+ return path.join(process.cwd(), primary);
19
48
  }
20
49
  //# sourceMappingURL=package-assets.js.map
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * sync-catalog-doc-templates.ts
4
+ *
5
+ * `docs/templates/` (repo root) is the editable source of truth for the
6
+ * blueprint / doc templates. `catalog/docs/templates/` is the published +
7
+ * scaffolded mirror: the npm `files` list ships `catalog/` but NOT repo-root
8
+ * `docs/` (which holds internal docs that must stay private), and `wp init`
9
+ * scaffolds templates into a consumer from `catalog/docs/templates/`.
10
+ *
11
+ * The two MUST stay byte-identical. Nothing synced them before, so they
12
+ * drifted — this script regenerates the mirror from the source and is wired
13
+ * into the build. The colocated drift test fails CI if they ever diverge.
14
+ *
15
+ * Default: regenerate the mirror from the source.
16
+ * `--check`: exit non-zero and list drift without writing (CI / pre-publish).
17
+ */
18
+ /**
19
+ * Names that are out of sync between source and mirror: content mismatch,
20
+ * missing from the mirror, or orphaned in the mirror.
21
+ */
22
+ export declare function diffDocTemplateMirror(): string[];
23
+ //# sourceMappingURL=sync-catalog-doc-templates.d.ts.map
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * sync-catalog-doc-templates.ts
4
+ *
5
+ * `docs/templates/` (repo root) is the editable source of truth for the
6
+ * blueprint / doc templates. `catalog/docs/templates/` is the published +
7
+ * scaffolded mirror: the npm `files` list ships `catalog/` but NOT repo-root
8
+ * `docs/` (which holds internal docs that must stay private), and `wp init`
9
+ * scaffolds templates into a consumer from `catalog/docs/templates/`.
10
+ *
11
+ * The two MUST stay byte-identical. Nothing synced them before, so they
12
+ * drifted — this script regenerates the mirror from the source and is wired
13
+ * into the build. The colocated drift test fails CI if they ever diverge.
14
+ *
15
+ * Default: regenerate the mirror from the source.
16
+ * `--check`: exit non-zero and list drift without writing (CI / pre-publish).
17
+ */
18
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'node:fs';
19
+ import { dirname, join } from 'node:path';
20
+ import { argv, exit } from 'node:process';
21
+ import { fileURLToPath } from 'node:url';
22
+ const PACKAGE_ROOT = dirname(dirname(import.meta.dirname));
23
+ const SOURCE_DIR = join(PACKAGE_ROOT, 'docs', 'templates');
24
+ const MIRROR_DIR = join(PACKAGE_ROOT, 'catalog', 'docs', 'templates');
25
+ function listFiles(dir) {
26
+ if (!existsSync(dir))
27
+ return [];
28
+ return readdirSync(dir, { withFileTypes: true })
29
+ .filter((entry) => entry.isFile())
30
+ .map((entry) => entry.name)
31
+ .sort();
32
+ }
33
+ /**
34
+ * Names that are out of sync between source and mirror: content mismatch,
35
+ * missing from the mirror, or orphaned in the mirror.
36
+ */
37
+ export function diffDocTemplateMirror() {
38
+ const sourceFiles = listFiles(SOURCE_DIR);
39
+ const mirrorFiles = listFiles(MIRROR_DIR);
40
+ const names = [...new Set([...sourceFiles, ...mirrorFiles])].sort();
41
+ const drift = [];
42
+ for (const name of names) {
43
+ const inSource = sourceFiles.includes(name);
44
+ const inMirror = mirrorFiles.includes(name);
45
+ if (!inSource || !inMirror) {
46
+ drift.push(name);
47
+ continue;
48
+ }
49
+ if (readFileSync(join(SOURCE_DIR, name), 'utf8') !== readFileSync(join(MIRROR_DIR, name), 'utf8')) {
50
+ drift.push(name);
51
+ }
52
+ }
53
+ return drift;
54
+ }
55
+ /** Regenerate the mirror from the source: copy every file, drop orphans. */
56
+ function syncDocTemplateMirror() {
57
+ mkdirSync(MIRROR_DIR, { recursive: true });
58
+ const sourceFiles = listFiles(SOURCE_DIR);
59
+ for (const name of listFiles(MIRROR_DIR)) {
60
+ if (!sourceFiles.includes(name))
61
+ rmSync(join(MIRROR_DIR, name));
62
+ }
63
+ for (const name of sourceFiles) {
64
+ cpSync(join(SOURCE_DIR, name), join(MIRROR_DIR, name));
65
+ }
66
+ return sourceFiles.length;
67
+ }
68
+ function main() {
69
+ if (!existsSync(SOURCE_DIR)) {
70
+ console.error(`doc templates source not found: ${SOURCE_DIR}`);
71
+ exit(1);
72
+ }
73
+ if (argv.includes('--check')) {
74
+ const drift = diffDocTemplateMirror();
75
+ if (drift.length > 0) {
76
+ console.error([
77
+ 'catalog/docs/templates/ is out of sync with docs/templates/:',
78
+ ...drift.map((name) => ` - ${name}`),
79
+ 'Run `bun src/build/sync-catalog-doc-templates.ts` and commit the result.',
80
+ ].join('\n'));
81
+ exit(1);
82
+ }
83
+ console.log('catalog/docs/templates/ is in sync with docs/templates/');
84
+ return;
85
+ }
86
+ const count = syncDocTemplateMirror();
87
+ console.log(`Synced ${count} template(s) → catalog/docs/templates/`);
88
+ }
89
+ // Run as a script, but stay side-effect-free when imported (e.g. by the test).
90
+ if (fileURLToPath(import.meta.url) === argv[1]) {
91
+ main();
92
+ }
93
+ //# sourceMappingURL=sync-catalog-doc-templates.js.map
@@ -9,6 +9,7 @@ import { existsSync, readFileSync } from 'node:fs';
9
9
  import path from 'node:path';
10
10
  import { runAuditDispatch } from './audit-core.js';
11
11
  import { runStryker } from '#audit/run-stryker';
12
+ import { resolveAuditScriptPath } from '#audit/resolve-audit-script';
12
13
  const REPO_AUDIT_REGISTRY = {
13
14
  'catalog-drift': async (root) => (await import('#audit/repo-guardrails')).auditCatalogDrift(root),
14
15
  'package-surface': async (root) => (await import('#audit/package-surface')).auditPackageSurface(root),
@@ -119,13 +120,7 @@ const AUDIT_KINDS = [
119
120
  ];
120
121
  const AUDIT_KIND_LIST = AUDIT_KINDS.join(', ');
121
122
  function resolveAuditScript(name) {
122
- const fromSource = new URL(`../../audit/${name}`, import.meta.url);
123
- if (existsSync(fromSource)) {
124
- return fromSource.pathname;
125
- }
126
- const bundleDir = path.dirname(new URL(import.meta.url).pathname);
127
- const packageRoot = path.resolve(bundleDir, '..');
128
- return path.join(packageRoot, 'src', 'audit', name);
123
+ return resolveAuditScriptPath(name, { moduleUrl: import.meta.url });
129
124
  }
130
125
  async function runAuditScript(script, extraArgs) {
131
126
  const runtime = process.env.BUN_INSTALL ? 'bun' : 'bun';
@@ -6,7 +6,7 @@ import { blueprintToSpecKit } from '#export/spec-kit/index';
6
6
  import { getProjectRoot } from '#cli/utils';
7
7
  import { resolveBlueprintRoot } from '#utils/blueprint-root';
8
8
  import { applyBlueprintLifecycleToFile, BlueprintCreationService, BlueprintService, complexitySchema, relativeBlueprintSlug, parseBlueprint, planStatusSchema, runBlueprintAudit, resolveBlueprintFile, serializeBlueprint, validateAllTasksDone, } from '#local';
9
- import { resolvePackageAsset } from '#utils/package-assets';
9
+ import { resolvePackageAssetPreferred } from '#utils/package-assets';
10
10
  import { describeBlueprintExecutionRuntime, buildBlueprintLaunchSpec, buildStoppedRuntimeEvidence, controlBlueprintExecution, initializeBlueprintExecutionProgressBridge, launchBlueprintExecution, persistBlueprintExecutionArtifacts, persistBlueprintExecutionMetadata, recordLaunchFailure, reconcileBlueprintRuntimeSnapshot, readBlueprintExecutionState, syncBlueprintExecutionProgress, writeBlueprintRuntimeSnapshot, } from './execution.js';
11
11
  import { advanceTask as advanceTaskMutation, finalizeBlueprint as finalizeBlueprintMutation, promoteBlueprint as promoteBlueprintMutation, } from './mutations.js';
12
12
  import { BlueprintAuditFailedError, executeBlueprintSubcommand } from './router-dispatch.js';
@@ -40,7 +40,10 @@ function assertBlueprintCanMoveToStatus(blueprint, nextStatus) {
40
40
  * when the lookup fails in unrelated contexts (e.g. `wp --help`).
41
41
  */
42
42
  function resolveRepoBlueprintTemplatePath() {
43
- return resolvePackageAsset('docs/templates/blueprint.md');
43
+ return resolvePackageAssetPreferred([
44
+ 'docs/templates/blueprint.md',
45
+ 'catalog/docs/templates/blueprint.md',
46
+ ]);
44
47
  }
45
48
  function todayIsoDate() {
46
49
  return new Date().toISOString().split('T')[0] ?? new Date().toISOString();
@@ -1,12 +1,16 @@
1
1
  import { readdirSync } from 'node:fs';
2
2
  import path from 'node:path';
3
- import { resolvePackageAsset } from '#utils/package-assets.js';
3
+ import { resolvePackageAssetPreferred } from '#utils/package-assets.js';
4
4
  /**
5
- * Default templates directory: docs/templates/ resolved relative to the
6
- * package root (same strategy as resolveRepoBlueprintTemplatePath in router.ts).
5
+ * Default templates directory: docs/templates/ in a source checkout, falling
6
+ * back to the shipped catalog/docs/templates/ in the published package (same
7
+ * strategy as resolveRepoBlueprintTemplatePath in router.ts).
7
8
  */
8
9
  function defaultTemplatesDir() {
9
- return path.dirname(resolvePackageAsset('docs/templates/blueprint.md'));
10
+ return path.dirname(resolvePackageAssetPreferred([
11
+ 'docs/templates/blueprint.md',
12
+ 'catalog/docs/templates/blueprint.md',
13
+ ]));
10
14
  }
11
15
  /**
12
16
  * List available templates from `templatesDir` (defaults to docs/templates/).
@@ -5,6 +5,8 @@ export const AGENT_HOSTS = ['codex', 'claude', 'opencode'];
5
5
  export const REQUIRED_CORE_CAPABILITIES = ['verify', 'plan-refine'];
6
6
  export const VISIBILITY_STATUSES = ['visible-now', 'visible-after-restart', 'not-visible'];
7
7
  export function parseAgentHosts(value) {
8
+ if (value?.trim() === 'none')
9
+ return [];
8
10
  if (!value || value.trim().length === 0 || value.trim() === 'all')
9
11
  return [...AGENT_HOSTS];
10
12
  const out = [];
@@ -19,7 +21,7 @@ export function parseAgentHosts(value) {
19
21
  unknown.push(token);
20
22
  }
21
23
  if (unknown.length > 0) {
22
- throw new Error(`Unknown host(s): ${unknown.join(', ')}. Expected one of: ${AGENT_HOSTS.join(', ')}, all.`);
24
+ throw new Error(`Unknown host(s): ${unknown.join(', ')}. Expected one of: ${AGENT_HOSTS.join(', ')}, all, none.`);
23
25
  }
24
26
  return [...new Set(out)];
25
27
  }
@@ -54,7 +56,7 @@ export function hostSkillRoots(repoRoot, host, homeDir = homedir()) {
54
56
  }
55
57
  }
56
58
  export function auditHostSkillVisibility(input) {
57
- const selectedHosts = input.hosts && input.hosts.length > 0 ? [...input.hosts] : [...AGENT_HOSTS];
59
+ const selectedHosts = input.hosts ? [...input.hosts] : [...AGENT_HOSTS];
58
60
  const requiredCapabilities = input.requiredCapabilities && input.requiredCapabilities.length > 0
59
61
  ? [...input.requiredCapabilities]
60
62
  : [...REQUIRED_CORE_CAPABILITIES];
@@ -6,7 +6,7 @@
6
6
  * config keys, and generated surfaces it owns while leaving consumer-owned
7
7
  * divergent files untouched unless `--overwrite` is passed.
8
8
  */
9
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
10
10
  import { basename, dirname, join, relative } from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import { isTelemetryEnabled, reportTthw } from '#telemetry/setup-tthw';
@@ -26,7 +26,7 @@ import { GENERATED_PATHS_BLOCK, patchGitignore } from './gitignore-patcher.js';
26
26
  import { scaffoldAgentsMd } from './scaffold-agents-md.js';
27
27
  import { scaffoldBlueprints } from './scaffold-blueprints.js';
28
28
  import { scaffoldDocs } from './scaffold-docs.js';
29
- import { scaffoldBaseKit } from './scaffold-base-kit.js';
29
+ import { BASE_KIT_QUALITY_TARGETS, collectRuntimeContractGuidance, scaffoldBaseKit, } from './scaffold-base-kit.js';
30
30
  import { scaffoldMonorepoNav } from './scaffold-monorepo-nav.js';
31
31
  import { REQUIRED_CORE_CAPABILITIES, auditHostSkillVisibility, parseAgentHosts, serializeHostVisibility, summarizeHostVisibility, } from './host-visibility.js';
32
32
  import { scaffoldAgentHooks, trustCodexWebpressoHooksForRepo, trustCodexPresetHooksForUser, } from './scaffolders/agent-hooks/index.js';
@@ -103,6 +103,31 @@ function inferBlueprintsDirOverride(repoRoot, existingConfig) {
103
103
  }
104
104
  return relativePath;
105
105
  }
106
+ function readPackageJsonSafe(repoRoot) {
107
+ const packageJsonPath = join(repoRoot, 'package.json');
108
+ if (!existsSync(packageJsonPath)) {
109
+ return null;
110
+ }
111
+ try {
112
+ return JSON.parse(readFileSync(packageJsonPath, 'utf8'));
113
+ }
114
+ catch {
115
+ return null;
116
+ }
117
+ }
118
+ function printRuntimeContractGuidance(packageJson) {
119
+ const guidance = collectRuntimeContractGuidance(packageJson);
120
+ console.log('\nRuntime-owned tooling contract:');
121
+ console.log(' wp now owns execution for test, e2e, lint, format, and typecheck.');
122
+ console.log(' Keep local dependencies that your tests, configs, or tsconfig types import directly.');
123
+ if (guidance.keepLocalAuthoringDeps.length > 0) {
124
+ console.log(` Keep local authoring deps when imported directly: ${guidance.keepLocalAuthoringDeps.join(', ')}`);
125
+ }
126
+ if (guidance.reviewForRemovalDeps.length > 0) {
127
+ console.log(` Review execution-only deps for removal if they only powered local binaries: ${guidance.reviewForRemovalDeps.join(', ')}`);
128
+ }
129
+ console.log(' Do not blanket-remove devDependencies just because wp can execute the tool.');
130
+ }
106
131
  export async function runInit(flags) {
107
132
  const startMs = Date.now();
108
133
  const cwd = flags.cwd ?? process.cwd();
@@ -612,6 +637,14 @@ export async function runInit(flags) {
612
637
  console.log(` drifted: ${summary.drifted}`);
613
638
  if (options.dryRun)
614
639
  console.log(` would-change: ${summary['skipped-dry']}`);
640
+ if (tier3Selection.includes('base-kit')) {
641
+ const qualityTargets = new Set(BASE_KIT_QUALITY_TARGETS);
642
+ const qualityResults = baseKitResults.filter((result) => qualityTargets.has(relative(consumer.repoRoot, result.targetPath).replaceAll('\\', '/')));
643
+ const qualityCreated = qualityResults.filter((result) => result.action === 'created').length;
644
+ const qualityPreserved = qualityResults.filter((result) => result.action === 'identical').length;
645
+ const qualityDryRun = qualityResults.filter((result) => result.action === 'skipped-dry').length;
646
+ console.log(` repo quality scaffold: ${options.dryRun ? `${qualityDryRun} would be created` : `${qualityCreated} created, ${qualityPreserved} preserved`}`);
647
+ }
615
648
  if (summary.drifted > 0) {
616
649
  console.log('\n Note: some consumer-owned files exist with different content and were left unchanged.\n' +
617
650
  ' Review the drift or re-run with `--overwrite` to force eligible managed files.');
@@ -629,8 +662,13 @@ export async function runInit(flags) {
629
662
  };
630
663
  writeConfig(consumer.repoRoot, config);
631
664
  console.log('\nHost skill visibility:');
632
- for (const line of summarizeHostVisibility(consumer.repoRoot, visibilityAudit)) {
633
- console.log(line);
665
+ if (visibilityAudit.selectedHosts.length === 0) {
666
+ console.log(' hosts: - skipped (--host none)');
667
+ }
668
+ else {
669
+ for (const line of summarizeHostVisibility(consumer.repoRoot, visibilityAudit)) {
670
+ console.log(line);
671
+ }
634
672
  }
635
673
  const missing = visibilityAudit.results.filter((result) => result.status === 'not-visible');
636
674
  if (missing.length > 0) {
@@ -659,7 +697,8 @@ export async function runInit(flags) {
659
697
  }
660
698
  }
661
699
  }
662
- console.log('\nwp init: done.');
700
+ printRuntimeContractGuidance(options.dryRun ? consumer.packageJson : readPackageJsonSafe(consumer.repoRoot) ?? consumer.packageJson);
701
+ console.log('\nwp init: setup phases finished.');
663
702
  if (omxFailure === 'not-found')
664
703
  return EXIT_SETUP_FAIL;
665
704
  if (omxFailure === 'spawn-failed')
@@ -698,7 +737,7 @@ export async function runInit(flags) {
698
737
  if (!options.dryRun) {
699
738
  console.log([
700
739
  '',
701
- '✅ Setup complete.',
740
+ '✅ Setup complete for the verified phases above.',
702
741
  '',
703
742
  ' Next: wp blueprint new "your first task"',
704
743
  ' wp gain # token savings after your first session',
@@ -730,7 +769,7 @@ export function registerInitCommand(cli, commandName = 'init') {
730
769
  .command(commandName, description)
731
770
  .option('--with <skills>', withHelp)
732
771
  .option('--without <skills>', withoutHelp)
733
- .option('--host <hosts>', 'Comma-separated host targets: codex, claude, opencode, all')
772
+ .option('--host <hosts>', 'Comma-separated host targets: codex, claude, opencode, all, none')
734
773
  .option('--all', 'Install every skill (Tier-1 + Tier-2 + all Tier-3)')
735
774
  .option('--overwrite', 'Force full-file replacement for eligible managed files (default: reconcile owned content and preserve divergent consumer files)')
736
775
  .option('--dry-run', 'Show what would change without writing anything')
@@ -5,5 +5,17 @@ export interface ScaffoldBaseKitInput {
5
5
  options: MergeOptions;
6
6
  globalInstall?: boolean;
7
7
  }
8
+ export interface RuntimeContractGuidance {
9
+ keepLocalAuthoringDeps: string[];
10
+ reviewForRemovalDeps: string[];
11
+ }
12
+ interface PackageJsonLike {
13
+ dependencies?: Record<string, string>;
14
+ devDependencies?: Record<string, string>;
15
+ [key: string]: unknown;
16
+ }
17
+ export declare function collectRuntimeContractGuidance(packageJson: PackageJsonLike | null | undefined): RuntimeContractGuidance;
18
+ export declare const BASE_KIT_QUALITY_TARGETS: string[];
8
19
  export declare function scaffoldBaseKit(input: ScaffoldBaseKitInput): MergeResult[];
20
+ export {};
9
21
  //# sourceMappingURL=scaffold-base-kit.d.ts.map