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,826 @@
1
+ param(
2
+ [string]$RunsRoot = ".\projects\TSS2026\analysis_mcpee\demo_runs",
3
+ [string]$OutputPath,
4
+ [string]$QualityPath = ".\projects\TSS2026\analysis_mcpee\demo-quality-rubric.json",
5
+ [string]$TokenMetricsPath = ".\projects\TSS2026\analysis_mcpee\demo-token-metrics.json",
6
+ [string]$McpSimMetricsPath = ".\projects\TSS2026\analysis_mcpee\demo-mcp-sim-metrics.json",
7
+ [switch]$ShowConsole = $true
8
+ )
9
+
10
+ Set-StrictMode -Version Latest
11
+ $ErrorActionPreference = 'Stop'
12
+
13
+ function Resolve-AbsolutePath {
14
+ param(
15
+ [string]$Path,
16
+ [string]$BasePath
17
+ )
18
+
19
+ if ([System.IO.Path]::IsPathRooted($Path)) {
20
+ return [System.IO.Path]::GetFullPath($Path)
21
+ }
22
+
23
+ return [System.IO.Path]::GetFullPath((Join-Path $BasePath $Path))
24
+ }
25
+
26
+ function Get-LatestSummaryBySuffix {
27
+ param(
28
+ [string]$Root,
29
+ [string]$Suffix
30
+ )
31
+
32
+ $dirs = @(Get-ChildItem -Path $Root -Directory -ErrorAction SilentlyContinue |
33
+ Where-Object { $_.Name -like "*-$Suffix" } |
34
+ Sort-Object LastWriteTime -Descending)
35
+
36
+ if (-not $dirs -or $dirs.Count -eq 0) {
37
+ return $null
38
+ }
39
+
40
+ $summaryPath = Join-Path $dirs[0].FullName 'summary.json'
41
+ if (-not (Test-Path $summaryPath)) {
42
+ return $null
43
+ }
44
+
45
+ return [pscustomobject]@{
46
+ Name = $dirs[0].Name
47
+ Path = $summaryPath
48
+ Data = (Get-Content -Path $summaryPath -Raw | ConvertFrom-Json -Depth 20)
49
+ }
50
+ }
51
+
52
+ function Get-QualityMap {
53
+ param(
54
+ [string]$Path,
55
+ [string]$BasePath
56
+ )
57
+
58
+ $qualityAbs = Resolve-AbsolutePath -Path $Path -BasePath $BasePath
59
+ if (-not (Test-Path $qualityAbs)) {
60
+ return @{}
61
+ }
62
+
63
+ $raw = Get-Content -Path $qualityAbs -Raw | ConvertFrom-Json -Depth 10
64
+ if ($null -eq $raw -or $null -eq $raw.rows) {
65
+ return @{}
66
+ }
67
+
68
+ $map = @{}
69
+ foreach ($row in @($raw.rows)) {
70
+ $name = [string]$row.arquitectura
71
+ if ([string]::IsNullOrWhiteSpace($name)) {
72
+ continue
73
+ }
74
+
75
+ $score = $null
76
+ if ($null -ne $row.calidad_1_5) {
77
+ $score = [double]$row.calidad_1_5
78
+ }
79
+
80
+ $map[$name] = [pscustomobject]@{
81
+ calidad_1_5 = $score
82
+ nota = [string]$row.nota
83
+ }
84
+ }
85
+
86
+ return $map
87
+ }
88
+
89
+ function Get-TokenMetricsData {
90
+ param(
91
+ [string]$Path,
92
+ [string]$BasePath
93
+ )
94
+
95
+ if ([string]::IsNullOrWhiteSpace($Path)) {
96
+ return [pscustomobject]@{
97
+ source_path = ''
98
+ source_name = 'disabled'
99
+ architecture_map = @{}
100
+ rag_map = @{}
101
+ }
102
+ }
103
+
104
+ $tokenAbs = Resolve-AbsolutePath -Path $Path -BasePath $BasePath
105
+ if (-not (Test-Path $tokenAbs)) {
106
+ return [pscustomobject]@{
107
+ source_path = $tokenAbs
108
+ source_name = 'missing'
109
+ architecture_map = @{}
110
+ rag_map = @{}
111
+ }
112
+ }
113
+
114
+ $raw = Get-Content -Path $tokenAbs -Raw | ConvertFrom-Json -Depth 10
115
+ $archMap = @{}
116
+ $ragMap = @{}
117
+
118
+ foreach ($row in @($raw.rows)) {
119
+ $name = [string]$row.arquitectura
120
+ if ([string]::IsNullOrWhiteSpace($name)) {
121
+ continue
122
+ }
123
+
124
+ $archMap[$name] = [pscustomobject]@{
125
+ tokens_prompt = if ($null -ne $row.tokens_prompt) { [double]$row.tokens_prompt } else { $null }
126
+ tokens_context = if ($null -ne $row.tokens_context) { [double]$row.tokens_context } else { $null }
127
+ tokens_response = if ($null -ne $row.tokens_response) { [double]$row.tokens_response } else { $null }
128
+ tokens_total = if ($null -ne $row.tokens_total) { [double]$row.tokens_total } else { $null }
129
+ cost_estimated_usd = if ($null -ne $row.cost_estimated_usd) { [double]$row.cost_estimated_usd } else { $null }
130
+ }
131
+ }
132
+
133
+ foreach ($row in @($raw.rag_rows)) {
134
+ $name = [string]$row.bloque
135
+ if ([string]::IsNullOrWhiteSpace($name)) {
136
+ continue
137
+ }
138
+
139
+ $ragMap[$name] = [pscustomobject]@{
140
+ tokens_total = if ($null -ne $row.tokens_total) { [double]$row.tokens_total } else { $null }
141
+ cost_estimated_usd = if ($null -ne $row.cost_estimated_usd) { [double]$row.cost_estimated_usd } else { $null }
142
+ }
143
+ }
144
+
145
+ return [pscustomobject]@{
146
+ source_path = $tokenAbs
147
+ source_name = if (-not [string]::IsNullOrWhiteSpace([string]$raw.source_name)) { [string]$raw.source_name } else { 'unspecified' }
148
+ architecture_map = $archMap
149
+ rag_map = $ragMap
150
+ }
151
+ }
152
+
153
+ function Get-McpSimMetricsData {
154
+ param(
155
+ [string]$Path,
156
+ [string]$BasePath
157
+ )
158
+
159
+ $mcpAbs = Resolve-AbsolutePath -Path $Path -BasePath $BasePath
160
+ if (-not (Test-Path $mcpAbs)) {
161
+ return [pscustomobject]@{
162
+ source_path = $mcpAbs
163
+ source_name = 'missing'
164
+ architecture_map = @{}
165
+ rag_map = @{}
166
+ }
167
+ }
168
+
169
+ $raw = Get-Content -Path $mcpAbs -Raw | ConvertFrom-Json -Depth 10
170
+ $archMap = @{}
171
+ $ragMap = @{}
172
+
173
+ foreach ($row in @($raw.rows)) {
174
+ $name = [string]$row.arquitectura
175
+ if ([string]::IsNullOrWhiteSpace($name)) { continue }
176
+ $archMap[$name] = [pscustomobject]@{
177
+ mcp_tokens_sim = if ($null -ne $row.mcp_tokens_sim) { [double]$row.mcp_tokens_sim } else { $null }
178
+ }
179
+ }
180
+
181
+ foreach ($row in @($raw.rag_rows)) {
182
+ $name = [string]$row.bloque
183
+ if ([string]::IsNullOrWhiteSpace($name)) { continue }
184
+ $ragMap[$name] = [pscustomobject]@{
185
+ mcp_tokens_sim = if ($null -ne $row.mcp_tokens_sim) { [double]$row.mcp_tokens_sim } else { $null }
186
+ }
187
+ }
188
+
189
+ return [pscustomobject]@{
190
+ source_path = $mcpAbs
191
+ source_name = if (-not [string]::IsNullOrWhiteSpace([string]$raw.source_name)) { [string]$raw.source_name } else { 'unspecified' }
192
+ architecture_map = $archMap
193
+ rag_map = $ragMap
194
+ }
195
+ }
196
+
197
+ function Convert-ToNullableDouble {
198
+ param([string]$Value)
199
+
200
+ if ([string]::IsNullOrWhiteSpace($Value)) {
201
+ return $null
202
+ }
203
+
204
+ $normalized = $Value.Trim().Replace(',', '.')
205
+ $parsed = 0.0
206
+ if ([double]::TryParse($normalized, [System.Globalization.NumberStyles]::Float, [System.Globalization.CultureInfo]::InvariantCulture, [ref]$parsed)) {
207
+ return [double]$parsed
208
+ }
209
+
210
+ return $null
211
+ }
212
+
213
+ function Get-PatternSum {
214
+ param(
215
+ [string]$Text,
216
+ [string]$Pattern
217
+ )
218
+
219
+ if ([string]::IsNullOrWhiteSpace($Text)) {
220
+ return $null
221
+ }
222
+
223
+ $matches = [regex]::Matches($Text, $Pattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
224
+ if ($matches.Count -eq 0) {
225
+ return $null
226
+ }
227
+
228
+ $sum = 0.0
229
+ $found = $false
230
+ foreach ($m in $matches) {
231
+ if ($m.Groups.Count -lt 2) {
232
+ continue
233
+ }
234
+ $n = Convert-ToNullableDouble -Value $m.Groups[1].Value
235
+ if ($null -ne $n) {
236
+ $sum += $n
237
+ $found = $true
238
+ }
239
+ }
240
+
241
+ if (-not $found) {
242
+ return $null
243
+ }
244
+
245
+ return [math]::Round($sum, 6)
246
+ }
247
+
248
+ function Get-TokenMetricsFromText {
249
+ param([string]$Text)
250
+
251
+ $prompt = Get-PatternSum -Text $Text -Pattern '(?:prompt_tokens|input_tokens)\s*[:=]\s*([0-9]+(?:[\.,][0-9]+)?)'
252
+ $context = Get-PatternSum -Text $Text -Pattern '(?:context_tokens)\s*[:=]\s*([0-9]+(?:[\.,][0-9]+)?)'
253
+ $response = Get-PatternSum -Text $Text -Pattern '(?:completion_tokens|output_tokens|response_tokens)\s*[:=]\s*([0-9]+(?:[\.,][0-9]+)?)'
254
+ $total = Get-PatternSum -Text $Text -Pattern '(?:total_tokens|tokens_total)\s*[:=]\s*([0-9]+(?:[\.,][0-9]+)?)'
255
+ if ($null -eq $total) {
256
+ $total = Get-PatternSum -Text $Text -Pattern '(?:Tokens)\s*:\s*([0-9]+(?:[\.,][0-9]+)?)'
257
+ }
258
+ $cost = Get-PatternSum -Text $Text -Pattern '(?:total_cost_usd|cost_estimated_usd|cost_usd|total_cost)\s*[:=]\s*([0-9]+(?:[\.,][0-9]+)?)'
259
+
260
+ return [pscustomobject]@{
261
+ tokens_prompt = $prompt
262
+ tokens_context = $context
263
+ tokens_response = $response
264
+ tokens_total = $total
265
+ cost_estimated_usd = $cost
266
+ }
267
+ }
268
+
269
+ function Merge-TokenMetrics {
270
+ param(
271
+ [pscustomobject]$Accumulator,
272
+ [pscustomobject]$Current
273
+ )
274
+
275
+ if ($null -eq $Accumulator) {
276
+ $Accumulator = [pscustomobject]@{
277
+ tokens_prompt = $null
278
+ tokens_context = $null
279
+ tokens_response = $null
280
+ tokens_total = $null
281
+ cost_estimated_usd = $null
282
+ }
283
+ }
284
+
285
+ foreach ($field in @('tokens_prompt', 'tokens_context', 'tokens_response', 'tokens_total', 'cost_estimated_usd')) {
286
+ $value = $Current.$field
287
+ if ($null -ne $value) {
288
+ if ($null -eq $Accumulator.$field) {
289
+ $Accumulator.$field = [double]$value
290
+ }
291
+ else {
292
+ $Accumulator.$field = [double]$Accumulator.$field + [double]$value
293
+ }
294
+ }
295
+ }
296
+
297
+ return $Accumulator
298
+ }
299
+
300
+ function Get-TokenMetricsFromResultsLogs {
301
+ param([object]$DemoData)
302
+
303
+ $acc = $null
304
+ foreach ($item in @($DemoData.results)) {
305
+ $logPath = [string]$item.combined_log
306
+ if ([string]::IsNullOrWhiteSpace($logPath) -or -not (Test-Path $logPath)) {
307
+ continue
308
+ }
309
+
310
+ $text = Get-Content -Path $logPath -Raw
311
+ $metrics = Get-TokenMetricsFromText -Text $text
312
+ $acc = Merge-TokenMetrics -Accumulator $acc -Current $metrics
313
+ }
314
+
315
+ return $acc
316
+ }
317
+
318
+ function Find-RepoRootFromWorkingDir {
319
+ param([string]$WorkingDir)
320
+
321
+ if ([string]::IsNullOrWhiteSpace($WorkingDir) -or -not (Test-Path $WorkingDir)) {
322
+ return $null
323
+ }
324
+
325
+ $current = [System.IO.Path]::GetFullPath($WorkingDir)
326
+ while ($true) {
327
+ if (Test-Path (Join-Path $current '.git')) {
328
+ return $current
329
+ }
330
+
331
+ $parent = Split-Path -Path $current -Parent
332
+ if ([string]::IsNullOrWhiteSpace($parent) -or $parent -eq $current) {
333
+ break
334
+ }
335
+ $current = $parent
336
+ }
337
+
338
+ return $null
339
+ }
340
+
341
+ function Get-RepoTelemetryFromDemo {
342
+ param([object]$DemoData)
343
+
344
+ $results = @($DemoData.results)
345
+ if ($results.Count -eq 0) {
346
+ return $null
347
+ }
348
+
349
+ $workingDir = [string]$results[0].working_dir
350
+ $repoRoot = Find-RepoRootFromWorkingDir -WorkingDir $workingDir
351
+ if ($null -eq $repoRoot) {
352
+ return $null
353
+ }
354
+
355
+ $reportPath = Join-Path $repoRoot 'observability\evals\iteration-value-report.json'
356
+ if (-not (Test-Path $reportPath)) {
357
+ return $null
358
+ }
359
+
360
+ $raw = Get-Content -Path $reportPath -Raw | ConvertFrom-Json -Depth 10
361
+
362
+ $kpis = $null
363
+ if ($raw.PSObject.Properties.Name -contains 'kpis' -and $null -ne $raw.kpis) {
364
+ $kpis = $raw.kpis
365
+ }
366
+
367
+ $totalTokens = $null
368
+ if ($null -ne $kpis -and $kpis.PSObject.Properties.Name -contains 'total_tokens' -and $null -ne $kpis.total_tokens) {
369
+ $totalTokens = [double]$kpis.total_tokens
370
+ }
371
+ elseif ($raw.PSObject.Properties.Name -contains 'total_tokens' -and $null -ne $raw.total_tokens) {
372
+ $totalTokens = [double]$raw.total_tokens
373
+ }
374
+
375
+ $totalCost = $null
376
+ if ($null -ne $kpis -and $kpis.PSObject.Properties.Name -contains 'total_cost_usd' -and $null -ne $kpis.total_cost_usd) {
377
+ $totalCost = [double]$kpis.total_cost_usd
378
+ }
379
+ elseif ($raw.PSObject.Properties.Name -contains 'total_cost_usd' -and $null -ne $raw.total_cost_usd) {
380
+ $totalCost = [double]$raw.total_cost_usd
381
+ }
382
+
383
+ return [pscustomobject]@{
384
+ tokens_prompt = $null
385
+ tokens_context = $null
386
+ tokens_response = $null
387
+ tokens_total = $totalTokens
388
+ cost_estimated_usd = $totalCost
389
+ }
390
+ }
391
+
392
+ function Resolve-ArchitectureTokenMetrics {
393
+ param(
394
+ [string]$Architecture,
395
+ [object]$DemoData,
396
+ [pscustomobject]$TokenData
397
+ )
398
+
399
+ if ($DemoData.PSObject.Properties.Name -contains 'token_metrics' -and $null -ne $DemoData.token_metrics) {
400
+ $tm = $DemoData.token_metrics
401
+ if ($null -ne $tm.tokens_total -or $null -ne $tm.total_tokens -or $null -ne $tm.cost_estimated_usd -or $null -ne $tm.total_cost_usd) {
402
+ $summaryMetrics = [pscustomobject]@{
403
+ tokens_prompt = if ($null -ne $tm.tokens_prompt) { [double]$tm.tokens_prompt } else { $null }
404
+ tokens_context = if ($null -ne $tm.tokens_context) { [double]$tm.tokens_context } else { $null }
405
+ tokens_response = if ($null -ne $tm.tokens_response) { [double]$tm.tokens_response } else { $null }
406
+ tokens_total = if ($null -ne $tm.tokens_total) { [double]$tm.tokens_total } elseif ($null -ne $tm.total_tokens) { [double]$tm.total_tokens } else { $null }
407
+ cost_estimated_usd = if ($null -ne $tm.cost_estimated_usd) { [double]$tm.cost_estimated_usd } elseif ($null -ne $tm.total_cost_usd) { [double]$tm.total_cost_usd } else { $null }
408
+ }
409
+
410
+ $summaryHasValue = ($null -ne $summaryMetrics.tokens_total -and [double]$summaryMetrics.tokens_total -gt 0) -or
411
+ ($null -ne $summaryMetrics.cost_estimated_usd -and [double]$summaryMetrics.cost_estimated_usd -gt 0) -or
412
+ ($null -ne $summaryMetrics.tokens_prompt -and [double]$summaryMetrics.tokens_prompt -gt 0) -or
413
+ ($null -ne $summaryMetrics.tokens_context -and [double]$summaryMetrics.tokens_context -gt 0) -or
414
+ ($null -ne $summaryMetrics.tokens_response -and [double]$summaryMetrics.tokens_response -gt 0)
415
+
416
+ if ($summaryHasValue) {
417
+ return [pscustomobject]@{
418
+ tokens_prompt = $summaryMetrics.tokens_prompt
419
+ tokens_context = $summaryMetrics.tokens_context
420
+ tokens_response = $summaryMetrics.tokens_response
421
+ tokens_total = $summaryMetrics.tokens_total
422
+ cost_estimated_usd = $summaryMetrics.cost_estimated_usd
423
+ source = 'summary'
424
+ }
425
+ }
426
+ }
427
+ }
428
+
429
+ $fromLogs = Get-TokenMetricsFromResultsLogs -DemoData $DemoData
430
+ $logsHaveValue = ($null -ne $fromLogs) -and (
431
+ ($null -ne $fromLogs.tokens_total -and [double]$fromLogs.tokens_total -gt 0) -or
432
+ ($null -ne $fromLogs.cost_estimated_usd -and [double]$fromLogs.cost_estimated_usd -gt 0) -or
433
+ ($null -ne $fromLogs.tokens_prompt -and [double]$fromLogs.tokens_prompt -gt 0) -or
434
+ ($null -ne $fromLogs.tokens_context -and [double]$fromLogs.tokens_context -gt 0) -or
435
+ ($null -ne $fromLogs.tokens_response -and [double]$fromLogs.tokens_response -gt 0)
436
+ )
437
+ if ($logsHaveValue) {
438
+ return [pscustomobject]@{
439
+ tokens_prompt = $fromLogs.tokens_prompt
440
+ tokens_context = $fromLogs.tokens_context
441
+ tokens_response = $fromLogs.tokens_response
442
+ tokens_total = $fromLogs.tokens_total
443
+ cost_estimated_usd = $fromLogs.cost_estimated_usd
444
+ source = 'logs'
445
+ }
446
+ }
447
+
448
+ $fromRepo = Get-RepoTelemetryFromDemo -DemoData $DemoData
449
+ $repoHasValue = ($null -ne $fromRepo) -and (
450
+ ($null -ne $fromRepo.tokens_total -and [double]$fromRepo.tokens_total -gt 0) -or
451
+ ($null -ne $fromRepo.cost_estimated_usd -and [double]$fromRepo.cost_estimated_usd -gt 0)
452
+ )
453
+ if ($repoHasValue) {
454
+ return [pscustomobject]@{
455
+ tokens_prompt = $fromRepo.tokens_prompt
456
+ tokens_context = $fromRepo.tokens_context
457
+ tokens_response = $fromRepo.tokens_response
458
+ tokens_total = $fromRepo.tokens_total
459
+ cost_estimated_usd = $fromRepo.cost_estimated_usd
460
+ source = 'repo-observability'
461
+ }
462
+ }
463
+
464
+ if ($TokenData.architecture_map.ContainsKey($Architecture)) {
465
+ $m = $TokenData.architecture_map[$Architecture]
466
+ return [pscustomobject]@{
467
+ tokens_prompt = $m.tokens_prompt
468
+ tokens_context = $m.tokens_context
469
+ tokens_response = $m.tokens_response
470
+ tokens_total = $m.tokens_total
471
+ cost_estimated_usd = $m.cost_estimated_usd
472
+ source = 'manual-fallback'
473
+ }
474
+ }
475
+
476
+ return [pscustomobject]@{
477
+ tokens_prompt = $null
478
+ tokens_context = $null
479
+ tokens_response = $null
480
+ tokens_total = $null
481
+ cost_estimated_usd = $null
482
+ source = 'none'
483
+ }
484
+ }
485
+
486
+ function Resolve-RagTokenMetrics {
487
+ param(
488
+ [object]$Step,
489
+ [pscustomobject]$TokenData
490
+ )
491
+
492
+ $logPath = [string]$Step.combined_log
493
+ if (-not [string]::IsNullOrWhiteSpace($logPath) -and (Test-Path $logPath)) {
494
+ $text = Get-Content -Path $logPath -Raw
495
+ $metrics = Get-TokenMetricsFromText -Text $text
496
+ $ragLogsHaveValue = ($null -ne $metrics.tokens_total -and [double]$metrics.tokens_total -gt 0) -or
497
+ ($null -ne $metrics.cost_estimated_usd -and [double]$metrics.cost_estimated_usd -gt 0)
498
+ if ($ragLogsHaveValue) {
499
+ return [pscustomobject]@{
500
+ tokens_total = $metrics.tokens_total
501
+ cost_estimated_usd = $metrics.cost_estimated_usd
502
+ source = 'logs'
503
+ }
504
+ }
505
+ }
506
+
507
+ $name = [string]$Step.name
508
+ if ($TokenData.rag_map.ContainsKey($name)) {
509
+ $m = $TokenData.rag_map[$name]
510
+ return [pscustomobject]@{
511
+ tokens_total = $m.tokens_total
512
+ cost_estimated_usd = $m.cost_estimated_usd
513
+ source = 'manual-fallback'
514
+ }
515
+ }
516
+
517
+ return [pscustomobject]@{
518
+ tokens_total = $null
519
+ cost_estimated_usd = $null
520
+ source = 'none'
521
+ }
522
+ }
523
+
524
+ $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
525
+ $runsAbsRoot = Resolve-AbsolutePath -Path $RunsRoot -BasePath $repoRoot
526
+ $qualityMap = Get-QualityMap -Path $QualityPath -BasePath $repoRoot
527
+ $tokenData = Get-TokenMetricsData -Path $TokenMetricsPath -BasePath $repoRoot
528
+ $mcpSimData = Get-McpSimMetricsData -Path $McpSimMetricsPath -BasePath $repoRoot
529
+
530
+ if (-not (Test-Path $runsAbsRoot)) {
531
+ throw "Runs folder not found: $runsAbsRoot"
532
+ }
533
+
534
+ $demo1 = Get-LatestSummaryBySuffix -Root $runsAbsRoot -Suffix 'demo1'
535
+ $demo2 = Get-LatestSummaryBySuffix -Root $runsAbsRoot -Suffix 'demo2'
536
+ $demo3 = Get-LatestSummaryBySuffix -Root $runsAbsRoot -Suffix 'demo3'
537
+ $demo4 = Get-LatestSummaryBySuffix -Root $runsAbsRoot -Suffix 'demo4'
538
+
539
+ if ($null -eq $demo1 -or $null -eq $demo2 -or $null -eq $demo3 -or $null -eq $demo4) {
540
+ throw 'Missing one or more demo summaries (demo1/demo2/demo3/demo4). Run demos first.'
541
+ }
542
+
543
+ $resolvedD1Tokens = Resolve-ArchitectureTokenMetrics -Architecture 'D1 Baseline' -DemoData $demo1.Data -TokenData $tokenData
544
+ $resolvedD2Tokens = Resolve-ArchitectureTokenMetrics -Architecture 'D2 Agentes' -DemoData $demo2.Data -TokenData $tokenData
545
+ $resolvedD3Tokens = Resolve-ArchitectureTokenMetrics -Architecture 'D3 RAG Local+Azure' -DemoData $demo3.Data -TokenData $tokenData
546
+ $resolvedD4Tokens = Resolve-ArchitectureTokenMetrics -Architecture 'D4 Master Orquestador' -DemoData $demo4.Data -TokenData $tokenData
547
+
548
+ function Get-FirstResultQuestion {
549
+ param([object]$DemoData)
550
+ $results = @($DemoData.results)
551
+ if ($results.Count -eq 0) { return '' }
552
+ return [string]$results[0].question
553
+ }
554
+
555
+ function Get-FirstResultFlow {
556
+ param([object]$DemoData)
557
+ $results = @($DemoData.results)
558
+ if ($results.Count -eq 0) { return '' }
559
+ return ((@($results[0].flow) | ForEach-Object { [string]$_ }) -join ' -> ')
560
+ }
561
+
562
+ $rows = @(
563
+ [pscustomobject]@{
564
+ arquitectura = 'D1 Baseline'
565
+ repo = 'TSS2026'
566
+ session = [string]$demo1.Data.session_name
567
+ pregunta = Get-FirstResultQuestion -DemoData $demo1.Data
568
+ flujo = Get-FirstResultFlow -DemoData $demo1.Data
569
+ duration_sec = [double]$demo1.Data.duration_sec
570
+ steps_ok = [int]$demo1.Data.steps_ok
571
+ steps_failed = [int]$demo1.Data.steps_failed
572
+ steps_timeout = [int]$demo1.Data.steps_timeout
573
+ calidad_1_5 = if ($qualityMap.ContainsKey('D1 Baseline')) { $qualityMap['D1 Baseline'].calidad_1_5 } else { $null }
574
+ nota_calidad = if ($qualityMap.ContainsKey('D1 Baseline')) { $qualityMap['D1 Baseline'].nota } else { '' }
575
+ tokens_prompt = $resolvedD1Tokens.tokens_prompt
576
+ tokens_context = $resolvedD1Tokens.tokens_context
577
+ tokens_response = $resolvedD1Tokens.tokens_response
578
+ tokens_total = $resolvedD1Tokens.tokens_total
579
+ cost_estimated_usd = $resolvedD1Tokens.cost_estimated_usd
580
+ token_source = $resolvedD1Tokens.source
581
+ mcp_tokens_sim = if ($mcpSimData.architecture_map.ContainsKey('D1 Baseline')) { $mcpSimData.architecture_map['D1 Baseline'].mcp_tokens_sim } else { $null }
582
+ run_folder = [string]$demo1.Data.run_folder
583
+ summary_json = $demo1.Path
584
+ },
585
+ [pscustomobject]@{
586
+ arquitectura = 'D2 Agentes'
587
+ repo = 'TSS2026_agentes'
588
+ session = [string]$demo2.Data.session_name
589
+ pregunta = Get-FirstResultQuestion -DemoData $demo2.Data
590
+ flujo = Get-FirstResultFlow -DemoData $demo2.Data
591
+ duration_sec = [double]$demo2.Data.duration_sec
592
+ steps_ok = [int]$demo2.Data.steps_ok
593
+ steps_failed = [int]$demo2.Data.steps_failed
594
+ steps_timeout = [int]$demo2.Data.steps_timeout
595
+ calidad_1_5 = if ($qualityMap.ContainsKey('D2 Agentes')) { $qualityMap['D2 Agentes'].calidad_1_5 } else { $null }
596
+ nota_calidad = if ($qualityMap.ContainsKey('D2 Agentes')) { $qualityMap['D2 Agentes'].nota } else { '' }
597
+ tokens_prompt = $resolvedD2Tokens.tokens_prompt
598
+ tokens_context = $resolvedD2Tokens.tokens_context
599
+ tokens_response = $resolvedD2Tokens.tokens_response
600
+ tokens_total = $resolvedD2Tokens.tokens_total
601
+ cost_estimated_usd = $resolvedD2Tokens.cost_estimated_usd
602
+ token_source = $resolvedD2Tokens.source
603
+ mcp_tokens_sim = if ($mcpSimData.architecture_map.ContainsKey('D2 Agentes')) { $mcpSimData.architecture_map['D2 Agentes'].mcp_tokens_sim } else { $null }
604
+ run_folder = [string]$demo2.Data.run_folder
605
+ summary_json = $demo2.Path
606
+ },
607
+ [pscustomobject]@{
608
+ arquitectura = 'D3 RAG Local+Azure'
609
+ repo = 'TSS2026_RAG'
610
+ session = [string]$demo3.Data.session_name
611
+ pregunta = Get-FirstResultQuestion -DemoData $demo3.Data
612
+ flujo = Get-FirstResultFlow -DemoData $demo3.Data
613
+ duration_sec = [double]$demo3.Data.duration_sec
614
+ steps_ok = [int]$demo3.Data.steps_ok
615
+ steps_failed = [int]$demo3.Data.steps_failed
616
+ steps_timeout = [int]$demo3.Data.steps_timeout
617
+ calidad_1_5 = if ($qualityMap.ContainsKey('D3 RAG Local+Azure')) { $qualityMap['D3 RAG Local+Azure'].calidad_1_5 } else { $null }
618
+ nota_calidad = if ($qualityMap.ContainsKey('D3 RAG Local+Azure')) { $qualityMap['D3 RAG Local+Azure'].nota } else { '' }
619
+ tokens_prompt = $resolvedD3Tokens.tokens_prompt
620
+ tokens_context = $resolvedD3Tokens.tokens_context
621
+ tokens_response = $resolvedD3Tokens.tokens_response
622
+ tokens_total = $resolvedD3Tokens.tokens_total
623
+ cost_estimated_usd = $resolvedD3Tokens.cost_estimated_usd
624
+ token_source = $resolvedD3Tokens.source
625
+ mcp_tokens_sim = if ($mcpSimData.architecture_map.ContainsKey('D3 RAG Local+Azure')) { $mcpSimData.architecture_map['D3 RAG Local+Azure'].mcp_tokens_sim } else { $null }
626
+ run_folder = [string]$demo3.Data.run_folder
627
+ summary_json = $demo3.Path
628
+ },
629
+ [pscustomobject]@{
630
+ arquitectura = 'D4 Master Orquestador'
631
+ repo = 'mcp-efficiency-engine'
632
+ session = [string]$demo4.Data.session_name
633
+ pregunta = Get-FirstResultQuestion -DemoData $demo4.Data
634
+ flujo = Get-FirstResultFlow -DemoData $demo4.Data
635
+ duration_sec = [double]$demo4.Data.duration_sec
636
+ steps_ok = [int]$demo4.Data.steps_ok
637
+ steps_failed = [int]$demo4.Data.steps_failed
638
+ steps_timeout = [int]$demo4.Data.steps_timeout
639
+ calidad_1_5 = if ($qualityMap.ContainsKey('D4 Master Orquestador')) { $qualityMap['D4 Master Orquestador'].calidad_1_5 } else { $null }
640
+ nota_calidad = if ($qualityMap.ContainsKey('D4 Master Orquestador')) { $qualityMap['D4 Master Orquestador'].nota } else { '' }
641
+ tokens_prompt = $resolvedD4Tokens.tokens_prompt
642
+ tokens_context = $resolvedD4Tokens.tokens_context
643
+ tokens_response = $resolvedD4Tokens.tokens_response
644
+ tokens_total = $resolvedD4Tokens.tokens_total
645
+ cost_estimated_usd = $resolvedD4Tokens.cost_estimated_usd
646
+ token_source = $resolvedD4Tokens.source
647
+ mcp_tokens_sim = if ($mcpSimData.architecture_map.ContainsKey('D4 Master Orquestador')) { $mcpSimData.architecture_map['D4 Master Orquestador'].mcp_tokens_sim } else { $null }
648
+ run_folder = [string]$demo4.Data.run_folder
649
+ summary_json = $demo4.Path
650
+ }
651
+ )
652
+
653
+ $ragSubRows = @()
654
+ foreach ($item in @($demo3.Data.results)) {
655
+ $ragToken = Resolve-RagTokenMetrics -Step $item -TokenData $tokenData
656
+ $ragSubRows += [pscustomobject]@{
657
+ bloque = [string]$item.name
658
+ pregunta = [string]$item.question
659
+ flujo = ((@($item.flow) | ForEach-Object { [string]$_ }) -join ' -> ')
660
+ duration_sec = [double]$item.duration_sec
661
+ status = [string]$item.status
662
+ exit_code = [int]$item.exit_code
663
+ tokens_total = $ragToken.tokens_total
664
+ cost_estimated_usd = $ragToken.cost_estimated_usd
665
+ token_source = $ragToken.source
666
+ mcp_tokens_sim = if ($mcpSimData.rag_map.ContainsKey([string]$item.name)) { $mcpSimData.rag_map[[string]$item.name].mcp_tokens_sim } else { $null }
667
+ }
668
+ }
669
+
670
+ $best = $rows | Sort-Object duration_sec | Select-Object -First 1
671
+ $worst = $rows | Sort-Object duration_sec -Descending | Select-Object -First 1
672
+ $delta = [math]::Round(($worst.duration_sec - $best.duration_sec), 2)
673
+ $qualityRows = @($rows | Where-Object { $null -ne $_.calidad_1_5 })
674
+ $bestQuality = if ($qualityRows.Count -gt 0) { $qualityRows | Sort-Object calidad_1_5 -Descending | Select-Object -First 1 } else { $null }
675
+ $tokenRows = @($rows | Where-Object { $null -ne $_.tokens_total })
676
+ $bestToken = if ($tokenRows.Count -gt 0) { $tokenRows | Sort-Object tokens_total | Select-Object -First 1 } else { $null }
677
+ $worstToken = if ($tokenRows.Count -gt 0) { $tokenRows | Sort-Object tokens_total -Descending | Select-Object -First 1 } else { $null }
678
+ $tokenDelta = if ($null -ne $bestToken -and $null -ne $worstToken) { [math]::Round(($worstToken.tokens_total - $bestToken.tokens_total), 2) } else { $null }
679
+
680
+ $stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
681
+ if ([string]::IsNullOrWhiteSpace($OutputPath)) {
682
+ $outputDir = Join-Path $runsAbsRoot ("$stamp-comparativa-arquitecturas")
683
+ New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
684
+ $outputMd = Join-Path $outputDir 'comparison.md'
685
+ $outputJson = Join-Path $outputDir 'comparison.json'
686
+ }
687
+ else {
688
+ $outputMdAbs = Resolve-AbsolutePath -Path $OutputPath -BasePath $repoRoot
689
+ $outputDir = Split-Path -Path $outputMdAbs -Parent
690
+ if (-not (Test-Path $outputDir)) {
691
+ New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
692
+ }
693
+ $outputMd = $outputMdAbs
694
+ $outputJson = [System.IO.Path]::ChangeExtension($outputMdAbs, '.json')
695
+ }
696
+
697
+ $comparison = [ordered]@{
698
+ generated_at = (Get-Date).ToString('o')
699
+ runs_root = $runsAbsRoot
700
+ quality_source = Resolve-AbsolutePath -Path $QualityPath -BasePath $repoRoot
701
+ token_metrics_source = $tokenData.source_path
702
+ token_metrics_source_name = $tokenData.source_name
703
+ mcp_sim_source = $mcpSimData.source_path
704
+ mcp_sim_source_name = $mcpSimData.source_name
705
+ best_architecture = $best.arquitectura
706
+ best_duration_sec = $best.duration_sec
707
+ worst_architecture = $worst.arquitectura
708
+ worst_duration_sec = $worst.duration_sec
709
+ duration_delta_sec = $delta
710
+ best_token_architecture = if ($null -ne $bestToken) { $bestToken.arquitectura } else { $null }
711
+ best_token_total = if ($null -ne $bestToken) { $bestToken.tokens_total } else { $null }
712
+ worst_token_architecture = if ($null -ne $worstToken) { $worstToken.arquitectura } else { $null }
713
+ worst_token_total = if ($null -ne $worstToken) { $worstToken.tokens_total } else { $null }
714
+ token_delta = $tokenDelta
715
+ best_quality_architecture = if ($null -ne $bestQuality) { $bestQuality.arquitectura } else { $null }
716
+ best_quality_score = if ($null -ne $bestQuality) { $bestQuality.calidad_1_5 } else { $null }
717
+ rows = $rows
718
+ rag_subrows = $ragSubRows
719
+ }
720
+
721
+ $comparison | ConvertTo-Json -Depth 10 | Set-Content -Path $outputJson -Encoding UTF8
722
+
723
+ $lines = @()
724
+ $lines += '# Comparativa Arquitecturas (Demo Session)'
725
+ $lines += ''
726
+ $lines += ('Generado: {0}' -f $comparison.generated_at)
727
+ $lines += ('Fuente tokens/coste fallback: {0} ({1})' -f $comparison.token_metrics_source_name, $comparison.token_metrics_source)
728
+ $lines += ('Fuente MCP simulado: {0} ({1})' -f $comparison.mcp_sim_source_name, $comparison.mcp_sim_source)
729
+ $lines += ''
730
+ $lines += '| Arquitectura | Repo | Pregunta | Flujo | Duracion (s) | Tokens total | Coste est. (USD) | Fuente tokens | MCP sim (tokens) | Calidad (1-5) | OK | Failed | Timeout | Session |'
731
+ $lines += '|---|---|---|---|---:|---:|---:|---|---:|---:|---:|---:|---:|---|'
732
+ foreach ($row in $rows) {
733
+ $qualityText = if ($null -ne $row.calidad_1_5) { [string]$row.calidad_1_5 } else { 'n/a' }
734
+ $tokensText = if ($null -ne $row.tokens_total) { [string]$row.tokens_total } else { 'n/a' }
735
+ $costText = if ($null -ne $row.cost_estimated_usd) { [string]$row.cost_estimated_usd } else { 'n/a' }
736
+ $tokenSourceText = if (-not [string]::IsNullOrWhiteSpace([string]$row.token_source)) { [string]$row.token_source } else { 'none' }
737
+ $mcpSimText = if ($null -ne $row.mcp_tokens_sim) { [string]$row.mcp_tokens_sim } else { 'n/a' }
738
+ $lines += ('| {0} | {1} | {2} | {3} | {4} | {5} | {6} | {7} | {8} | {9} | {10} | {11} | {12} | {13} |' -f $row.arquitectura, $row.repo, $row.pregunta, $row.flujo, $row.duration_sec, $tokensText, $costText, $tokenSourceText, $mcpSimText, $qualityText, $row.steps_ok, $row.steps_failed, $row.steps_timeout, $row.session)
739
+ }
740
+ $lines += ''
741
+ $lines += '## Subcomparativa RAG (Local vs Azure)'
742
+ $lines += ''
743
+ $lines += '| Bloque RAG | Pregunta | Flujo | Duracion (s) | Tokens total | Coste est. (USD) | Fuente tokens | MCP sim (tokens) | Estado | Exit |'
744
+ $lines += '|---|---|---|---:|---:|---:|---|---:|---|---:|'
745
+ foreach ($row in $ragSubRows) {
746
+ $tokensText = if ($null -ne $row.tokens_total) { [string]$row.tokens_total } else { 'n/a' }
747
+ $costText = if ($null -ne $row.cost_estimated_usd) { [string]$row.cost_estimated_usd } else { 'n/a' }
748
+ $tokenSourceText = if (-not [string]::IsNullOrWhiteSpace([string]$row.token_source)) { [string]$row.token_source } else { 'none' }
749
+ $mcpSimText = if ($null -ne $row.mcp_tokens_sim) { [string]$row.mcp_tokens_sim } else { 'n/a' }
750
+ $lines += ('| {0} | {1} | {2} | {3} | {4} | {5} | {6} | {7} | {8} | {9} |' -f $row.bloque, $row.pregunta, $row.flujo, $row.duration_sec, $tokensText, $costText, $tokenSourceText, $mcpSimText, $row.status, $row.exit_code)
751
+ }
752
+ $lines += ''
753
+ $lines += '## Lectura Ejecutiva'
754
+ $lines += ''
755
+ $lines += ('- Mejor tiempo: {0} ({1}s)' -f $comparison.best_architecture, $comparison.best_duration_sec)
756
+ $lines += ('- Peor tiempo: {0} ({1}s)' -f $comparison.worst_architecture, $comparison.worst_duration_sec)
757
+ $lines += ('- Delta entre mejor y peor: {0}s' -f $comparison.duration_delta_sec)
758
+ if ($null -ne $comparison.best_token_architecture) {
759
+ $lines += ('- Menor gasto tokens: {0} ({1})' -f $comparison.best_token_architecture, $comparison.best_token_total)
760
+ $lines += ('- Mayor gasto tokens: {0} ({1})' -f $comparison.worst_token_architecture, $comparison.worst_token_total)
761
+ $lines += ('- Delta tokens entre mejor y peor: {0}' -f $comparison.token_delta)
762
+ }
763
+ if ($null -ne $comparison.best_quality_architecture) {
764
+ $lines += ('- Mejor calidad: {0} ({1}/5)' -f $comparison.best_quality_architecture, $comparison.best_quality_score)
765
+ }
766
+ $lines += ''
767
+ $lines += '## Evidencias'
768
+ $lines += ''
769
+ foreach ($row in $rows) {
770
+ $lines += ('- {0}: {1}' -f $row.arquitectura, $row.summary_json)
771
+ if (-not [string]::IsNullOrWhiteSpace($row.nota_calidad)) {
772
+ $lines += (' Nota calidad: {0}' -f $row.nota_calidad)
773
+ }
774
+ }
775
+
776
+ Set-Content -Path $outputMd -Value $lines -Encoding UTF8
777
+
778
+ if ($ShowConsole) {
779
+ Write-Host ''
780
+ Write-Host '=== COMPARATIVA ARQUITECTURAS ===' -ForegroundColor Cyan
781
+ foreach ($row in $rows) {
782
+ $qualityText = if ($null -ne $row.calidad_1_5) { [string]$row.calidad_1_5 } else { 'n/a' }
783
+ $tokensText = if ($null -ne $row.tokens_total) { [string]$row.tokens_total } else { 'n/a' }
784
+ $costText = if ($null -ne $row.cost_estimated_usd) { [string]$row.cost_estimated_usd } else { 'n/a' }
785
+ $tokenSourceText = if (-not [string]::IsNullOrWhiteSpace([string]$row.token_source)) { [string]$row.token_source } else { 'none' }
786
+ $mcpSimText = if ($null -ne $row.mcp_tokens_sim) { [string]$row.mcp_tokens_sim } else { 'n/a' }
787
+ Write-Host ('- {0} [{1}]: {2}s | Tokens={3} | CosteUSD={4} | FuenteTokens={5} | MCPsim={6} | Calidad={7}/5 | OK={8} Failed={9} Timeout={10}' -f $row.arquitectura, $row.repo, $row.duration_sec, $tokensText, $costText, $tokenSourceText, $mcpSimText, $qualityText, $row.steps_ok, $row.steps_failed, $row.steps_timeout)
788
+ if (-not [string]::IsNullOrWhiteSpace([string]$row.pregunta)) {
789
+ Write-Host (' pregunta: {0}' -f $row.pregunta)
790
+ }
791
+ if (-not [string]::IsNullOrWhiteSpace([string]$row.flujo)) {
792
+ Write-Host (' flujo: {0}' -f $row.flujo)
793
+ }
794
+ }
795
+
796
+ if ($ragSubRows.Count -gt 0) {
797
+ Write-Host ''
798
+ Write-Host '--- Subcomparativa RAG (Local vs Azure) ---' -ForegroundColor Cyan
799
+ foreach ($row in $ragSubRows) {
800
+ $tokensText = if ($null -ne $row.tokens_total) { [string]$row.tokens_total } else { 'n/a' }
801
+ $costText = if ($null -ne $row.cost_estimated_usd) { [string]$row.cost_estimated_usd } else { 'n/a' }
802
+ $tokenSourceText = if (-not [string]::IsNullOrWhiteSpace([string]$row.token_source)) { [string]$row.token_source } else { 'none' }
803
+ $mcpSimText = if ($null -ne $row.mcp_tokens_sim) { [string]$row.mcp_tokens_sim } else { 'n/a' }
804
+ Write-Host ('- {0}: {1}s | tokens={2} | costeUSD={3} | fuenteTokens={4} | mcpSim={5} | status={6} exit={7}' -f $row.bloque, $row.duration_sec, $tokensText, $costText, $tokenSourceText, $mcpSimText, $row.status, $row.exit_code)
805
+ if (-not [string]::IsNullOrWhiteSpace([string]$row.pregunta)) {
806
+ Write-Host (' pregunta: {0}' -f $row.pregunta)
807
+ }
808
+ if (-not [string]::IsNullOrWhiteSpace([string]$row.flujo)) {
809
+ Write-Host (' flujo: {0}' -f $row.flujo)
810
+ }
811
+ }
812
+ }
813
+ Write-Host ('- Mejor: {0} ({1}s)' -f $comparison.best_architecture, $comparison.best_duration_sec) -ForegroundColor Green
814
+ Write-Host ('- Peor: {0} ({1}s)' -f $comparison.worst_architecture, $comparison.worst_duration_sec) -ForegroundColor Yellow
815
+ Write-Host ('- Delta: {0}s' -f $comparison.duration_delta_sec)
816
+ if ($null -ne $comparison.best_token_architecture) {
817
+ Write-Host ('- Menor tokens: {0} ({1})' -f $comparison.best_token_architecture, $comparison.best_token_total) -ForegroundColor Green
818
+ Write-Host ('- Mayor tokens: {0} ({1})' -f $comparison.worst_token_architecture, $comparison.worst_token_total) -ForegroundColor Yellow
819
+ Write-Host ('- Delta tokens: {0}' -f $comparison.token_delta)
820
+ }
821
+ if ($null -ne $comparison.best_quality_architecture) {
822
+ Write-Host ('- Mejor calidad: {0} ({1}/5)' -f $comparison.best_quality_architecture, $comparison.best_quality_score) -ForegroundColor Green
823
+ }
824
+ Write-Host ('MD: {0}' -f $outputMd)
825
+ Write-Host ('JSON: {0}' -f $outputJson)
826
+ }