@guanlin4924/devflow-pi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/README.md +164 -0
  2. package/docs/OMP-NATIVE-ARCHITECTURE.md +104 -0
  3. package/package.json +40 -0
  4. package/plugins/devflow-core/extensions/devflow-core.ts +1642 -0
  5. package/plugins/devflow-core/package.json +14 -0
  6. package/plugins/devflow-core/runtime/hooks/context_sync_gate.py +174 -0
  7. package/plugins/devflow-core/runtime/hooks/hook_common.py +696 -0
  8. package/plugins/devflow-core/runtime/hooks/index_gate.py +63 -0
  9. package/plugins/devflow-core/runtime/hooks/injection_code_specification.py +7 -0
  10. package/plugins/devflow-core/runtime/hooks/post_tool.py +44 -0
  11. package/plugins/devflow-core/runtime/hooks/start.py +288 -0
  12. package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +265 -0
  13. package/plugins/devflow-core/skills/workflow-orchestrator/agents/openai.yaml +4 -0
  14. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +520 -0
  15. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/control_io.rb +42 -0
  16. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_state.rb +138 -0
  17. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_workflow.rb +121 -0
  18. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +553 -0
  19. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/manage_lessons.rb +219 -0
  20. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/sync_artifacts.rb +168 -0
  21. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/update_triage_route.rb +110 -0
  22. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +565 -0
  23. package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +783 -0
  24. package/plugins/devflow-core/skills/workflow-orchestrator/templates/uat-remediation.yaml +143 -0
  25. package/plugins/devflow-core/skills/workflow-orchestrator/templates/workflows-README.md +10 -0
  26. package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +117 -0
  27. package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +167 -0
  28. package/plugins/devflow-core/skills/workflow-pipeline/references/slice-safety-guide.md +125 -0
  29. package/plugins/devflow-core/skills/workflow-project-context/SKILL.md +819 -0
  30. package/plugins/devflow-core/skills/workflow-project-context/assets/agents-md-template.md +25 -0
  31. package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-backend-spec-template.md +68 -0
  32. package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-frontend-spec-template.md +64 -0
  33. package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-navigation-template.md +168 -0
  34. package/plugins/devflow-core/skills/workflow-project-context/assets/context-domain-index-template.md +43 -0
  35. package/plugins/devflow-core/skills/workflow-project-context/assets/context-spec-index-template.md +45 -0
  36. package/plugins/devflow-core/skills/workflow-project-context/assets/execution-contract-template.md +57 -0
  37. package/plugins/devflow-core/skills/workflow-project-context/assets/navigation-index-template.md +40 -0
  38. package/plugins/devflow-core/skills/workflow-project-context/assets/project-initialization-template.md +109 -0
  39. package/plugins/devflow-core/skills/workflow-project-context/assets/rules-index-template.md +80 -0
  40. package/plugins/devflow-core/skills/workflow-project-context/assets/run-manifest-template.json +40 -0
  41. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/directory-structure.md +46 -0
  42. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/engine.md +46 -0
  43. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/errors.md +46 -0
  44. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/locator.md +46 -0
  45. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/model.md +46 -0
  46. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/repository.md +46 -0
  47. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/router.md +46 -0
  48. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/scheduler.md +46 -0
  49. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/schema.md +46 -0
  50. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/service.md +46 -0
  51. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/testing.md +46 -0
  52. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/api-client.md +46 -0
  53. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/case-editor.md +46 -0
  54. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/components.md +46 -0
  55. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/directory-structure.md +46 -0
  56. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/forms.md +46 -0
  57. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/routing.md +46 -0
  58. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/state.md +46 -0
  59. package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/testing.md +46 -0
  60. package/plugins/devflow-core/skills/workflow-project-context/assets/stack-spec-template.md +106 -0
  61. package/plugins/devflow-core/skills/workflow-project-context/assets/state-template.md +77 -0
  62. package/plugins/devflow-core/skills/workflow-project-context/assets/toolchain-template.md +37 -0
  63. package/plugins/devflow-core/skills/workflow-project-context/references/navigation-guide.md +262 -0
  64. package/plugins/devflow-core/skills/workflow-project-context/scripts/validate_initialization.py +545 -0
  65. package/plugins/devflow-design/agents/contract-auditor.md +18 -0
  66. package/plugins/devflow-design/extensions/devflow-design.ts +47 -0
  67. package/plugins/devflow-design/package.json +14 -0
  68. package/plugins/devflow-design/skills/workflow-api-call-guide/SKILL.md +142 -0
  69. package/plugins/devflow-design/skills/workflow-api-contract/SKILL.md +150 -0
  70. package/plugins/devflow-design/skills/workflow-api-supplement/SKILL.md +121 -0
  71. package/plugins/devflow-design/skills/workflow-backend-tech-spec/SKILL.md +257 -0
  72. package/plugins/devflow-design/skills/workflow-backend-tech-spec/assets/adr-template.md +57 -0
  73. package/plugins/devflow-design/skills/workflow-backend-tech-spec/assets/backend-spec-template.md +205 -0
  74. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/affected-module-exploration.md +59 -0
  75. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/backend-conventions.md +30 -0
  76. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/code-explore-guide.md +40 -0
  77. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/project-rule-contract.md +66 -0
  78. package/plugins/devflow-design/skills/workflow-design-rule-pack/SKILL.md +91 -0
  79. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/index.md +71 -0
  80. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/accessibility.md +31 -0
  81. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/component-library.md +31 -0
  82. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/design-systems.md +47 -0
  83. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/responsive-grid.md +29 -0
  84. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/stack-guidelines.md +31 -0
  85. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/ux-patterns.md +40 -0
  86. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tokens/project-tokens.md +19 -0
  87. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/SKILL.md +377 -0
  88. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/charts.csv +26 -0
  89. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/colors.csv +97 -0
  90. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/icons.csv +101 -0
  91. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/landing.csv +31 -0
  92. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/products.csv +97 -0
  93. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/react-performance.csv +45 -0
  94. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  95. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  96. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  97. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  98. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  99. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  100. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  101. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  102. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/react.csv +54 -0
  103. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  104. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  105. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  106. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  107. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/styles.csv +68 -0
  108. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/typography.csv +58 -0
  109. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  110. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  111. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/web-interface.csv +31 -0
  112. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/scripts/core.py +253 -0
  113. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/scripts/design_system.py +1067 -0
  114. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/scripts/search.py +114 -0
  115. package/plugins/devflow-design/skills/workflow-design-rule-pack/scripts/install.py +67 -0
  116. package/plugins/devflow-design/skills/workflow-feature-breakdown/SKILL.md +370 -0
  117. package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/admin-system-template.md +57 -0
  118. package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/api-service-template.md +42 -0
  119. package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/c-end-system-template.md +25 -0
  120. package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/output-template.md +139 -0
  121. package/plugins/devflow-design/skills/workflow-feature-breakdown/references/bug-rules.md +12 -0
  122. package/plugins/devflow-design/skills/workflow-feature-breakdown/references/exception-checklist.md +31 -0
  123. package/plugins/devflow-design/skills/workflow-feature-breakdown/references/trace-integrity-guide.md +153 -0
  124. package/plugins/devflow-design/skills/workflow-feature-breakdown/references/writing-guide.md +92 -0
  125. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/SKILL.md +223 -0
  126. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/assets/frontend-spec-template.md +204 -0
  127. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/affected-module-exploration.md +58 -0
  128. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/component-patterns.md +42 -0
  129. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-conventions.md +28 -0
  130. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/common-web.md +53 -0
  131. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/next.md +40 -0
  132. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/react.md +41 -0
  133. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/vue.md +41 -0
  134. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/project-rule-contract.md +95 -0
  135. package/plugins/devflow-design/skills/workflow-integration-verify/SKILL.md +172 -0
  136. package/plugins/devflow-design/skills/workflow-ui-spec/SKILL.md +302 -0
  137. package/plugins/devflow-design/skills/workflow-ui-spec/assets/ui-spec-template.md +244 -0
  138. package/plugins/devflow-design/skills/workflow-ui-spec/references/affected-module-exploration.md +55 -0
  139. package/plugins/devflow-implementation/agents/implementation-worker.md +20 -0
  140. package/plugins/devflow-implementation/package.json +6 -0
  141. package/plugins/devflow-implementation/skills/workflow-bug-fix/SKILL.md +124 -0
  142. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/INDEX.md +13 -0
  143. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/adversarial-review.md +35 -0
  144. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/first-principles.md +26 -0
  145. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/lesson-format.md +28 -0
  146. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/root-cause-ladder.md +51 -0
  147. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/seam-analysis.md +30 -0
  148. package/plugins/devflow-implementation/skills/workflow-change-plan/SKILL.md +160 -0
  149. package/plugins/devflow-implementation/skills/workflow-change-plan/references/code-conventions.md +33 -0
  150. package/plugins/devflow-implementation/skills/workflow-change-plan/references/ddl-guidelines.md +60 -0
  151. package/plugins/devflow-implementation/skills/workflow-change-plan/references/output-template.md +217 -0
  152. package/plugins/devflow-implementation/skills/workflow-change-plan/references/project-rule-contract.md +55 -0
  153. package/plugins/devflow-implementation/skills/workflow-execute-phase/SKILL.md +271 -0
  154. package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md +1251 -0
  155. package/plugins/devflow-implementation/skills/workflow-execute-phase/references/ui-brand.md +160 -0
  156. package/plugins/devflow-intel/agents/project-scout.md +27 -0
  157. package/plugins/devflow-intel/extensions/devflow-intel.ts +104 -0
  158. package/plugins/devflow-intel/package.json +14 -0
  159. package/plugins/devflow-intel/skills/code-index-query/SKILL.md +37 -0
  160. package/plugins/devflow-intel/skills/code-index-query/references/query-patterns.md +27 -0
  161. package/plugins/devflow-intel/skills/workflow-code-index/SKILL.md +68 -0
  162. package/plugins/devflow-intel/skills/workflow-code-index/references/adapter-contract.md +38 -0
  163. package/plugins/devflow-intel/skills/workflow-code-index/references/audit-checklist.md +10 -0
  164. package/plugins/devflow-intel/skills/workflow-code-index/references/confidence-rules.md +43 -0
  165. package/plugins/devflow-intel/skills/workflow-code-index/references/data-model.md +74 -0
  166. package/plugins/devflow-intel/skills/workflow-code-index/references/discovery.md +24 -0
  167. package/plugins/devflow-intel/skills/workflow-code-index/references/query-guide.md +20 -0
  168. package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/__init__.py +1 -0
  169. package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/base.py +30 -0
  170. package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/generic_text.py +287 -0
  171. package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/registry.py +17 -0
  172. package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +437 -0
  173. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/__init__.py +1 -0
  174. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/discovery.py +139 -0
  175. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/hashing.py +11 -0
  176. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/scanner.py +115 -0
  177. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/schema.py +123 -0
  178. package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/__init__.py +1 -0
  179. package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/project_binding_check.py +66 -0
  180. package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/relation_check.py +36 -0
  181. package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/schema_validate.py +11 -0
  182. package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/stale_check.py +42 -0
  183. package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/__init__.py +1 -0
  184. package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/jsonl_writer.py +25 -0
  185. package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/markdown_writer.py +106 -0
  186. package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/sqlite_writer.py +143 -0
  187. package/plugins/devflow-intel/skills/workflow-context-sync/SKILL.md +381 -0
  188. package/plugins/devflow-intel/skills/workflow-context-sync/agents/openai.yaml +4 -0
  189. package/plugins/devflow-intel/skills/workflow-context-sync/scripts/context_sync_cursor.py +241 -0
  190. package/plugins/devflow-intel/skills/workflow-update-navigation/SKILL.md +186 -0
  191. package/plugins/devflow-intel/skills/workflow-update-navigation/references/incremental-update-guide.md +47 -0
  192. package/plugins/devflow-quality/agents/code-reviewer.md +18 -0
  193. package/plugins/devflow-quality/agents/verification-runner.md +21 -0
  194. package/plugins/devflow-quality/extensions/devflow-quality.ts +59 -0
  195. package/plugins/devflow-quality/package.json +14 -0
  196. package/plugins/devflow-quality/skills/code-review/SKILL.md +288 -0
  197. package/plugins/devflow-quality/skills/code-review/references/cross-layer-checklist.md +70 -0
  198. package/plugins/devflow-quality/skills/code-review/references/dao-checklist.md +70 -0
  199. package/plugins/devflow-quality/skills/code-review/references/handler-checklist.md +48 -0
  200. package/plugins/devflow-quality/skills/code-review/references/repository-checklist.md +44 -0
  201. package/plugins/devflow-quality/skills/code-review/references/service-checklist.md +57 -0
  202. package/plugins/devflow-quality/skills/code-review/references/spec-checklist.md +34 -0
  203. package/plugins/devflow-quality/skills/code-review/references/vo-checklist.md +26 -0
  204. package/plugins/devflow-quality/skills/workflow-audit-milestone/SKILL.md +31 -0
  205. package/plugins/devflow-quality/skills/workflow-audit-milestone/references/audit-milestone.md +328 -0
  206. package/plugins/devflow-quality/skills/workflow-complete-milestone/SKILL.md +132 -0
  207. package/plugins/devflow-quality/skills/workflow-complete-milestone/assets/milestone-archive.md +123 -0
  208. package/plugins/devflow-quality/skills/workflow-complete-milestone/references/complete-milestone.md +775 -0
  209. package/plugins/devflow-quality/skills/workflow-complete-milestone/references/milestone-archive.md +123 -0
  210. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +126 -0
  211. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/api-mainflow-rules.md +27 -0
  212. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/codebase-discovery.md +54 -0
  213. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/intermediate-format.md +244 -0
  214. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/mainflow-selection.md +36 -0
  215. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/project-dsl-contract.md +190 -0
  216. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/ui-mainflow-rules.md +110 -0
  217. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +583 -0
  218. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/discover_codebases.py +199 -0
  219. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/normalize_case_payloads.py +177 -0
  220. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/validate_case_payloads.py +370 -0
  221. package/plugins/devflow-quality/skills/workflow-verify-work/SKILL.md +106 -0
  222. package/plugins/devflow-quality/skills/workflow-verify-work/assets/UAT.md +265 -0
  223. package/plugins/devflow-quality/skills/workflow-verify-work/references/verify-work.md +759 -0
  224. package/plugins/devflow-requirements/agents/requirements-auditor.md +20 -0
  225. package/plugins/devflow-requirements/package.json +6 -0
  226. package/plugins/devflow-requirements/skills/requirement-feasibility-review/SKILL.md +219 -0
  227. package/plugins/devflow-requirements/skills/requirement-feasibility-review/agents/openai.yaml +4 -0
  228. package/plugins/devflow-requirements/skills/requirement-feasibility-review/references/review-method.md +257 -0
  229. package/plugins/devflow-requirements/skills/requirement-feasibility-review/references/review-template.md +80 -0
  230. package/plugins/devflow-requirements/skills/workflow-demand-clarify/SKILL.md +325 -0
  231. package/plugins/devflow-requirements/skills/workflow-domain-modeling/SKILL.md +163 -0
  232. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/SKILL.md +748 -0
  233. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/assets/baseline-template.md +281 -0
  234. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/antipatterns.md +69 -0
  235. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/challenge-review-guide.md +158 -0
  236. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/decomposition-guide.md +115 -0
  237. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/project-context-guide.md +119 -0
  238. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/questioning.md +76 -0
  239. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/requirement-review-checklist.md +115 -0
  240. package/plugins/devflow-requirements/skills/workflow-requirement-triage/SKILL.md +204 -0
  241. package/plugins/devflow-requirements/skills/workflow-wayfinder/SKILL.md +183 -0
  242. package/src/cli.ts +76 -0
  243. package/src/constants.ts +15 -0
  244. package/src/doctor.ts +66 -0
  245. package/src/paths.ts +37 -0
  246. package/src/platform-extension.ts +46 -0
  247. package/src/project-context.ts +165 -0
  248. package/src/runtime.ts +167 -0
  249. package/src/usage-stats.ts +101 -0
  250. package/templates/commands/start.md +58 -0
  251. package/templates/omp/AGENTS.md +36 -0
  252. package/templates/omp/config.yml +112 -0
  253. package/templates/omp/hook-config.json +18 -0
  254. package/templates/omp/index-policy.json +57 -0
@@ -0,0 +1,115 @@
1
+ import os
2
+ import subprocess
3
+ from pathlib import Path
4
+ from typing import Iterable, List, Sequence
5
+
6
+
7
+ DEFAULT_EXCLUDES = {
8
+ ".git",
9
+ "node_modules",
10
+ "vendor",
11
+ "dist",
12
+ "build",
13
+ "coverage",
14
+ "target",
15
+ ".next",
16
+ ".nuxt",
17
+ ".cache",
18
+ ".pytest_cache",
19
+ ".mypy_cache",
20
+ ".gradle",
21
+ ".dart_tool",
22
+ "__pycache__",
23
+ "Pods",
24
+ }
25
+
26
+ TEXT_EXTENSIONS = {
27
+ ".py",
28
+ ".js",
29
+ ".jsx",
30
+ ".ts",
31
+ ".tsx",
32
+ ".vue",
33
+ ".go",
34
+ ".rs",
35
+ ".php",
36
+ ".java",
37
+ ".kt",
38
+ ".kts",
39
+ ".dart",
40
+ ".c",
41
+ ".cc",
42
+ ".cpp",
43
+ ".h",
44
+ ".hpp",
45
+ ".cs",
46
+ ".rb",
47
+ ".swift",
48
+ ".sql",
49
+ ".sh",
50
+ ".yaml",
51
+ ".yml",
52
+ ".json",
53
+ ".toml",
54
+ ".xml",
55
+ ".md",
56
+ }
57
+
58
+
59
+ def scan_files(root: Path, excludes: Iterable[str] = (), max_bytes: int = 1_500_000) -> List[Path]:
60
+ root = root.resolve()
61
+ excluded = DEFAULT_EXCLUDES | set(excludes)
62
+ paths = _scan_with_rg(root, excluded) or _scan_with_walk(root, excluded)
63
+ result: List[Path] = []
64
+ for path in sorted(paths):
65
+ if not path.is_file():
66
+ continue
67
+ if _is_excluded(path, root, excluded):
68
+ continue
69
+ if path.suffix and path.suffix.lower() not in TEXT_EXTENSIONS:
70
+ continue
71
+ try:
72
+ if path.stat().st_size > max_bytes:
73
+ continue
74
+ except OSError:
75
+ continue
76
+ result.append(path)
77
+ return result
78
+
79
+
80
+ def _scan_with_rg(root: Path, excluded: Sequence[str]) -> List[Path]:
81
+ ignore_args = []
82
+ for name in excluded:
83
+ ignore_args.extend(["--glob", f"!**/{name}/**"])
84
+ try:
85
+ proc = subprocess.run(
86
+ ["rg", "--files", *ignore_args],
87
+ cwd=str(root),
88
+ text=True,
89
+ stdout=subprocess.PIPE,
90
+ stderr=subprocess.DEVNULL,
91
+ check=False,
92
+ )
93
+ except (OSError, FileNotFoundError):
94
+ return []
95
+ if proc.returncode not in (0, 1):
96
+ return []
97
+ return [root / line.strip() for line in proc.stdout.splitlines() if line.strip()]
98
+
99
+
100
+ def _scan_with_walk(root: Path, excluded: Sequence[str]) -> List[Path]:
101
+ paths: List[Path] = []
102
+ for current, dirs, files in os.walk(root):
103
+ dirs[:] = [name for name in dirs if name not in excluded]
104
+ for filename in files:
105
+ paths.append(Path(current) / filename)
106
+ return paths
107
+
108
+
109
+ def _is_excluded(path: Path, root: Path, excluded: Sequence[str]) -> bool:
110
+ try:
111
+ parts = path.resolve().relative_to(root).parts
112
+ except ValueError:
113
+ return True
114
+ return any(part in excluded for part in parts)
115
+
@@ -0,0 +1,123 @@
1
+ import hashlib
2
+ import json
3
+ import re
4
+ from typing import Dict, Iterable, List
5
+
6
+
7
+ RELATION_TYPES = {
8
+ "contains",
9
+ "imports",
10
+ "calls",
11
+ "extends",
12
+ "implements",
13
+ "routes_to",
14
+ "reads",
15
+ "writes",
16
+ "tested_by",
17
+ "config_uses",
18
+ }
19
+
20
+ CONFIDENCE = {"exact", "inferred", "heuristic"}
21
+
22
+ SYMBOL_KINDS = {
23
+ "function",
24
+ "method",
25
+ "class",
26
+ "struct",
27
+ "interface",
28
+ "trait",
29
+ "route",
30
+ "file",
31
+ "table",
32
+ "config",
33
+ "test",
34
+ "component",
35
+ "module",
36
+ "variable",
37
+ }
38
+
39
+ DIAGNOSTIC_SEVERITY = {"info", "warning", "error"}
40
+
41
+
42
+ def stable_key(value: str) -> str:
43
+ value = value.strip().replace("\\", "/")
44
+ value = re.sub(r"[^A-Za-z0-9_./:$#-]+", ".", value)
45
+ value = re.sub(r"\.+", ".", value).strip(".")
46
+ return value or "unknown"
47
+
48
+
49
+ def short_hash(value: str, length: int = 12) -> str:
50
+ return hashlib.sha256(value.encode("utf-8", errors="ignore")).hexdigest()[:length]
51
+
52
+
53
+ def json_dumps(value) -> str:
54
+ return json.dumps(value or {}, ensure_ascii=False, sort_keys=True)
55
+
56
+
57
+ def validate_file(record: Dict) -> List[str]:
58
+ required = ["id", "codebase", "path", "language", "size_bytes", "content_hash", "indexed_at", "parser"]
59
+ return _missing(record, required)
60
+
61
+
62
+ def validate_symbol(record: Dict) -> List[str]:
63
+ required = [
64
+ "id",
65
+ "codebase",
66
+ "kind",
67
+ "name",
68
+ "path",
69
+ "line_start",
70
+ "line_end",
71
+ "language",
72
+ "content_hash",
73
+ ]
74
+ errors = _missing(record, required)
75
+ if record.get("kind") not in SYMBOL_KINDS:
76
+ errors.append(f"invalid symbol kind: {record.get('kind')}")
77
+ if int(record.get("line_start", 0) or 0) < 1:
78
+ errors.append("line_start must be >= 1")
79
+ if int(record.get("line_end", 0) or 0) < int(record.get("line_start", 0) or 0):
80
+ errors.append("line_end must be >= line_start")
81
+ return errors
82
+
83
+
84
+ def validate_relation(record: Dict) -> List[str]:
85
+ required = ["from_id", "relation_type", "evidence_path", "evidence_line", "confidence", "parser"]
86
+ errors = _missing(record, required)
87
+ if not record.get("to_id") and not record.get("to_external"):
88
+ errors.append("relation requires to_id or to_external")
89
+ if record.get("relation_type") not in RELATION_TYPES:
90
+ errors.append(f"invalid relation_type: {record.get('relation_type')}")
91
+ if record.get("confidence") not in CONFIDENCE:
92
+ errors.append(f"invalid confidence: {record.get('confidence')}")
93
+ if int(record.get("evidence_line", 0) or 0) < 1:
94
+ errors.append("evidence_line must be >= 1")
95
+ return errors
96
+
97
+
98
+ def validate_diagnostic(record: Dict) -> List[str]:
99
+ required = ["codebase", "severity", "kind", "message"]
100
+ errors = _missing(record, required)
101
+ if record.get("severity") not in DIAGNOSTIC_SEVERITY:
102
+ errors.append(f"invalid diagnostic severity: {record.get('severity')}")
103
+ return errors
104
+
105
+
106
+ def validate_records(kind: str, records: Iterable[Dict]) -> List[str]:
107
+ validators = {
108
+ "files": validate_file,
109
+ "symbols": validate_symbol,
110
+ "relations": validate_relation,
111
+ "diagnostics": validate_diagnostic,
112
+ }
113
+ validate = validators[kind]
114
+ errors: List[str] = []
115
+ for index, record in enumerate(records, start=1):
116
+ for error in validate(record):
117
+ errors.append(f"{kind}[{index}]: {error}")
118
+ return errors
119
+
120
+
121
+ def _missing(record: Dict, required: List[str]) -> List[str]:
122
+ return [f"missing required field: {field}" for field in required if record.get(field) in (None, "")]
123
+
@@ -0,0 +1,66 @@
1
+ import re
2
+ from pathlib import Path
3
+
4
+
5
+ PLACEHOLDER_OK = re.compile(r"\{[A-Za-z0-9_:-]+\}")
6
+
7
+ GENERIC_TOKENS = (
8
+ ".planning/",
9
+ ".context/",
10
+ ".skills/",
11
+ "references/",
12
+ "scripts/",
13
+ "core/",
14
+ "adapters/",
15
+ "writers/",
16
+ "validators/",
17
+ "path/to/",
18
+ "name/path/kind",
19
+ "tree-sitter-",
20
+ "lsp-",
21
+ "framework-",
22
+ )
23
+
24
+
25
+ def audit_project_binding(paths):
26
+ findings = []
27
+ path_like = re.compile(r"(?<![`{])(?:[A-Za-z0-9_.-]+/){2,}[A-Za-z0-9_.-]+")
28
+ code_id_like = re.compile(r"\b(?:[a-z]+:)?[A-Za-z0-9_-]+:[A-Za-z0-9_./-]+:[A-Za-z0-9_.:$#-]+")
29
+ for root in paths:
30
+ root = Path(root)
31
+ if not root.exists():
32
+ continue
33
+ for path in root.rglob("*"):
34
+ if not path.is_file() or path.suffix.lower() not in {".md", ".py", ".yaml", ".yml"}:
35
+ continue
36
+ text = path.read_text(encoding="utf-8", errors="ignore")
37
+ for lineno, line in enumerate(text.splitlines(), start=1):
38
+ if line.startswith("#!") or any(token in line for token in GENERIC_TOKENS):
39
+ continue
40
+ stripped = PLACEHOLDER_OK.sub("", line)
41
+ if (
42
+ path_like.search(stripped)
43
+ and ".planning/" not in stripped
44
+ and ".context/" not in stripped
45
+ and ".skills/" not in stripped
46
+ ):
47
+ findings.append(
48
+ {
49
+ "severity": "warning",
50
+ "kind": "project_binding",
51
+ "message": "possible project-specific path in generic skill artifact",
52
+ "path": str(path),
53
+ "line": lineno,
54
+ }
55
+ )
56
+ if code_id_like.search(stripped) and "{codebase}" not in line:
57
+ findings.append(
58
+ {
59
+ "severity": "info",
60
+ "kind": "project_binding",
61
+ "message": "possible concrete code-index id in generic skill artifact",
62
+ "path": str(path),
63
+ "line": lineno,
64
+ }
65
+ )
66
+ return findings
@@ -0,0 +1,36 @@
1
+ def audit_relations(symbols, relations):
2
+ symbol_ids = {record["id"] for record in symbols}
3
+ findings = []
4
+ for index, relation in enumerate(relations, start=1):
5
+ if relation.get("to_id") and relation["to_id"] not in symbol_ids:
6
+ findings.append(
7
+ {
8
+ "severity": "error",
9
+ "kind": "dangling_relation",
10
+ "message": f"relations[{index}] points to missing symbol {relation['to_id']}",
11
+ "path": relation.get("evidence_path"),
12
+ "line": relation.get("evidence_line"),
13
+ }
14
+ )
15
+ if not relation.get("evidence_path") or not relation.get("evidence_line"):
16
+ findings.append(
17
+ {
18
+ "severity": "error",
19
+ "kind": "missing_evidence",
20
+ "message": f"relations[{index}] has no evidence path/line",
21
+ "path": relation.get("evidence_path"),
22
+ "line": relation.get("evidence_line"),
23
+ }
24
+ )
25
+ if relation.get("confidence") == "exact" and relation.get("to_external", "").startswith("call:"):
26
+ findings.append(
27
+ {
28
+ "severity": "warning",
29
+ "kind": "confidence_mismatch",
30
+ "message": f"relations[{index}] marks unresolved call as exact",
31
+ "path": relation.get("evidence_path"),
32
+ "line": relation.get("evidence_line"),
33
+ }
34
+ )
35
+ return findings
36
+
@@ -0,0 +1,11 @@
1
+ from core.schema import validate_records
2
+
3
+
4
+ def validate_index(files, symbols, relations, diagnostics):
5
+ errors = []
6
+ errors.extend(validate_records("files", files))
7
+ errors.extend(validate_records("symbols", symbols))
8
+ errors.extend(validate_records("relations", relations))
9
+ errors.extend(validate_records("diagnostics", diagnostics))
10
+ return errors
11
+
@@ -0,0 +1,42 @@
1
+ from pathlib import Path
2
+
3
+ from core.hashing import file_sha256
4
+
5
+
6
+ def audit_stale(root: Path, files):
7
+ findings = []
8
+ for record in files:
9
+ path = root / record["path"]
10
+ if not path.exists():
11
+ findings.append(
12
+ {
13
+ "severity": "error",
14
+ "kind": "stale_index",
15
+ "message": f"indexed file no longer exists: {record['path']}",
16
+ "path": record["path"],
17
+ }
18
+ )
19
+ continue
20
+ try:
21
+ current = file_sha256(path)
22
+ except OSError as exc:
23
+ findings.append(
24
+ {
25
+ "severity": "warning",
26
+ "kind": "stale_index",
27
+ "message": f"could not hash indexed file: {exc}",
28
+ "path": record["path"],
29
+ }
30
+ )
31
+ continue
32
+ if current != record["content_hash"]:
33
+ findings.append(
34
+ {
35
+ "severity": "error",
36
+ "kind": "stale_index",
37
+ "message": f"indexed hash differs from source hash: {record['path']}",
38
+ "path": record["path"],
39
+ }
40
+ )
41
+ return findings
42
+
@@ -0,0 +1,25 @@
1
+ import json
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Iterable
5
+
6
+
7
+ def write_jsonl(path: Path, records: Iterable[dict]) -> None:
8
+ path.parent.mkdir(parents=True, exist_ok=True)
9
+ with path.open("w", encoding="utf-8") as handle:
10
+ for record in records:
11
+ handle.write(json.dumps(record, ensure_ascii=False, sort_keys=True) + "\n")
12
+ handle.flush()
13
+ os.fsync(handle.fileno())
14
+
15
+
16
+ def read_jsonl(path: Path):
17
+ if not path.exists():
18
+ return []
19
+ records = []
20
+ with path.open("r", encoding="utf-8") as handle:
21
+ for line in handle:
22
+ line = line.strip()
23
+ if line:
24
+ records.append(json.loads(line))
25
+ return records
@@ -0,0 +1,106 @@
1
+ from collections import Counter, defaultdict
2
+ from datetime import datetime, timezone
3
+ from pathlib import Path
4
+
5
+
6
+ def write_markdown(output: Path, files, symbols, relations, diagnostics) -> None:
7
+ output.mkdir(parents=True, exist_ok=True)
8
+ now = datetime.now(timezone.utc).isoformat()
9
+ _write_index(output / "INDEX.md", now, files, symbols, relations, diagnostics)
10
+ _write_symbols(output / "SYMBOLS.md", now, symbols)
11
+ _write_relations(output / "RELATIONS.md", now, relations)
12
+ _write_entrypoints(output / "ENTRYPOINTS.md", now, symbols)
13
+ _write_dataflow(output / "DATAFLOW.md", now, relations)
14
+
15
+
16
+ def write_audit(output: Path, audit) -> None:
17
+ output.mkdir(parents=True, exist_ok=True)
18
+ lines = ["# Code Index Audit", "", f"- Generated at: {datetime.now(timezone.utc).isoformat()}", ""]
19
+ lines.append("## Summary")
20
+ lines.append("")
21
+ lines.append(f"- Status: {'pass' if not audit else 'fail'}")
22
+ lines.append(f"- Findings: {len(audit)}")
23
+ lines.append("")
24
+ if audit:
25
+ lines.append("## Findings")
26
+ lines.append("")
27
+ for item in audit:
28
+ lines.append(f"- **{item.get('severity', 'warning')}** `{item.get('kind', 'unknown')}`: {item.get('message', '')}")
29
+ if item.get("path"):
30
+ lines.append(f" - Path: `{item.get('path')}`")
31
+ if item.get("line"):
32
+ lines.append(f" - Line: `{item.get('line')}`")
33
+ (output / "AUDIT.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
34
+
35
+
36
+ def _write_index(path: Path, now: str, files, symbols, relations, diagnostics) -> None:
37
+ codebases = Counter(record["codebase"] for record in files)
38
+ languages = Counter(record["language"] for record in files)
39
+ lines = ["# Code Index", "", f"- Generated at: {now}", "- Index version: 1", ""]
40
+ lines.extend(["## Coverage", "", "| Codebase | Files |", "|----------|-------|"])
41
+ for name, count in sorted(codebases.items()):
42
+ lines.append(f"| `{name}` | {count} |")
43
+ lines.extend(["", "## Languages", "", "| Language | Files |", "|----------|-------|"])
44
+ for name, count in sorted(languages.items()):
45
+ lines.append(f"| `{name}` | {count} |")
46
+ lines.extend(["", "## Counts", ""])
47
+ lines.append(f"- Files: {len(files)}")
48
+ lines.append(f"- Symbols: {len(symbols)}")
49
+ lines.append(f"- Relations: {len(relations)}")
50
+ lines.append(f"- Diagnostics: {len(diagnostics)}")
51
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
52
+
53
+
54
+ def _write_symbols(path: Path, now: str, symbols) -> None:
55
+ grouped = defaultdict(Counter)
56
+ for symbol in symbols:
57
+ grouped[symbol["codebase"]][symbol["kind"]] += 1
58
+ lines = ["# Symbols", "", f"- Generated at: {now}", ""]
59
+ for codebase in sorted(grouped):
60
+ lines.extend([f"## `{codebase}`", "", "| Kind | Count |", "|------|-------|"])
61
+ for kind, count in sorted(grouped[codebase].items()):
62
+ lines.append(f"| `{kind}` | {count} |")
63
+ lines.append("")
64
+ lines.extend(["## Sample", "", "| Symbol | Kind | Path | Lines |", "|--------|------|------|-------|"])
65
+ for symbol in symbols[:200]:
66
+ lines.append(
67
+ f"| `{symbol['name']}` | `{symbol['kind']}` | `{symbol['path']}` | {symbol['line_start']}-{symbol['line_end']} |"
68
+ )
69
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
70
+
71
+
72
+ def _write_relations(path: Path, now: str, relations) -> None:
73
+ counts = Counter((record["relation_type"], record["confidence"]) for record in relations)
74
+ lines = ["# Relations", "", f"- Generated at: {now}", "", "| Relation | Confidence | Count |", "|----------|------------|-------|"]
75
+ for (relation_type, confidence), count in sorted(counts.items()):
76
+ lines.append(f"| `{relation_type}` | `{confidence}` | {count} |")
77
+ lines.extend(["", "## Sample", "", "| Type | From | To | Evidence | Confidence |", "|------|------|----|----------|------------|"])
78
+ for record in relations[:200]:
79
+ target = record.get("to_id") or record.get("to_external") or ""
80
+ lines.append(
81
+ f"| `{record['relation_type']}` | `{record['from_id']}` | `{target}` | `{record['evidence_path']}:{record['evidence_line']}` | `{record['confidence']}` |"
82
+ )
83
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
84
+
85
+
86
+ def _write_entrypoints(path: Path, now: str, symbols) -> None:
87
+ entry_kinds = {"route", "test", "component", "module", "file"}
88
+ lines = ["# Entrypoints", "", f"- Generated at: {now}", "", "| Symbol | Kind | Path | Lines |", "|--------|------|------|-------|"]
89
+ for symbol in symbols:
90
+ if symbol["kind"] in entry_kinds:
91
+ lines.append(
92
+ f"| `{symbol['name']}` | `{symbol['kind']}` | `{symbol['path']}` | {symbol['line_start']}-{symbol['line_end']} |"
93
+ )
94
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
95
+
96
+
97
+ def _write_dataflow(path: Path, now: str, relations) -> None:
98
+ lines = ["# Dataflow", "", f"- Generated at: {now}", "", "| Type | Target | Evidence | Confidence |", "|------|--------|----------|------------|"]
99
+ for record in relations:
100
+ if record["relation_type"] in {"reads", "writes", "config_uses"}:
101
+ target = record.get("to_id") or record.get("to_external") or ""
102
+ lines.append(
103
+ f"| `{record['relation_type']}` | `{target}` | `{record['evidence_path']}:{record['evidence_line']}` | `{record['confidence']}` |"
104
+ )
105
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
106
+
@@ -0,0 +1,143 @@
1
+ import sqlite3
2
+ import os
3
+ from pathlib import Path
4
+
5
+ from core.schema import json_dumps
6
+
7
+
8
+ SCHEMA = """
9
+ CREATE TABLE IF NOT EXISTS code_files (
10
+ id TEXT PRIMARY KEY,
11
+ codebase TEXT NOT NULL,
12
+ path TEXT NOT NULL,
13
+ language TEXT NOT NULL,
14
+ size_bytes INTEGER NOT NULL,
15
+ content_hash TEXT NOT NULL,
16
+ indexed_at TEXT NOT NULL,
17
+ parser TEXT NOT NULL
18
+ );
19
+
20
+ CREATE TABLE IF NOT EXISTS symbols (
21
+ id TEXT PRIMARY KEY,
22
+ codebase TEXT NOT NULL,
23
+ kind TEXT NOT NULL,
24
+ name TEXT NOT NULL,
25
+ qualified_name TEXT,
26
+ container_id TEXT,
27
+ path TEXT NOT NULL,
28
+ line_start INTEGER NOT NULL,
29
+ line_end INTEGER NOT NULL,
30
+ signature TEXT,
31
+ language TEXT NOT NULL,
32
+ content_hash TEXT NOT NULL,
33
+ visibility TEXT,
34
+ metadata_json TEXT
35
+ );
36
+
37
+ CREATE TABLE IF NOT EXISTS relations (
38
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
39
+ from_id TEXT NOT NULL,
40
+ relation_type TEXT NOT NULL,
41
+ to_id TEXT,
42
+ to_external TEXT,
43
+ evidence_path TEXT NOT NULL,
44
+ evidence_line INTEGER NOT NULL,
45
+ confidence TEXT NOT NULL,
46
+ parser TEXT NOT NULL,
47
+ metadata_json TEXT
48
+ );
49
+
50
+ CREATE TABLE IF NOT EXISTS diagnostics (
51
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
52
+ codebase TEXT NOT NULL,
53
+ path TEXT,
54
+ line INTEGER,
55
+ severity TEXT NOT NULL,
56
+ kind TEXT NOT NULL,
57
+ message TEXT NOT NULL,
58
+ parser TEXT
59
+ );
60
+
61
+ CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(
62
+ id UNINDEXED,
63
+ codebase UNINDEXED,
64
+ name,
65
+ qualified_name,
66
+ signature,
67
+ path,
68
+ metadata_json
69
+ );
70
+
71
+ CREATE INDEX IF NOT EXISTS idx_symbols_codebase ON symbols(codebase);
72
+ CREATE INDEX IF NOT EXISTS idx_symbols_path ON symbols(path);
73
+ CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);
74
+ CREATE INDEX IF NOT EXISTS idx_relations_from ON relations(from_id);
75
+ CREATE INDEX IF NOT EXISTS idx_relations_to ON relations(to_id);
76
+ CREATE INDEX IF NOT EXISTS idx_relations_type ON relations(relation_type);
77
+ CREATE INDEX IF NOT EXISTS idx_relations_external ON relations(to_external);
78
+ """
79
+
80
+
81
+ def write_sqlite(path: Path, files, symbols, relations, diagnostics) -> None:
82
+ path.parent.mkdir(parents=True, exist_ok=True)
83
+ if path.exists():
84
+ path.unlink()
85
+ conn = sqlite3.connect(str(path))
86
+ try:
87
+ conn.executescript(SCHEMA)
88
+ conn.executemany(
89
+ """
90
+ INSERT INTO code_files(id, codebase, path, language, size_bytes, content_hash, indexed_at, parser)
91
+ VALUES(:id, :codebase, :path, :language, :size_bytes, :content_hash, :indexed_at, :parser)
92
+ """,
93
+ files,
94
+ )
95
+ conn.executemany(
96
+ """
97
+ INSERT INTO symbols(id, codebase, kind, name, qualified_name, container_id, path, line_start, line_end,
98
+ signature, language, content_hash, visibility, metadata_json)
99
+ VALUES(:id, :codebase, :kind, :name, :qualified_name, :container_id, :path, :line_start, :line_end,
100
+ :signature, :language, :content_hash, :visibility, :metadata_json)
101
+ """,
102
+ [_symbol_row(record) for record in symbols],
103
+ )
104
+ conn.executemany(
105
+ """
106
+ INSERT INTO relations(from_id, relation_type, to_id, to_external, evidence_path, evidence_line,
107
+ confidence, parser, metadata_json)
108
+ VALUES(:from_id, :relation_type, :to_id, :to_external, :evidence_path, :evidence_line,
109
+ :confidence, :parser, :metadata_json)
110
+ """,
111
+ [_relation_row(record) for record in relations],
112
+ )
113
+ conn.executemany(
114
+ """
115
+ INSERT INTO diagnostics(codebase, path, line, severity, kind, message, parser)
116
+ VALUES(:codebase, :path, :line, :severity, :kind, :message, :parser)
117
+ """,
118
+ diagnostics,
119
+ )
120
+ conn.executemany(
121
+ """
122
+ INSERT INTO symbols_fts(id, codebase, name, qualified_name, signature, path, metadata_json)
123
+ VALUES(:id, :codebase, :name, :qualified_name, :signature, :path, :metadata_json)
124
+ """,
125
+ [_symbol_row(record) for record in symbols],
126
+ )
127
+ conn.commit()
128
+ finally:
129
+ conn.close()
130
+ with path.open("rb") as handle:
131
+ os.fsync(handle.fileno())
132
+
133
+
134
+ def _symbol_row(record):
135
+ row = dict(record)
136
+ row["metadata_json"] = json_dumps(row.pop("metadata", {}))
137
+ return row
138
+
139
+
140
+ def _relation_row(record):
141
+ row = dict(record)
142
+ row["metadata_json"] = json_dumps(row.pop("metadata", {}))
143
+ return row