frappe-builder 1.1.0-dev.8

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 (423) hide show
  1. package/.fb/state.db +0 -0
  2. package/AGENTS.md +167 -0
  3. package/README.md +89 -0
  4. package/_bmad/_config/agent-manifest.csv +10 -0
  5. package/_bmad/_config/agents/bmm-analyst.customize.yaml +41 -0
  6. package/_bmad/_config/agents/bmm-architect.customize.yaml +41 -0
  7. package/_bmad/_config/agents/bmm-dev.customize.yaml +41 -0
  8. package/_bmad/_config/agents/bmm-pm.customize.yaml +41 -0
  9. package/_bmad/_config/agents/bmm-qa.customize.yaml +41 -0
  10. package/_bmad/_config/agents/bmm-quick-flow-solo-dev.customize.yaml +41 -0
  11. package/_bmad/_config/agents/bmm-sm.customize.yaml +41 -0
  12. package/_bmad/_config/agents/bmm-tech-writer.customize.yaml +41 -0
  13. package/_bmad/_config/agents/bmm-ux-designer.customize.yaml +41 -0
  14. package/_bmad/_config/bmad-help.csv +47 -0
  15. package/_bmad/_config/files-manifest.csv +369 -0
  16. package/_bmad/_config/ides/claude-code.yaml +5 -0
  17. package/_bmad/_config/manifest.yaml +28 -0
  18. package/_bmad/_config/skill-manifest.csv +41 -0
  19. package/_bmad/_config/task-manifest.csv +1 -0
  20. package/_bmad/_config/tool-manifest.csv +1 -0
  21. package/_bmad/_config/workflow-manifest.csv +1 -0
  22. package/_bmad/_memory/config.yaml +11 -0
  23. package/_bmad/_memory/tech-writer-sidecar/documentation-standards.md +224 -0
  24. package/_bmad/bmm/agents/analyst.md +69 -0
  25. package/_bmad/bmm/agents/architect.md +59 -0
  26. package/_bmad/bmm/agents/bmad-skill-manifest.yaml +39 -0
  27. package/_bmad/bmm/agents/dev.md +66 -0
  28. package/_bmad/bmm/agents/pm.md +63 -0
  29. package/_bmad/bmm/agents/qa.md +89 -0
  30. package/_bmad/bmm/agents/quick-flow-solo-dev.md +61 -0
  31. package/_bmad/bmm/agents/sm.md +67 -0
  32. package/_bmad/bmm/agents/tech-writer/bmad-skill-manifest.yaml +3 -0
  33. package/_bmad/bmm/agents/tech-writer/tech-writer.md +67 -0
  34. package/_bmad/bmm/agents/ux-designer.md +58 -0
  35. package/_bmad/bmm/config.yaml +16 -0
  36. package/_bmad/bmm/data/project-context-template.md +26 -0
  37. package/_bmad/bmm/module-help.csv +32 -0
  38. package/_bmad/bmm/teams/default-party.csv +20 -0
  39. package/_bmad/bmm/teams/team-fullstack.yaml +12 -0
  40. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/SKILL.md +6 -0
  41. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/bmad-skill-manifest.yaml +1 -0
  42. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/product-brief.template.md +10 -0
  43. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-01-init.md +170 -0
  44. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-01b-continue.md +158 -0
  45. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-02-vision.md +193 -0
  46. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-03-users.md +196 -0
  47. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-04-metrics.md +199 -0
  48. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-05-scope.md +213 -0
  49. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-06-complete.md +159 -0
  50. package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/workflow.md +55 -0
  51. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/SKILL.md +88 -0
  52. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/artifact-analyzer.md +60 -0
  53. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/opportunity-reviewer.md +44 -0
  54. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/skeptic-reviewer.md +44 -0
  55. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/web-researcher.md +49 -0
  56. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/bmad-manifest.json +17 -0
  57. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/bmad-skill-manifest.yaml +1 -0
  58. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/contextual-discovery.md +57 -0
  59. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/draft-and-review.md +86 -0
  60. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/finalize.md +75 -0
  61. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/guided-elicitation.md +70 -0
  62. package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/resources/brief-template.md +60 -0
  63. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/SKILL.md +6 -0
  64. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/bmad-skill-manifest.yaml +1 -0
  65. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-01-init.md +137 -0
  66. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-02-domain-analysis.md +229 -0
  67. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-03-competitive-landscape.md +238 -0
  68. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-04-regulatory-focus.md +206 -0
  69. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-05-technical-trends.md +234 -0
  70. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-06-research-synthesis.md +444 -0
  71. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/research.template.md +29 -0
  72. package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/workflow.md +49 -0
  73. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/SKILL.md +6 -0
  74. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/bmad-skill-manifest.yaml +1 -0
  75. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/research.template.md +29 -0
  76. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-01-init.md +184 -0
  77. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-02-customer-behavior.md +239 -0
  78. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-03-customer-pain-points.md +251 -0
  79. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-04-customer-decisions.md +261 -0
  80. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-05-competitive-analysis.md +173 -0
  81. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-06-research-completion.md +478 -0
  82. package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/workflow.md +49 -0
  83. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/SKILL.md +6 -0
  84. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/bmad-skill-manifest.yaml +1 -0
  85. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/research.template.md +29 -0
  86. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-01-init.md +137 -0
  87. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-02-technical-overview.md +239 -0
  88. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-03-integration-patterns.md +248 -0
  89. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-04-architectural-patterns.md +202 -0
  90. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-05-implementation-research.md +233 -0
  91. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-06-research-synthesis.md +487 -0
  92. package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/workflow.md +50 -0
  93. package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +182 -0
  94. package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +237 -0
  95. package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +249 -0
  96. package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +259 -0
  97. package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +177 -0
  98. package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +476 -0
  99. package/_bmad/bmm/workflows/1-analysis/research/research.template.md +29 -0
  100. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/SKILL.md +6 -0
  101. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/bmad-skill-manifest.yaml +1 -0
  102. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-01-init.md +135 -0
  103. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-01b-continue.md +127 -0
  104. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-02-discovery.md +190 -0
  105. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-03-core-experience.md +217 -0
  106. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-04-emotional-response.md +220 -0
  107. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-05-inspiration.md +235 -0
  108. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-06-design-system.md +253 -0
  109. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-07-defining-experience.md +255 -0
  110. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-08-visual-foundation.md +225 -0
  111. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-09-design-directions.md +225 -0
  112. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-10-user-journeys.md +242 -0
  113. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-11-component-strategy.md +249 -0
  114. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-12-ux-patterns.md +238 -0
  115. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-13-responsive-accessibility.md +265 -0
  116. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-14-complete.md +171 -0
  117. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/ux-design-template.md +13 -0
  118. package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/workflow.md +36 -0
  119. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/SKILL.md +6 -0
  120. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/bmad-skill-manifest.yaml +1 -0
  121. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01-discovery.md +242 -0
  122. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01b-legacy-conversion.md +204 -0
  123. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-02-review.md +245 -0
  124. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-03-edit.md +250 -0
  125. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-04-complete.md +165 -0
  126. package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/workflow.md +63 -0
  127. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/SKILL.md +6 -0
  128. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/bmad-skill-manifest.yaml +1 -0
  129. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/data/domain-complexity.csv +15 -0
  130. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/data/prd-purpose.md +197 -0
  131. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/data/project-types.csv +11 -0
  132. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-01-discovery.md +221 -0
  133. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-02-format-detection.md +188 -0
  134. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-02b-parity-check.md +206 -0
  135. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-03-density-validation.md +171 -0
  136. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-04-brief-coverage-validation.md +211 -0
  137. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-05-measurability-validation.md +225 -0
  138. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-06-traceability-validation.md +214 -0
  139. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-07-implementation-leakage-validation.md +202 -0
  140. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-08-domain-compliance-validation.md +240 -0
  141. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-09-project-type-validation.md +260 -0
  142. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-10-smart-validation.md +206 -0
  143. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-11-holistic-quality-validation.md +261 -0
  144. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-12-completeness-validation.md +239 -0
  145. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-13-report-complete.md +229 -0
  146. package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/workflow.md +62 -0
  147. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv +15 -0
  148. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md +197 -0
  149. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/project-types.csv +11 -0
  150. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +224 -0
  151. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +191 -0
  152. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +209 -0
  153. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +174 -0
  154. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
  155. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +228 -0
  156. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +217 -0
  157. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
  158. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
  159. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +263 -0
  160. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +209 -0
  161. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
  162. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +242 -0
  163. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +232 -0
  164. package/_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +65 -0
  165. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/SKILL.md +6 -0
  166. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/bmad-skill-manifest.yaml +1 -0
  167. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-01-document-discovery.md +179 -0
  168. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-02-prd-analysis.md +168 -0
  169. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +169 -0
  170. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-04-ux-alignment.md +129 -0
  171. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-05-epic-quality-review.md +241 -0
  172. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-06-final-assessment.md +126 -0
  173. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/templates/readiness-report-template.md +4 -0
  174. package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/workflow.md +49 -0
  175. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/SKILL.md +6 -0
  176. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/architecture-decision-template.md +12 -0
  177. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/bmad-skill-manifest.yaml +1 -0
  178. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/data/domain-complexity.csv +13 -0
  179. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/data/project-types.csv +7 -0
  180. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-01-init.md +153 -0
  181. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-01b-continue.md +173 -0
  182. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-02-context.md +224 -0
  183. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-03-starter.md +329 -0
  184. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-04-decisions.md +318 -0
  185. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-05-patterns.md +359 -0
  186. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-06-structure.md +379 -0
  187. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-07-validation.md +359 -0
  188. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-08-complete.md +76 -0
  189. package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/workflow.md +38 -0
  190. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/SKILL.md +6 -0
  191. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/bmad-skill-manifest.yaml +1 -0
  192. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md +255 -0
  193. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-02-design-epics.md +212 -0
  194. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
  195. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-04-final-validation.md +131 -0
  196. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/templates/epics-template.md +61 -0
  197. package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/workflow.md +53 -0
  198. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/SKILL.md +6 -0
  199. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/bmad-skill-manifest.yaml +1 -0
  200. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-01-gather-context.md +61 -0
  201. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-02-review.md +41 -0
  202. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-03-triage.md +50 -0
  203. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-04-present.md +38 -0
  204. package/_bmad/bmm/workflows/4-implementation/bmad-code-review/workflow.md +54 -0
  205. package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/SKILL.md +6 -0
  206. package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/bmad-skill-manifest.yaml +1 -0
  207. package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/checklist.md +288 -0
  208. package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/workflow.md +267 -0
  209. package/_bmad/bmm/workflows/4-implementation/bmad-create-story/SKILL.md +6 -0
  210. package/_bmad/bmm/workflows/4-implementation/bmad-create-story/bmad-skill-manifest.yaml +1 -0
  211. package/_bmad/bmm/workflows/4-implementation/bmad-create-story/checklist.md +357 -0
  212. package/_bmad/bmm/workflows/4-implementation/bmad-create-story/discover-inputs.md +88 -0
  213. package/_bmad/bmm/workflows/4-implementation/bmad-create-story/template.md +49 -0
  214. package/_bmad/bmm/workflows/4-implementation/bmad-create-story/workflow.md +380 -0
  215. package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/SKILL.md +6 -0
  216. package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/bmad-skill-manifest.yaml +1 -0
  217. package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/checklist.md +80 -0
  218. package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/workflow.md +450 -0
  219. package/_bmad/bmm/workflows/4-implementation/bmad-retrospective/SKILL.md +6 -0
  220. package/_bmad/bmm/workflows/4-implementation/bmad-retrospective/bmad-skill-manifest.yaml +1 -0
  221. package/_bmad/bmm/workflows/4-implementation/bmad-retrospective/workflow.md +1479 -0
  222. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/SKILL.md +6 -0
  223. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/bmad-skill-manifest.yaml +1 -0
  224. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/checklist.md +33 -0
  225. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/sprint-status-template.yaml +56 -0
  226. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/workflow.md +263 -0
  227. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-status/SKILL.md +6 -0
  228. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-status/bmad-skill-manifest.yaml +1 -0
  229. package/_bmad/bmm/workflows/4-implementation/bmad-sprint-status/workflow.md +261 -0
  230. package/_bmad/bmm/workflows/bmad-document-project/SKILL.md +6 -0
  231. package/_bmad/bmm/workflows/bmad-document-project/bmad-skill-manifest.yaml +1 -0
  232. package/_bmad/bmm/workflows/bmad-document-project/checklist.md +245 -0
  233. package/_bmad/bmm/workflows/bmad-document-project/documentation-requirements.csv +12 -0
  234. package/_bmad/bmm/workflows/bmad-document-project/instructions.md +128 -0
  235. package/_bmad/bmm/workflows/bmad-document-project/templates/deep-dive-template.md +345 -0
  236. package/_bmad/bmm/workflows/bmad-document-project/templates/index-template.md +169 -0
  237. package/_bmad/bmm/workflows/bmad-document-project/templates/project-overview-template.md +103 -0
  238. package/_bmad/bmm/workflows/bmad-document-project/templates/project-scan-report-schema.json +160 -0
  239. package/_bmad/bmm/workflows/bmad-document-project/templates/source-tree-template.md +135 -0
  240. package/_bmad/bmm/workflows/bmad-document-project/workflow.md +27 -0
  241. package/_bmad/bmm/workflows/bmad-document-project/workflows/deep-dive-instructions.md +299 -0
  242. package/_bmad/bmm/workflows/bmad-document-project/workflows/deep-dive-workflow.md +34 -0
  243. package/_bmad/bmm/workflows/bmad-document-project/workflows/full-scan-instructions.md +1107 -0
  244. package/_bmad/bmm/workflows/bmad-document-project/workflows/full-scan-workflow.md +34 -0
  245. package/_bmad/bmm/workflows/bmad-generate-project-context/SKILL.md +6 -0
  246. package/_bmad/bmm/workflows/bmad-generate-project-context/bmad-skill-manifest.yaml +1 -0
  247. package/_bmad/bmm/workflows/bmad-generate-project-context/project-context-template.md +21 -0
  248. package/_bmad/bmm/workflows/bmad-generate-project-context/steps/step-01-discover.md +186 -0
  249. package/_bmad/bmm/workflows/bmad-generate-project-context/steps/step-02-generate.md +321 -0
  250. package/_bmad/bmm/workflows/bmad-generate-project-context/steps/step-03-complete.md +278 -0
  251. package/_bmad/bmm/workflows/bmad-generate-project-context/workflow.md +43 -0
  252. package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/SKILL.md +6 -0
  253. package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/bmad-skill-manifest.yaml +1 -0
  254. package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/checklist.md +33 -0
  255. package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/workflow.md +136 -0
  256. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/SKILL.md +6 -0
  257. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/bmad-skill-manifest.yaml +1 -0
  258. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-01-mode-detection.md +169 -0
  259. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-02-context-gathering.md +114 -0
  260. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-03-execute.md +107 -0
  261. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-04-self-check.md +107 -0
  262. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-05-adversarial-review.md +94 -0
  263. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-06-resolve-findings.md +144 -0
  264. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/workflow.md +38 -0
  265. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/SKILL.md +6 -0
  266. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/bmad-skill-manifest.yaml +1 -0
  267. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-01-clarify-and-route.md +51 -0
  268. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-02-plan.md +35 -0
  269. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-03-implement.md +33 -0
  270. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md +50 -0
  271. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-05-present.md +17 -0
  272. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/tech-spec-template.md +90 -0
  273. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +79 -0
  274. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/SKILL.md +6 -0
  275. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/bmad-skill-manifest.yaml +1 -0
  276. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-01-understand.md +185 -0
  277. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-02-investigate.md +140 -0
  278. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-03-generate.md +123 -0
  279. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-04-review.md +195 -0
  280. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/tech-spec-template.md +74 -0
  281. package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/workflow.md +73 -0
  282. package/_bmad/cis/config.yaml +12 -0
  283. package/_bmad/cis/module-help.csv +6 -0
  284. package/_bmad/cis/skills/bmad-cis-agent-brainstorming-coach/SKILL.md +51 -0
  285. package/_bmad/cis/skills/bmad-cis-agent-brainstorming-coach/bmad-skill-manifest.yaml +11 -0
  286. package/_bmad/cis/skills/bmad-cis-agent-creative-problem-solver/SKILL.md +51 -0
  287. package/_bmad/cis/skills/bmad-cis-agent-creative-problem-solver/bmad-skill-manifest.yaml +11 -0
  288. package/_bmad/cis/skills/bmad-cis-agent-design-thinking-coach/SKILL.md +52 -0
  289. package/_bmad/cis/skills/bmad-cis-agent-design-thinking-coach/bmad-skill-manifest.yaml +11 -0
  290. package/_bmad/cis/skills/bmad-cis-agent-innovation-strategist/SKILL.md +51 -0
  291. package/_bmad/cis/skills/bmad-cis-agent-innovation-strategist/bmad-skill-manifest.yaml +11 -0
  292. package/_bmad/cis/skills/bmad-cis-agent-presentation-master/SKILL.md +62 -0
  293. package/_bmad/cis/skills/bmad-cis-agent-presentation-master/bmad-skill-manifest.yaml +11 -0
  294. package/_bmad/cis/skills/bmad-cis-agent-storyteller/SKILL.md +56 -0
  295. package/_bmad/cis/skills/bmad-cis-agent-storyteller/bmad-skill-manifest.yaml +11 -0
  296. package/_bmad/cis/skills/bmad-cis-agent-storyteller/stories-told.md +7 -0
  297. package/_bmad/cis/skills/bmad-cis-agent-storyteller/story-preferences.md +7 -0
  298. package/_bmad/cis/skills/bmad-cis-design-thinking/SKILL.md +6 -0
  299. package/_bmad/cis/skills/bmad-cis-design-thinking/bmad-skill-manifest.yaml +1 -0
  300. package/_bmad/cis/skills/bmad-cis-design-thinking/design-methods.csv +31 -0
  301. package/_bmad/cis/skills/bmad-cis-design-thinking/template.md +111 -0
  302. package/_bmad/cis/skills/bmad-cis-design-thinking/workflow.md +242 -0
  303. package/_bmad/cis/skills/bmad-cis-innovation-strategy/SKILL.md +6 -0
  304. package/_bmad/cis/skills/bmad-cis-innovation-strategy/bmad-skill-manifest.yaml +1 -0
  305. package/_bmad/cis/skills/bmad-cis-innovation-strategy/innovation-frameworks.csv +31 -0
  306. package/_bmad/cis/skills/bmad-cis-innovation-strategy/template.md +189 -0
  307. package/_bmad/cis/skills/bmad-cis-innovation-strategy/workflow.md +315 -0
  308. package/_bmad/cis/skills/bmad-cis-problem-solving/SKILL.md +6 -0
  309. package/_bmad/cis/skills/bmad-cis-problem-solving/bmad-skill-manifest.yaml +1 -0
  310. package/_bmad/cis/skills/bmad-cis-problem-solving/solving-methods.csv +31 -0
  311. package/_bmad/cis/skills/bmad-cis-problem-solving/template.md +165 -0
  312. package/_bmad/cis/skills/bmad-cis-problem-solving/workflow.md +291 -0
  313. package/_bmad/cis/skills/bmad-cis-storytelling/SKILL.md +6 -0
  314. package/_bmad/cis/skills/bmad-cis-storytelling/bmad-skill-manifest.yaml +1 -0
  315. package/_bmad/cis/skills/bmad-cis-storytelling/story-types.csv +26 -0
  316. package/_bmad/cis/skills/bmad-cis-storytelling/template.md +113 -0
  317. package/_bmad/cis/skills/bmad-cis-storytelling/workflow.md +321 -0
  318. package/_bmad/core/config.yaml +9 -0
  319. package/_bmad/core/module-help.csv +11 -0
  320. package/_bmad/core/skills/bmad-advanced-elicitation/SKILL.md +6 -0
  321. package/_bmad/core/skills/bmad-advanced-elicitation/bmad-skill-manifest.yaml +1 -0
  322. package/_bmad/core/skills/bmad-advanced-elicitation/methods.csv +51 -0
  323. package/_bmad/core/skills/bmad-advanced-elicitation/workflow.md +135 -0
  324. package/_bmad/core/skills/bmad-brainstorming/SKILL.md +6 -0
  325. package/_bmad/core/skills/bmad-brainstorming/bmad-skill-manifest.yaml +1 -0
  326. package/_bmad/core/skills/bmad-brainstorming/brain-methods.csv +62 -0
  327. package/_bmad/core/skills/bmad-brainstorming/steps/step-01-session-setup.md +214 -0
  328. package/_bmad/core/skills/bmad-brainstorming/steps/step-01b-continue.md +124 -0
  329. package/_bmad/core/skills/bmad-brainstorming/steps/step-02a-user-selected.md +229 -0
  330. package/_bmad/core/skills/bmad-brainstorming/steps/step-02b-ai-recommended.md +239 -0
  331. package/_bmad/core/skills/bmad-brainstorming/steps/step-02c-random-selection.md +211 -0
  332. package/_bmad/core/skills/bmad-brainstorming/steps/step-02d-progressive-flow.md +266 -0
  333. package/_bmad/core/skills/bmad-brainstorming/steps/step-03-technique-execution.md +401 -0
  334. package/_bmad/core/skills/bmad-brainstorming/steps/step-04-idea-organization.md +305 -0
  335. package/_bmad/core/skills/bmad-brainstorming/template.md +15 -0
  336. package/_bmad/core/skills/bmad-brainstorming/workflow.md +53 -0
  337. package/_bmad/core/skills/bmad-distillator/SKILL.md +178 -0
  338. package/_bmad/core/skills/bmad-distillator/agents/distillate-compressor.md +116 -0
  339. package/_bmad/core/skills/bmad-distillator/agents/round-trip-reconstructor.md +68 -0
  340. package/_bmad/core/skills/bmad-distillator/bmad-skill-manifest.yaml +15 -0
  341. package/_bmad/core/skills/bmad-distillator/resources/compression-rules.md +51 -0
  342. package/_bmad/core/skills/bmad-distillator/resources/distillate-format-reference.md +227 -0
  343. package/_bmad/core/skills/bmad-distillator/resources/splitting-strategy.md +78 -0
  344. package/_bmad/core/skills/bmad-editorial-review-prose/SKILL.md +6 -0
  345. package/_bmad/core/skills/bmad-editorial-review-prose/bmad-skill-manifest.yaml +1 -0
  346. package/_bmad/core/skills/bmad-editorial-review-prose/workflow.md +81 -0
  347. package/_bmad/core/skills/bmad-editorial-review-structure/SKILL.md +6 -0
  348. package/_bmad/core/skills/bmad-editorial-review-structure/bmad-skill-manifest.yaml +1 -0
  349. package/_bmad/core/skills/bmad-editorial-review-structure/workflow.md +174 -0
  350. package/_bmad/core/skills/bmad-help/SKILL.md +6 -0
  351. package/_bmad/core/skills/bmad-help/bmad-skill-manifest.yaml +1 -0
  352. package/_bmad/core/skills/bmad-help/workflow.md +88 -0
  353. package/_bmad/core/skills/bmad-index-docs/SKILL.md +6 -0
  354. package/_bmad/core/skills/bmad-index-docs/bmad-skill-manifest.yaml +1 -0
  355. package/_bmad/core/skills/bmad-index-docs/workflow.md +61 -0
  356. package/_bmad/core/skills/bmad-party-mode/SKILL.md +6 -0
  357. package/_bmad/core/skills/bmad-party-mode/bmad-skill-manifest.yaml +1 -0
  358. package/_bmad/core/skills/bmad-party-mode/steps/step-01-agent-loading.md +138 -0
  359. package/_bmad/core/skills/bmad-party-mode/steps/step-02-discussion-orchestration.md +187 -0
  360. package/_bmad/core/skills/bmad-party-mode/steps/step-03-graceful-exit.md +167 -0
  361. package/_bmad/core/skills/bmad-party-mode/workflow.md +190 -0
  362. package/_bmad/core/skills/bmad-review-adversarial-general/SKILL.md +6 -0
  363. package/_bmad/core/skills/bmad-review-adversarial-general/bmad-skill-manifest.yaml +1 -0
  364. package/_bmad/core/skills/bmad-review-adversarial-general/workflow.md +32 -0
  365. package/_bmad/core/skills/bmad-review-edge-case-hunter/SKILL.md +6 -0
  366. package/_bmad/core/skills/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml +1 -0
  367. package/_bmad/core/skills/bmad-review-edge-case-hunter/workflow.md +62 -0
  368. package/_bmad/core/skills/bmad-shard-doc/SKILL.md +6 -0
  369. package/_bmad/core/skills/bmad-shard-doc/bmad-skill-manifest.yaml +1 -0
  370. package/_bmad/core/skills/bmad-shard-doc/workflow.md +100 -0
  371. package/_bmad/core/tasks/bmad-create-prd/SKILL.md +6 -0
  372. package/_bmad/core/tasks/bmad-create-prd/bmad-skill-manifest.yaml +1 -0
  373. package/_bmad/core/tasks/bmad-create-prd/data/domain-complexity.csv +15 -0
  374. package/_bmad/core/tasks/bmad-create-prd/data/prd-purpose.md +197 -0
  375. package/_bmad/core/tasks/bmad-create-prd/data/project-types.csv +11 -0
  376. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-01-init.md +178 -0
  377. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-01b-continue.md +161 -0
  378. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-02-discovery.md +208 -0
  379. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-02b-vision.md +142 -0
  380. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-02c-executive-summary.md +158 -0
  381. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-03-success.md +214 -0
  382. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-04-journeys.md +201 -0
  383. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-05-domain.md +194 -0
  384. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-06-innovation.md +211 -0
  385. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-07-project-type.md +222 -0
  386. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-08-scoping.md +216 -0
  387. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-09-functional.md +219 -0
  388. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-10-nonfunctional.md +230 -0
  389. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-11-polish.md +221 -0
  390. package/_bmad/core/tasks/bmad-create-prd/steps-c/step-12-complete.md +115 -0
  391. package/_bmad/core/tasks/bmad-create-prd/templates/prd-template.md +10 -0
  392. package/_bmad/core/tasks/bmad-create-prd/workflow.md +62 -0
  393. package/config/allowed-commands.ts +39 -0
  394. package/config/defaults.ts +19 -0
  395. package/config/loader.ts +105 -0
  396. package/extensions/frappe-gates.ts +160 -0
  397. package/extensions/frappe-session.ts +324 -0
  398. package/extensions/frappe-state.ts +235 -0
  399. package/extensions/frappe-tools.ts +278 -0
  400. package/extensions/frappe-ui.ts +119 -0
  401. package/extensions/frappe-workflow.ts +85 -0
  402. package/gates/coverage-check.ts +37 -0
  403. package/gates/frappe-native-check.ts +65 -0
  404. package/gates/permission-check.ts +65 -0
  405. package/gates/query-check.ts +40 -0
  406. package/gates/server-side-check.ts +67 -0
  407. package/gates/style-check.ts +92 -0
  408. package/gates/types.ts +13 -0
  409. package/package.json +43 -0
  410. package/project-context.md +146 -0
  411. package/state/db.ts +85 -0
  412. package/state/fsm.ts +68 -0
  413. package/state/journal.ts +164 -0
  414. package/state/schema.ts +41 -0
  415. package/tools/agent-tools.ts +60 -0
  416. package/tools/bench-tools.ts +63 -0
  417. package/tools/context-sandbox.ts +31 -0
  418. package/tools/debug-tools.ts +12 -0
  419. package/tools/feature-tools.ts +126 -0
  420. package/tools/frappe-context7.ts +70 -0
  421. package/tools/frappe-query-tools.ts +47 -0
  422. package/tools/project-tools.ts +107 -0
  423. package/tsdown.config.ts +6 -0
@@ -0,0 +1,278 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { startFeature, completeComponent } from "../tools/feature-tools.js";
3
+ import { setActiveProject, getProjectStatus } from "../tools/project-tools.js";
4
+ import { getAuditLog } from "../state/journal.js";
5
+ import { invokeDebugger, endDebug } from "../tools/debug-tools.js";
6
+ import { spawnAgent } from "../tools/agent-tools.js";
7
+ import { scaffoldDoctype, benchExecute, runTests } from "../tools/bench-tools.js";
8
+ import { frappeQuery } from "../tools/frappe-query-tools.js";
9
+ import { getFrappeDocs } from "../tools/frappe-context7.js";
10
+
11
+ // pi.registerTool's execute callback is untyped (pi is `any`); params are
12
+ // enforced at runtime via TypeBox schemas. One explicit-any alias avoids
13
+ // noImplicitAny errors across all callbacks without per-line suppressions.
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ type ToolParams = any;
16
+
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ export default function (pi: any) {
19
+ pi.registerTool({
20
+ name: "start_feature",
21
+ label: "Start Feature",
22
+ description:
23
+ "Creates and names a new feature within the active project, initialising its state in state.db. Valid only in the 'idle' phase.",
24
+ parameters: Type.Object({
25
+ name: Type.String({ description: "Feature name (e.g. 'PO Approval')" }),
26
+ mode: Type.Union([Type.Literal("full"), Type.Literal("quick")], {
27
+ description: "Workflow mode: 'full' for all phases, 'quick' for rapid delivery",
28
+ }),
29
+ }),
30
+ execute: async (_toolCallId: string, params: ToolParams) => {
31
+ const result = startFeature(params);
32
+ return {
33
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
34
+ details: result,
35
+ };
36
+ },
37
+ });
38
+
39
+ pi.registerTool({
40
+ name: "complete_component",
41
+ label: "Complete Component",
42
+ description:
43
+ "Marks a feature component as complete in state.db and creates an automatic git checkpoint commit. Valid only in the 'implementation' phase.",
44
+ parameters: Type.Object({
45
+ featureId: Type.String({ description: "Feature ID (kebab-case slug, e.g. 'po-approval')" }),
46
+ componentId: Type.String({ description: "Component ID (e.g. 'auth-module')" }),
47
+ }),
48
+ execute: async (_toolCallId: string, params: ToolParams) => {
49
+ const result = await completeComponent(params);
50
+ return {
51
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
52
+ details: result,
53
+ };
54
+ },
55
+ });
56
+
57
+ pi.registerTool({
58
+ name: "set_active_project",
59
+ label: "Set Active Project",
60
+ description:
61
+ "Switches the active Frappe project and site. Flushes current session state, creates a new session for the target project (restoring prior phase if known), and reloads the system prompt context. Available in any phase.",
62
+ parameters: Type.Object({
63
+ projectId: Type.String({ description: "Project identifier (e.g. 'my-frappe-site')" }),
64
+ sitePath: Type.String({ description: "Absolute path to the Frappe bench site (e.g. '/home/user/frappe-bench/sites/site1.local')" }),
65
+ }),
66
+ execute: async (_toolCallId: string, params: ToolParams) => {
67
+ const result = await setActiveProject(params);
68
+ return {
69
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
70
+ details: result,
71
+ };
72
+ },
73
+ });
74
+
75
+ pi.registerTool({
76
+ name: "invoke_debugger",
77
+ label: "Invoke Debugger",
78
+ description:
79
+ "Loads the frappe-debugger specialist without triggering a phase transition. Valid in any phase (FR34).",
80
+ parameters: Type.Object({}),
81
+ execute: async (_toolCallId: string, _params: ToolParams) => {
82
+ const result = invokeDebugger();
83
+ return {
84
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
85
+ details: result,
86
+ };
87
+ },
88
+ });
89
+
90
+ pi.registerTool({
91
+ name: "end_debug",
92
+ label: "End Debug",
93
+ description:
94
+ "Exits the debugger session and restores the specialist for the preserved phase. Valid in any phase.",
95
+ parameters: Type.Object({}),
96
+ execute: async (_toolCallId: string, _params: ToolParams) => {
97
+ const result = endDebug();
98
+ return {
99
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
100
+ details: result,
101
+ };
102
+ },
103
+ });
104
+
105
+ pi.registerTool({
106
+ name: "spawn_agent",
107
+ label: "Spawn Agent",
108
+ description:
109
+ "Spawns a sub-agent for parallel work. Requires explicit user approval when requirePermission is true in config. Valid in any phase.",
110
+ parameters: Type.Object({
111
+ skill: Type.String({ description: "Sub-agent skill name (e.g. 'dev-agent')" }),
112
+ trigger: Type.String({ description: "Trigger reason (e.g. 'scaffold')" }),
113
+ reason: Type.String({ description: "Human-readable reason for spawning" }),
114
+ approved: Type.Optional(Type.Boolean({ description: "User approval decision (set after permission prompt)" })),
115
+ }),
116
+ execute: async (_toolCallId: string, params: ToolParams) => {
117
+ const result = await spawnAgent(params);
118
+ return {
119
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
120
+ details: result,
121
+ };
122
+ },
123
+ });
124
+
125
+ pi.registerTool({
126
+ name: "scaffold_doctype",
127
+ label: "Scaffold DocType",
128
+ description:
129
+ "Creates a new Frappe DocType via bench. Valid only in the 'implementation' phase. (Story 4.2 deferred)",
130
+ parameters: Type.Object({
131
+ name: Type.String({ description: "DocType name in PascalCase (e.g. 'Purchase Order')" }),
132
+ module: Type.String({ description: "Frappe module name (e.g. 'Buying')" }),
133
+ }),
134
+ execute: async (_toolCallId: string, params: ToolParams) => {
135
+ const result = scaffoldDoctype(params);
136
+ return {
137
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
138
+ details: result,
139
+ };
140
+ },
141
+ });
142
+
143
+ pi.registerTool({
144
+ name: "run_tests",
145
+ label: "Run Tests",
146
+ description:
147
+ "Runs the Frappe test suite for the active feature via bench. Valid only in the 'testing' phase. (Epic 6)",
148
+ parameters: Type.Object({
149
+ featureId: Type.Optional(Type.String({ description: "Feature ID to scope tests (optional)" })),
150
+ }),
151
+ execute: async (_toolCallId: string, params: ToolParams) => {
152
+ const result = runTests(params);
153
+ return {
154
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
155
+ details: result,
156
+ };
157
+ },
158
+ });
159
+
160
+ pi.registerTool({
161
+ name: "get_project_status",
162
+ label: "Get Project Status",
163
+ description:
164
+ "Returns a dashboard summary of the active project: features, components, phase, and progress. Available in any phase. (Story 5.2)",
165
+ parameters: Type.Object({}),
166
+ execute: async (_toolCallId: string, _params: ToolParams) => {
167
+ const result = getProjectStatus();
168
+ return {
169
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
170
+ details: result,
171
+ };
172
+ },
173
+ });
174
+
175
+ pi.registerTool({
176
+ name: "frappe_query",
177
+ label: "Frappe Query",
178
+ description:
179
+ "Queries Frappe data via mcp2cli subprocess. Output is routed through the context-mode sandbox — raw payloads never enter the LLM context. Available in any phase.",
180
+ parameters: Type.Object({
181
+ doctype: Type.String({ description: "Frappe DocType to query (e.g. 'Sales Order')" }),
182
+ filters: Type.Optional(Type.Record(Type.String(), Type.Unknown(), {
183
+ description: "Filter key-value pairs (e.g. { status: 'Draft' })",
184
+ })),
185
+ }),
186
+ execute: async (_toolCallId: string, params: ToolParams) => {
187
+ const result = await frappeQuery(params);
188
+ return {
189
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
190
+ details: result,
191
+ };
192
+ },
193
+ });
194
+
195
+ // 9th tool — outside the 8 core Frappe-semantic tools; bypasses phase guard via ALWAYS_ALLOWED_TOOLS
196
+ pi.registerTool({
197
+ name: "get_frappe_docs",
198
+ label: "Get Frappe Docs",
199
+ description:
200
+ "Retrieves compressed Frappe/ERPNext documentation via context7 MCP. Raw web content never enters the LLM context (~90% token reduction). Valid in any phase. (Story 4.4)",
201
+ parameters: Type.Object({
202
+ topic: Type.String({ description: "Documentation topic (e.g. 'DocType', 'hooks', 'frappe.db')" }),
203
+ version: Type.Optional(Type.String({ description: "Frappe version to scope docs (e.g. 'v15')" })),
204
+ }),
205
+ execute: async (_toolCallId: string, params: ToolParams) => {
206
+ const result = await getFrappeDocs(params);
207
+ return {
208
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
209
+ details: result,
210
+ };
211
+ },
212
+ });
213
+
214
+ pi.registerTool({
215
+ name: "get_audit_log",
216
+ label: "Get Audit Log",
217
+ description:
218
+ "Queries JSONL audit log entries from session files. Supports filtering by sessionId, featureId, and limit. Available in any phase. (Story 5.3)",
219
+ parameters: Type.Object({
220
+ sessionId: Type.Optional(Type.String({ description: "Session ID to query (omit for all sessions)" })),
221
+ featureId: Type.Optional(Type.String({ description: "Feature ID to filter entries by payload.feature" })),
222
+ limit: Type.Optional(Type.Number({ description: "Maximum number of entries to return (default: all)" })),
223
+ }),
224
+ execute: async (_toolCallId: string, params: ToolParams) => {
225
+ const result = getAuditLog(params);
226
+ return {
227
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
228
+ details: result,
229
+ };
230
+ },
231
+ });
232
+
233
+ // /status slash command — displays project dashboard (FR21, Story 5.2)
234
+ // Defensive: pi.registerCommand may not be available in all pi-mono versions
235
+ if (typeof pi.registerCommand === "function") {
236
+ pi.registerCommand("status", {
237
+ description: "Show project dashboard: features, components, phase, and progress",
238
+ handler: async (_args: string, ctx: Record<string, unknown>) => {
239
+ const status = getProjectStatus();
240
+ const lines: string[] = [];
241
+ if (status.message) {
242
+ lines.push(status.message);
243
+ } else {
244
+ for (const f of status.features) {
245
+ lines.push(`[${f.phase}] ${f.name} (${f.componentsDone}/${f.componentsTotal} done)`);
246
+ for (const c of f.components) {
247
+ const mark = c.status === "complete" ? "✓" : "·";
248
+ lines.push(` ${mark} ${c.componentId}`);
249
+ }
250
+ }
251
+ }
252
+ const output = lines.join("\n") || "No project data";
253
+ if (ctx.hasUI && ctx.ui && typeof (ctx.ui as Record<string, unknown>).notify === "function") {
254
+ (ctx.ui as { notify: (msg: string, sev: string) => void }).notify(output, "info");
255
+ }
256
+ return output;
257
+ },
258
+ });
259
+ }
260
+
261
+ pi.registerTool({
262
+ name: "bench_execute",
263
+ label: "Bench Execute",
264
+ description:
265
+ "Runs a whitelisted bench command via subprocess. Output sandboxed through context-mode. Valid only in the 'implementation' phase. (Story 4.3)",
266
+ parameters: Type.Object({
267
+ command: Type.String({ description: "Bench command (e.g. 'migrate')" }),
268
+ args: Type.Optional(Type.Array(Type.String(), { description: "Additional arguments" })),
269
+ }),
270
+ execute: async (_toolCallId: string, params: ToolParams) => {
271
+ const result = benchExecute(params);
272
+ return {
273
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
274
+ details: result,
275
+ };
276
+ },
277
+ });
278
+ }
@@ -0,0 +1,119 @@
1
+ import type { AfterToolCallContext, AfterToolCallResult } from "@mariozechner/pi-agent-core";
2
+ import { db, getCurrentPhase } from "../state/db.js";
3
+
4
+ interface FooterState {
5
+ projectId: string | null;
6
+ featureName: string | null;
7
+ phase: string;
8
+ tokenCount: number;
9
+ }
10
+
11
+ function readFooterState(): FooterState {
12
+ try {
13
+ const session = db
14
+ .prepare(
15
+ `SELECT s.project_id, f.name AS feature_name, s.current_phase
16
+ FROM sessions s
17
+ LEFT JOIN features f ON f.feature_id = s.feature_id
18
+ WHERE s.is_active = 1 LIMIT 1`
19
+ )
20
+ .get() as
21
+ | { project_id: string | null; feature_name: string | null; current_phase: string }
22
+ | undefined;
23
+
24
+ // Token count: count journal_entries for active session; table may not exist yet
25
+ let tokenCount = 0;
26
+ try {
27
+ const tokenRow = db
28
+ .prepare(
29
+ `SELECT COUNT(*) as count FROM journal_entries
30
+ WHERE session_id = (SELECT session_id FROM sessions WHERE is_active = 1 LIMIT 1)`
31
+ )
32
+ .get() as { count: number } | undefined;
33
+ tokenCount = tokenRow?.count ?? 0;
34
+ } catch {
35
+ // journal_entries table not yet created — default to 0
36
+ }
37
+
38
+ return {
39
+ projectId: session?.project_id ?? null,
40
+ featureName: session?.feature_name ?? null,
41
+ phase: session?.current_phase ?? "idle",
42
+ tokenCount,
43
+ };
44
+ } catch {
45
+ return { projectId: null, featureName: null, phase: "idle", tokenCount: 0 };
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Pure formatting function — no I/O, no side effects.
51
+ * Exported for unit testing.
52
+ */
53
+ export function formatFooter(state: FooterState): string {
54
+ if (!state.projectId) {
55
+ return `No active project | Phase: ${state.phase}`;
56
+ }
57
+ if (!state.featureName) {
58
+ return `Project: ${state.projectId} | No active feature | Phase: ${state.phase}`;
59
+ }
60
+ return `Project: ${state.projectId} | Feature: ${state.featureName} | Phase: ${state.phase} | Tokens: ${state.tokenCount}`;
61
+ }
62
+
63
+ function renderFooter(): void {
64
+ try {
65
+ const state = readFooterState();
66
+ const line = formatFooter(state);
67
+ process.stderr.write(`\r\x1b[2K[frappe-builder] ${line}\n`);
68
+ } catch {
69
+ // Silently swallow all rendering errors — footer is non-critical
70
+ }
71
+ }
72
+
73
+ /**
74
+ * beforeToolCall announcement hook — writes "→ Calling {tool} [{phase}]" to stderr.
75
+ * Always returns undefined — this hook only announces, never blocks.
76
+ * Wrap in try/catch so announcement failure never crashes the session.
77
+ *
78
+ * Load order note: frappe-ui must load before frappe-workflow so this fires
79
+ * before the FSM guard. Load order is controlled by the pi extension list;
80
+ * package.json "pi" field is currently empty so order is determined by the
81
+ * pi CLI -e flags at startup.
82
+ */
83
+ export function handleBeforeToolCall(toolName: string): undefined {
84
+ try {
85
+ const phase = getCurrentPhase();
86
+ process.stderr.write(`→ Calling ${toolName} [${phase}]\n`);
87
+ } catch {
88
+ // Swallow — announcement is non-critical, must never block or crash
89
+ }
90
+ return undefined;
91
+ }
92
+
93
+ /**
94
+ * afterToolCall hook — renders the footer and returns undefined so the
95
+ * original tool result passes through unmodified.
96
+ */
97
+ export async function handleAfterToolCall(
98
+ _context: AfterToolCallContext,
99
+ _signal?: AbortSignal
100
+ ): Promise<AfterToolCallResult | undefined> {
101
+ renderFooter();
102
+ return undefined;
103
+ }
104
+
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ export default function (pi: any) {
107
+ pi.on("session_start", () => {
108
+ renderFooter();
109
+ });
110
+
111
+ // Announcement hook — fires before FSM guard in frappe-workflow.ts (FR25)
112
+ pi.on("tool_call", (event: { toolName?: string }) => {
113
+ return handleBeforeToolCall(event.toolName ?? "");
114
+ });
115
+
116
+ pi.on("after_tool_call", async (context: AfterToolCallContext) => {
117
+ return await handleAfterToolCall(context);
118
+ });
119
+ }
@@ -0,0 +1,85 @@
1
+ import { getCurrentPhase, db } from "../state/db.js";
2
+ import { isToolAllowedInPhase, getValidPhase, type Phase } from "../state/fsm.js";
3
+ import { appendEntry } from "../state/journal.js";
4
+
5
+ interface BlockedResponse {
6
+ blocked: true;
7
+ tool: string;
8
+ current_phase: Phase;
9
+ valid_phase: Phase | "any";
10
+ message: string;
11
+ }
12
+
13
+ function buildBlockedResponse(
14
+ tool: string,
15
+ currentPhase: Phase,
16
+ validPhase: Phase | "any"
17
+ ): BlockedResponse {
18
+ return {
19
+ blocked: true,
20
+ tool,
21
+ current_phase: currentPhase,
22
+ valid_phase: validPhase,
23
+ message: `${tool} is not available in ${currentPhase} phase. Available in: ${validPhase}`,
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Phase guard logic for beforeToolCall. Returns a blocked response if the tool
29
+ * is not valid in the current phase, undefined to allow.
30
+ *
31
+ * Override: if args.override === true, writes a JSONL entry and allows the tool
32
+ * regardless of phase. Does NOT disable quality gates (frappe-gates.ts).
33
+ *
34
+ * Never throws — always returns a value or undefined.
35
+ */
36
+ // Tools valid in all phases — never blocked by the phase guard (FR34)
37
+ const ALWAYS_ALLOWED_TOOLS = ["invoke_debugger", "end_debug", "spawn_agent", "get_frappe_docs", "get_audit_log"];
38
+
39
+ export function beforeToolCall(
40
+ toolName: string,
41
+ args: Record<string, unknown>
42
+ ): BlockedResponse | undefined {
43
+ // Always-allowed bypass — checked before everything else
44
+ if (ALWAYS_ALLOWED_TOOLS.includes(toolName)) return undefined;
45
+
46
+ const currentPhase = getCurrentPhase() as Phase;
47
+
48
+ // Override bypass — checked BEFORE phase guard (FR10 escape hatch)
49
+ if (args.override === true) {
50
+ const session = db
51
+ .prepare("SELECT session_id FROM sessions WHERE is_active = 1 LIMIT 1")
52
+ .get() as { session_id: string } | undefined;
53
+
54
+ appendEntry({
55
+ ts: new Date().toISOString(),
56
+ sessionId: session?.session_id ?? "unknown",
57
+ type: "tool_call",
58
+ payload: {
59
+ override: true,
60
+ reason: (args.reason as string) ?? "unspecified",
61
+ tool: toolName,
62
+ phase: currentPhase,
63
+ },
64
+ });
65
+ return undefined; // allow
66
+ }
67
+
68
+ // Phase guard
69
+ if (!isToolAllowedInPhase(toolName, currentPhase)) {
70
+ return buildBlockedResponse(toolName, currentPhase, getValidPhase(toolName));
71
+ }
72
+
73
+ return undefined; // allow
74
+ }
75
+
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ export default function (pi: any) {
78
+ pi.on("tool_call", (event: { toolName?: string; input?: Record<string, unknown> }) => {
79
+ const result = beforeToolCall(event.toolName ?? "", event.input ?? {});
80
+ if (result) {
81
+ return { block: true, reason: result.message };
82
+ }
83
+ return undefined;
84
+ });
85
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * gates/coverage-check.ts — Async coverage gate (NOT a pure function).
3
+ * Runs `bench run-tests --coverage` via execa and parses the result.
4
+ *
5
+ * NOT wired via frappe-gates.ts — integrated directly in completeComponent().
6
+ * Triggers when the final component is completed in `testing` phase. (FR29)
7
+ */
8
+ import { execa } from "execa";
9
+ import type { GateContext } from "./types.js";
10
+
11
+ export type CoverageResult =
12
+ | { passed: true; coverage: number }
13
+ | { passed: false; coverage: number; required: string; error?: string };
14
+
15
+ function parseCoverage(stdout: string): number {
16
+ const match = stdout.match(/^TOTAL\s+\d+\s+\d+\s+(\d+)%/m);
17
+ return match ? parseInt(match[1], 10) : 0;
18
+ }
19
+
20
+ export async function coverageCheck(_context: GateContext): Promise<CoverageResult> {
21
+ try {
22
+ const { stdout } = await execa("bench", ["run-tests", "--coverage"], {
23
+ cwd: process.env.FRAPPE_BENCH_PATH ?? process.cwd(),
24
+ reject: false, // don't throw on non-zero exit — coverage data may still be in stdout
25
+ timeout: 120_000, // 2 minute timeout
26
+ });
27
+
28
+ const coverage = parseCoverage(stdout ?? "");
29
+
30
+ if (coverage < 70) {
31
+ return { passed: false, coverage, required: "70%" };
32
+ }
33
+ return { passed: true, coverage };
34
+ } catch (err) {
35
+ return { passed: false, coverage: 0, required: "70%", error: (err as Error).message };
36
+ }
37
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * gates/frappe-native-check.ts — pure gate function, no side effects.
3
+ * No imports from state/, extensions/, or config/.
4
+ * No async, no db, no I/O. Same input always produces same output.
5
+ */
6
+
7
+ export type NativeCheckResult =
8
+ | { passed: true }
9
+ | { passed: true; result: "override"; justification: string; detectedPatterns: string[] }
10
+ | { passed: false; requiresJustification: true; message: string; detectedPatterns: string[] };
11
+
12
+ export const NON_NATIVE_PATTERNS: { pattern: RegExp; label: string }[] = [
13
+ // HTTP clients — use frappe.call() or frappe.db instead
14
+ { pattern: /import\s+axios/, label: "axios (use frappe.call)" },
15
+ { pattern: /require\(['"]axios['"]\)/, label: "axios (use frappe.call)" },
16
+ { pattern: /import\s+requests/, label: "requests (use frappe.call)" },
17
+ { pattern: /from\s+requests\s+import/, label: "requests (use frappe.call)" },
18
+
19
+ // Raw database access — use Frappe ORM
20
+ { pattern: /cursor\.execute\s*\(/, label: "raw SQL cursor (use frappe.db.sql or ORM)" },
21
+ { pattern: /pymysql|psycopg2|sqlite3\.connect/, label: "direct DB driver (use Frappe ORM)" },
22
+ { pattern: /mongoose|sequelize|typeorm/i, label: "external ORM (use Frappe DocType)" },
23
+
24
+ // Custom auth — use frappe.whitelist()
25
+ { pattern: /jwt\.sign|jsonwebtoken/, label: "JWT auth (use frappe.whitelist + session)" },
26
+ { pattern: /passport\.authenticate/, label: "passport auth (use Frappe auth)" },
27
+
28
+ // External data processing — use Frappe reports/scripts
29
+ { pattern: /import\s+pandas/, label: "pandas (use Frappe Script Report)" },
30
+ { pattern: /import\s+numpy/, label: "numpy (use Frappe computation)" },
31
+
32
+ // File system — use Frappe file manager
33
+ { pattern: /fs\.writeFileSync|fs\.readFileSync/, label: "raw fs (use frappe.get_file_url or File DocType)" },
34
+
35
+ // HTTP server — use Frappe whitelisted methods
36
+ { pattern: /express\(\)|fastapi|flask\.Flask/, label: "external web framework (use Frappe whitelist)" },
37
+ ];
38
+
39
+ /**
40
+ * Scans `content` for non-Frappe-native patterns.
41
+ *
42
+ * - No detected patterns → { passed: true }
43
+ * - Detected + no justification → { passed: false, requiresJustification: true, ... }
44
+ * - Detected + justification provided → { passed: true, result: "override", ... }
45
+ */
46
+ export function checkFrappeNative(content: string, justification?: string): NativeCheckResult {
47
+ const detectedPatterns = NON_NATIVE_PATTERNS
48
+ .filter(({ pattern }) => pattern.test(content))
49
+ .map(({ label }) => label);
50
+
51
+ if (detectedPatterns.length === 0) {
52
+ return { passed: true };
53
+ }
54
+
55
+ if (justification) {
56
+ return { passed: true, result: "override", justification, detectedPatterns };
57
+ }
58
+
59
+ return {
60
+ passed: false,
61
+ requiresJustification: true,
62
+ message: "This uses a non-Frappe-native approach. Justification required to proceed.",
63
+ detectedPatterns,
64
+ };
65
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * gates/permission-check.ts — Pure gate function, no side effects.
3
+ * No imports from state/, extensions/, or config/.
4
+ * No async, no db, no I/O. Same input always produces same output.
5
+ *
6
+ * Scans Python code for @frappe.whitelist() decorated methods that lack
7
+ * a permission check inside their function body. (FR26)
8
+ */
9
+ import type { GateContext, GateResult } from "./types.js";
10
+
11
+ const PERMISSION_PATTERNS = [
12
+ /frappe\.has_permission\s*\(/,
13
+ /frappe\.only_for\s*\(/,
14
+ /frappe\.check_permission\s*\(/,
15
+ /frappe\.has_role\s*\(/,
16
+ /frappe\.session\.user/,
17
+ ];
18
+
19
+ function getLineNumber(code: string, offset: number): number {
20
+ return code.slice(0, offset).split("\n").length;
21
+ }
22
+
23
+ function extractFunctionBody(code: string, defStart: number): string {
24
+ const bodyStart = code.indexOf("\n", defStart) + 1;
25
+ // Find next top-level def/class/decorator (at column 0)
26
+ const nextTopLevel = /\n(?=def |class |@)/g;
27
+ nextTopLevel.lastIndex = bodyStart;
28
+ const match = nextTopLevel.exec(code);
29
+ return match ? code.slice(bodyStart, match.index) : code.slice(bodyStart);
30
+ }
31
+
32
+ function hasPermissionCheck(body: string): boolean {
33
+ return PERMISSION_PATTERNS.some((p) => p.test(body));
34
+ }
35
+
36
+ export function permissionCheck(code: string, context: GateContext): GateResult {
37
+ // Only scan Python files
38
+ if (!context.file.endsWith(".py")) return { passed: true };
39
+
40
+ // Find all @frappe.whitelist(...) followed by a def
41
+ const WHITELIST_DECORATOR = /@frappe\.whitelist\([^)]*\)\s*\ndef\s+(\w+)/g;
42
+
43
+ const violations: Array<{ method: string; line: number; reason: string }> = [];
44
+ let match: RegExpExecArray | null;
45
+
46
+ while ((match = WHITELIST_DECORATOR.exec(code)) !== null) {
47
+ const decoratorOffset = match.index;
48
+ const methodName = match[1];
49
+ const line = getLineNumber(code, decoratorOffset);
50
+
51
+ // defStart: position of "def " within the full match
52
+ const defStart = code.indexOf("\ndef ", decoratorOffset) + 1;
53
+ const body = extractFunctionBody(code, defStart);
54
+
55
+ if (!hasPermissionCheck(body)) {
56
+ violations.push({ method: methodName, line, reason: "missing permission check" });
57
+ }
58
+ }
59
+
60
+ if (violations.length > 0) {
61
+ return { passed: false, violations };
62
+ }
63
+
64
+ return { passed: true };
65
+ }