@blxzer/cursor-trellis 0.4.1 → 0.4.3

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 (337) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +25 -14
  3. package/README.zh-CN.md +14 -10
  4. package/bin/smart-search.js +10 -2
  5. package/dist/cli/index.d.ts.map +1 -1
  6. package/dist/cli/index.js +36 -15
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/commands/init.d.ts +1 -1
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +42 -153
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/commands/migrate.d.ts +10 -0
  13. package/dist/commands/migrate.d.ts.map +1 -0
  14. package/dist/commands/migrate.js +38 -0
  15. package/dist/commands/migrate.js.map +1 -0
  16. package/dist/commands/update.d.ts +5 -0
  17. package/dist/commands/update.d.ts.map +1 -1
  18. package/dist/commands/update.js +144 -41
  19. package/dist/commands/update.js.map +1 -1
  20. package/dist/configurators/cursor.d.ts +2 -1
  21. package/dist/configurators/cursor.d.ts.map +1 -1
  22. package/dist/configurators/cursor.js +4 -2
  23. package/dist/configurators/cursor.js.map +1 -1
  24. package/dist/configurators/index.js +4 -4
  25. package/dist/configurators/index.js.map +1 -1
  26. package/dist/configurators/shared.d.ts +8 -0
  27. package/dist/configurators/shared.d.ts.map +1 -1
  28. package/dist/configurators/shared.js +27 -1
  29. package/dist/configurators/shared.js.map +1 -1
  30. package/dist/configurators/workflow.d.ts +0 -9
  31. package/dist/configurators/workflow.d.ts.map +1 -1
  32. package/dist/configurators/workflow.js +12 -45
  33. package/dist/configurators/workflow.js.map +1 -1
  34. package/dist/constants/paths.d.ts +13 -0
  35. package/dist/constants/paths.d.ts.map +1 -1
  36. package/dist/constants/paths.js +17 -0
  37. package/dist/constants/paths.js.map +1 -1
  38. package/dist/migrations/manifests/0.3.0.json +1 -1
  39. package/dist/templates/common/bundled-skills/cstl-check/SKILL.md +1 -1
  40. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/hooks-and-settings.md +2 -2
  41. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/overview.md +1 -1
  42. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/skills-and-commands.md +2 -4
  43. package/dist/templates/common/bundled-skills/cstl-skill-creator/SKILL.md +10 -7
  44. package/dist/templates/common/bundled-skills/cstl-skill-creator/references/authoring-rules.md +93 -19
  45. package/dist/templates/common/bundled-skills/cstl-skill-creator/references/general-authoring.md +189 -0
  46. package/dist/templates/common/bundled-skills/cstl-skill-creator/references/review-checklist.md +10 -5
  47. package/dist/templates/common/commands/continue.md +6 -5
  48. package/dist/templates/common/index.d.ts +20 -0
  49. package/dist/templates/common/index.d.ts.map +1 -1
  50. package/dist/templates/common/index.js +21 -2
  51. package/dist/templates/common/index.js.map +1 -1
  52. package/dist/templates/common/optional-skills/chrome-cdp/SKILL.md +179 -0
  53. package/dist/templates/common/optional-skills/chrome-cdp/examples/fetch-hook-api-capture.md +149 -0
  54. package/dist/templates/common/optional-skills/chrome-cdp/scripts/cdp.mjs +903 -0
  55. package/dist/templates/common/skills/brainstorm.md +2 -2
  56. package/dist/templates/cursor/agents/cstl-check.md +2 -2
  57. package/dist/templates/cursor/agents/cstl-implement.md +1 -1
  58. package/dist/templates/cursor/agents/cstl-research.md +2 -2
  59. package/dist/templates/cursor/fixtures/expected-rules.d.ts +1 -1
  60. package/dist/templates/cursor/fixtures/expected-rules.d.ts.map +1 -1
  61. package/dist/templates/cursor/fixtures/expected-rules.js +7 -24
  62. package/dist/templates/cursor/fixtures/expected-rules.js.map +1 -1
  63. package/dist/templates/cursor/hooks.json +4 -0
  64. package/dist/templates/cursor/index.d.ts +1 -1
  65. package/dist/templates/cursor/index.js +1 -1
  66. package/dist/templates/cursor/rules/cstl-bootstrap.mdc +17 -0
  67. package/dist/templates/markdown/agents.md +36 -3
  68. package/dist/templates/markdown/{spec/guides → framework}/cursor-native-modes-guide.md.txt +13 -10
  69. package/dist/templates/markdown/{spec/guides → framework}/cursor-subagent-policy.md.txt +63 -127
  70. package/dist/templates/markdown/framework/dogfood-only-surfaces.md.txt +29 -0
  71. package/dist/templates/markdown/{spec/guides → framework}/execution-strategy.md.txt +2 -0
  72. package/dist/templates/markdown/framework/index.md.txt +31 -0
  73. package/dist/templates/markdown/framework/internal-skills-cursor-reachability.md.txt +45 -0
  74. package/dist/templates/markdown/framework/middleware-protocol.md.txt +83 -0
  75. package/dist/templates/markdown/framework/parallel-first-execution.md.txt +78 -0
  76. package/dist/templates/markdown/framework/prd-grill-frontier.md.txt +83 -0
  77. package/dist/templates/markdown/framework/release-boundary.md.txt +30 -0
  78. package/dist/templates/markdown/{spec/guides → framework}/retrieval-daily-guide.md.txt +1 -1
  79. package/dist/templates/markdown/framework/upgrade.md.txt +15 -0
  80. package/dist/templates/markdown/{spec/guides → framework}/verification-strength-guide.md.txt +2 -2
  81. package/dist/templates/markdown/index.d.ts +26 -10
  82. package/dist/templates/markdown/index.d.ts.map +1 -1
  83. package/dist/templates/markdown/index.js +87 -11
  84. package/dist/templates/markdown/index.js.map +1 -1
  85. package/dist/templates/markdown/prompts/run-semantic-slice-12.md.txt +1 -1
  86. package/dist/templates/markdown/spec/guides/index.md.txt +5 -19
  87. package/dist/templates/markdown/spec/guides/prototype-guide.md.txt +10 -10
  88. package/dist/templates/markdown/spec/guides/test-discipline-guide.md.txt +1 -1
  89. package/dist/templates/shared-hooks/event-bridge.py +60 -0
  90. package/dist/templates/shared-hooks/index.d.ts +1 -1
  91. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  92. package/dist/templates/shared-hooks/index.js +1 -0
  93. package/dist/templates/shared-hooks/index.js.map +1 -1
  94. package/dist/templates/shared-hooks/session-start.py +19 -2
  95. package/dist/templates/trellis/CONTEXT.md +63 -3
  96. package/dist/templates/trellis/config.yaml +1 -1
  97. package/dist/templates/trellis/gitignore.txt +39 -39
  98. package/dist/templates/trellis/index.d.ts +12 -0
  99. package/dist/templates/trellis/index.d.ts.map +1 -1
  100. package/dist/templates/trellis/index.js +73 -15
  101. package/dist/templates/trellis/index.js.map +1 -1
  102. package/dist/templates/trellis/pool/README.md +12 -3
  103. package/dist/templates/trellis/pool/plan.md +24 -5
  104. package/dist/templates/trellis/scripts/common/adapter_middleware.py +158 -0
  105. package/dist/templates/trellis/scripts/common/artifact_locale.py +12 -3
  106. package/dist/templates/trellis/scripts/common/cursor_retrieval_env.py +5 -2
  107. package/dist/templates/trellis/scripts/common/full_quality.py +237 -0
  108. package/dist/templates/trellis/scripts/common/git.py +6 -0
  109. package/dist/templates/trellis/scripts/common/git_context.py +17 -5
  110. package/dist/templates/trellis/scripts/common/kernel_command.py +367 -0
  111. package/dist/templates/trellis/scripts/common/lite_context.py +280 -0
  112. package/dist/templates/trellis/scripts/common/ondemand_topology.py +225 -0
  113. package/dist/templates/trellis/scripts/common/parent_orchestration.py +1 -1
  114. package/dist/templates/trellis/scripts/common/pool_store.py +16 -4
  115. package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +2 -2
  116. package/dist/templates/trellis/scripts/common/session_context.py +28 -2
  117. package/dist/templates/trellis/scripts/common/task_gates.py +73 -12
  118. package/dist/templates/trellis/scripts/common/task_map.py +42 -9
  119. package/dist/templates/trellis/scripts/common/task_store.py +293 -61
  120. package/dist/templates/trellis/scripts/common/test_adapter_middleware.py +56 -0
  121. package/dist/templates/trellis/scripts/common/test_depends_mode_block.py +9 -0
  122. package/dist/templates/trellis/scripts/common/test_full_quality.py +197 -0
  123. package/dist/templates/trellis/scripts/common/test_kernel_command.py +326 -0
  124. package/dist/templates/trellis/scripts/common/test_lite_path.py +190 -0
  125. package/dist/templates/trellis/scripts/common/test_observable_defaults.py +10 -4
  126. package/dist/templates/trellis/scripts/common/test_ondemand_topology.py +122 -0
  127. package/dist/templates/trellis/scripts/common/test_pool_store.py +17 -0
  128. package/dist/templates/trellis/scripts/common/test_task_store_kernel_patch.py +163 -0
  129. package/dist/templates/trellis/scripts/common/workflow_phase.py +3 -0
  130. package/dist/templates/trellis/scripts/cursor_retrieval_probe_prompt.md +4 -5
  131. package/dist/templates/trellis/scripts/get_context.py +1 -0
  132. package/dist/templates/trellis/scripts/pool.py +5 -0
  133. package/dist/templates/trellis/scripts/task.py +83 -7
  134. package/dist/templates/trellis/workflow.md +109 -23
  135. package/dist/utils/cursor-retrieval-env.d.ts +2 -1
  136. package/dist/utils/cursor-retrieval-env.d.ts.map +1 -1
  137. package/dist/utils/cursor-retrieval-env.js +3 -2
  138. package/dist/utils/cursor-retrieval-env.js.map +1 -1
  139. package/dist/utils/cursor2plus-residue-cleanup.d.ts +38 -0
  140. package/dist/utils/cursor2plus-residue-cleanup.d.ts.map +1 -0
  141. package/dist/utils/cursor2plus-residue-cleanup.js +145 -0
  142. package/dist/utils/cursor2plus-residue-cleanup.js.map +1 -0
  143. package/dist/utils/manifest-prune.d.ts.map +1 -1
  144. package/dist/utils/manifest-prune.js +7 -2
  145. package/dist/utils/manifest-prune.js.map +1 -1
  146. package/dist/utils/p36-upgrade.d.ts +62 -0
  147. package/dist/utils/p36-upgrade.d.ts.map +1 -0
  148. package/dist/utils/p36-upgrade.js +160 -0
  149. package/dist/utils/p36-upgrade.js.map +1 -0
  150. package/dist/utils/project-capabilities.d.ts +1 -12
  151. package/dist/utils/project-capabilities.d.ts.map +1 -1
  152. package/dist/utils/project-capabilities.js +3 -100
  153. package/dist/utils/project-capabilities.js.map +1 -1
  154. package/dist/utils/readiness.d.ts +10 -0
  155. package/dist/utils/readiness.d.ts.map +1 -1
  156. package/dist/utils/readiness.js +58 -26
  157. package/dist/utils/readiness.js.map +1 -1
  158. package/dist/utils/retrieval-agent-instructions.js +1 -1
  159. package/dist/utils/retrieval-agent-instructions.js.map +1 -1
  160. package/dist/utils/retrieval-execution-telemetry.js +1 -1
  161. package/dist/utils/retrieval-execution-telemetry.js.map +1 -1
  162. package/dist/utils/template-hash.d.ts.map +1 -1
  163. package/dist/utils/template-hash.js +11 -1
  164. package/dist/utils/template-hash.js.map +1 -1
  165. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  166. package/dist/utils/uninstall-scrubbers.js +52 -14
  167. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  168. package/dist/utils/update-rollout-report.d.ts +14 -0
  169. package/dist/utils/update-rollout-report.d.ts.map +1 -1
  170. package/dist/utils/update-rollout-report.js +1 -0
  171. package/dist/utils/update-rollout-report.js.map +1 -1
  172. package/dist/utils/workflow-ownership.d.ts +1 -1
  173. package/dist/utils/workflow-ownership.js +4 -4
  174. package/dist/utils/workflow-ownership.js.map +1 -1
  175. package/package.json +5 -4
  176. package/scripts/postinstall.js +6 -7
  177. package/dist/commands/campaign/canvas-render.d.ts +0 -68
  178. package/dist/commands/campaign/canvas-render.d.ts.map +0 -1
  179. package/dist/commands/campaign/canvas-render.js +0 -414
  180. package/dist/commands/campaign/canvas-render.js.map +0 -1
  181. package/dist/commands/campaign/compose.d.ts +0 -15
  182. package/dist/commands/campaign/compose.d.ts.map +0 -1
  183. package/dist/commands/campaign/compose.js +0 -110
  184. package/dist/commands/campaign/compose.js.map +0 -1
  185. package/dist/commands/campaign/index.d.ts +0 -13
  186. package/dist/commands/campaign/index.d.ts.map +0 -1
  187. package/dist/commands/campaign/index.js +0 -134
  188. package/dist/commands/campaign/index.js.map +0 -1
  189. package/dist/commands/campaign/kind-map.d.ts +0 -6
  190. package/dist/commands/campaign/kind-map.d.ts.map +0 -1
  191. package/dist/commands/campaign/kind-map.js +0 -21
  192. package/dist/commands/campaign/kind-map.js.map +0 -1
  193. package/dist/commands/campaign/mcp-server.d.ts +0 -6
  194. package/dist/commands/campaign/mcp-server.d.ts.map +0 -1
  195. package/dist/commands/campaign/mcp-server.js +0 -167
  196. package/dist/commands/campaign/mcp-server.js.map +0 -1
  197. package/dist/commands/campaign/render.d.ts +0 -5
  198. package/dist/commands/campaign/render.d.ts.map +0 -1
  199. package/dist/commands/campaign/render.js +0 -103
  200. package/dist/commands/campaign/render.js.map +0 -1
  201. package/dist/commands/campaign/trellis-load.d.ts +0 -13
  202. package/dist/commands/campaign/trellis-load.d.ts.map +0 -1
  203. package/dist/commands/campaign/trellis-load.js +0 -122
  204. package/dist/commands/campaign/trellis-load.js.map +0 -1
  205. package/dist/commands/campaign/types.d.ts +0 -61
  206. package/dist/commands/campaign/types.d.ts.map +0 -1
  207. package/dist/commands/campaign/types.js +0 -3
  208. package/dist/commands/campaign/types.js.map +0 -1
  209. package/dist/commands/goal/index.d.ts +0 -3
  210. package/dist/commands/goal/index.d.ts.map +0 -1
  211. package/dist/commands/goal/index.js +0 -159
  212. package/dist/commands/goal/index.js.map +0 -1
  213. package/dist/commands/goal/review.d.ts +0 -6
  214. package/dist/commands/goal/review.d.ts.map +0 -1
  215. package/dist/commands/goal/review.js +0 -28
  216. package/dist/commands/goal/review.js.map +0 -1
  217. package/dist/commands/rpc/client.d.ts +0 -51
  218. package/dist/commands/rpc/client.d.ts.map +0 -1
  219. package/dist/commands/rpc/client.js +0 -147
  220. package/dist/commands/rpc/client.js.map +0 -1
  221. package/dist/commands/rpc/index.d.ts +0 -10
  222. package/dist/commands/rpc/index.d.ts.map +0 -1
  223. package/dist/commands/rpc/index.js +0 -157
  224. package/dist/commands/rpc/index.js.map +0 -1
  225. package/dist/commands/rpc/serve.d.ts +0 -23
  226. package/dist/commands/rpc/serve.d.ts.map +0 -1
  227. package/dist/commands/rpc/serve.js +0 -60
  228. package/dist/commands/rpc/serve.js.map +0 -1
  229. package/dist/commands/rpc/smoke.d.ts +0 -16
  230. package/dist/commands/rpc/smoke.d.ts.map +0 -1
  231. package/dist/commands/rpc/smoke.js +0 -92
  232. package/dist/commands/rpc/smoke.js.map +0 -1
  233. package/dist/commands/sdk/index.d.ts +0 -9
  234. package/dist/commands/sdk/index.d.ts.map +0 -1
  235. package/dist/commands/sdk/index.js +0 -58
  236. package/dist/commands/sdk/index.js.map +0 -1
  237. package/dist/commands/sdk/run.d.ts +0 -42
  238. package/dist/commands/sdk/run.d.ts.map +0 -1
  239. package/dist/commands/sdk/run.js +0 -220
  240. package/dist/commands/sdk/run.js.map +0 -1
  241. package/dist/commands/sdk/status.d.ts +0 -14
  242. package/dist/commands/sdk/status.d.ts.map +0 -1
  243. package/dist/commands/sdk/status.js +0 -69
  244. package/dist/commands/sdk/status.js.map +0 -1
  245. package/dist/configurators/cursor2plus-local.d.ts +0 -6
  246. package/dist/configurators/cursor2plus-local.d.ts.map +0 -1
  247. package/dist/configurators/cursor2plus-local.js +0 -21
  248. package/dist/configurators/cursor2plus-local.js.map +0 -1
  249. package/dist/goal/action-packet.d.ts +0 -89
  250. package/dist/goal/action-packet.d.ts.map +0 -1
  251. package/dist/goal/action-packet.js +0 -113
  252. package/dist/goal/action-packet.js.map +0 -1
  253. package/dist/goal/audit.d.ts +0 -14
  254. package/dist/goal/audit.d.ts.map +0 -1
  255. package/dist/goal/audit.js +0 -12
  256. package/dist/goal/audit.js.map +0 -1
  257. package/dist/goal/constants.d.ts +0 -26
  258. package/dist/goal/constants.d.ts.map +0 -1
  259. package/dist/goal/constants.js +0 -24
  260. package/dist/goal/constants.js.map +0 -1
  261. package/dist/goal/paths.d.ts +0 -8
  262. package/dist/goal/paths.d.ts.map +0 -1
  263. package/dist/goal/paths.js +0 -36
  264. package/dist/goal/paths.js.map +0 -1
  265. package/dist/goal/preflight.d.ts +0 -21
  266. package/dist/goal/preflight.d.ts.map +0 -1
  267. package/dist/goal/preflight.js +0 -97
  268. package/dist/goal/preflight.js.map +0 -1
  269. package/dist/goal/review-seam.d.ts +0 -44
  270. package/dist/goal/review-seam.d.ts.map +0 -1
  271. package/dist/goal/review-seam.js +0 -153
  272. package/dist/goal/review-seam.js.map +0 -1
  273. package/dist/goal/reviewer-rules.d.ts +0 -13
  274. package/dist/goal/reviewer-rules.d.ts.map +0 -1
  275. package/dist/goal/reviewer-rules.js +0 -153
  276. package/dist/goal/reviewer-rules.js.map +0 -1
  277. package/dist/goal/reviewer.d.ts +0 -9
  278. package/dist/goal/reviewer.d.ts.map +0 -1
  279. package/dist/goal/reviewer.js +0 -54
  280. package/dist/goal/reviewer.js.map +0 -1
  281. package/dist/goal/runtime.d.ts +0 -32
  282. package/dist/goal/runtime.d.ts.map +0 -1
  283. package/dist/goal/runtime.js +0 -242
  284. package/dist/goal/runtime.js.map +0 -1
  285. package/dist/goal/sdk-client.d.ts +0 -10
  286. package/dist/goal/sdk-client.d.ts.map +0 -1
  287. package/dist/goal/sdk-client.js +0 -34
  288. package/dist/goal/sdk-client.js.map +0 -1
  289. package/dist/goal/state.d.ts +0 -40
  290. package/dist/goal/state.d.ts.map +0 -1
  291. package/dist/goal/state.js +0 -37
  292. package/dist/goal/state.js.map +0 -1
  293. package/dist/goal/task-triggers.d.ts +0 -15
  294. package/dist/goal/task-triggers.d.ts.map +0 -1
  295. package/dist/goal/task-triggers.js +0 -23
  296. package/dist/goal/task-triggers.js.map +0 -1
  297. package/dist/goal/walls.d.ts +0 -12
  298. package/dist/goal/walls.d.ts.map +0 -1
  299. package/dist/goal/walls.js +0 -65
  300. package/dist/goal/walls.js.map +0 -1
  301. package/dist/goal/worker-prompt.d.ts +0 -13
  302. package/dist/goal/worker-prompt.d.ts.map +0 -1
  303. package/dist/goal/worker-prompt.js +0 -41
  304. package/dist/goal/worker-prompt.js.map +0 -1
  305. package/dist/goal/worker.d.ts +0 -42
  306. package/dist/goal/worker.d.ts.map +0 -1
  307. package/dist/goal/worker.js +0 -180
  308. package/dist/goal/worker.js.map +0 -1
  309. package/dist/templates/common/bundled-skills/cstl-cursor2plus-setup/SKILL.md +0 -63
  310. package/dist/templates/cursor/commands/cursor2plus-setup.md +0 -82
  311. package/dist/templates/cursor/rules/cstl-cursor-modes.mdc +0 -32
  312. package/dist/templates/cursor/rules/cstl-session-rename.mdc +0 -31
  313. package/dist/templates/cursor/rules/cstl-subagent-dispatch.mdc +0 -34
  314. package/dist/templates/cursor/rules/cstl-triage.mdc +0 -36
  315. package/dist/templates/cursor/rules/retrieval-routing.mdc +0 -78
  316. package/dist/templates/markdown/spec/guides/cursor-trellis-release-coexistence-guide.md.txt +0 -166
  317. package/dist/templates/markdown/spec/guides/goal-release-regression-runbook.md.txt +0 -132
  318. package/dist/templates/trellis/local/README.md +0 -85
  319. package/dist/templates/trellis/local/config.local.json.example +0 -6
  320. package/dist/templates/trellis/local/index.d.ts +0 -8
  321. package/dist/templates/trellis/local/index.d.ts.map +0 -1
  322. package/dist/templates/trellis/local/index.js +0 -15
  323. package/dist/templates/trellis/local/index.js.map +0 -1
  324. package/dist/templates/trellis/local/patch_wpelc8.py +0 -421
  325. package/dist/templates/trellis/local/smoke.py +0 -94
  326. package/dist/templates/trellis/local/subagent-models.json.example +0 -4
  327. package/dist/templates/trellis/local/trellis-task-models.json.example +0 -10
  328. package/dist/templates/trellis/local/trellis-task-models.json5.example +0 -45
  329. package/dist/templates/trellis/local/trellis_task_models_config.py +0 -200
  330. package/dist/utils/cursor-sdk-gate.d.ts +0 -10
  331. package/dist/utils/cursor-sdk-gate.d.ts.map +0 -1
  332. package/dist/utils/cursor-sdk-gate.js +0 -32
  333. package/dist/utils/cursor-sdk-gate.js.map +0 -1
  334. /package/dist/templates/markdown/{spec/guides → framework}/artifact-locale-guide.md.txt +0 -0
  335. /package/dist/templates/markdown/{spec/guides → framework}/cursor-context-injection-guide.md.txt +0 -0
  336. /package/dist/templates/markdown/{spec/guides → framework}/cursor-semantic-compliance.md.txt +0 -0
  337. /package/dist/templates/markdown/{spec/guides → framework}/injection-budget-guide.md.txt +0 -0
@@ -0,0 +1,158 @@
1
+ """Stage 6 Event Bridge + Middleware Provider projection.
2
+
3
+ Kernel extras remain authoritative. This module mirrors the contract for
4
+ hooks and tests. It does not write a second store or invent Command ops.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ STAGE6_SOURCE = "stage6-adapter-middleware"
12
+ STAGE6_SCHEMA_VERSION = 1
13
+ SMART_SEARCH_PROVIDER = "smart-search"
14
+ EXTERNAL_KNOWLEDGE_CAPABILITY = "external-knowledge"
15
+ RETRIEVAL_INTENTS = ("exact", "semantic", "structural", "external")
16
+ OPTIONAL_CODE_INTEL_PROVIDERS = ("codegraph", "fast-context")
17
+
18
+
19
+ class AdapterMiddlewareError(RuntimeError):
20
+ """Event Bridge / Middleware contract rejected a request."""
21
+
22
+
23
+ def default_event_bridge() -> dict[str, Any]:
24
+ return {
25
+ "schema_version": STAGE6_SCHEMA_VERSION,
26
+ "source": STAGE6_SOURCE,
27
+ "subscriptions": [],
28
+ }
29
+
30
+
31
+ def default_middleware_providers() -> dict[str, Any]:
32
+ return {
33
+ "schema_version": STAGE6_SCHEMA_VERSION,
34
+ "source": STAGE6_SOURCE,
35
+ "registered": [SMART_SEARCH_PROVIDER],
36
+ "required": [SMART_SEARCH_PROVIDER],
37
+ "active": [],
38
+ "degraded": [],
39
+ "readiness": {
40
+ SMART_SEARCH_PROVIDER: {
41
+ "status": "unknown",
42
+ "capability": EXTERNAL_KNOWLEDGE_CAPABILITY,
43
+ "evidence": None,
44
+ }
45
+ },
46
+ }
47
+
48
+
49
+ def default_capability_router() -> dict[str, Any]:
50
+ return {
51
+ "schema_version": STAGE6_SCHEMA_VERSION,
52
+ "source": STAGE6_SOURCE,
53
+ "exact": True,
54
+ "semantic": True,
55
+ "structural": True,
56
+ "external": True,
57
+ }
58
+
59
+
60
+ def dispatch_hook_event(
61
+ event_bridge: dict[str, Any],
62
+ event: str,
63
+ *,
64
+ source: str = "cursor-hooks",
65
+ at: str | None = None,
66
+ ) -> dict[str, Any]:
67
+ name = (event or "").strip()
68
+ if not name:
69
+ raise AdapterMiddlewareError("event_bridge.last_event.event must be a non-empty string")
70
+ delivered: list[str] = []
71
+ skipped: list[str] = []
72
+ for item in event_bridge.get("subscriptions") or []:
73
+ if not isinstance(item, dict):
74
+ continue
75
+ module = str(item.get("module") or "").strip()
76
+ if not module:
77
+ continue
78
+ if item.get("event") == name:
79
+ if module not in delivered:
80
+ delivered.append(module)
81
+ else:
82
+ skipped.append(module)
83
+ return {
84
+ "event": name,
85
+ "at": at or "",
86
+ "source": source,
87
+ "delivered": delivered,
88
+ "skipped": skipped,
89
+ }
90
+
91
+
92
+ def probe_smart_search_readiness(*, available: bool | None = None, status: str | None = None) -> dict[str, Any]:
93
+ resolved = status
94
+ if resolved not in {"ready", "missing", "failed", "unknown"}:
95
+ if available is True:
96
+ resolved = "ready"
97
+ elif available is False:
98
+ resolved = "missing"
99
+ else:
100
+ resolved = "unknown"
101
+ return {
102
+ "status": resolved,
103
+ "capability": EXTERNAL_KNOWLEDGE_CAPABILITY,
104
+ "evidence": None,
105
+ }
106
+
107
+
108
+ def normalize_capability_router(raw: Any) -> dict[str, Any]:
109
+ if raw is None:
110
+ return default_capability_router()
111
+ if not isinstance(raw, dict):
112
+ raise AdapterMiddlewareError("capability_router must be a JSON object")
113
+ for key in list(raw.keys()):
114
+ if key in OPTIONAL_CODE_INTEL_PROVIDERS or key in {
115
+ "fast_context_search",
116
+ "codegraph_explore",
117
+ "codegraph_search",
118
+ "codegraph_callers",
119
+ }:
120
+ raise AdapterMiddlewareError("capability_router must not bind Optional tool names")
121
+ next_router = default_capability_router()
122
+ for intent in RETRIEVAL_INTENTS:
123
+ if raw.get(intent) is False:
124
+ next_router.pop(intent, None)
125
+ else:
126
+ next_router[intent] = True
127
+ return next_router
128
+
129
+
130
+ def required_capabilities(extras: dict[str, Any]) -> list[str]:
131
+ raw = extras.get("required_capabilities") or []
132
+ if not isinstance(raw, list):
133
+ return []
134
+ out: list[str] = []
135
+ for item in raw:
136
+ if isinstance(item, str) and item.strip() and item not in out:
137
+ out.append(item.strip())
138
+ return out
139
+
140
+
141
+ def assert_external_knowledge(
142
+ extras: dict[str, Any],
143
+ readiness: dict[str, Any],
144
+ *,
145
+ phase: str,
146
+ ) -> None:
147
+ if phase in {"create", "patch"}:
148
+ return
149
+ if EXTERNAL_KNOWLEDGE_CAPABILITY not in required_capabilities(extras):
150
+ return
151
+ if readiness.get("status") == "ready":
152
+ return
153
+ if extras.get("external_knowledge_policy") == "degrade":
154
+ extras["profile_health"] = "degraded"
155
+ return
156
+ raise AdapterMiddlewareError(
157
+ "external-knowledge required but smart-search Provider is not ready"
158
+ )
@@ -8,7 +8,8 @@ import sys
8
8
  from pathlib import Path
9
9
 
10
10
  from .config import CONFIG_FILE
11
- from .io import read_json, write_json
11
+ from .io import read_json
12
+ from .kernel_command import kernel_expected_revision, kernel_patch, kernel_projection_extras
12
13
  from .paths import DIR_TASKS, DIR_WORKFLOW, FILE_TASK_JSON, get_repo_root
13
14
 
14
15
  VALID_LOCALES = ("zh", "en")
@@ -272,7 +273,7 @@ def set_workspace_artifact_locale(locale: str, repo_root: Path | None = None) ->
272
273
 
273
274
 
274
275
  def set_task_artifact_locale(task_dir: Path, locale: str, repo_root: Path | None = None) -> None:
275
- """Write task.json meta.artifact_locale."""
276
+ """Write task.json meta.artifact_locale via Kernel patch."""
276
277
  _ = repo_root
277
278
  normalized = normalize_locale(locale)
278
279
  if not normalized:
@@ -291,4 +292,12 @@ def set_task_artifact_locale(task_dir: Path, locale: str, repo_root: Path | None
291
292
  meta = {}
292
293
  meta[_ARTIFACT_LOCALE_KEY] = normalized
293
294
  data["meta"] = meta
294
- write_json(task_json, data)
295
+ kernel_patch(
296
+ task_dir,
297
+ data,
298
+ kernel_projection_extras(data),
299
+ expected_revision=kernel_expected_revision(task_dir),
300
+ actor="artifact_locale.set_task_artifact_locale",
301
+ idempotency_key=f"patch:artifact-locale:{task_dir.name}:{normalized}",
302
+ evidence="meta.artifact_locale",
303
+ )
@@ -1,4 +1,7 @@
1
- """Detect Cursor Native vs Cursor++ BYOK for retrieval routing."""
1
+ """Detect Cursor Native vs BYOK environment for retrieval routing.
2
+
3
+ This is an environment probe, not a product install surface.
4
+ """
2
5
 
3
6
  from __future__ import annotations
4
7
 
@@ -92,7 +95,7 @@ def semantic_route_spec(cursor_env: CursorRetrievalEnv) -> dict[str, object]:
92
95
  return {
93
96
  "commands": ["fast_context_search (fast-context MCP)"],
94
97
  "rationale_suffix": (
95
- " Cursor++ BYOK: built-in semantic unavailable; fast-context MCP primary."
98
+ " BYOK env probe: built-in semantic unavailable; Optional fast-context only if selected."
96
99
  + unknown_caveat
97
100
  ),
98
101
  "platformNative": False,
@@ -0,0 +1,237 @@
1
+ """Stage 4 Full Quality helpers (controls, AC ledger, graded Independent Check).
2
+
3
+ Python projection of the Kernel Full Quality contract. Kernel remains the
4
+ writer; these helpers validate extras before archive and prefer persisted
5
+ required_controls over inferring Rigor from files.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import re
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ FULL_QUALITY_SOURCE = "full-quality-contract"
16
+ FULL_QUALITY_SCHEMA_VERSION = 1
17
+ FULL_BASELINE_CONTROLS = (
18
+ "definition",
19
+ "execution-contract",
20
+ "verification-plan",
21
+ "evidence",
22
+ "independent-check",
23
+ )
24
+ DEFAULT_CONTROL_SURFACES = {
25
+ "definition": "prd.md",
26
+ "execution-contract": "implement.md",
27
+ "verification-plan": "implement.md",
28
+ "evidence": "verify.md",
29
+ "design": "design.md",
30
+ }
31
+ DESIGN_RISK_SIGNALS = {
32
+ "architecture",
33
+ "public-contract",
34
+ "schema",
35
+ "security",
36
+ "secret",
37
+ "framework-semantics",
38
+ "runtime-semantics",
39
+ }
40
+ PLACEHOLDER_VALUE_RE = re.compile(
41
+ r"(?i)^(TBD|TODO|待定|待补充|N/?A|NA|NONE|-|\.\.\.)$"
42
+ )
43
+ AC_ITEM_RE = re.compile(r"(?im)^\s*-\s*\[[ xX]\]\s+(.+)$")
44
+
45
+
46
+ class FullQualityError(RuntimeError):
47
+ """Full Quality contract rejected a start/close request."""
48
+
49
+
50
+ def quality_fingerprint(payload: str) -> str:
51
+ digest = hashlib.sha256(payload.encode("utf-8")).hexdigest()
52
+ return f"sha256:{digest}"
53
+
54
+
55
+ def resolve_required_controls(
56
+ *,
57
+ rigor: str = "lite",
58
+ verification_profile: str | None = None,
59
+ risk_signals: list[str] | None = None,
60
+ policy_requires_design: bool = False,
61
+ explicit_controls: list[str] | None = None,
62
+ surfaces: dict[str, str] | None = None,
63
+ ) -> dict[str, Any]:
64
+ normalized = "full" if rigor == "full" else "lite"
65
+ signals = [str(item).strip().lower() for item in (risk_signals or []) if item]
66
+ design_required = normalized == "full" and (
67
+ policy_requires_design
68
+ or verification_profile == "architecture"
69
+ or any(signal in DESIGN_RISK_SIGNALS for signal in signals)
70
+ )
71
+ if explicit_controls:
72
+ controls = _unique(explicit_controls)
73
+ elif normalized == "full":
74
+ controls = list(FULL_BASELINE_CONTROLS)
75
+ if design_required:
76
+ controls.append("design")
77
+ else:
78
+ controls = ["definition", "evidence"]
79
+ if design_required and "design" not in controls:
80
+ controls.append("design")
81
+ return {
82
+ "schema_version": FULL_QUALITY_SCHEMA_VERSION,
83
+ "source": FULL_QUALITY_SOURCE,
84
+ "rigor": normalized,
85
+ "controls": controls,
86
+ "surfaces": {**DEFAULT_CONTROL_SURFACES, **(surfaces or {})},
87
+ "resolved_from": {
88
+ "verification_profile": verification_profile,
89
+ "risk_signals": signals,
90
+ "policy_requires_design": policy_requires_design,
91
+ },
92
+ }
93
+
94
+
95
+ def rigor_from_required_controls(task_data: dict | None) -> str | None:
96
+ extras = task_data or {}
97
+ bundle = extras.get("required_controls")
98
+ if not isinstance(bundle, dict):
99
+ return None
100
+ rigor = bundle.get("rigor")
101
+ if rigor in ("lite", "full"):
102
+ return rigor
103
+ return None
104
+
105
+
106
+ def parse_acceptance_items(prd_text: str) -> list[dict[str, str]]:
107
+ items: list[dict[str, str]] = []
108
+ index = 0
109
+ for match in AC_ITEM_RE.finditer(prd_text):
110
+ statement = match.group(1).strip()
111
+ if not statement or PLACEHOLDER_VALUE_RE.match(statement):
112
+ continue
113
+ index += 1
114
+ items.append({"id": f"AC-{index}", "statement": statement})
115
+ return items
116
+
117
+
118
+ def evaluate_independent_check(
119
+ *,
120
+ mode: str,
121
+ independent_worker_available: bool,
122
+ evidence: str,
123
+ code_fingerprint: str,
124
+ attempted_writes: bool = False,
125
+ ) -> dict[str, Any]:
126
+ if attempted_writes:
127
+ raise FullQualityError("Independent Check is read-only; repairs return to Execute")
128
+ if mode not in ("self-review", "true-independent"):
129
+ raise FullQualityError("Independent Check mode must be self-review or true-independent")
130
+ if mode == "true-independent" and not independent_worker_available:
131
+ return {
132
+ "schema_version": FULL_QUALITY_SCHEMA_VERSION,
133
+ "mode": "true-independent",
134
+ "readonly": True,
135
+ "result": "BLOCKED",
136
+ "evidence": evidence.strip(),
137
+ "independent_worker": False,
138
+ "code_fingerprint": code_fingerprint,
139
+ }
140
+ if not evidence.strip() or PLACEHOLDER_VALUE_RE.match(evidence.strip()):
141
+ raise FullQualityError(
142
+ "Independent Check PASS/FAIL requires non-empty evidence (no fake-green)"
143
+ )
144
+ return {
145
+ "schema_version": FULL_QUALITY_SCHEMA_VERSION,
146
+ "mode": mode,
147
+ "readonly": True,
148
+ "result": "PASS",
149
+ "evidence": evidence.strip(),
150
+ "independent_worker": independent_worker_available,
151
+ "code_fingerprint": code_fingerprint,
152
+ }
153
+
154
+
155
+ def full_quality_archive_errors(task_dir: Path, task_data: dict | None) -> list[str]:
156
+ """Return archive errors for persisted Full required_controls only.
157
+
158
+ Lite and legacy file-heuristic Full are unchanged: this does not force
159
+ Independent Check onto Lite.
160
+ """
161
+ data = task_data or {}
162
+ bundle = data.get("required_controls")
163
+ if not isinstance(bundle, dict) or bundle.get("rigor") != "full":
164
+ return []
165
+ errors: list[str] = []
166
+ controls = bundle.get("controls")
167
+ if not isinstance(controls, list):
168
+ controls = list(FULL_BASELINE_CONTROLS)
169
+ surfaces = bundle.get("surfaces") if isinstance(bundle.get("surfaces"), dict) else {}
170
+ seen: set[str] = set()
171
+ for control in controls:
172
+ if control in ("independent-check",):
173
+ continue
174
+ relative = surfaces.get(control) or DEFAULT_CONTROL_SURFACES.get(control)
175
+ if not relative or relative in seen:
176
+ continue
177
+ seen.add(relative)
178
+ path = task_dir / relative
179
+ if not path.is_file() or not path.read_text(encoding="utf-8").strip():
180
+ errors.append(f"Full required control {control} missing surface {relative}")
181
+
182
+ ledger = data.get("ac_evidence_ledger")
183
+ if not isinstance(ledger, dict):
184
+ errors.append("Full Close requires a machine-readable AC → Evidence ledger")
185
+ else:
186
+ definition = surfaces.get("definition") or DEFAULT_CONTROL_SURFACES["definition"]
187
+ prd_path = task_dir / definition
188
+ prd_text = prd_path.read_text(encoding="utf-8") if prd_path.is_file() else ""
189
+ acceptance = parse_acceptance_items(prd_text)
190
+ mapped = {
191
+ item.get("ac_id"): item
192
+ for item in ledger.get("items", [])
193
+ if isinstance(item, dict)
194
+ }
195
+ if not acceptance:
196
+ errors.append(f"{definition} has no Acceptance Criteria items to map")
197
+ for item in acceptance:
198
+ mapping = mapped.get(item["id"])
199
+ ref = mapping.get("evidence_ref") if isinstance(mapping, dict) else ""
200
+ if not isinstance(ref, str) or not ref.strip() or PLACEHOLDER_VALUE_RE.match(ref.strip()):
201
+ errors.append(f"AC → Evidence ledger missing mapping for {item['id']}")
202
+ current_source = quality_fingerprint(prd_text)
203
+ if ledger.get("source_fingerprint") and ledger.get("source_fingerprint") != current_source:
204
+ errors.append("AC → Evidence ledger is stale after Definition/code change")
205
+
206
+ check = data.get("independent_check")
207
+ if not isinstance(check, dict):
208
+ errors.append("Full Close requires a graded Independent Check verdict")
209
+ else:
210
+ if check.get("readonly") is False:
211
+ errors.append("Independent Check is read-only; repairs return to Execute")
212
+ mode = check.get("mode") or check.get("assurance")
213
+ if mode == "true-independent" and check.get("independent_worker") is not True:
214
+ errors.append("true-independent Check cannot be satisfied without an independent worker")
215
+ if check.get("result") != "PASS":
216
+ errors.append("Full Close requires Independent Check result PASS")
217
+ evidence = check.get("evidence")
218
+ if not isinstance(evidence, str) or not evidence.strip():
219
+ errors.append("Independent Check PASS requires non-empty evidence (no fake-green)")
220
+ ledger = data.get("ac_evidence_ledger")
221
+ if (
222
+ isinstance(ledger, dict)
223
+ and isinstance(ledger.get("tested_code_fingerprint"), str)
224
+ and isinstance(check.get("code_fingerprint"), str)
225
+ and check.get("code_fingerprint") != ledger.get("tested_code_fingerprint")
226
+ ):
227
+ errors.append("Independent Check verdict is stale after code change")
228
+ return errors
229
+
230
+
231
+ def _unique(values: list[str]) -> list[str]:
232
+ out: list[str] = []
233
+ for value in values:
234
+ item = value.strip()
235
+ if item and item not in out:
236
+ out.append(item)
237
+ return out
@@ -29,3 +29,9 @@ def run_git(args: list[str], cwd: Path | None = None) -> tuple[int, str, str]:
29
29
  return result.returncode, result.stdout, result.stderr
30
30
  except Exception as e:
31
31
  return 1, "", str(e)
32
+
33
+
34
+ def is_git_worktree(path: Path) -> bool:
35
+ """Return True when path is inside a Git worktree. VCS is On-demand."""
36
+ rc, out, _ = run_git(["rev-parse", "--is-inside-work-tree"], cwd=path)
37
+ return rc == 0 and out.strip().lower() == "true"
@@ -28,8 +28,7 @@ from .packages_context import (
28
28
  get_context_packages_json,
29
29
  )
30
30
  from .paths import get_repo_root
31
- from .project_file_stats import resolve_project_file_count_arg
32
- from .retrieval_pack_context import output_retrieval_pack_json, read_evidence_input
31
+ from .lite_context import LiteContextPackError, get_lite_context_json
33
32
  from .trellis_config import read_trellis_config
34
33
  from .workflow_phase import (
35
34
  filter_platform,
@@ -60,13 +59,14 @@ def main() -> None:
60
59
  parser.add_argument(
61
60
  "--mode",
62
61
  "-m",
63
- choices=["default", "record", "packages", "phase", "retrieval-pack"],
62
+ choices=["default", "record", "packages", "phase", "retrieval-pack", "lite"],
64
63
  default="default",
65
64
  help=(
66
65
  "Output mode: default (full context), record (for record-session), "
67
66
  "packages (package info only), phase (workflow step extraction), "
68
67
  "retrieval-pack (score and pack already-collected retrieval evidence; "
69
- "use after research collection, not on every SessionStart)"
68
+ "use after research collection, not on every SessionStart), "
69
+ "lite (Personal Lite phase pack with budget; no Parent/VCS/retrieval-extended)"
70
70
  ),
71
71
  )
72
72
  parser.add_argument(
@@ -138,12 +138,18 @@ def main() -> None:
138
138
  print(content, end="")
139
139
  elif args.mode == "retrieval-pack":
140
140
  try:
141
+ from .project_file_stats import resolve_project_file_count_arg
142
+ from .retrieval_pack_context import (
143
+ output_retrieval_pack_json,
144
+ read_evidence_input,
145
+ )
146
+
141
147
  evidence = read_evidence_input(args.input)
142
148
  project_file_count = resolve_project_file_count_arg(
143
149
  args.project_file_count,
144
150
  repo_root=get_repo_root(),
145
151
  )
146
- except (OSError, json.JSONDecodeError, ValueError) as error:
152
+ except (OSError, json.JSONDecodeError, ValueError, ImportError) as error:
147
153
  parser.exit(1, f"retrieval pack error: {error}\n")
148
154
  output_retrieval_pack_json(
149
155
  evidence_input=evidence,
@@ -153,6 +159,12 @@ def main() -> None:
153
159
  pretty=args.json,
154
160
  project_file_count=project_file_count,
155
161
  )
162
+ elif args.mode == "lite":
163
+ try:
164
+ pack = get_lite_context_json()
165
+ except LiteContextPackError as error:
166
+ parser.exit(1, f"lite context pack error: {error}\n")
167
+ print(json.dumps(pack, indent=2 if args.json else None, ensure_ascii=False))
156
168
  else:
157
169
  if args.json:
158
170
  output_json()