@guanlin4924/devflow-pi 0.1.94 → 0.1.96

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 (245) hide show
  1. package/README.md +34 -4
  2. package/node_modules/@playwright/test/LICENSE +202 -0
  3. package/node_modules/@playwright/test/NOTICE +5 -0
  4. package/node_modules/@playwright/test/README.md +318 -0
  5. package/node_modules/@playwright/test/cli.js +19 -0
  6. package/node_modules/@playwright/test/index.d.ts +18 -0
  7. package/node_modules/@playwright/test/index.js +17 -0
  8. package/node_modules/@playwright/test/index.mjs +18 -0
  9. package/node_modules/@playwright/test/package.json +35 -0
  10. package/node_modules/@playwright/test/reporter.d.ts +17 -0
  11. package/node_modules/@playwright/test/reporter.js +17 -0
  12. package/node_modules/@playwright/test/reporter.mjs +17 -0
  13. package/node_modules/playwright/LICENSE +202 -0
  14. package/node_modules/playwright/NOTICE +5 -0
  15. package/node_modules/playwright/README.md +318 -0
  16. package/node_modules/playwright/ThirdPartyNotices.txt +14 -0
  17. package/node_modules/playwright/cli.js +19 -0
  18. package/node_modules/playwright/index.d.ts +17 -0
  19. package/node_modules/playwright/index.js +17 -0
  20. package/node_modules/playwright/index.mjs +18 -0
  21. package/node_modules/playwright/jsx-runtime.js +42 -0
  22. package/node_modules/playwright/jsx-runtime.mjs +21 -0
  23. package/node_modules/playwright/lib/agents/agentParser.js +89 -0
  24. package/node_modules/playwright/lib/agents/copilot-setup-steps.yml +34 -0
  25. package/node_modules/playwright/lib/agents/generateAgents.js +395 -0
  26. package/node_modules/playwright/lib/agents/playwright-test-coverage.prompt.md +31 -0
  27. package/node_modules/playwright/lib/agents/playwright-test-generate.prompt.md +8 -0
  28. package/node_modules/playwright/lib/agents/playwright-test-generator.agent.md +88 -0
  29. package/node_modules/playwright/lib/agents/playwright-test-heal.prompt.md +6 -0
  30. package/node_modules/playwright/lib/agents/playwright-test-healer.agent.md +56 -0
  31. package/node_modules/playwright/lib/agents/playwright-test-plan.prompt.md +9 -0
  32. package/node_modules/playwright/lib/agents/playwright-test-planner.agent.md +74 -0
  33. package/node_modules/playwright/lib/cli/reportActions.js +78 -0
  34. package/node_modules/playwright/lib/cli/testActions.js +214 -0
  35. package/node_modules/playwright/lib/common/index.js +2923 -0
  36. package/node_modules/playwright/lib/common/index.js.txt +34 -0
  37. package/node_modules/playwright/lib/errorContext.js +129 -0
  38. package/node_modules/playwright/lib/globals.js +58 -0
  39. package/node_modules/playwright/lib/index.js +815 -0
  40. package/node_modules/playwright/lib/isomorphic.js +260 -0
  41. package/node_modules/playwright/lib/isomorphic.js.txt +9 -0
  42. package/node_modules/playwright/lib/loader/loaderProcessEntry.js +34 -0
  43. package/node_modules/playwright/lib/loader/loaderProcessEntry.js.txt +9 -0
  44. package/node_modules/playwright/lib/matchers/expect.js +13490 -0
  45. package/node_modules/playwright/lib/matchers/expect.js.LICENSE +640 -0
  46. package/node_modules/playwright/lib/matchers/expect.js.txt +67 -0
  47. package/node_modules/playwright/lib/mcp/test/browserBackend.js +135 -0
  48. package/node_modules/playwright/lib/mcp/test/generatorTools.js +122 -0
  49. package/node_modules/playwright/lib/mcp/test/plannerTools.js +150 -0
  50. package/node_modules/playwright/lib/mcp/test/seed.js +82 -0
  51. package/node_modules/playwright/lib/mcp/test/streams.js +44 -0
  52. package/node_modules/playwright/lib/mcp/test/testBackend.js +99 -0
  53. package/node_modules/playwright/lib/mcp/test/testContext.js +306 -0
  54. package/node_modules/playwright/lib/mcp/test/testTool.js +30 -0
  55. package/node_modules/playwright/lib/mcp/test/testTools.js +98 -0
  56. package/node_modules/playwright/lib/package.js +47 -0
  57. package/node_modules/playwright/lib/program.js +241 -0
  58. package/node_modules/playwright/lib/runner/index.js +8527 -0
  59. package/node_modules/playwright/lib/runner/index.js.txt +61 -0
  60. package/node_modules/playwright/lib/transform/babelBundle.js +72274 -0
  61. package/node_modules/playwright/lib/transform/babelBundle.js.LICENSE +2384 -0
  62. package/node_modules/playwright/lib/transform/babelBundle.js.txt +325 -0
  63. package/node_modules/playwright/lib/transform/esmLoader.js +8054 -0
  64. package/node_modules/playwright/lib/transform/esmLoader.js.LICENSE +355 -0
  65. package/node_modules/playwright/lib/transform/esmLoader.js.txt +60 -0
  66. package/node_modules/playwright/lib/util.js +373 -0
  67. package/node_modules/playwright/lib/worker/workerProcessEntry.js +1861 -0
  68. package/node_modules/playwright/lib/worker/workerProcessEntry.js.txt +19 -0
  69. package/node_modules/playwright/package.json +55 -0
  70. package/node_modules/playwright/test.d.ts +18 -0
  71. package/node_modules/playwright/test.js +24 -0
  72. package/node_modules/playwright/test.mjs +35 -0
  73. package/node_modules/playwright/types/test.d.ts +11074 -0
  74. package/node_modules/playwright/types/testReporter.d.ts +950 -0
  75. package/node_modules/playwright-core/LICENSE +202 -0
  76. package/node_modules/playwright-core/NOTICE +5 -0
  77. package/node_modules/playwright-core/README.md +3 -0
  78. package/node_modules/playwright-core/ThirdPartyNotices.txt +13 -0
  79. package/node_modules/playwright-core/bin/install_media_pack.ps1 +5 -0
  80. package/node_modules/playwright-core/bin/install_webkit_wsl.ps1 +33 -0
  81. package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +42 -0
  82. package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +13 -0
  83. package/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 +24 -0
  84. package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +42 -0
  85. package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +12 -0
  86. package/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 +24 -0
  87. package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +48 -0
  88. package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +11 -0
  89. package/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 +23 -0
  90. package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +48 -0
  91. package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +11 -0
  92. package/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 +23 -0
  93. package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +48 -0
  94. package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +11 -0
  95. package/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 +24 -0
  96. package/node_modules/playwright-core/browsers.json +52 -0
  97. package/node_modules/playwright-core/cli.js +21 -0
  98. package/node_modules/playwright-core/index.d.ts +17 -0
  99. package/node_modules/playwright-core/index.js +17 -0
  100. package/node_modules/playwright-core/index.mjs +28 -0
  101. package/node_modules/playwright-core/lib/bootstrap.js +88 -0
  102. package/node_modules/playwright-core/lib/coreBundle.js +75813 -0
  103. package/node_modules/playwright-core/lib/entry/cliDaemon.js +5 -0
  104. package/node_modules/playwright-core/lib/entry/dashboardApp.js +3 -0
  105. package/node_modules/playwright-core/lib/entry/mcp.js +10 -0
  106. package/node_modules/playwright-core/lib/entry/oopBrowserDownload.js +3 -0
  107. package/node_modules/playwright-core/lib/package.js +50 -0
  108. package/node_modules/playwright-core/lib/server/chromium/appIcon.png +0 -0
  109. package/node_modules/playwright-core/lib/server/electron/loader.js +116 -0
  110. package/node_modules/playwright-core/lib/serverRegistry.js +1939 -0
  111. package/node_modules/playwright-core/lib/serverRegistry.js.LICENSE +65 -0
  112. package/node_modules/playwright-core/lib/tools/cli-client/channelSessions.js +141 -0
  113. package/node_modules/playwright-core/lib/tools/cli-client/cli.js +6 -0
  114. package/node_modules/playwright-core/lib/tools/cli-client/help.json +721 -0
  115. package/node_modules/playwright-core/lib/tools/cli-client/minimist.js +128 -0
  116. package/node_modules/playwright-core/lib/tools/cli-client/output.js +351 -0
  117. package/node_modules/playwright-core/lib/tools/cli-client/program.js +418 -0
  118. package/node_modules/playwright-core/lib/tools/cli-client/registry.js +180 -0
  119. package/node_modules/playwright-core/lib/tools/cli-client/session.js +259 -0
  120. package/node_modules/playwright-core/lib/tools/dashboard/appIcon.png +0 -0
  121. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/SKILL.md +425 -0
  122. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
  123. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
  124. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
  125. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
  126. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
  127. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
  128. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
  129. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
  130. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
  131. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/SKILL.md +136 -0
  132. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
  133. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/migration.md +89 -0
  134. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/react.md +69 -0
  135. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/typing.md +173 -0
  136. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/vue.md +77 -0
  137. package/node_modules/playwright-core/lib/tools/skills/playwright-trace/SKILL.md +174 -0
  138. package/node_modules/playwright-core/lib/tools/utils/extension.js +112 -0
  139. package/node_modules/playwright-core/lib/tools/utils/socketConnection.js +108 -0
  140. package/node_modules/playwright-core/lib/utilsBundle.js +85357 -0
  141. package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +1890 -0
  142. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule--QdMvsKi.css +1 -0
  143. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule-CQ8RZGBm.js +32 -0
  144. package/node_modules/playwright-core/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
  145. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
  146. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
  147. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
  148. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-AwgwcYie.css +1 -0
  149. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-hRvO4yU2.js +12 -0
  150. package/node_modules/playwright-core/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
  151. package/node_modules/playwright-core/lib/vite/dashboard/index.html +29 -0
  152. package/node_modules/playwright-core/lib/vite/dashboard/playwright-logo.svg +24 -0
  153. package/node_modules/playwright-core/lib/vite/htmlReport/index.html +16 -0
  154. package/node_modules/playwright-core/lib/vite/htmlReport/report.css +2 -0
  155. package/node_modules/playwright-core/lib/vite/htmlReport/report.js +32 -0
  156. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
  157. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-CVQWJZAA.js +32 -0
  158. package/node_modules/playwright-core/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  159. package/node_modules/playwright-core/lib/vite/recorder/assets/index-BZpYJZ-P.css +1 -0
  160. package/node_modules/playwright-core/lib/vite/recorder/assets/index-hrlLqLtq.js +129 -0
  161. package/node_modules/playwright-core/lib/vite/recorder/index.html +29 -0
  162. package/node_modules/playwright-core/lib/vite/recorder/playwright-logo.svg +9 -0
  163. package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BbkfBe3n.js +32 -0
  164. package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Ds6CBOo0.js +182 -0
  165. package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
  166. package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-DywYcAf8.js +7 -0
  167. package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
  168. package/node_modules/playwright-core/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  169. package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.Bqk9acqE.css +1 -0
  170. package/node_modules/playwright-core/lib/vite/traceViewer/index.B4cLoZK3.js +1 -0
  171. package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
  172. package/node_modules/playwright-core/lib/vite/traceViewer/index.html +44 -0
  173. package/node_modules/playwright-core/lib/vite/traceViewer/manifest.webmanifest +16 -0
  174. package/node_modules/playwright-core/lib/vite/traceViewer/playwright-logo.svg +9 -0
  175. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
  176. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +10 -0
  177. package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -0
  178. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CU5KtEkS.js +5 -0
  179. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CyMfwkXJ.css +1 -0
  180. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +18 -0
  181. package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
  182. package/node_modules/playwright-core/lib/webp_codec.LICENSE +173 -0
  183. package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
  184. package/node_modules/playwright-core/lib/xdg-open +1267 -0
  185. package/node_modules/playwright-core/package.json +34 -0
  186. package/node_modules/playwright-core/types/protocol.d.ts +24645 -0
  187. package/node_modules/playwright-core/types/structs.d.ts +52 -0
  188. package/node_modules/playwright-core/types/types.d.ts +26632 -0
  189. package/package.json +13 -2
  190. package/plugins/devflow-core/extensions/devflow-core.ts +432 -7
  191. package/plugins/devflow-core/runtime/hooks/hook_common.py +514 -0
  192. package/plugins/devflow-core/runtime/hooks/index_gate.py +47 -16
  193. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_runner.py +488 -71
  194. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +51 -0
  195. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/approval_pins.py +433 -0
  196. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/approval_store.py +137 -0
  197. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_coverage.py +87 -0
  198. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_draft.py +53 -0
  199. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_v1.py +318 -0
  200. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/environment_profile.py +134 -0
  201. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +1 -0
  202. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_surface.py +138 -0
  203. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/playwright_adapter.py +515 -0
  204. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/tc_hash.py +132 -0
  205. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_command_policy.py +102 -8
  206. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +13 -0
  207. package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +13 -34
  208. package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +3 -1
  209. package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +68 -140
  210. package/plugins/devflow-core/skills/workflow-project-context/scripts/validate_initialization_database.py +1 -1
  211. package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md +3 -1
  212. package/plugins/devflow-intel/extensions/devflow-intel.ts +1 -1
  213. package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +23 -4
  214. package/plugins/devflow-quality/runtime/playwright/devflow-test-dsl-v1.schema.json +872 -0
  215. package/plugins/devflow-quality/runtime/playwright/playwright.config.mjs +46 -0
  216. package/plugins/devflow-quality/runtime/playwright/reporter.mjs +311 -0
  217. package/plugins/devflow-quality/runtime/playwright/runner.spec.mjs +1308 -0
  218. package/plugins/devflow-quality/runtime/playwright/runtime-manifest.json +11 -0
  219. package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +3 -0
  220. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +71 -58
  221. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/api-mainflow-rules.md +20 -15
  222. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/codebase-discovery.md +3 -1
  223. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/intermediate-format.md +115 -192
  224. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/mainflow-selection.md +27 -23
  225. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/project-dsl-contract.md +78 -153
  226. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/ui-mainflow-rules.md +36 -83
  227. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +497 -556
  228. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/export_legacy_testagent.py +647 -0
  229. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/normalize_case_payloads.py +10 -3
  230. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/validate_case_payloads.py +165 -275
  231. package/plugins/devflow-quality/skills/workflow-human-acceptance/SKILL.md +63 -0
  232. package/plugins/devflow-quality/skills/workflow-release-closeout/SKILL.md +4 -4
  233. package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +17 -9
  234. package/src/approval-store.ts +340 -0
  235. package/src/cli.ts +10 -0
  236. package/src/constants.ts +1 -1
  237. package/src/doctor.ts +268 -2
  238. package/src/initialization-store.ts +48 -1
  239. package/src/mcp/auth.ts +103 -0
  240. package/src/mcp/core.ts +102 -0
  241. package/src/mcp/server.ts +193 -0
  242. package/src/mcp/types.ts +5 -0
  243. package/src/paths.ts +12 -1
  244. package/src/project-context.ts +24 -1
  245. package/templates/omp/hook-config.json +6 -0
@@ -0,0 +1,193 @@
1
+ import { appendFile, mkdir, readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { z } from "zod";
7
+
8
+ import { devflowHome } from "../paths.ts";
9
+ import { authorize, FEATURE_RE, loadAuthorization, MAX_DSL_BYTES, McpError, requestHash } from "./auth.ts";
10
+ import { dslScript, invokeCore, runPython } from "./core.ts";
11
+ import type { CoreRunner, McpServerOptions, McpToolName } from "./types.ts";
12
+
13
+ const RESPONSE_LIMIT = 64 * 1024;
14
+
15
+ type ProgressCallback = () => void | Promise<void>;
16
+
17
+ function bounded(value: unknown): string {
18
+ const text = JSON.stringify(value);
19
+ if (text.length <= RESPONSE_LIMIT) return text;
20
+ return JSON.stringify({
21
+ ok: false,
22
+ reason: "response_truncated",
23
+ truncated: true,
24
+ output: text.slice(0, RESPONSE_LIMIT - 80),
25
+ });
26
+ }
27
+
28
+ function toolResult(value: unknown) {
29
+ return {
30
+ content: [{ type: "text" as const, text: bounded(value) }],
31
+ isError: Boolean(value && typeof value === "object" && (value as { ok?: unknown }).ok === false),
32
+ };
33
+ }
34
+
35
+ async function audit(home: string, row: Record<string, unknown>): Promise<void> {
36
+ const directory = path.join(home, "mcp-audit");
37
+ await mkdir(directory, { recursive: true, mode: 0o700 });
38
+ const file = path.join(directory, `${new Date().toISOString().slice(0, 7)}.jsonl`);
39
+ await appendFile(file, `${JSON.stringify(row)}\n`, { mode: 0o600 });
40
+ }
41
+
42
+ function collectEnvironmentProfiles(value: unknown): Set<string> {
43
+ const profiles = new Set<string>();
44
+ const visit = (current: unknown): void => {
45
+ if (Array.isArray(current)) {
46
+ current.forEach(visit);
47
+ return;
48
+ }
49
+ if (!current || typeof current !== "object") return;
50
+ const record = current as Record<string, unknown>;
51
+ if ((record.kind === "devflow_playwright" || record.adapter_kind === "devflow_playwright") && typeof record.environment_profile === "string") {
52
+ profiles.add(record.environment_profile);
53
+ }
54
+ Object.values(record).forEach(visit);
55
+ };
56
+ visit(value);
57
+ return profiles;
58
+ }
59
+
60
+ const MAX_FAILURE_ERRORS = 50;
61
+ const MAX_FAILURE_ERROR_CHARS = 500;
62
+
63
+ // Failure details must not expose project or run locations (same rule as the Core report).
64
+ function scrubPaths(text: string): string {
65
+ return text
66
+ .replace(/(?:[A-Za-z]:)?[^\s,;()"']+[\/][^\s,;()"']+/g, "<path>")
67
+ .slice(0, MAX_FAILURE_ERROR_CHARS);
68
+ }
69
+
70
+ // A run that executed TCs always answers with the Core report, even when TCs failed or are
71
+ // blocked: the report's gate says whether acceptance passed. Only runs that never produced
72
+ // results (lock held, invalid bindings/approvals, Core crash) short-circuit with an error.
73
+ function runFailure(value: Record<string, unknown>): Record<string, unknown> {
74
+ const code = typeof value.error_code === "string" ? value.error_code
75
+ : typeof value.reason === "string" && value.reason ? value.reason
76
+ : Array.isArray(value.errors) && value.errors.length > 0 ? "acceptance_validation_failed"
77
+ : "core_failed";
78
+ const errors = Array.isArray(value.errors) ? value.errors.slice(0, MAX_FAILURE_ERRORS).map(item => scrubPaths(String(item))) : [];
79
+ return { ok: false, error_code: code, reason: code, errors };
80
+ }
81
+
82
+ export async function createMcpServer(options: McpServerOptions) {
83
+ const home = options.home ?? devflowHome();
84
+ const config = await loadAuthorization(options.client, home);
85
+ const runner: CoreRunner = options.runner ?? runPython;
86
+ let running = false;
87
+
88
+ const server = new McpServer({ name: "devflow-acceptance", version: "1.0.0" });
89
+
90
+ const call = async (tool: McpToolName, args: Record<string, unknown>, onProgress?: ProgressCallback): Promise<Record<string, unknown>> => {
91
+ const started = Date.now();
92
+ let ok = false;
93
+ let reason: string | null = null;
94
+ try {
95
+ if (tool === "dsl_draft_validate") {
96
+ const dslText = JSON.stringify(args.dsl);
97
+ if (typeof dslText !== "string" || Buffer.byteLength(dslText) > MAX_DSL_BYTES) {
98
+ throw new McpError("mcp_input_invalid", "DSL exceeds 2 MiB or is not JSON");
99
+ }
100
+ const auth = await authorize(config, options.client, tool, args.project ?? process.cwd());
101
+ const raw = await runner(dslScript, [], auth.project, JSON.stringify({ dsl: args.dsl, tc_data: args.tc_data }));
102
+ if (raw.timedOut) return { ok: false, error_code: "core_failed", reason: "core_failed" };
103
+ try {
104
+ const parsed = JSON.parse(raw.stdout) as Record<string, unknown>;
105
+ ok = parsed.ok === true;
106
+ return parsed;
107
+ } catch {
108
+ return { ok: false, error_code: "core_failed", reason: raw.stderr || raw.stdout };
109
+ }
110
+ }
111
+
112
+ const feature = args.feature;
113
+ const auth = await authorize(config, options.client, tool, args.project, feature);
114
+ if (tool === "run_feature" && running) throw new McpError("mcp_busy", "another run_feature is in progress");
115
+
116
+ if (tool === "run_feature") {
117
+ const bindingFile = path.join(auth.project, ".devflow/planning/features", String(feature), "acceptance-test-bindings.json");
118
+ let bindings: unknown;
119
+ try {
120
+ bindings = JSON.parse(await readFile(bindingFile, "utf8"));
121
+ } catch {
122
+ throw new McpError("mcp_input_invalid", "acceptance-test-bindings.json is missing or invalid");
123
+ }
124
+ const profiles = collectEnvironmentProfiles(bindings);
125
+ if ([...profiles].some(profile => !auth.grant.environment_profiles.includes(profile))) {
126
+ throw new McpError("mcp_environment_not_allowed", "environment profile is not authorized");
127
+ }
128
+
129
+ running = true;
130
+ try {
131
+ const runResult = await invokeCore(
132
+ runner,
133
+ "run",
134
+ auth.project,
135
+ String(feature),
136
+ Math.min(7_200_000, Math.max(1, options.runTimeoutSeconds ?? 7200) * 1000),
137
+ onProgress,
138
+ );
139
+ if (!Array.isArray(runResult.results)) return runFailure(runResult);
140
+ const report = await invokeCore(runner, "report", auth.project, String(feature));
141
+ ok = report.ok === true;
142
+ return report;
143
+ } finally {
144
+ running = false;
145
+ }
146
+ }
147
+
148
+ const coreResult = await invokeCore(runner, tool === "validate_feature" ? "validate" : "report", auth.project, String(feature));
149
+ ok = coreResult.ok === true;
150
+ return coreResult;
151
+ } catch (error) {
152
+ const mcpError = error instanceof McpError
153
+ ? error
154
+ : new McpError("core_failed", error instanceof Error ? error.message : String(error));
155
+ reason = mcpError.code;
156
+ return { ok: false, error_code: mcpError.code, reason: mcpError.message };
157
+ } finally {
158
+ await audit(home, {
159
+ ts: new Date().toISOString(),
160
+ client: options.client,
161
+ project_id: typeof args.project === "string" ? requestHash(path.resolve(args.project)) : null,
162
+ tool,
163
+ feature: args.feature ?? null,
164
+ ok,
165
+ reason,
166
+ duration_ms: Date.now() - started,
167
+ request_sha256: requestHash(args),
168
+ });
169
+ }
170
+ };
171
+
172
+ const input = z.object({ project: z.string(), feature: z.string().regex(FEATURE_RE) });
173
+ const withProgress = (tool: McpToolName) => (args: any, extra: any) => {
174
+ const token = extra._meta?.progressToken;
175
+ const progress = token === undefined
176
+ ? undefined
177
+ : () => extra.sendNotification({ method: "notifications/progress", params: { progressToken: token, progress: Date.now(), message: "run_feature is still running" } });
178
+ return call(tool, args, progress).then(toolResult);
179
+ };
180
+
181
+ server.registerTool("validate_feature", { description: "Validate a feature; no artifacts are returned.", inputSchema: input.shape }, withProgress("validate_feature"));
182
+ server.registerTool("run_feature", { description: "Run a feature, then return only the Core report. Approval is never confirmed here; blocked tests require /devflow.", inputSchema: input.shape }, withProgress("run_feature"));
183
+ server.registerTool("get_feature_report", { description: "Get the Core feature report; no artifacts are returned.", inputSchema: input.shape }, withProgress("get_feature_report"));
184
+ server.registerTool("dsl_draft_validate", { description: "Validate DSL schema and coverage only; this does not make the draft executable and does not check approvals or manifests.", inputSchema: { project: z.string(), dsl: z.unknown(), tc_data: z.unknown() } }, withProgress("dsl_draft_validate"));
185
+
186
+ Object.assign(server, { invoke: call, boundedForTest: bounded });
187
+ return server;
188
+ }
189
+
190
+ export async function startMcpServer(options: McpServerOptions): Promise<void> {
191
+ const server = await createMcpServer(options);
192
+ await server.connect(new StdioServerTransport());
193
+ }
@@ -0,0 +1,5 @@
1
+ export type McpToolName = "validate_feature" | "run_feature" | "get_feature_report" | "dsl_draft_validate";
2
+ export type CoreResult = { ok: boolean; [key: string]: unknown };
3
+ export type CoreRunnerResult = { exitCode: number | null; stdout: string; stderr: string; timedOut?: boolean };
4
+ export type CoreRunner = (script: string, args: string[], cwd: string, stdin?: string, timeoutMs?: number, onProgress?: () => void | Promise<void>) => Promise<CoreRunnerResult>;
5
+ export type McpServerOptions = { client: string; runTimeoutSeconds?: number; runner?: CoreRunner; home?: string };
package/src/paths.ts CHANGED
@@ -8,8 +8,19 @@ export function packageRoot(): string {
8
8
  return path.resolve(import.meta.dir, "..");
9
9
  }
10
10
 
11
+ /**
12
+ * DEVFLOW_HOME rule (shared with the Python readers and hooks): unset, empty or whitespace-only
13
+ * falls back to ~/.devflow-pi; otherwise a leading `~` is expanded and the path made absolute
14
+ * (path.resolve semantics, existence not required).
15
+ */
16
+ export function normalizeDevflowHome(value: string | undefined): string {
17
+ if (value === undefined || value.trim() === "") return path.resolve(path.join(os.homedir(), ".devflow-pi"));
18
+ const expanded = value === "~" || value.startsWith("~/") ? os.homedir() + value.slice(1) : value;
19
+ return path.resolve(expanded);
20
+ }
21
+
11
22
  export function devflowHome(): string {
12
- return path.resolve(process.env.DEVFLOW_HOME || path.join(os.homedir(), ".devflow-pi"));
23
+ return normalizeDevflowHome(process.env.DEVFLOW_HOME);
13
24
  }
14
25
 
15
26
  export function devflowAgentDir(): string {
@@ -172,13 +172,35 @@ async function atomicWriteJson(target: string, value: unknown): Promise<void> {
172
172
  await rename(temporary, target);
173
173
  }
174
174
 
175
+ async function ensureTestRuntimeLayout(root: string, planningRoot: string): Promise<void> {
176
+ const environments = path.join(planningRoot, "test-environments");
177
+ const runs = path.join(root, ".devflow", "runs");
178
+ await mkdir(environments, { recursive: true });
179
+ await mkdir(runs, { recursive: true });
180
+ const example = path.join(environments, "local.example.json");
181
+ if (!(await exists(example))) {
182
+ await atomicWriteJson(example, {
183
+ profile: "local",
184
+ base_url: "http://127.0.0.1:3000",
185
+ navigation_origins: ["http://127.0.0.1:3000"],
186
+ api_origins: ["http://127.0.0.1:3000"],
187
+ subresources: { policy: "same-site-plus-declared", allowed_origins: [] },
188
+ secret_env: {},
189
+ trace: "on_failure",
190
+ screenshots: "on_failure",
191
+ });
192
+ }
193
+ }
194
+
175
195
  export async function initializeProject(root: string): Promise<{ context: ProjectContext; created: boolean }> {
176
196
  const canonicalRoot = await canonicalDirectory(root);
177
197
  const { devflowRoot: devflowDir, manifestPath, planningRoot } = projectLayout(canonicalRoot);
178
198
  await mkdir(devflowDir, { recursive: true });
179
199
  await assertPlanningBoundary(canonicalRoot);
180
200
  if (await exists(manifestPath)) {
181
- return { context: await loadProjectContext(canonicalRoot), created: false };
201
+ const context = await loadProjectContext(canonicalRoot);
202
+ await ensureTestRuntimeLayout(canonicalRoot, context.planningRoot);
203
+ return { context, created: false };
182
204
  }
183
205
  const manifest: ProjectManifest = {
184
206
  schemaVersion: PROJECT_SCHEMA_VERSION,
@@ -198,6 +220,7 @@ export async function initializeProject(root: string): Promise<{ context: Projec
198
220
  manifest.layoutVersion = PROJECT_LAYOUT_VERSION;
199
221
  await atomicWriteJson(manifestPath, manifest);
200
222
  await mkdir(planningRoot, { recursive: true });
223
+ await ensureTestRuntimeLayout(canonicalRoot, planningRoot);
201
224
  const bootstrapStore = await InitializationStore.open({ root: canonicalRoot, manifest });
202
225
  try { await bootstrapStore.registerWorkspace(); } finally { bootstrapStore.close(); }
203
226
  return {
@@ -13,6 +13,12 @@
13
13
  "gates": {
14
14
  "index_first": {
15
15
  "policy": ".agent-gates/index-first.json"
16
+ },
17
+ "control_store": {
18
+ "hook": "index_gate.py",
19
+ "enforcement": "always",
20
+ "protected": ["control.db* (all access)", "$DEVFLOW_HOME/projects/** (all access)", "SQL writes to approval_proposals/approvals/authority_state", "acceptance-results*.json under .devflow/planning/test-runs (write-only; Read tools allowed)"],
21
+ "extra_protected_paths": []
16
22
  }
17
23
  }
18
24
  }