mcp-efficiency-engine 0.1.0 → 0.1.1

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 (183) hide show
  1. package/.github/workflows/autodocs-sync.yml +2 -15
  2. package/.github/workflows/release-npm.yml +111 -0
  3. package/FINAL_USAGE_GUIDE.md +56 -0
  4. package/README.md +133 -0
  5. package/autodocs/README.md +6 -0
  6. package/observability/metrics.md +33 -0
  7. package/observability/scoring-rubric.md +20 -0
  8. package/orchestrator/wiki/graph_consolidator.py +60 -1
  9. package/orchestrator/wiki/incremental_engine.py +23 -1
  10. package/orchestrator/wiki/plugin_manager.py +87 -22
  11. package/package.json +8 -2
  12. package/requirements.txt +1 -0
  13. package/scripts/intake/resolve-routing.py +124 -87
  14. package/scripts/intake/validate-database-routing.py +13 -4
  15. package/scripts/intake/validate-rag-routing.py +4 -3
  16. package/scripts/learning/learning-loop-report.py +28 -10
  17. package/scripts/ops/llm-token-probe.py +103 -39
  18. package/scripts/ops/telemetry-benchmark.py +184 -0
  19. package/scripts/wiki/compiler_main.py +108 -76
  20. package/scripts/wiki/providers/repo_content_provider.py +51 -0
  21. package/scripts/wiki/validator.py +40 -15
  22. package/telemetry/__init__.py +4 -0
  23. package/telemetry/bootstrap.py +47 -0
  24. package/telemetry/collector/engine.py +261 -0
  25. package/telemetry/config.json +20 -0
  26. package/telemetry/config.py +131 -0
  27. package/telemetry/context/propagation.py +85 -0
  28. package/telemetry/events/catalog.py +24 -0
  29. package/telemetry/events/factory.py +42 -0
  30. package/telemetry/exporters/base.py +16 -0
  31. package/telemetry/exporters/console/exporter.py +30 -0
  32. package/telemetry/exporters/json/exporter.py +34 -0
  33. package/telemetry/exporters/langsmith/exporter.py +415 -0
  34. package/telemetry/metrics/aggregator.py +60 -0
  35. package/telemetry/scoring/efficiency.py +68 -0
  36. package/telemetry/tracing/span.py +43 -0
  37. package/observability/evals/chat-token-usage-report.json +0 -64
  38. package/observability/evals/chat-token-usage-report.md +0 -33
  39. package/observability/evals/iteration-value-report.json +0 -76
  40. package/observability/evals/iteration-value-report.md +0 -39
  41. package/observability/evals/learning-loop-report.json +0 -268
  42. package/observability/evals/learning-loop-report.md +0 -37
  43. package/observability/evals/repo-intake-eval-cases.md +0 -23
  44. package/observability/evals/routing-eval-cases.json +0 -68
  45. package/observability/evals/routing-eval-cases.md +0 -25
  46. package/observability/evals/routing-eval-report.json +0 -72
  47. package/observability/logs/copilot-usage-ingest-report.json +0 -13
  48. package/observability/logs/iteration-metrics.jsonl +0 -75
  49. package/observability/logs/learning-feedback.jsonl +0 -152
  50. package/observability/logs/routing-decisions.jsonl +0 -333
  51. package/observability/logs/session/agent-pipeline-preflight-20260701-004146.log +0 -8
  52. package/observability/logs/session/agent-pipeline-preflight-20260701-005554.log +0 -8
  53. package/observability/logs/session/agent-pipeline-preflight-20260701-010351.log +0 -8
  54. package/observability/logs/session/agent-pipeline-preflight-20260704-145829.log +0 -8
  55. package/observability/logs/session/agent-pipeline-preflight-20260704-150021.log +0 -8
  56. package/observability/logs/session/agent-pipeline-preflight-20260704-154328.log +0 -8
  57. package/observability/logs/session/bye-20260629-221513.json +0 -39
  58. package/observability/logs/session/bye-20260629-221545.json +0 -59
  59. package/observability/logs/session/bye-20260629-222007.json +0 -52
  60. package/observability/logs/session/bye-20260629-222133.json +0 -59
  61. package/observability/logs/session/bye-20260629-222412.json +0 -45
  62. package/observability/logs/session/bye-20260629-223224.json +0 -52
  63. package/observability/logs/session/bye-20260629-224050.json +0 -59
  64. package/observability/logs/session/bye-20260630-105732.json +0 -24
  65. package/observability/logs/session/bye-20260630-211536.json +0 -87
  66. package/observability/logs/session/bye-20260630-223423.json +0 -87
  67. package/observability/logs/session/bye-20260630-232534.json +0 -87
  68. package/observability/logs/session/bye-20260701-003638.json +0 -126
  69. package/observability/logs/session/bye-20260701-003849.json +0 -126
  70. package/observability/logs/session/bye-20260701-004315.json +0 -138
  71. package/observability/logs/session/bye-20260701-004559.json +0 -76
  72. package/observability/logs/session/bye-20260701-005913.json +0 -138
  73. package/observability/logs/session/bye-20260701-010753.json +0 -138
  74. package/observability/logs/session/bye-20260703-194106.json +0 -24
  75. package/observability/logs/session/bye-20260703-233443.json +0 -76
  76. package/observability/logs/session/bye-20260703-233653.json +0 -76
  77. package/observability/logs/session/bye-20260704-150317.json +0 -152
  78. package/observability/logs/session/bye-20260704-150929.json +0 -75
  79. package/observability/logs/session/bye-20260704-151050.json +0 -75
  80. package/observability/logs/session/bye-20260705-115458.json +0 -165
  81. package/observability/logs/session/codegraph-status-20260701-004228.log +0 -39
  82. package/observability/logs/session/codegraph-status-20260701-004310.log +0 -39
  83. package/observability/logs/session/codegraph-status-20260701-005637.log +0 -39
  84. package/observability/logs/session/codegraph-status-20260701-005908.log +0 -39
  85. package/observability/logs/session/codegraph-status-20260701-010444.log +0 -39
  86. package/observability/logs/session/codegraph-status-20260701-010747.log +0 -39
  87. package/observability/logs/session/codegraph-status-20260704-150137.log +0 -26
  88. package/observability/logs/session/codegraph-status-20260704-150313.log +0 -28
  89. package/observability/logs/session/codegraph-status-20260704-154445.log +0 -26
  90. package/observability/logs/session/codegraph-status-20260705-115454.log +0 -27
  91. package/observability/logs/session/codegraph-sync-20260701-004211.log +0 -88
  92. package/observability/logs/session/codegraph-sync-20260701-004241.log +0 -82
  93. package/observability/logs/session/codegraph-sync-20260701-005620.log +0 -89
  94. package/observability/logs/session/codegraph-sync-20260701-005840.log +0 -88
  95. package/observability/logs/session/codegraph-sync-20260701-010419.log +0 -93
  96. package/observability/logs/session/codegraph-sync-20260701-010609.log +0 -90
  97. package/observability/logs/session/codegraph-sync-20260704-145856.log +0 -70
  98. package/observability/logs/session/codegraph-sync-20260704-150047.log +0 -53
  99. package/observability/logs/session/codegraph-sync-20260704-150204.log +0 -44
  100. package/observability/logs/session/codegraph-sync-20260704-154353.log +0 -26
  101. package/observability/logs/session/codegraph-sync-20260705-115337.log +0 -32
  102. package/observability/logs/session/hi-20260629-221459.json +0 -38
  103. package/observability/logs/session/hi-20260629-221945.json +0 -59
  104. package/observability/logs/session/hi-20260629-222108.json +0 -66
  105. package/observability/logs/session/hi-20260629-222352.json +0 -45
  106. package/observability/logs/session/hi-20260629-225719.json +0 -59
  107. package/observability/logs/session/hi-20260629-233722.json +0 -52
  108. package/observability/logs/session/hi-20260629-233913.json +0 -198
  109. package/observability/logs/session/hi-20260630-110156.json +0 -177
  110. package/observability/logs/session/hi-20260630-191243.json +0 -184
  111. package/observability/logs/session/hi-20260630-230050.json +0 -234
  112. package/observability/logs/session/hi-20260630-230523.json +0 -227
  113. package/observability/logs/session/hi-20260630-230855.json +0 -227
  114. package/observability/logs/session/hi-20260630-231638.json +0 -227
  115. package/observability/logs/session/hi-20260630-231756.json +0 -219
  116. package/observability/logs/session/hi-20260701-002842.json +0 -234
  117. package/observability/logs/session/hi-20260701-003458.json +0 -282
  118. package/observability/logs/session/hi-20260701-004233.json +0 -290
  119. package/observability/logs/session/hi-20260701-004554.json +0 -236
  120. package/observability/logs/session/hi-20260701-005641.json +0 -290
  121. package/observability/logs/session/hi-20260701-010450.json +0 -290
  122. package/observability/logs/session/hi-20260703-233854.json +0 -312
  123. package/observability/logs/session/hi-20260703-234448.json +0 -318
  124. package/observability/logs/session/hi-20260704-145907.json +0 -353
  125. package/observability/logs/session/hi-20260704-150141.json +0 -392
  126. package/observability/logs/session/hi-20260704-154448.json +0 -392
  127. package/observability/logs/session/iteration-value-refresh-20260701-004309.log +0 -3
  128. package/observability/logs/session/iteration-value-refresh-20260701-005907.log +0 -3
  129. package/observability/logs/session/iteration-value-refresh-20260701-010747.log +0 -3
  130. package/observability/logs/session/iteration-value-refresh-20260704-150312.log +0 -3
  131. package/observability/logs/session/iteration-value-refresh-20260705-115453.log +0 -3
  132. package/observability/logs/session/learning-loop-refresh-20260701-004309.log +0 -3
  133. package/observability/logs/session/learning-loop-refresh-20260701-005906.log +0 -3
  134. package/observability/logs/session/learning-loop-refresh-20260701-010745.log +0 -3
  135. package/observability/logs/session/learning-loop-refresh-20260704-150309.log +0 -3
  136. package/observability/logs/session/learning-loop-refresh-20260705-115450.log +0 -3
  137. package/observability/logs/session/project-notes-refresh-20260701-004227.log +0 -1
  138. package/observability/logs/session/project-notes-refresh-20260701-004308.log +0 -1
  139. package/observability/logs/session/project-notes-refresh-20260701-005636.log +0 -1
  140. package/observability/logs/session/project-notes-refresh-20260701-005906.log +0 -1
  141. package/observability/logs/session/project-notes-refresh-20260701-010443.log +0 -1
  142. package/observability/logs/session/project-notes-refresh-20260701-010744.log +0 -1
  143. package/observability/logs/session/project-notes-refresh-20260704-150133.log +0 -1
  144. package/observability/logs/session/project-notes-refresh-20260704-150309.log +0 -1
  145. package/observability/logs/session/project-notes-refresh-20260704-154442.log +0 -1
  146. package/observability/logs/session/project-notes-refresh-20260705-115449.log +0 -1
  147. package/observability/logs/session/repo-intake-20260701-004218.log +0 -6
  148. package/observability/logs/session/repo-intake-20260701-005626.log +0 -6
  149. package/observability/logs/session/repo-intake-20260701-010433.log +0 -6
  150. package/observability/logs/session/repo-intake-20260704-150053.log +0 -6
  151. package/observability/logs/session/repo-intake-20260704-154404.log +0 -6
  152. package/observability/logs/session/repo-intake-refresh-20260701-004247.log +0 -6
  153. package/observability/logs/session/repo-intake-refresh-20260701-005847.log +0 -6
  154. package/observability/logs/session/repo-intake-refresh-20260701-010615.log +0 -6
  155. package/observability/logs/session/repo-intake-refresh-20260704-150209.log +0 -6
  156. package/observability/logs/session/repo-intake-refresh-20260705-115342.log +0 -6
  157. package/observability/logs/session/repo-registry-validation-20260701-004234.log +0 -2
  158. package/observability/logs/session/repo-registry-validation-20260701-004556.log +0 -2
  159. package/observability/logs/session/repo-registry-validation-20260701-005833.log +0 -2
  160. package/observability/logs/session/repo-registry-validation-20260701-010601.log +0 -2
  161. package/observability/logs/session/repo-registry-validation-20260704-150155.log +0 -2
  162. package/observability/logs/session/repo-registry-validation-20260705-115323.log +0 -2
  163. package/observability/logs/session/repomix-refresh-20260701-003823.log +0 -4236
  164. package/observability/logs/session/repomix-refresh-20260701-004251.log +0 -4275
  165. package/observability/logs/session/repomix-refresh-20260701-005850.log +0 -4248
  166. package/observability/logs/session/repomix-refresh-20260701-010619.log +0 -6531
  167. package/observability/logs/session/repomix-refresh-20260704-150239.log +0 -652
  168. package/observability/logs/session/repomix-refresh-20260705-115419.log +0 -178
  169. package/observability/logs/session/routing-evals-20260701-004221.log +0 -2
  170. package/observability/logs/session/routing-evals-20260701-004235.log +0 -2
  171. package/observability/logs/session/routing-evals-20260701-005629.log +0 -2
  172. package/observability/logs/session/routing-evals-20260701-005834.log +0 -2
  173. package/observability/logs/session/routing-evals-20260701-010437.log +0 -2
  174. package/observability/logs/session/routing-evals-20260701-010603.log +0 -2
  175. package/observability/logs/session/routing-evals-20260704-150125.log +0 -2
  176. package/observability/logs/session/routing-evals-20260704-150157.log +0 -2
  177. package/observability/logs/session/routing-evals-20260704-154434.log +0 -2
  178. package/observability/logs/session/routing-evals-20260705-115327.log +0 -2
  179. package/observability/logs/session/sibling-discovery-refresh-20260701-004250.log +0 -3
  180. package/observability/logs/session/sibling-discovery-refresh-20260701-005850.log +0 -3
  181. package/observability/logs/session/sibling-discovery-refresh-20260701-010618.log +0 -3
  182. package/observability/logs/session/sibling-discovery-refresh-20260704-150238.log +0 -3
  183. package/observability/logs/session/sibling-discovery-refresh-20260705-115418.log +0 -3
@@ -3,22 +3,8 @@ name: AutoDocs Sync
3
3
  on:
4
4
  push:
5
5
  branches: [ main, develop ]
6
- paths:
7
- - 'repo-intake/generated/**'
8
- - 'autodocs/**'
9
- - 'scripts/wiki/**'
10
- - 'orchestrator/wiki/**'
11
- - '.github/skills/wiki-tools.json'
12
- - '.github/agents/wiki-agent.agent.md'
13
6
  pull_request:
14
7
  branches: [ main, develop ]
15
- paths:
16
- - 'repo-intake/generated/**'
17
- - 'autodocs/**'
18
- - 'scripts/wiki/**'
19
- - 'orchestrator/wiki/**'
20
- - '.github/skills/wiki-tools.json'
21
- - '.github/agents/wiki-agent.agent.md'
22
8
  workflow_dispatch:
23
9
 
24
10
  permissions:
@@ -68,7 +54,7 @@ jobs:
68
54
  echo "- Required artifacts: autodocs/generated + autodocs/site" >> $env:GITHUB_STEP_SUMMARY
69
55
 
70
56
  autodocs-sync:
71
- if: github.event_name != 'pull_request' && github.actor != 'github-actions[bot]'
57
+ if: github.actor != 'github-actions[bot]'
72
58
  permissions:
73
59
  contents: write
74
60
  runs-on: windows-latest
@@ -89,6 +75,7 @@ jobs:
89
75
  shell: pwsh
90
76
 
91
77
  - name: Commit projected docs and unified graph
78
+ if: github.event_name != 'pull_request'
92
79
  shell: pwsh
93
80
  run: |
94
81
  git config user.name "github-actions[bot]"
@@ -0,0 +1,111 @@
1
+ name: Release & Publish NPM
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ workflow_dispatch:
7
+ inputs:
8
+ npm_version:
9
+ description: "Version especifica a publicar (ej. 0.2.0). Si se omite, se autoajusta."
10
+ required: false
11
+ type: string
12
+
13
+ permissions:
14
+ contents: write
15
+
16
+ jobs:
17
+ release-and-publish:
18
+ runs-on: ubuntu-latest
19
+
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v5
23
+ with:
24
+ fetch-depth: 0
25
+
26
+ - name: Setup Node.js
27
+ uses: actions/setup-node@v4
28
+ with:
29
+ node-version: 20
30
+ registry-url: https://registry.npmjs.org
31
+
32
+ - name: Resolve publish version
33
+ id: version
34
+ run: |
35
+ PACKAGE_NAME=$(node -p "require('./package.json').name")
36
+ BASE_VERSION=$(node -p "require('./package.json').version")
37
+ REQUESTED_VERSION="${{ github.event.inputs.npm_version || '' }}"
38
+
39
+ version_exists() {
40
+ npm view "$PACKAGE_NAME@$1" version >/dev/null 2>&1
41
+ }
42
+
43
+ if [ -n "$REQUESTED_VERSION" ]; then
44
+ TARGET_VERSION="$REQUESTED_VERSION"
45
+ MODE="explicit"
46
+ else
47
+ TARGET_VERSION="$BASE_VERSION"
48
+ MODE="auto"
49
+ fi
50
+
51
+ if [ "$MODE" = "explicit" ]; then
52
+ if version_exists "$TARGET_VERSION"; then
53
+ echo "Requested version $TARGET_VERSION is already published in npm."
54
+ exit 1
55
+ fi
56
+ else
57
+ CANDIDATE="$TARGET_VERSION"
58
+ while version_exists "$CANDIDATE"; do
59
+ CANDIDATE=$(node -e "const parts = process.argv[1].split('.').map(Number); if (parts.length !== 3 || parts.some(Number.isNaN)) { process.exit(2); } parts[2] += 1; process.stdout.write(parts.join('.'));" "$CANDIDATE") || {
60
+ echo "Cannot auto-bump non x.y.z version: $CANDIDATE"
61
+ exit 1
62
+ }
63
+ done
64
+ TARGET_VERSION="$CANDIDATE"
65
+ fi
66
+
67
+ CHANGED=false
68
+ if [ "$TARGET_VERSION" != "$BASE_VERSION" ]; then
69
+ npm version "$TARGET_VERSION" --no-git-tag-version
70
+ CHANGED=true
71
+ fi
72
+
73
+ echo "version=$TARGET_VERSION" >> "$GITHUB_OUTPUT"
74
+ echo "tag=v$TARGET_VERSION" >> "$GITHUB_OUTPUT"
75
+ echo "changed=$CHANGED" >> "$GITHUB_OUTPUT"
76
+ echo "mode=$MODE" >> "$GITHUB_OUTPUT"
77
+
78
+ - name: Ensure NPM token is configured
79
+ run: |
80
+ if [ -z "${NODE_AUTH_TOKEN}" ]; then
81
+ echo "Missing NODE_AUTH_TOKEN/NPM_TOKEN secret. Configure repository secret NPM_TOKEN."
82
+ exit 1
83
+ fi
84
+ env:
85
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
86
+
87
+ - name: Remove Python cache artifacts from workspace
88
+ run: |
89
+ find . -type d -name "__pycache__" -prune -exec rm -rf {} +
90
+ find . -type f -name "*.pyc" -delete
91
+
92
+ - name: Publish to npm
93
+ run: npm publish --access public
94
+ env:
95
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
96
+
97
+ - name: Sync package.json version to repository
98
+ if: steps.version.outputs.changed == 'true'
99
+ run: |
100
+ git config user.name "github-actions[bot]"
101
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
102
+ git add package.json
103
+ git commit -m "chore(release): sync npm version to ${{ steps.version.outputs.tag }} [skip ci]"
104
+ git push
105
+
106
+ - name: Create GitHub release
107
+ uses: softprops/action-gh-release@v2
108
+ with:
109
+ tag_name: ${{ steps.version.outputs.tag }}
110
+ name: ${{ steps.version.outputs.tag }}
111
+ generate_release_notes: true
@@ -85,6 +85,62 @@ Esto significa:
85
85
  - las fuentes se conservan cuando sean obligatorias,
86
86
  - el sistema solo aumenta detalle si el usuario o el caso lo requiere.
87
87
 
88
+ ## 7. Telemetry Engine
89
+
90
+ El sistema incluye un engine de telemetría desacoplado con collector único.
91
+
92
+ Flujo:
93
+
94
+ ```txt
95
+ Componente -> TelemetryCollector -> Pipeline -> Exporters
96
+ ```
97
+
98
+ Exporters soportados:
99
+
100
+ - `console` (siempre disponible)
101
+ - `json` (persistencia local en `.telemetry/`)
102
+ - `langsmith` (opcional, solo con configuración válida)
103
+
104
+ Si un exporter falla:
105
+
106
+ - se registra warning,
107
+ - los demás exporters continúan,
108
+ - la ejecución principal no se detiene.
109
+
110
+ ### Configuración rápida
111
+
112
+ Archivo `telemetry/config.json`:
113
+
114
+ ```json
115
+ {
116
+ "telemetry": {
117
+ "enabled": true,
118
+ "batch_size": 25,
119
+ "telemetry_dir": ".telemetry",
120
+ "exporters": ["console", "json", "langsmith"]
121
+ },
122
+ "langsmith": {
123
+ "enabled": false,
124
+ "api_key": "",
125
+ "project": "",
126
+ "endpoint": ""
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### Cómo activar LangSmith
132
+
133
+ 1. Configurar `LANGSMITH_ENABLED=true`.
134
+ 2. Definir `LANGSMITH_API_KEY` y `LANGSMITH_PROJECT`.
135
+ 3. Mantener `langsmith` en `telemetry.exporters`.
136
+
137
+ Si falta configuración, se omite automáticamente.
138
+
139
+ ### Cómo deshabilitar exporters
140
+
141
+ - Desactivar todo: `TELEMETRY_ENABLED=false`
142
+ - Solo algunos: `TELEMETRY_EXPORTERS=console,json`
143
+
88
144
  ## Diagrama Visual De Uso Diario
89
145
 
90
146
  ```mermaid
package/README.md CHANGED
@@ -245,6 +245,139 @@ Artefactos canónicos:
245
245
 
246
246
  ## Observabilidad
247
247
 
248
+ ### Telemetry Engine (desacoplado y extensible)
249
+
250
+ La observabilidad ahora se soporta mediante un engine propio en `telemetry/`.
251
+
252
+ Principios:
253
+
254
+ - Telemetría siempre activa a nivel de modelo de datos.
255
+ - Exporters opcionales (`console`, `json`, `langsmith`).
256
+ - Ningún flujo de negocio depende de LangSmith.
257
+ - Si un exporter falla, la ejecución principal continua.
258
+
259
+ Arquitectura:
260
+
261
+ ```mermaid
262
+ flowchart TD
263
+ T[Tool/Flow] --> C[TelemetryCollector]
264
+ C --> P[Telemetry Pipeline]
265
+ P --> EX1[Console Exporter]
266
+ P --> EX2[JSON Exporter]
267
+ P --> EX3[LangSmith Exporter]
268
+ P --> EXN[Future Exporters]
269
+ ```
270
+
271
+ Trazas jerárquicas:
272
+
273
+ - Cada ejecución genera `execution_id`, `trace_id`, `span_id`, `parent_span_id`.
274
+ - Se propaga contexto con `contextvars` (sin variables globales).
275
+ - Spans soportan `events`, `status`, `duration_ms` y error asociado.
276
+
277
+ Configuración base (`telemetry/config.json`):
278
+
279
+ ```json
280
+ {
281
+ "telemetry": {
282
+ "enabled": true,
283
+ "batch_size": 100,
284
+ "telemetry_dir": ".telemetry",
285
+ "exporters": ["console", "json"]
286
+ },
287
+ "langsmith": {
288
+ "enabled": false,
289
+ "api_key": "",
290
+ "project": "",
291
+ "endpoint": "",
292
+ "high_signal_only": true,
293
+ "min_span_duration_ms": 100,
294
+ "emit_execution_summary": true
295
+ }
296
+ }
297
+ ```
298
+
299
+ Conexión segura a LangSmith (sin subir token al repo/npm):
300
+
301
+ 1. No guardes el token en `telemetry/config.json`.
302
+ 2. Define variables de entorno locales (usuario o sesión).
303
+ 3. Activa exporter por entorno con `TELEMETRY_EXPORTERS=console,json,langsmith`.
304
+ 4. Verifica que `.env` y variantes están ignorados por Git y npm.
305
+
306
+ Ejemplo (PowerShell, solo sesión actual):
307
+
308
+ ```powershell
309
+ $env:LANGSMITH_ENABLED='true'
310
+ $env:LANGSMITH_API_KEY='tu_token'
311
+ $env:LANGSMITH_PROJECT='mcpee-local'
312
+ $env:LANGSMITH_ENDPOINT='https://api.smith.langchain.com'
313
+ $env:LANGSMITH_HIGH_SIGNAL_ONLY='true'
314
+ $env:LANGSMITH_MIN_SPAN_DURATION_MS='100'
315
+ $env:LANGSMITH_EMIT_EXECUTION_SUMMARY='true'
316
+ $env:TELEMETRY_EXPORTERS='console,json,langsmith'
317
+ ```
318
+
319
+ Persistente para tu usuario Windows:
320
+
321
+ ```powershell
322
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_ENABLED','true','User')
323
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_API_KEY','tu_token','User')
324
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_PROJECT','mcpee-local','User')
325
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_ENDPOINT','https://api.smith.langchain.com','User')
326
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_HIGH_SIGNAL_ONLY','true','User')
327
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_MIN_SPAN_DURATION_MS','100','User')
328
+ [System.Environment]::SetEnvironmentVariable('LANGSMITH_EMIT_EXECUTION_SUMMARY','true','User')
329
+ [System.Environment]::SetEnvironmentVariable('TELEMETRY_EXPORTERS','console,json,langsmith','User')
330
+
331
+ Modo high-signal recomendado en LangSmith:
332
+
333
+ - `LANGSMITH_HIGH_SIGNAL_ONLY=true` (default): prioriza trazas útiles y reduce ruido.
334
+ - `LANGSMITH_MIN_SPAN_DURATION_MS=100` (default): solo mantiene spans rápidos cuando fallan; los de éxito deben superar el umbral.
335
+ - `LANGSMITH_EMIT_EXECUTION_SUMMARY=true` (default): añade un resumen consolidado por ejecución (duración, estado, warnings/errors, tokens/coste).
336
+ - Mantiene eventos clave (`ExecutionStarted`, `ExecutionFinished`, `RoutingResolved`, warnings/errores) y resumen `UsageSummary` con modelo/tokens/coste.
337
+ - Omite eventos de bajo valor para la UI de LangSmith, pero conserva debug detallado en exporters locales (`console`, `json`).
338
+ ```
339
+
340
+ Para volver al modo local sin LangSmith:
341
+
342
+ ```powershell
343
+ $env:LANGSMITH_ENABLED='false'
344
+ $env:TELEMETRY_EXPORTERS='console,json'
345
+ ```
346
+
347
+ Variables de entorno soportadas:
348
+
349
+ - `TELEMETRY_ENABLED`
350
+ - `TELEMETRY_EXPORTERS`
351
+ - `TELEMETRY_BATCH_SIZE`
352
+ - `TELEMETRY_DIR`
353
+ - `LANGSMITH_ENABLED`
354
+ - `LANGSMITH_API_KEY`
355
+ - `LANGSMITH_PROJECT`
356
+ - `LANGSMITH_ENDPOINT`
357
+ - `LANGSMITH_WORKSPACE_ID` (opcional, recomendado para cuentas con multiples workspaces)
358
+
359
+ Nota: el engine carga automáticamente `.env` en la raíz del repo. Si también existe variable en el entorno del sistema/proceso, esa tiene prioridad.
360
+
361
+ Dependencia runtime: `langsmith` está incluida en `requirements.txt` para que `scripts/setup/setup-prerequisites.ps1` la instale automáticamente cuando prepares el entorno Python.
362
+
363
+ Cómo crear un exporter nuevo:
364
+
365
+ 1. Implementar contrato `export/flush/shutdown` en `telemetry/exporters/<nuevo>/exporter.py`.
366
+ 2. Registrar el exporter en `telemetry/bootstrap.py`.
367
+ 3. Añadirlo en `telemetry/config.json` o `TELEMETRY_EXPORTERS`.
368
+
369
+ Si LangSmith no está configurado correctamente, el exporter se omite y el engine sigue funcionando con `console/json`.
370
+
371
+ Benchmark de overhead on/off:
372
+
373
+ ```powershell
374
+ py -3 .\scripts\ops\telemetry-benchmark.py --iterations 10
375
+ ```
376
+
377
+ Salida:
378
+
379
+ - `observability/evals/telemetry-overhead-benchmark.json`
380
+
248
381
  Registros principales:
249
382
 
250
383
  - `observability/logs/routing-decisions.jsonl`
@@ -14,6 +14,12 @@ AutoDocs es la wiki interna nativa de `mcp-efficiency-engine`.
14
14
  py -3 -m scripts.wiki.wiki_compiler
15
15
  ```
16
16
 
17
+ ## Sincronizacion automatica
18
+
19
+ - En CI, el workflow `autodocs-sync` valida en PR y sincroniza en `main`/`develop`.
20
+ - La ejecucion ya no depende de filtros de path: cualquier cambio potencialmente relevante recompila AutoDocs.
21
+ - Si hay drift, CI exige regenerar y commitear `autodocs/generated` y `autodocs/site`.
22
+
17
23
  ## Artefactos clave
18
24
 
19
25
  - `autodocs/generated/unified-graph.json`
@@ -28,6 +28,39 @@ Métricas: routing accuracy, tool usage, tool misuse, tool switching, grounding
28
28
  - token_efficiency: tendencia estable o mejorando
29
29
  - caveman_effectiveness: `>= 85%`
30
30
 
31
+ ## Telemetry Engine native metrics
32
+
33
+ El engine expone métricas propias y no depende de proveedores externos:
34
+
35
+ - execution_time_ms
36
+ - tool_duration_ms
37
+ - average_duration_ms
38
+ - parallel_tasks
39
+ - sequential_tasks
40
+ - retry_count
41
+ - error_count
42
+ - warning_count
43
+ - llm_calls
44
+ - provider_calls
45
+ - mcp_calls
46
+ - tool_invocations
47
+ - tokens_input
48
+ - tokens_output
49
+ - total_tokens
50
+ - estimated_cost
51
+ - cache_hits
52
+ - cache_misses
53
+ - compression_ratio
54
+ - parallel_efficiency
55
+ - prompt_reduction
56
+ - context_reduction
57
+ - efficiency_score (0-100)
58
+
59
+ Los cálculos viven en:
60
+
61
+ - `telemetry/metrics/aggregator.py`
62
+ - `telemetry/scoring/efficiency.py`
63
+
31
64
  ## Semaforo
32
65
 
33
66
  - `OK`: todos los umbrales en rango.
@@ -1,5 +1,7 @@
1
1
  # Scoring Rubric
2
2
 
3
+ > El score de eficiencia es nativo del Telemetry Engine y no depende de LangSmith.
4
+
3
5
  ## Componentes y pesos
4
6
 
5
7
  - Routing score: 40%
@@ -36,3 +38,21 @@
36
38
  - `80-89`: Aceptable
37
39
  - `70-79`: Mejorable
38
40
  - `< 70`: No apto
41
+
42
+ ## Efficiency Score (Telemetry Engine)
43
+
44
+ Salida: `0..100`.
45
+
46
+ Factores por defecto:
47
+
48
+ - time
49
+ - cost
50
+ - tokens
51
+ - cache
52
+ - parallelism
53
+ - reuse
54
+ - calls
55
+ - compression
56
+
57
+ Implementación base en `telemetry/scoring/efficiency.py`.
58
+ Los pesos son configurables y el algoritmo se puede ajustar sin tocar exporters.
@@ -11,12 +11,21 @@ SECTIONS = section_catalog()
11
11
 
12
12
 
13
13
  class GraphConsolidator:
14
- def __init__(self, output_graph_path: Path, markdown_output_dir: Path) -> None:
14
+ def __init__(self, output_graph_path: Path, markdown_output_dir: Path, telemetry_collector: Any | None = None) -> None:
15
15
  self.output_graph_path = output_graph_path
16
16
  self.markdown_output_dir = markdown_output_dir
17
17
  self.generated_output_dir = output_graph_path.parent
18
+ self._telemetry = telemetry_collector
18
19
 
19
20
  def consolidate(self, provider_contracts: List[Dict[str, Any]]) -> Dict[str, Any]:
21
+ if self._telemetry is not None:
22
+ self._telemetry.record_event(
23
+ "KnowledgeGenerated",
24
+ {
25
+ "operation": "graph_consolidate_start",
26
+ "provider_contracts": len(provider_contracts),
27
+ },
28
+ )
20
29
  raw_nodes: Dict[str, Dict[str, Any]] = {}
21
30
  wiki_nodes: Dict[str, Dict[str, Any]] = {}
22
31
  for contract in provider_contracts:
@@ -54,6 +63,17 @@ class GraphConsolidator:
54
63
  relations_index = self._build_relations_index(wiki_nodes)
55
64
  section_manifest = self._build_section_manifest(wiki_nodes)
56
65
 
66
+ if self._telemetry is not None:
67
+ self._telemetry.record_metric("tool_invocations", float(len(provider_contracts)), unit="count")
68
+ self._telemetry.record_metric("cache_misses", 0.0, unit="count")
69
+ self._telemetry.record_event(
70
+ "KnowledgeGenerated",
71
+ {
72
+ "operation": "graph_consolidate_finish",
73
+ "nodes": len(wiki_nodes),
74
+ },
75
+ )
76
+
57
77
  return {
58
78
  "last_updated": self._deterministic_marker(wiki_nodes),
59
79
  "nodes": wiki_nodes,
@@ -71,11 +91,23 @@ class GraphConsolidator:
71
91
  return f"sha256:{digest}"
72
92
 
73
93
  def persist_graph(self, unified_graph: Dict[str, Any]) -> None:
94
+ if self._telemetry is not None:
95
+ self._telemetry.record_event("ToolStarted", {"tool": "persist_graph"})
74
96
  self.output_graph_path.parent.mkdir(parents=True, exist_ok=True)
75
97
  with self.output_graph_path.open("w", encoding="utf-8") as handle:
76
98
  json.dump(unified_graph, handle, indent=2, ensure_ascii=True)
99
+ if self._telemetry is not None:
100
+ self._telemetry.record_event(
101
+ "ToolFinished",
102
+ {
103
+ "tool": "persist_graph",
104
+ "path": str(self.output_graph_path),
105
+ },
106
+ )
77
107
 
78
108
  def persist_manifests(self, unified_graph: Dict[str, Any]) -> Dict[str, int]:
109
+ if self._telemetry is not None:
110
+ self._telemetry.record_event("ToolStarted", {"tool": "persist_manifests"})
79
111
  self.generated_output_dir.mkdir(parents=True, exist_ok=True)
80
112
  artifacts = {
81
113
  "search-index.json": unified_graph.get("search_index", []),
@@ -87,6 +119,14 @@ class GraphConsolidator:
87
119
  output_path = self.generated_output_dir / file_name
88
120
  with output_path.open("w", encoding="utf-8") as handle:
89
121
  json.dump(payload, handle, indent=2, ensure_ascii=True)
122
+ if self._telemetry is not None:
123
+ self._telemetry.record_event(
124
+ "ToolFinished",
125
+ {
126
+ "tool": "persist_manifests",
127
+ "manifests": len(artifacts),
128
+ },
129
+ )
90
130
  return {"manifests": len(artifacts)}
91
131
 
92
132
  def project_dirty_nodes(
@@ -96,6 +136,15 @@ class GraphConsolidator:
96
136
  all_nodes: Dict[str, Dict[str, Any]],
97
137
  cached_nodes: Dict[str, Dict[str, Any]],
98
138
  ) -> Dict[str, int]:
139
+ if self._telemetry is not None:
140
+ self._telemetry.record_event(
141
+ "ToolStarted",
142
+ {
143
+ "tool": "project_dirty_nodes",
144
+ "dirty_nodes": len(dirty_nodes),
145
+ "deleted_nodes": len(deleted_nodes),
146
+ },
147
+ )
99
148
  self.markdown_output_dir.mkdir(parents=True, exist_ok=True)
100
149
 
101
150
  rendered = 0
@@ -124,6 +173,16 @@ class GraphConsolidator:
124
173
  deleted += 1
125
174
 
126
175
  indexes = self._render_index_pages(all_nodes)
176
+ if self._telemetry is not None:
177
+ self._telemetry.record_event(
178
+ "ToolFinished",
179
+ {
180
+ "tool": "project_dirty_nodes",
181
+ "rendered": rendered,
182
+ "deleted": deleted,
183
+ "indexes": indexes,
184
+ },
185
+ )
127
186
  return {
128
187
  "rendered": rendered,
129
188
  "deleted": deleted,
@@ -4,8 +4,9 @@ from typing import Any, Dict
4
4
 
5
5
 
6
6
  class IncrementalEngine:
7
- def __init__(self, cache_path: Path) -> None:
7
+ def __init__(self, cache_path: Path, telemetry_collector: Any | None = None) -> None:
8
8
  self.cache_path = cache_path
9
+ self._telemetry = telemetry_collector
9
10
 
10
11
  def _extract_nodes(self, loaded: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
11
12
  preferred = loaded.get("wiki_nodes")
@@ -37,6 +38,14 @@ class IncrementalEngine:
37
38
  return {"last_updated": "", "nodes": {}}
38
39
 
39
40
  def diff(self, incoming_nodes: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
41
+ if self._telemetry is not None:
42
+ self._telemetry.record_event(
43
+ "ToolStarted",
44
+ {
45
+ "tool": "incremental_diff",
46
+ "incoming_nodes": len(incoming_nodes),
47
+ },
48
+ )
40
49
  cached = self._load_cached_graph()
41
50
  cached_nodes = cached.get("nodes", {})
42
51
 
@@ -50,6 +59,19 @@ class IncrementalEngine:
50
59
  dirty_nodes[node_key] = incoming
51
60
 
52
61
  deleted_nodes = [key for key in cached_nodes.keys() if key not in incoming_nodes]
62
+ if self._telemetry is not None:
63
+ cache_hits = max(0, len(incoming_nodes) - len(dirty_nodes))
64
+ cache_misses = len(dirty_nodes)
65
+ self._telemetry.record_event(
66
+ "ToolFinished",
67
+ {
68
+ "tool": "incremental_diff",
69
+ "dirty_nodes": len(dirty_nodes),
70
+ "deleted_nodes": len(deleted_nodes),
71
+ },
72
+ )
73
+ self._telemetry.record_metric("cache_hits", float(cache_hits), unit="count")
74
+ self._telemetry.record_metric("cache_misses", float(cache_misses), unit="count")
53
75
  return {
54
76
  "dirty_nodes": dirty_nodes,
55
77
  "deleted_nodes": deleted_nodes,