mcp-efficiency-engine 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 (360) hide show
  1. package/.github/CODEOWNERS +40 -0
  2. package/.github/GITHUB_MCP_INTEGRATION.md +366 -0
  3. package/.github/ISSUE_TEMPLATE/bug.md +51 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +45 -0
  5. package/.github/ISSUE_TEMPLATE/question.md +18 -0
  6. package/.github/agents/backend.agent.md +18 -0
  7. package/.github/agents/community-manager.agent.md +18 -0
  8. package/.github/agents/dba.agent.md +18 -0
  9. package/.github/agents/frontend-agent.agent.md +18 -0
  10. package/.github/agents/github-repository-manager.agent.md +338 -0
  11. package/.github/agents/iot.agent.md +20 -0
  12. package/.github/agents/legacy.agent.md +18 -0
  13. package/.github/agents/rag-azure.agent.md +18 -0
  14. package/.github/agents/rag-local.agent.md +18 -0
  15. package/.github/agents/snapshot.agent.md +18 -0
  16. package/.github/agents/ux-ui.agent.md +18 -0
  17. package/.github/agents/wiki-agent.agent.md +23 -0
  18. package/.github/copilot-instructions.md +44 -0
  19. package/.github/instructions/always-on-optimization.instructions.md +54 -0
  20. package/.github/prompts/auto-route.prompt.md +33 -0
  21. package/.github/prompts/azure-rag.query.prompt.md +19 -0
  22. package/.github/prompts/backend.fix-bug.prompt.md +13 -0
  23. package/.github/prompts/cavecrew.prompt.md +16 -0
  24. package/.github/prompts/caveman-commit.prompt.md +14 -0
  25. package/.github/prompts/caveman-compress.prompt.md +15 -0
  26. package/.github/prompts/caveman-debug.prompt.md +13 -0
  27. package/.github/prompts/caveman-help.prompt.md +11 -0
  28. package/.github/prompts/caveman-review.prompt.md +15 -0
  29. package/.github/prompts/caveman-stats.prompt.md +11 -0
  30. package/.github/prompts/caveman.prompt.md +11 -0
  31. package/.github/prompts/community.post.prompt.md +14 -0
  32. package/.github/prompts/dba.query-review.prompt.md +15 -0
  33. package/.github/prompts/dev.fix-bug.prompt.md +13 -0
  34. package/.github/prompts/frontend.code.prompt.md +13 -0
  35. package/.github/prompts/legacy.impact-analysis.prompt.md +14 -0
  36. package/.github/prompts/project.kickoff-analysis.prompt.md +51 -0
  37. package/.github/prompts/rag.knowledge-answer.prompt.md +13 -0
  38. package/.github/prompts/token-saver-review.prompt.md +14 -0
  39. package/.github/prompts/ux-ui.review.prompt.md +14 -0
  40. package/.github/pull_request_template.md +71 -0
  41. package/.github/skills/ahorro-tokens/SKILL.md +36 -0
  42. package/.github/skills/azure-rag-enterprise/SKILL.md +24 -0
  43. package/.github/skills/backend-coding/SKILL.md +24 -0
  44. package/.github/skills/cavecrew/SKILL.md +17 -0
  45. package/.github/skills/caveman/SKILL.md +25 -0
  46. package/.github/skills/caveman-commit/SKILL.md +15 -0
  47. package/.github/skills/caveman-compress/SKILL.md +14 -0
  48. package/.github/skills/caveman-help/SKILL.md +19 -0
  49. package/.github/skills/caveman-mode/SKILL.md +43 -0
  50. package/.github/skills/caveman-review/SKILL.md +16 -0
  51. package/.github/skills/caveman-stats/SKILL.md +13 -0
  52. package/.github/skills/community-content/SKILL.md +22 -0
  53. package/.github/skills/database-analysis/SKILL.md +23 -0
  54. package/.github/skills/dev-coding/SKILL.md +24 -0
  55. package/.github/skills/frontend-coding/SKILL.md +24 -0
  56. package/.github/skills/human-in-the-loop/SKILL.md +47 -0
  57. package/.github/skills/iot-architecture/SKILL.md +22 -0
  58. package/.github/skills/legacy-migration/SKILL.md +22 -0
  59. package/.github/skills/rag-knowledge/SKILL.md +21 -0
  60. package/.github/skills/token-saver/SKILL.md +36 -0
  61. package/.github/skills/ux-ui-governance/SKILL.md +24 -0
  62. package/.github/skills/wiki-tools.json +24 -0
  63. package/.github/workflows/auto-devlog.yml +56 -0
  64. package/.github/workflows/auto-manage-issues.yml +64 -0
  65. package/.github/workflows/auto-sync.yml +54 -0
  66. package/.github/workflows/autodocs-sync.yml +114 -0
  67. package/.github/workflows/ci.yml +68 -0
  68. package/.github/workflows/pages.yml +59 -0
  69. package/.github/workflows/routing-evals.yml +59 -0
  70. package/.github/workflows/techriders-coverage-effective.yml +91 -0
  71. package/.vscode/mcp.json +44 -0
  72. package/AGENTS.md +160 -0
  73. package/ARCHITECTURE.md +57 -0
  74. package/FINAL_USAGE_GUIDE.md +106 -0
  75. package/LICENSE +21 -0
  76. package/README.md +385 -0
  77. package/README_WIKI.md +130 -0
  78. package/autodocs/README.md +22 -0
  79. package/autodocs/schema/wiki-node.schema.json +56 -0
  80. package/autolearning/feedback-loop.md +90 -0
  81. package/bin/install-host.js +326 -0
  82. package/bin/mcpee.js +116 -0
  83. package/context/repomix/repomix.config.json +20 -0
  84. package/memory/cross-memory-reasoning.md +17 -0
  85. package/memory/mempry-registry.yml +16 -0
  86. package/observability/evals/chat-token-usage-report.json +64 -0
  87. package/observability/evals/chat-token-usage-report.md +33 -0
  88. package/observability/evals/iteration-value-report.json +76 -0
  89. package/observability/evals/iteration-value-report.md +39 -0
  90. package/observability/evals/learning-loop-report.json +268 -0
  91. package/observability/evals/learning-loop-report.md +37 -0
  92. package/observability/evals/repo-intake-eval-cases.md +23 -0
  93. package/observability/evals/routing-eval-cases.json +68 -0
  94. package/observability/evals/routing-eval-cases.md +25 -0
  95. package/observability/evals/routing-eval-report.json +72 -0
  96. package/observability/evaluation.md +34 -0
  97. package/observability/logs/copilot-usage-ingest-report.json +13 -0
  98. package/observability/logs/iteration-metrics.jsonl +75 -0
  99. package/observability/logs/learning-feedback.jsonl +152 -0
  100. package/observability/logs/routing-decisions.jsonl +333 -0
  101. package/observability/logs/session/agent-pipeline-preflight-20260701-004146.log +8 -0
  102. package/observability/logs/session/agent-pipeline-preflight-20260701-005554.log +8 -0
  103. package/observability/logs/session/agent-pipeline-preflight-20260701-010351.log +8 -0
  104. package/observability/logs/session/agent-pipeline-preflight-20260704-145829.log +8 -0
  105. package/observability/logs/session/agent-pipeline-preflight-20260704-150021.log +8 -0
  106. package/observability/logs/session/agent-pipeline-preflight-20260704-154328.log +8 -0
  107. package/observability/logs/session/bye-20260629-221513.json +39 -0
  108. package/observability/logs/session/bye-20260629-221545.json +59 -0
  109. package/observability/logs/session/bye-20260629-222007.json +52 -0
  110. package/observability/logs/session/bye-20260629-222133.json +59 -0
  111. package/observability/logs/session/bye-20260629-222412.json +45 -0
  112. package/observability/logs/session/bye-20260629-223224.json +52 -0
  113. package/observability/logs/session/bye-20260629-224050.json +59 -0
  114. package/observability/logs/session/bye-20260630-105732.json +24 -0
  115. package/observability/logs/session/bye-20260630-211536.json +87 -0
  116. package/observability/logs/session/bye-20260630-223423.json +87 -0
  117. package/observability/logs/session/bye-20260630-232534.json +87 -0
  118. package/observability/logs/session/bye-20260701-003638.json +126 -0
  119. package/observability/logs/session/bye-20260701-003849.json +126 -0
  120. package/observability/logs/session/bye-20260701-004315.json +138 -0
  121. package/observability/logs/session/bye-20260701-004559.json +76 -0
  122. package/observability/logs/session/bye-20260701-005913.json +138 -0
  123. package/observability/logs/session/bye-20260701-010753.json +138 -0
  124. package/observability/logs/session/bye-20260703-194106.json +24 -0
  125. package/observability/logs/session/bye-20260703-233443.json +76 -0
  126. package/observability/logs/session/bye-20260703-233653.json +76 -0
  127. package/observability/logs/session/bye-20260704-150317.json +152 -0
  128. package/observability/logs/session/bye-20260704-150929.json +75 -0
  129. package/observability/logs/session/bye-20260704-151050.json +75 -0
  130. package/observability/logs/session/bye-20260705-115458.json +165 -0
  131. package/observability/logs/session/codegraph-status-20260701-004228.log +39 -0
  132. package/observability/logs/session/codegraph-status-20260701-004310.log +39 -0
  133. package/observability/logs/session/codegraph-status-20260701-005637.log +39 -0
  134. package/observability/logs/session/codegraph-status-20260701-005908.log +39 -0
  135. package/observability/logs/session/codegraph-status-20260701-010444.log +39 -0
  136. package/observability/logs/session/codegraph-status-20260701-010747.log +39 -0
  137. package/observability/logs/session/codegraph-status-20260704-150137.log +26 -0
  138. package/observability/logs/session/codegraph-status-20260704-150313.log +28 -0
  139. package/observability/logs/session/codegraph-status-20260704-154445.log +26 -0
  140. package/observability/logs/session/codegraph-status-20260705-115454.log +27 -0
  141. package/observability/logs/session/codegraph-sync-20260701-004211.log +88 -0
  142. package/observability/logs/session/codegraph-sync-20260701-004241.log +82 -0
  143. package/observability/logs/session/codegraph-sync-20260701-005620.log +89 -0
  144. package/observability/logs/session/codegraph-sync-20260701-005840.log +88 -0
  145. package/observability/logs/session/codegraph-sync-20260701-010419.log +93 -0
  146. package/observability/logs/session/codegraph-sync-20260701-010609.log +90 -0
  147. package/observability/logs/session/codegraph-sync-20260704-145856.log +70 -0
  148. package/observability/logs/session/codegraph-sync-20260704-150047.log +53 -0
  149. package/observability/logs/session/codegraph-sync-20260704-150204.log +44 -0
  150. package/observability/logs/session/codegraph-sync-20260704-154353.log +26 -0
  151. package/observability/logs/session/codegraph-sync-20260705-115337.log +32 -0
  152. package/observability/logs/session/hi-20260629-221459.json +38 -0
  153. package/observability/logs/session/hi-20260629-221945.json +59 -0
  154. package/observability/logs/session/hi-20260629-222108.json +66 -0
  155. package/observability/logs/session/hi-20260629-222352.json +45 -0
  156. package/observability/logs/session/hi-20260629-225719.json +59 -0
  157. package/observability/logs/session/hi-20260629-233722.json +52 -0
  158. package/observability/logs/session/hi-20260629-233913.json +198 -0
  159. package/observability/logs/session/hi-20260630-110156.json +177 -0
  160. package/observability/logs/session/hi-20260630-191243.json +184 -0
  161. package/observability/logs/session/hi-20260630-230050.json +234 -0
  162. package/observability/logs/session/hi-20260630-230523.json +227 -0
  163. package/observability/logs/session/hi-20260630-230855.json +227 -0
  164. package/observability/logs/session/hi-20260630-231638.json +227 -0
  165. package/observability/logs/session/hi-20260630-231756.json +219 -0
  166. package/observability/logs/session/hi-20260701-002842.json +234 -0
  167. package/observability/logs/session/hi-20260701-003458.json +282 -0
  168. package/observability/logs/session/hi-20260701-004233.json +290 -0
  169. package/observability/logs/session/hi-20260701-004554.json +236 -0
  170. package/observability/logs/session/hi-20260701-005641.json +290 -0
  171. package/observability/logs/session/hi-20260701-010450.json +290 -0
  172. package/observability/logs/session/hi-20260703-233854.json +312 -0
  173. package/observability/logs/session/hi-20260703-234448.json +318 -0
  174. package/observability/logs/session/hi-20260704-145907.json +353 -0
  175. package/observability/logs/session/hi-20260704-150141.json +392 -0
  176. package/observability/logs/session/hi-20260704-154448.json +392 -0
  177. package/observability/logs/session/iteration-value-refresh-20260701-004309.log +3 -0
  178. package/observability/logs/session/iteration-value-refresh-20260701-005907.log +3 -0
  179. package/observability/logs/session/iteration-value-refresh-20260701-010747.log +3 -0
  180. package/observability/logs/session/iteration-value-refresh-20260704-150312.log +3 -0
  181. package/observability/logs/session/iteration-value-refresh-20260705-115453.log +3 -0
  182. package/observability/logs/session/learning-loop-refresh-20260701-004309.log +3 -0
  183. package/observability/logs/session/learning-loop-refresh-20260701-005906.log +3 -0
  184. package/observability/logs/session/learning-loop-refresh-20260701-010745.log +3 -0
  185. package/observability/logs/session/learning-loop-refresh-20260704-150309.log +3 -0
  186. package/observability/logs/session/learning-loop-refresh-20260705-115450.log +3 -0
  187. package/observability/logs/session/project-notes-refresh-20260701-004227.log +1 -0
  188. package/observability/logs/session/project-notes-refresh-20260701-004308.log +1 -0
  189. package/observability/logs/session/project-notes-refresh-20260701-005636.log +1 -0
  190. package/observability/logs/session/project-notes-refresh-20260701-005906.log +1 -0
  191. package/observability/logs/session/project-notes-refresh-20260701-010443.log +1 -0
  192. package/observability/logs/session/project-notes-refresh-20260701-010744.log +1 -0
  193. package/observability/logs/session/project-notes-refresh-20260704-150133.log +1 -0
  194. package/observability/logs/session/project-notes-refresh-20260704-150309.log +1 -0
  195. package/observability/logs/session/project-notes-refresh-20260704-154442.log +1 -0
  196. package/observability/logs/session/project-notes-refresh-20260705-115449.log +1 -0
  197. package/observability/logs/session/repo-intake-20260701-004218.log +6 -0
  198. package/observability/logs/session/repo-intake-20260701-005626.log +6 -0
  199. package/observability/logs/session/repo-intake-20260701-010433.log +6 -0
  200. package/observability/logs/session/repo-intake-20260704-150053.log +6 -0
  201. package/observability/logs/session/repo-intake-20260704-154404.log +6 -0
  202. package/observability/logs/session/repo-intake-refresh-20260701-004247.log +6 -0
  203. package/observability/logs/session/repo-intake-refresh-20260701-005847.log +6 -0
  204. package/observability/logs/session/repo-intake-refresh-20260701-010615.log +6 -0
  205. package/observability/logs/session/repo-intake-refresh-20260704-150209.log +6 -0
  206. package/observability/logs/session/repo-intake-refresh-20260705-115342.log +6 -0
  207. package/observability/logs/session/repo-registry-validation-20260701-004234.log +2 -0
  208. package/observability/logs/session/repo-registry-validation-20260701-004556.log +2 -0
  209. package/observability/logs/session/repo-registry-validation-20260701-005833.log +2 -0
  210. package/observability/logs/session/repo-registry-validation-20260701-010601.log +2 -0
  211. package/observability/logs/session/repo-registry-validation-20260704-150155.log +2 -0
  212. package/observability/logs/session/repo-registry-validation-20260705-115323.log +2 -0
  213. package/observability/logs/session/repomix-refresh-20260701-003823.log +4236 -0
  214. package/observability/logs/session/repomix-refresh-20260701-004251.log +4275 -0
  215. package/observability/logs/session/repomix-refresh-20260701-005850.log +4248 -0
  216. package/observability/logs/session/repomix-refresh-20260701-010619.log +6531 -0
  217. package/observability/logs/session/repomix-refresh-20260704-150239.log +652 -0
  218. package/observability/logs/session/repomix-refresh-20260705-115419.log +178 -0
  219. package/observability/logs/session/routing-evals-20260701-004221.log +2 -0
  220. package/observability/logs/session/routing-evals-20260701-004235.log +2 -0
  221. package/observability/logs/session/routing-evals-20260701-005629.log +2 -0
  222. package/observability/logs/session/routing-evals-20260701-005834.log +2 -0
  223. package/observability/logs/session/routing-evals-20260701-010437.log +2 -0
  224. package/observability/logs/session/routing-evals-20260701-010603.log +2 -0
  225. package/observability/logs/session/routing-evals-20260704-150125.log +2 -0
  226. package/observability/logs/session/routing-evals-20260704-150157.log +2 -0
  227. package/observability/logs/session/routing-evals-20260704-154434.log +2 -0
  228. package/observability/logs/session/routing-evals-20260705-115327.log +2 -0
  229. package/observability/logs/session/sibling-discovery-refresh-20260701-004250.log +3 -0
  230. package/observability/logs/session/sibling-discovery-refresh-20260701-005850.log +3 -0
  231. package/observability/logs/session/sibling-discovery-refresh-20260701-010618.log +3 -0
  232. package/observability/logs/session/sibling-discovery-refresh-20260704-150238.log +3 -0
  233. package/observability/logs/session/sibling-discovery-refresh-20260705-115418.log +3 -0
  234. package/observability/logs.schema.json +95 -0
  235. package/observability/logs.schema.md +26 -0
  236. package/observability/metrics.md +35 -0
  237. package/observability/routing-evaluator.md +37 -0
  238. package/observability/scoring-rubric.md +38 -0
  239. package/optimization/ALWAYS_ON_OPTIMIZATION.md +98 -0
  240. package/optimization/caveman-mode.md +62 -0
  241. package/optimization/examples/login-bug.md +25 -0
  242. package/optimization/examples/sla-query.md +25 -0
  243. package/optimization/optimization-routing.md +30 -0
  244. package/optimization/policies/response-style.policy.md +45 -0
  245. package/optimization/policies/token-budget.policy.md +28 -0
  246. package/optimization/profiles/always-on.profile.md +19 -0
  247. package/optimization/profiles/architecture.profile.md +20 -0
  248. package/optimization/profiles/debug.profile.md +20 -0
  249. package/optimization/profiles/enterprise-rag.profile.md +20 -0
  250. package/optimization/profiles/training.profile.md +20 -0
  251. package/optimization/token-saver.md +58 -0
  252. package/orchestrator/corporate-routing.md +51 -0
  253. package/orchestrator/decision-matrix.md +33 -0
  254. package/orchestrator/fallback.md +29 -0
  255. package/orchestrator/repo-routing.md +58 -0
  256. package/orchestrator/router.md +75 -0
  257. package/orchestrator/wiki/__init__.py +5 -0
  258. package/orchestrator/wiki/graph_consolidator.py +506 -0
  259. package/orchestrator/wiki/incremental_engine.py +57 -0
  260. package/orchestrator/wiki/plugin_manager.py +40 -0
  261. package/package.json +70 -0
  262. package/policies/context-policy.md +25 -0
  263. package/policies/cost-policy.md +25 -0
  264. package/policies/repo-intake-policy.md +36 -0
  265. package/policies/security-policy.md +25 -0
  266. package/repo-intake/README.md +81 -0
  267. package/repo-intake/templates/agent.template.md +4 -0
  268. package/repo-intake/templates/context-manifest.template.md +4 -0
  269. package/repo-intake/templates/skill.template.md +3 -0
  270. package/repo-registry/repos.schema.json +102 -0
  271. package/repo-registry/repos.template.json +26 -0
  272. package/requirements.txt +1 -0
  273. package/scripts/README.md +109 -0
  274. package/scripts/__init__.py +0 -0
  275. package/scripts/bootstrap-portable.cmd +4 -0
  276. package/scripts/bootstrap-portable.ps1 +90 -0
  277. package/scripts/context/azure-rag-mcp-adapter.py +1 -0
  278. package/scripts/context/build-graphify.ps1 +1 -0
  279. package/scripts/context/build-repomix.ps1 +1 -0
  280. package/scripts/discovery/discover-boost-repos.cmd +4 -0
  281. package/scripts/discovery/discover-boost-repos.py +186 -0
  282. package/scripts/discovery/refresh-project-notes.py +179 -0
  283. package/scripts/github/INSTALL.md +295 -0
  284. package/scripts/github/README.md +455 -0
  285. package/scripts/github/apply-boost-templates.ps1 +163 -0
  286. package/scripts/github/apply-single-repo.ps1 +85 -0
  287. package/scripts/github/create-devlog.ps1 +380 -0
  288. package/scripts/github/manage-issues.ps1 +332 -0
  289. package/scripts/github/sync-repo.ps1 +267 -0
  290. package/scripts/intake/agent-pipeline-preflight.py +151 -0
  291. package/scripts/intake/init-template-registry.cmd +4 -0
  292. package/scripts/intake/init-template-registry.ps1 +258 -0
  293. package/scripts/intake/repo-intake.py +354 -0
  294. package/scripts/intake/resolve-routing.py +620 -0
  295. package/scripts/intake/run-repo-intake.cmd +4 -0
  296. package/scripts/intake/run-repo-intake.ps1 +46 -0
  297. package/scripts/intake/run-routing-evals.py +147 -0
  298. package/scripts/intake/validate-database-routing.py +91 -0
  299. package/scripts/intake/validate-rag-routing.py +85 -0
  300. package/scripts/intake/validate-repo-registry.ps1 +20 -0
  301. package/scripts/intake/validate-repo-registry.py +286 -0
  302. package/scripts/intake/validate-security.py +170 -0
  303. package/scripts/learning/autolearning-gate.py +71 -0
  304. package/scripts/learning/chat-token-usage-report.py +326 -0
  305. package/scripts/learning/ingest-copilot-session-usage.py +421 -0
  306. package/scripts/learning/iteration-value-report.py +275 -0
  307. package/scripts/learning/learning-loop-report.py +272 -0
  308. package/scripts/learning/record-iteration-metrics.py +116 -0
  309. package/scripts/learning/record-learning-feedback.py +91 -0
  310. package/scripts/ops/bye.ps1 +620 -0
  311. package/scripts/ops/compare-demo-results.ps1 +826 -0
  312. package/scripts/ops/demo1.ps1 +11 -0
  313. package/scripts/ops/demo2.ps1 +11 -0
  314. package/scripts/ops/demo3.ps1 +11 -0
  315. package/scripts/ops/demo4.ps1 +11 -0
  316. package/scripts/ops/hi.ps1 +1045 -0
  317. package/scripts/ops/llm-token-probe.py +164 -0
  318. package/scripts/ops/run-all-demos.ps1 +39 -0
  319. package/scripts/ops/run-demo-block.ps1 +85 -0
  320. package/scripts/ops/run-demo-session.ps1 +532 -0
  321. package/scripts/setup/optimize-engines.ps1 +183 -0
  322. package/scripts/setup/setup-codegraph.ps1 +3 -0
  323. package/scripts/setup/setup-gitnexus.ps1 +3 -0
  324. package/scripts/setup/setup-graphify.ps1 +2 -0
  325. package/scripts/setup/setup-prerequisites.ps1 +205 -0
  326. package/scripts/setup/start-gitnexus.ps1 +71 -0
  327. package/scripts/setup/validate-context.ps1 +361 -0
  328. package/scripts/wiki/__init__.py +0 -0
  329. package/scripts/wiki/compiler_main.py +189 -0
  330. package/scripts/wiki/normalizer.py +206 -0
  331. package/scripts/wiki/providers/base_provider.py +25 -0
  332. package/scripts/wiki/providers/codegraph_provider.py +49 -0
  333. package/scripts/wiki/providers/graphify_provider.py +49 -0
  334. package/scripts/wiki/providers/repo_content_provider.py +408 -0
  335. package/scripts/wiki/query_autodocs.py +60 -0
  336. package/scripts/wiki/validator.py +183 -0
  337. package/scripts/wiki/wiki_compiler.py +5 -0
  338. package/specs/architecture.spec.md +32 -0
  339. package/specs/azure-rag.spec.md +28 -0
  340. package/specs/coding-standards.spec.md +24 -0
  341. package/specs/database.spec.md +29 -0
  342. package/specs/migration.spec.md +26 -0
  343. package/specs/observability.spec.md +24 -0
  344. package/specs/optimization.spec.md +31 -0
  345. package/specs/rag.spec.md +30 -0
  346. package/specs/repo-intake.spec.md +25 -0
  347. package/specs/routing.spec.md +24 -0
  348. package/specs/security.spec.md +30 -0
  349. package/specs/wiki/provider-contract.json +33 -0
  350. package/specs/wiki/unified-knowledge-graph.json +25 -0
  351. package/templates/BOOST_README_TEMPLATE.md +96 -0
  352. package/templates/CODEOWNERS_TEMPLATE.txt +29 -0
  353. package/templates/LICENSE_MIT_TEMPLATE.txt +21 -0
  354. package/templates/PERSONAL_README_TEMPLATE.md +90 -0
  355. package/templates/README_boost_RAG_Azure.md +46 -0
  356. package/templates/README_boost_azure_iot_edge.md +48 -0
  357. package/templates/README_boost_backend.md +47 -0
  358. package/templates/README_boost_dba.md +57 -0
  359. package/templates/ci.yml.template +73 -0
  360. package/tooling/tooling.manifest.json +72 -0
@@ -0,0 +1,506 @@
1
+ import json
2
+ import os
3
+ import hashlib
4
+ from pathlib import Path
5
+ from typing import Any, Dict, List
6
+
7
+ from scripts.wiki.normalizer import normalize_node, section_catalog
8
+
9
+
10
+ SECTIONS = section_catalog()
11
+
12
+
13
+ class GraphConsolidator:
14
+ def __init__(self, output_graph_path: Path, markdown_output_dir: Path) -> None:
15
+ self.output_graph_path = output_graph_path
16
+ self.markdown_output_dir = markdown_output_dir
17
+ self.generated_output_dir = output_graph_path.parent
18
+
19
+ def consolidate(self, provider_contracts: List[Dict[str, Any]]) -> Dict[str, Any]:
20
+ raw_nodes: Dict[str, Dict[str, Any]] = {}
21
+ wiki_nodes: Dict[str, Dict[str, Any]] = {}
22
+ for contract in provider_contracts:
23
+ provider_id = str(contract.get("provider_id", "unknown"))
24
+ entities = contract.get("entities", [])
25
+ if not isinstance(entities, list):
26
+ continue
27
+
28
+ for entity in entities:
29
+ if not isinstance(entity, dict):
30
+ continue
31
+ entity_id = str(entity.get("id", "")).strip()
32
+ if not entity_id:
33
+ continue
34
+
35
+ node_key = f"{provider_id}::{entity_id}"
36
+ relations = self._normalize_relations(provider_id, entity.get("relations", []))
37
+ raw_data = entity.get("raw_data", {})
38
+ metadata = raw_data if isinstance(raw_data, dict) else {}
39
+
40
+ raw_node = {
41
+ "node_id": node_key,
42
+ "provider": provider_id,
43
+ "type": str(entity.get("type", "unknown")),
44
+ "checksum": str(entity.get("checksum", "")),
45
+ "metadata": metadata,
46
+ "relations": relations,
47
+ "semantic_summary": str(metadata.get("semantic_summary", "")),
48
+ }
49
+ raw_nodes[node_key] = raw_node
50
+ wiki_nodes[node_key] = normalize_node(node_key, raw_node)
51
+
52
+ navigation_tree = self._build_navigation_tree(wiki_nodes)
53
+ search_index = self._build_search_index(wiki_nodes)
54
+ relations_index = self._build_relations_index(wiki_nodes)
55
+ section_manifest = self._build_section_manifest(wiki_nodes)
56
+
57
+ return {
58
+ "last_updated": self._deterministic_marker(wiki_nodes),
59
+ "nodes": wiki_nodes,
60
+ "raw_nodes": raw_nodes,
61
+ "wiki_nodes": wiki_nodes,
62
+ "navigation_tree": navigation_tree,
63
+ "search_index": search_index,
64
+ "relations_index": relations_index,
65
+ "section_manifest": section_manifest,
66
+ }
67
+
68
+ def _deterministic_marker(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> str:
69
+ payload = json.dumps(wiki_nodes, sort_keys=True, ensure_ascii=True, separators=(",", ":"))
70
+ digest = hashlib.sha256(payload.encode("utf-8")).hexdigest()
71
+ return f"sha256:{digest}"
72
+
73
+ def persist_graph(self, unified_graph: Dict[str, Any]) -> None:
74
+ self.output_graph_path.parent.mkdir(parents=True, exist_ok=True)
75
+ with self.output_graph_path.open("w", encoding="utf-8") as handle:
76
+ json.dump(unified_graph, handle, indent=2, ensure_ascii=True)
77
+
78
+ def persist_manifests(self, unified_graph: Dict[str, Any]) -> Dict[str, int]:
79
+ self.generated_output_dir.mkdir(parents=True, exist_ok=True)
80
+ artifacts = {
81
+ "search-index.json": unified_graph.get("search_index", []),
82
+ "relations-index.json": unified_graph.get("relations_index", []),
83
+ "section-manifest.json": unified_graph.get("section_manifest", []),
84
+ "navigation-tree.json": unified_graph.get("navigation_tree", {}),
85
+ }
86
+ for file_name, payload in artifacts.items():
87
+ output_path = self.generated_output_dir / file_name
88
+ with output_path.open("w", encoding="utf-8") as handle:
89
+ json.dump(payload, handle, indent=2, ensure_ascii=True)
90
+ return {"manifests": len(artifacts)}
91
+
92
+ def project_dirty_nodes(
93
+ self,
94
+ dirty_nodes: Dict[str, Dict[str, Any]],
95
+ deleted_nodes: List[str],
96
+ all_nodes: Dict[str, Dict[str, Any]],
97
+ cached_nodes: Dict[str, Dict[str, Any]],
98
+ ) -> Dict[str, int]:
99
+ self.markdown_output_dir.mkdir(parents=True, exist_ok=True)
100
+
101
+ rendered = 0
102
+ for node_key, node in dirty_nodes.items():
103
+ previous_node = cached_nodes.get(node_key)
104
+ if isinstance(previous_node, dict):
105
+ previous_path = self._node_markdown_path(previous_node)
106
+ next_path = self._node_markdown_path(node)
107
+ if previous_path != next_path and previous_path.exists():
108
+ previous_path.unlink()
109
+
110
+ file_path = self._node_markdown_path(node)
111
+ file_path.parent.mkdir(parents=True, exist_ok=True)
112
+ with file_path.open("w", encoding="utf-8") as handle:
113
+ handle.write(self._render_node_markdown(node_key, node, all_nodes))
114
+ rendered += 1
115
+
116
+ deleted = 0
117
+ for node_key in deleted_nodes:
118
+ cached_node = cached_nodes.get(node_key)
119
+ if not isinstance(cached_node, dict):
120
+ continue
121
+ file_path = self._node_markdown_path(cached_node)
122
+ if file_path.exists():
123
+ file_path.unlink()
124
+ deleted += 1
125
+
126
+ indexes = self._render_index_pages(all_nodes)
127
+ return {
128
+ "rendered": rendered,
129
+ "deleted": deleted,
130
+ "indexes": indexes,
131
+ "manifests": 4,
132
+ }
133
+
134
+ def _normalize_relations(self, provider_id: str, relations: Any) -> List[Dict[str, str]]:
135
+ if not isinstance(relations, list):
136
+ return []
137
+ normalized: List[Dict[str, str]] = []
138
+ for relation in relations:
139
+ if not isinstance(relation, dict):
140
+ continue
141
+ target = str(relation.get("target", "")).strip()
142
+ rel_type = str(relation.get("type", "related_to")).strip() or "related_to"
143
+ if not target:
144
+ continue
145
+ if "::" not in target:
146
+ target = f"{provider_id}::{target}"
147
+ normalized.append({"target": target, "type": rel_type})
148
+ return normalized
149
+
150
+ def _node_markdown_path(self, node: Dict[str, Any]) -> Path:
151
+ navigation = node.get("navigation", {}) if isinstance(node.get("navigation", {}), dict) else {}
152
+ section = str(navigation.get("section", "misc")).strip() or "misc"
153
+ slug = str(node.get("slug", "untitled")).strip() or "untitled"
154
+ return self.markdown_output_dir / section / f"{slug}.md"
155
+
156
+ def _render_node_markdown(
157
+ self,
158
+ node_key: str,
159
+ node: Dict[str, Any],
160
+ all_nodes: Dict[str, Dict[str, Any]],
161
+ ) -> str:
162
+ lines: List[str] = []
163
+ lines.append(f"# {node.get('title', node_key)}")
164
+ lines.append("")
165
+ summary = str(node.get("summary", "")).strip()
166
+ if summary:
167
+ lines.append(summary)
168
+ lines.append("")
169
+
170
+ lines.append("## Contexto")
171
+ lines.append("")
172
+ lines.append(f"- kind: {node.get('kind', '')}")
173
+ lines.append(f"- domain: {node.get('domain', '')}")
174
+ lines.append(f"- section: {node.get('navigation', {}).get('section', '')}")
175
+ lines.append(f"- provider: {node.get('provider', '')}")
176
+ lines.append(f"- checksum: {node.get('checksum', '')}")
177
+
178
+ owner = str(node.get("owner", "")).strip()
179
+ if owner:
180
+ lines.append(f"- owner: {owner}")
181
+
182
+ tags = node.get("tags", [])
183
+ if isinstance(tags, list) and tags:
184
+ lines.append(f"- tags: {', '.join(str(tag) for tag in tags)}")
185
+
186
+ lines.append("")
187
+
188
+ lines.append("## Navegacion")
189
+ lines.append("")
190
+ section = str(node.get("navigation", {}).get("section", "misc"))
191
+ lines.append(f"- section_index: [{section}](index.md)")
192
+ lines.append(f"- wiki_home: [autodocs](../index.md)")
193
+ sibling_links = self._sibling_links(node, all_nodes)
194
+ if sibling_links:
195
+ lines.append(f"- related_in_section: {', '.join(sibling_links)}")
196
+ lines.append("")
197
+
198
+ lines.append("## Fuentes")
199
+ lines.append("")
200
+ source_refs = node.get("source_refs", [])
201
+ if isinstance(source_refs, list) and source_refs:
202
+ current_path = self._node_markdown_path(node)
203
+ for source_ref in source_refs:
204
+ target_path = self.output_graph_path.parents[1] / str(source_ref)
205
+ relative = os.path.relpath(target_path, current_path.parent).replace("\\", "/")
206
+ lines.append(f"- [{source_ref}]({relative})")
207
+ else:
208
+ lines.append("- none")
209
+
210
+ lines.append("")
211
+ lines.append("## Relaciones")
212
+ lines.append("")
213
+ lines.append("| relation_type | target |")
214
+ lines.append("|---|---|")
215
+
216
+ relation_count = 0
217
+ for relation in node.get("relations", []):
218
+ if not isinstance(relation, dict):
219
+ continue
220
+ target_key = str(relation.get("target", "")).strip()
221
+ if not target_key:
222
+ continue
223
+
224
+ relation_count += 1
225
+ relation_type = str(relation.get("type", "related_to")).strip() or "related_to"
226
+ target_node = all_nodes.get(target_key)
227
+
228
+ if isinstance(target_node, dict):
229
+ current_path = self._node_markdown_path(node)
230
+ target_path = self._node_markdown_path(target_node)
231
+ relative = os.path.relpath(target_path, current_path.parent).replace("\\", "/")
232
+ target_title = str(target_node.get("title", target_key))
233
+ lines.append(f"| {relation_type} | [{target_title}]({relative}) |")
234
+ else:
235
+ lines.append(f"| {relation_type} | {target_key} |")
236
+
237
+ if relation_count == 0:
238
+ lines.append("| none | none |")
239
+
240
+ metadata = node.get("metadata", {}) if isinstance(node.get("metadata", {}), dict) else {}
241
+ if metadata:
242
+ lines.append("")
243
+ lines.append("## Datos tecnicos")
244
+ lines.append("")
245
+ lines.append("<details>")
246
+ lines.append("<summary>Ver payload normalizado</summary>")
247
+ lines.append("")
248
+ lines.append("```json")
249
+ lines.append(json.dumps(metadata, indent=2, ensure_ascii=True))
250
+ lines.append("```")
251
+ lines.append("</details>")
252
+ lines.append("")
253
+
254
+ return "\n".join(lines)
255
+
256
+ def _build_navigation_tree(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
257
+ sections = []
258
+ for section in SECTIONS:
259
+ section_id = section["id"]
260
+ pages = [
261
+ {
262
+ "title": node.get("title", ""),
263
+ "slug": node.get("slug", ""),
264
+ "path": node.get("path", ""),
265
+ }
266
+ for node in wiki_nodes.values()
267
+ if node.get("navigation", {}).get("section") == section_id
268
+ ]
269
+ pages.sort(key=lambda item: item["title"])
270
+ sections.append(
271
+ {
272
+ "id": section_id,
273
+ "title": section["title"],
274
+ "description": section["description"],
275
+ "page_count": len(pages),
276
+ "pages": pages,
277
+ }
278
+ )
279
+ return {"sections": sections}
280
+
281
+ def _build_search_index(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
282
+ entries = []
283
+ for node in wiki_nodes.values():
284
+ entries.append(
285
+ {
286
+ "title": node.get("title", ""),
287
+ "summary": node.get("summary", ""),
288
+ "kind": node.get("kind", ""),
289
+ "domain": node.get("domain", ""),
290
+ "section": node.get("navigation", {}).get("section", ""),
291
+ "tags": node.get("tags", []),
292
+ "path": node.get("path", ""),
293
+ }
294
+ )
295
+ entries.sort(key=lambda item: (str(item.get("section", "")), str(item.get("title", ""))))
296
+ return entries
297
+
298
+ def _build_relations_index(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
299
+ edges: List[Dict[str, Any]] = []
300
+ for node_key, node in wiki_nodes.items():
301
+ for relation in node.get("relations", []):
302
+ if not isinstance(relation, dict):
303
+ continue
304
+ edges.append(
305
+ {
306
+ "source": node_key,
307
+ "source_title": node.get("title", node_key),
308
+ "type": relation.get("type", "related_to"),
309
+ "target": relation.get("target", ""),
310
+ }
311
+ )
312
+ edges.sort(key=lambda item: (str(item.get("type", "")), str(item.get("source_title", ""))))
313
+ return edges
314
+
315
+ def _build_section_manifest(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
316
+ manifests: List[Dict[str, Any]] = []
317
+ for section in SECTIONS:
318
+ section_id = section["id"]
319
+ pages = [
320
+ node.get("path", "")
321
+ for node in wiki_nodes.values()
322
+ if node.get("navigation", {}).get("section") == section_id
323
+ ]
324
+ pages.sort()
325
+ manifests.append(
326
+ {
327
+ "id": section_id,
328
+ "title": section["title"],
329
+ "description": section["description"],
330
+ "page_count": len(pages),
331
+ "pages": pages,
332
+ }
333
+ )
334
+ return manifests
335
+
336
+ def _render_index_pages(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> int:
337
+ count = 0
338
+ self.markdown_output_dir.mkdir(parents=True, exist_ok=True)
339
+
340
+ root_index = self.markdown_output_dir / "index.md"
341
+ with root_index.open("w", encoding="utf-8") as handle:
342
+ handle.write(self._render_root_index(wiki_nodes))
343
+ count += 1
344
+
345
+ for section in SECTIONS:
346
+ section_dir = self.markdown_output_dir / section["id"]
347
+ section_dir.mkdir(parents=True, exist_ok=True)
348
+ section_index = section_dir / "index.md"
349
+ with section_index.open("w", encoding="utf-8") as handle:
350
+ handle.write(self._render_section_index(section, wiki_nodes))
351
+ count += 1
352
+
353
+ return count
354
+
355
+ def _render_root_index(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> str:
356
+ top_sections = self._top_sections(wiki_nodes, limit=4)
357
+ featured_pages = self._featured_pages(wiki_nodes, limit=8)
358
+ lines = [
359
+ "# AutoDocs",
360
+ "",
361
+ "Wiki interna de MCP Efficiency Engine. El source of truth es el grafo",
362
+ "unificado y el Markdown es una proyeccion derivada para lectura humana.",
363
+ "",
364
+ "## Resumen",
365
+ "",
366
+ f"- total_pages: {len(wiki_nodes)}",
367
+ f"- generated_graph: {self.output_graph_path.as_posix().replace(str(self.output_graph_path.parents[1]).replace('\\', '/'), 'autodocs') if False else 'autodocs/generated/unified-graph.json'}",
368
+ f"- search_manifest: autodocs/generated/search-index.json",
369
+ f"- validation_report: autodocs/generated/validation-report.md",
370
+ "",
371
+ "## Entry Points",
372
+ "",
373
+ ]
374
+
375
+ for section_id, page_count in top_sections:
376
+ section = next((item for item in SECTIONS if item["id"] == section_id), None)
377
+ if not section:
378
+ continue
379
+ lines.append(f"- [{section['title']}]({section_id}/index.md) - {page_count} paginas")
380
+
381
+ lines.extend([
382
+ "",
383
+ "## Destacados",
384
+ "",
385
+ ])
386
+
387
+ for page in featured_pages:
388
+ lines.append(
389
+ f"- [{page.get('title', '')}]({page.get('path', '')}) - {page.get('summary', '')}"
390
+ )
391
+
392
+ lines.extend([
393
+ "",
394
+ "## Secciones",
395
+ "",
396
+ "| section | description | pages |",
397
+ "|---|---|---|",
398
+ ])
399
+
400
+ for section in SECTIONS:
401
+ page_count = sum(
402
+ 1
403
+ for node in wiki_nodes.values()
404
+ if node.get("navigation", {}).get("section") == section["id"]
405
+ )
406
+ lines.append(
407
+ f"| [{section['title']}]({section['id']}/index.md) | {section['description']} | {page_count} |"
408
+ )
409
+
410
+ lines.append("")
411
+ return "\n".join(lines)
412
+
413
+ def _render_section_index(self, section: Dict[str, str], wiki_nodes: Dict[str, Dict[str, Any]]) -> str:
414
+ pages = [
415
+ node
416
+ for node in wiki_nodes.values()
417
+ if node.get("navigation", {}).get("section") == section["id"]
418
+ ]
419
+ pages.sort(key=lambda item: str(item.get("title", "")))
420
+
421
+ lines = [
422
+ f"# {section['title']}",
423
+ "",
424
+ section["description"],
425
+ "",
426
+ "[Volver a AutoDocs](../index.md)",
427
+ "",
428
+ ]
429
+
430
+ if not pages:
431
+ lines.append("Sin contenido proyectado todavia.")
432
+ lines.append("")
433
+ return "\n".join(lines)
434
+
435
+ lines.append("## Resumen")
436
+ lines.append("")
437
+ lines.append(f"- total_pages: {len(pages)}")
438
+ domain_counts = self._domain_counts(pages)
439
+ if domain_counts:
440
+ lines.append(
441
+ "- domains: " + ", ".join(f"{domain} ({count})" for domain, count in domain_counts)
442
+ )
443
+ lines.append("")
444
+
445
+ lines.append("## Paginas")
446
+ lines.append("")
447
+
448
+ for page in pages:
449
+ page_path = Path(str(page.get("path", ""))).name
450
+ lines.append(f"- [{page.get('title', '')}]({page_path}) - {page.get('summary', '')}")
451
+
452
+ lines.append("")
453
+ return "\n".join(lines)
454
+
455
+ def _top_sections(self, wiki_nodes: Dict[str, Dict[str, Any]], limit: int) -> List[tuple[str, int]]:
456
+ counts = []
457
+ for section in SECTIONS:
458
+ page_count = sum(
459
+ 1
460
+ for node in wiki_nodes.values()
461
+ if node.get("navigation", {}).get("section") == section["id"]
462
+ )
463
+ if page_count > 0:
464
+ counts.append((section["id"], page_count))
465
+ counts.sort(key=lambda item: (-item[1], item[0]))
466
+ return counts[:limit]
467
+
468
+ def _featured_pages(self, wiki_nodes: Dict[str, Dict[str, Any]], limit: int) -> List[Dict[str, Any]]:
469
+ preferred_sections = ["routing", "agents", "skills", "policies", "specs", "observability", "reports"]
470
+ featured: List[Dict[str, Any]] = []
471
+ for section_id in preferred_sections:
472
+ candidates = [
473
+ node
474
+ for node in wiki_nodes.values()
475
+ if node.get("navigation", {}).get("section") == section_id
476
+ ]
477
+ candidates.sort(key=lambda item: str(item.get("title", "")))
478
+ if candidates:
479
+ featured.append(candidates[0])
480
+ if len(featured) >= limit:
481
+ break
482
+ return featured[:limit]
483
+
484
+ def _domain_counts(self, pages: List[Dict[str, Any]]) -> List[tuple[str, int]]:
485
+ counts: Dict[str, int] = {}
486
+ for page in pages:
487
+ domain = str(page.get("domain", "unknown")).strip() or "unknown"
488
+ counts[domain] = counts.get(domain, 0) + 1
489
+ ordered = sorted(counts.items(), key=lambda item: (-item[1], item[0]))
490
+ return ordered[:6]
491
+
492
+ def _sibling_links(self, node: Dict[str, Any], all_nodes: Dict[str, Dict[str, Any]]) -> List[str]:
493
+ section = str(node.get("navigation", {}).get("section", "misc"))
494
+ current_path = self._node_markdown_path(node)
495
+ siblings = [
496
+ candidate
497
+ for candidate in all_nodes.values()
498
+ if candidate.get("navigation", {}).get("section") == section and candidate.get("slug") != node.get("slug")
499
+ ]
500
+ siblings.sort(key=lambda item: str(item.get("title", "")))
501
+ links: List[str] = []
502
+ for sibling in siblings[:3]:
503
+ sibling_path = self._node_markdown_path(sibling)
504
+ relative = os.path.relpath(sibling_path, current_path.parent).replace("\\", "/")
505
+ links.append(f"[{sibling.get('title', '')}]({relative})")
506
+ return links
@@ -0,0 +1,57 @@
1
+ import json
2
+ from pathlib import Path
3
+ from typing import Any, Dict
4
+
5
+
6
+ class IncrementalEngine:
7
+ def __init__(self, cache_path: Path) -> None:
8
+ self.cache_path = cache_path
9
+
10
+ def _extract_nodes(self, loaded: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
11
+ preferred = loaded.get("wiki_nodes")
12
+ if isinstance(preferred, dict):
13
+ return preferred
14
+
15
+ compatibility = loaded.get("nodes")
16
+ if isinstance(compatibility, dict):
17
+ return compatibility
18
+
19
+ return {}
20
+
21
+ def _load_cached_graph(self) -> Dict[str, Any]:
22
+ if not self.cache_path.exists():
23
+ return {"last_updated": "", "nodes": {}}
24
+ try:
25
+ with self.cache_path.open("r", encoding="utf-8") as handle:
26
+ loaded = json.load(handle)
27
+
28
+ if not isinstance(loaded, dict):
29
+ return {"last_updated": "", "nodes": {}}
30
+
31
+ nodes = self._extract_nodes(loaded)
32
+ return {
33
+ "last_updated": str(loaded.get("last_updated", "")),
34
+ "nodes": nodes,
35
+ }
36
+ except Exception:
37
+ return {"last_updated": "", "nodes": {}}
38
+
39
+ def diff(self, incoming_nodes: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
40
+ cached = self._load_cached_graph()
41
+ cached_nodes = cached.get("nodes", {})
42
+
43
+ dirty_nodes: Dict[str, Dict[str, Any]] = {}
44
+ for node_key, incoming in incoming_nodes.items():
45
+ old = cached_nodes.get(node_key)
46
+ if old is None:
47
+ dirty_nodes[node_key] = incoming
48
+ continue
49
+ if str(old.get("checksum", "")) != str(incoming.get("checksum", "")):
50
+ dirty_nodes[node_key] = incoming
51
+
52
+ deleted_nodes = [key for key in cached_nodes.keys() if key not in incoming_nodes]
53
+ return {
54
+ "dirty_nodes": dirty_nodes,
55
+ "deleted_nodes": deleted_nodes,
56
+ "cached_graph": cached,
57
+ }
@@ -0,0 +1,40 @@
1
+ from datetime import datetime, timezone
2
+ from typing import Any, Dict, List
3
+
4
+
5
+ class PluginManager:
6
+ def __init__(self) -> None:
7
+ self._providers: List[Any] = []
8
+
9
+ def register_provider(self, provider: Any) -> None:
10
+ if not hasattr(provider, "provider_id"):
11
+ raise ValueError("Provider must define provider_id")
12
+ if not hasattr(provider, "gather_knowledge"):
13
+ raise ValueError("Provider must implement gather_knowledge()")
14
+ self._providers.append(provider)
15
+
16
+ def gather_all(self) -> Dict[str, List[Dict[str, Any]]]:
17
+ contracts: List[Dict[str, Any]] = []
18
+ errors: List[Dict[str, Any]] = []
19
+ for provider in self._providers:
20
+ try:
21
+ contract = provider.gather_knowledge()
22
+ if isinstance(contract, dict):
23
+ contracts.append(contract)
24
+ else:
25
+ errors.append(
26
+ {
27
+ "timestamp": datetime.now(timezone.utc).isoformat(),
28
+ "provider_id": str(getattr(provider, "provider_id", "unknown")),
29
+ "error": "Provider returned non-dict contract",
30
+ }
31
+ )
32
+ except Exception as exc:
33
+ errors.append(
34
+ {
35
+ "timestamp": datetime.now(timezone.utc).isoformat(),
36
+ "provider_id": str(getattr(provider, "provider_id", "unknown")),
37
+ "error": str(exc),
38
+ }
39
+ )
40
+ return {"contracts": contracts, "errors": errors}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "mcp-efficiency-engine",
3
+ "version": "0.1.0",
4
+ "description": "Motor de orquestacion para agentes MCP con routing por dominio y bootstrap portable.",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "bin": {
8
+ "mcpee": "./bin/mcpee.js",
9
+ "mcp-efficiency-engine": "./bin/mcpee.js"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "autodocs/README.md",
14
+ "autodocs/schema/",
15
+ "autolearning/",
16
+ "scripts/",
17
+ "tooling/",
18
+ "templates/",
19
+ "repo-intake/",
20
+ "repo-registry/repos.schema.json",
21
+ "repo-registry/repos.template.json",
22
+ "orchestrator/",
23
+ "observability/",
24
+ "optimization/",
25
+ "policies/",
26
+ "specs/",
27
+ "memory/",
28
+ "context/repomix/repomix.config.json",
29
+ ".github/",
30
+ ".vscode/mcp.json",
31
+ "AGENTS.md",
32
+ "ARCHITECTURE.md",
33
+ "FINAL_USAGE_GUIDE.md",
34
+ "README.md",
35
+ "README_WIKI.md",
36
+ "LICENSE",
37
+ "requirements.txt"
38
+ ],
39
+ "scripts": {
40
+ "postinstall": "node ./bin/install-host.js --postinstall",
41
+ "install:host": "node ./bin/install-host.js",
42
+ "bootstrap": "node ./bin/mcpee.js bootstrap",
43
+ "validate": "node ./bin/mcpee.js validate",
44
+ "hi": "node ./bin/mcpee.js hi",
45
+ "bye": "node ./bin/mcpee.js bye",
46
+ "intake": "node ./bin/mcpee.js intake",
47
+ "pack:check": "npm pack --dry-run"
48
+ },
49
+ "engines": {
50
+ "node": ">=18"
51
+ },
52
+ "keywords": [
53
+ "mcp",
54
+ "agents",
55
+ "routing",
56
+ "codegraph",
57
+ "gitnexus",
58
+ "bootstrap",
59
+ "autodocs",
60
+ "autolearning",
61
+ "observability"
62
+ ],
63
+ "devDependencies": {
64
+ "@storybook/addon-a11y": "^10.4.6",
65
+ "@storybook/addon-essentials": "^8.6.14",
66
+ "@storybook/addon-interactions": "^8.6.14",
67
+ "@storybook/angular": "^10.4.6",
68
+ "storybook": "^10.4.6"
69
+ }
70
+ }