mcp-efficiency-engine 0.1.0 → 0.1.2

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 (191) hide show
  1. package/.githooks/post-commit +20 -0
  2. package/.github/workflows/autodocs-sync.yml +2 -15
  3. package/.github/workflows/release-npm.yml +111 -0
  4. package/FINAL_USAGE_GUIDE.md +78 -0
  5. package/README.md +231 -0
  6. package/autodocs/README.md +6 -0
  7. package/bin/install-host.js +26 -1
  8. package/observability/metrics.md +33 -0
  9. package/observability/scoring-rubric.md +20 -0
  10. package/orchestrator/wiki/graph_consolidator.py +60 -1
  11. package/orchestrator/wiki/incremental_engine.py +23 -1
  12. package/orchestrator/wiki/plugin_manager.py +87 -22
  13. package/package.json +10 -2
  14. package/requirements.txt +2 -0
  15. package/scripts/intake/resolve-routing.py +124 -87
  16. package/scripts/intake/validate-database-routing.py +13 -4
  17. package/scripts/intake/validate-rag-routing.py +4 -3
  18. package/scripts/learning/learning-loop-report.py +28 -10
  19. package/scripts/ops/bye.ps1 +30 -0
  20. package/scripts/ops/hi.ps1 +13 -0
  21. package/scripts/ops/llm-token-probe.py +103 -39
  22. package/scripts/ops/post-commit-refresh.ps1 +110 -0
  23. package/scripts/ops/publish-langsmith-kpis.py +302 -0
  24. package/scripts/ops/telemetry-benchmark.py +184 -0
  25. package/scripts/setup/install-project-hooks.ps1 +33 -0
  26. package/scripts/setup/setup-prerequisites.ps1 +42 -15
  27. package/scripts/wiki/compiler_main.py +108 -76
  28. package/scripts/wiki/providers/repo_content_provider.py +51 -0
  29. package/scripts/wiki/validator.py +40 -15
  30. package/telemetry/__init__.py +4 -0
  31. package/telemetry/bootstrap.py +47 -0
  32. package/telemetry/collector/engine.py +261 -0
  33. package/telemetry/config.json +20 -0
  34. package/telemetry/config.py +131 -0
  35. package/telemetry/context/propagation.py +85 -0
  36. package/telemetry/events/catalog.py +24 -0
  37. package/telemetry/events/factory.py +42 -0
  38. package/telemetry/exporters/base.py +16 -0
  39. package/telemetry/exporters/console/exporter.py +30 -0
  40. package/telemetry/exporters/json/exporter.py +34 -0
  41. package/telemetry/exporters/langsmith/exporter.py +415 -0
  42. package/telemetry/metrics/aggregator.py +60 -0
  43. package/telemetry/scoring/efficiency.py +68 -0
  44. package/telemetry/tracing/span.py +43 -0
  45. package/observability/evals/chat-token-usage-report.json +0 -64
  46. package/observability/evals/chat-token-usage-report.md +0 -33
  47. package/observability/evals/iteration-value-report.json +0 -76
  48. package/observability/evals/iteration-value-report.md +0 -39
  49. package/observability/evals/learning-loop-report.json +0 -268
  50. package/observability/evals/learning-loop-report.md +0 -37
  51. package/observability/evals/repo-intake-eval-cases.md +0 -23
  52. package/observability/evals/routing-eval-cases.json +0 -68
  53. package/observability/evals/routing-eval-cases.md +0 -25
  54. package/observability/evals/routing-eval-report.json +0 -72
  55. package/observability/logs/copilot-usage-ingest-report.json +0 -13
  56. package/observability/logs/iteration-metrics.jsonl +0 -75
  57. package/observability/logs/learning-feedback.jsonl +0 -152
  58. package/observability/logs/routing-decisions.jsonl +0 -333
  59. package/observability/logs/session/agent-pipeline-preflight-20260701-004146.log +0 -8
  60. package/observability/logs/session/agent-pipeline-preflight-20260701-005554.log +0 -8
  61. package/observability/logs/session/agent-pipeline-preflight-20260701-010351.log +0 -8
  62. package/observability/logs/session/agent-pipeline-preflight-20260704-145829.log +0 -8
  63. package/observability/logs/session/agent-pipeline-preflight-20260704-150021.log +0 -8
  64. package/observability/logs/session/agent-pipeline-preflight-20260704-154328.log +0 -8
  65. package/observability/logs/session/bye-20260629-221513.json +0 -39
  66. package/observability/logs/session/bye-20260629-221545.json +0 -59
  67. package/observability/logs/session/bye-20260629-222007.json +0 -52
  68. package/observability/logs/session/bye-20260629-222133.json +0 -59
  69. package/observability/logs/session/bye-20260629-222412.json +0 -45
  70. package/observability/logs/session/bye-20260629-223224.json +0 -52
  71. package/observability/logs/session/bye-20260629-224050.json +0 -59
  72. package/observability/logs/session/bye-20260630-105732.json +0 -24
  73. package/observability/logs/session/bye-20260630-211536.json +0 -87
  74. package/observability/logs/session/bye-20260630-223423.json +0 -87
  75. package/observability/logs/session/bye-20260630-232534.json +0 -87
  76. package/observability/logs/session/bye-20260701-003638.json +0 -126
  77. package/observability/logs/session/bye-20260701-003849.json +0 -126
  78. package/observability/logs/session/bye-20260701-004315.json +0 -138
  79. package/observability/logs/session/bye-20260701-004559.json +0 -76
  80. package/observability/logs/session/bye-20260701-005913.json +0 -138
  81. package/observability/logs/session/bye-20260701-010753.json +0 -138
  82. package/observability/logs/session/bye-20260703-194106.json +0 -24
  83. package/observability/logs/session/bye-20260703-233443.json +0 -76
  84. package/observability/logs/session/bye-20260703-233653.json +0 -76
  85. package/observability/logs/session/bye-20260704-150317.json +0 -152
  86. package/observability/logs/session/bye-20260704-150929.json +0 -75
  87. package/observability/logs/session/bye-20260704-151050.json +0 -75
  88. package/observability/logs/session/bye-20260705-115458.json +0 -165
  89. package/observability/logs/session/codegraph-status-20260701-004228.log +0 -39
  90. package/observability/logs/session/codegraph-status-20260701-004310.log +0 -39
  91. package/observability/logs/session/codegraph-status-20260701-005637.log +0 -39
  92. package/observability/logs/session/codegraph-status-20260701-005908.log +0 -39
  93. package/observability/logs/session/codegraph-status-20260701-010444.log +0 -39
  94. package/observability/logs/session/codegraph-status-20260701-010747.log +0 -39
  95. package/observability/logs/session/codegraph-status-20260704-150137.log +0 -26
  96. package/observability/logs/session/codegraph-status-20260704-150313.log +0 -28
  97. package/observability/logs/session/codegraph-status-20260704-154445.log +0 -26
  98. package/observability/logs/session/codegraph-status-20260705-115454.log +0 -27
  99. package/observability/logs/session/codegraph-sync-20260701-004211.log +0 -88
  100. package/observability/logs/session/codegraph-sync-20260701-004241.log +0 -82
  101. package/observability/logs/session/codegraph-sync-20260701-005620.log +0 -89
  102. package/observability/logs/session/codegraph-sync-20260701-005840.log +0 -88
  103. package/observability/logs/session/codegraph-sync-20260701-010419.log +0 -93
  104. package/observability/logs/session/codegraph-sync-20260701-010609.log +0 -90
  105. package/observability/logs/session/codegraph-sync-20260704-145856.log +0 -70
  106. package/observability/logs/session/codegraph-sync-20260704-150047.log +0 -53
  107. package/observability/logs/session/codegraph-sync-20260704-150204.log +0 -44
  108. package/observability/logs/session/codegraph-sync-20260704-154353.log +0 -26
  109. package/observability/logs/session/codegraph-sync-20260705-115337.log +0 -32
  110. package/observability/logs/session/hi-20260629-221459.json +0 -38
  111. package/observability/logs/session/hi-20260629-221945.json +0 -59
  112. package/observability/logs/session/hi-20260629-222108.json +0 -66
  113. package/observability/logs/session/hi-20260629-222352.json +0 -45
  114. package/observability/logs/session/hi-20260629-225719.json +0 -59
  115. package/observability/logs/session/hi-20260629-233722.json +0 -52
  116. package/observability/logs/session/hi-20260629-233913.json +0 -198
  117. package/observability/logs/session/hi-20260630-110156.json +0 -177
  118. package/observability/logs/session/hi-20260630-191243.json +0 -184
  119. package/observability/logs/session/hi-20260630-230050.json +0 -234
  120. package/observability/logs/session/hi-20260630-230523.json +0 -227
  121. package/observability/logs/session/hi-20260630-230855.json +0 -227
  122. package/observability/logs/session/hi-20260630-231638.json +0 -227
  123. package/observability/logs/session/hi-20260630-231756.json +0 -219
  124. package/observability/logs/session/hi-20260701-002842.json +0 -234
  125. package/observability/logs/session/hi-20260701-003458.json +0 -282
  126. package/observability/logs/session/hi-20260701-004233.json +0 -290
  127. package/observability/logs/session/hi-20260701-004554.json +0 -236
  128. package/observability/logs/session/hi-20260701-005641.json +0 -290
  129. package/observability/logs/session/hi-20260701-010450.json +0 -290
  130. package/observability/logs/session/hi-20260703-233854.json +0 -312
  131. package/observability/logs/session/hi-20260703-234448.json +0 -318
  132. package/observability/logs/session/hi-20260704-145907.json +0 -353
  133. package/observability/logs/session/hi-20260704-150141.json +0 -392
  134. package/observability/logs/session/hi-20260704-154448.json +0 -392
  135. package/observability/logs/session/iteration-value-refresh-20260701-004309.log +0 -3
  136. package/observability/logs/session/iteration-value-refresh-20260701-005907.log +0 -3
  137. package/observability/logs/session/iteration-value-refresh-20260701-010747.log +0 -3
  138. package/observability/logs/session/iteration-value-refresh-20260704-150312.log +0 -3
  139. package/observability/logs/session/iteration-value-refresh-20260705-115453.log +0 -3
  140. package/observability/logs/session/learning-loop-refresh-20260701-004309.log +0 -3
  141. package/observability/logs/session/learning-loop-refresh-20260701-005906.log +0 -3
  142. package/observability/logs/session/learning-loop-refresh-20260701-010745.log +0 -3
  143. package/observability/logs/session/learning-loop-refresh-20260704-150309.log +0 -3
  144. package/observability/logs/session/learning-loop-refresh-20260705-115450.log +0 -3
  145. package/observability/logs/session/project-notes-refresh-20260701-004227.log +0 -1
  146. package/observability/logs/session/project-notes-refresh-20260701-004308.log +0 -1
  147. package/observability/logs/session/project-notes-refresh-20260701-005636.log +0 -1
  148. package/observability/logs/session/project-notes-refresh-20260701-005906.log +0 -1
  149. package/observability/logs/session/project-notes-refresh-20260701-010443.log +0 -1
  150. package/observability/logs/session/project-notes-refresh-20260701-010744.log +0 -1
  151. package/observability/logs/session/project-notes-refresh-20260704-150133.log +0 -1
  152. package/observability/logs/session/project-notes-refresh-20260704-150309.log +0 -1
  153. package/observability/logs/session/project-notes-refresh-20260704-154442.log +0 -1
  154. package/observability/logs/session/project-notes-refresh-20260705-115449.log +0 -1
  155. package/observability/logs/session/repo-intake-20260701-004218.log +0 -6
  156. package/observability/logs/session/repo-intake-20260701-005626.log +0 -6
  157. package/observability/logs/session/repo-intake-20260701-010433.log +0 -6
  158. package/observability/logs/session/repo-intake-20260704-150053.log +0 -6
  159. package/observability/logs/session/repo-intake-20260704-154404.log +0 -6
  160. package/observability/logs/session/repo-intake-refresh-20260701-004247.log +0 -6
  161. package/observability/logs/session/repo-intake-refresh-20260701-005847.log +0 -6
  162. package/observability/logs/session/repo-intake-refresh-20260701-010615.log +0 -6
  163. package/observability/logs/session/repo-intake-refresh-20260704-150209.log +0 -6
  164. package/observability/logs/session/repo-intake-refresh-20260705-115342.log +0 -6
  165. package/observability/logs/session/repo-registry-validation-20260701-004234.log +0 -2
  166. package/observability/logs/session/repo-registry-validation-20260701-004556.log +0 -2
  167. package/observability/logs/session/repo-registry-validation-20260701-005833.log +0 -2
  168. package/observability/logs/session/repo-registry-validation-20260701-010601.log +0 -2
  169. package/observability/logs/session/repo-registry-validation-20260704-150155.log +0 -2
  170. package/observability/logs/session/repo-registry-validation-20260705-115323.log +0 -2
  171. package/observability/logs/session/repomix-refresh-20260701-003823.log +0 -4236
  172. package/observability/logs/session/repomix-refresh-20260701-004251.log +0 -4275
  173. package/observability/logs/session/repomix-refresh-20260701-005850.log +0 -4248
  174. package/observability/logs/session/repomix-refresh-20260701-010619.log +0 -6531
  175. package/observability/logs/session/repomix-refresh-20260704-150239.log +0 -652
  176. package/observability/logs/session/repomix-refresh-20260705-115419.log +0 -178
  177. package/observability/logs/session/routing-evals-20260701-004221.log +0 -2
  178. package/observability/logs/session/routing-evals-20260701-004235.log +0 -2
  179. package/observability/logs/session/routing-evals-20260701-005629.log +0 -2
  180. package/observability/logs/session/routing-evals-20260701-005834.log +0 -2
  181. package/observability/logs/session/routing-evals-20260701-010437.log +0 -2
  182. package/observability/logs/session/routing-evals-20260701-010603.log +0 -2
  183. package/observability/logs/session/routing-evals-20260704-150125.log +0 -2
  184. package/observability/logs/session/routing-evals-20260704-150157.log +0 -2
  185. package/observability/logs/session/routing-evals-20260704-154434.log +0 -2
  186. package/observability/logs/session/routing-evals-20260705-115327.log +0 -2
  187. package/observability/logs/session/sibling-discovery-refresh-20260701-004250.log +0 -3
  188. package/observability/logs/session/sibling-discovery-refresh-20260701-005850.log +0 -3
  189. package/observability/logs/session/sibling-discovery-refresh-20260701-010618.log +0 -3
  190. package/observability/logs/session/sibling-discovery-refresh-20260704-150238.log +0 -3
  191. package/observability/logs/session/sibling-discovery-refresh-20260705-115418.log +0 -3
@@ -1,9 +1,16 @@
1
1
  import json
2
2
  import os
3
+ import sys
3
4
  from datetime import datetime, timezone
4
5
  from pathlib import Path
5
6
  from typing import Any, Dict, List
6
7
 
8
+ _REPO_ROOT = Path(__file__).resolve().parents[2]
9
+ if str(_REPO_ROOT) not in sys.path:
10
+ sys.path.insert(0, str(_REPO_ROOT))
11
+
12
+ from telemetry import build_telemetry_collector
13
+
7
14
  from orchestrator.wiki.graph_consolidator import GraphConsolidator
8
15
  from orchestrator.wiki.incremental_engine import IncrementalEngine
9
16
  from orchestrator.wiki.plugin_manager import PluginManager
@@ -106,82 +113,107 @@ def _write_routing_event(
106
113
  def main() -> int:
107
114
  start = datetime.now(timezone.utc)
108
115
  env_snapshot = _read_session_env()
109
-
110
- manager = PluginManager()
111
- include_external = str(os.getenv("AUTODOCS_INCLUDE_EXTERNAL_PROVIDERS", "")).strip().lower() in {
112
- "1",
113
- "true",
114
- "yes",
115
- "on",
116
- }
117
-
118
- # Keep CI output deterministic: external providers depend on local intake artifacts that
119
- # may not exist on clean runners.
120
- if include_external:
121
- manager.register_provider(CodeGraphProvider(REPO_ROOT / "repo-intake" / "generated"))
122
- manager.register_provider(GraphifyProvider(REPO_ROOT / "repo-intake" / "generated"))
123
-
124
- manager.register_provider(RepoContentProvider(REPO_ROOT))
125
-
126
- provider_result = manager.gather_all()
127
- contracts = provider_result.get("contracts", [])
128
- provider_errors = provider_result.get("errors", [])
129
-
130
- consolidator = GraphConsolidator(
131
- output_graph_path=UNIFIED_GRAPH_PATH,
132
- markdown_output_dir=MARKDOWN_OUTPUT_DIR,
133
- )
134
- unified_graph = consolidator.consolidate(contracts)
135
- wiki_nodes = unified_graph.get("wiki_nodes", {})
136
-
137
- incremental_engine = IncrementalEngine(UNIFIED_GRAPH_PATH)
138
- diff = incremental_engine.diff(wiki_nodes)
139
- dirty_nodes = diff.get("dirty_nodes", {})
140
- deleted_nodes = diff.get("deleted_nodes", [])
141
- cached_nodes = diff.get("cached_graph", {}).get("nodes", {})
142
-
143
- validator = WikiValidator(SCHEMA_PATH)
144
- validation_report = validator.validate(wiki_nodes)
145
- validator.write_reports(
146
- json_path=VALIDATION_REPORT_JSON,
147
- markdown_path=VALIDATION_REPORT_MD,
148
- report=validation_report,
149
- )
150
-
151
- project_stats = consolidator.project_dirty_nodes(
152
- dirty_nodes=dirty_nodes,
153
- deleted_nodes=deleted_nodes,
154
- all_nodes=wiki_nodes,
155
- cached_nodes=cached_nodes,
156
- )
157
- consolidator.persist_graph(unified_graph)
158
- consolidator.persist_manifests(unified_graph)
159
-
160
- elapsed_ms = int((datetime.now(timezone.utc) - start).total_seconds() * 1000)
161
- iteration_event: Dict[str, Any] = {
162
- "timestamp": datetime.now(timezone.utc).isoformat(),
163
- "source_type": "technical-docs",
164
- "module": "autodocs",
165
- "total_nodes": len(wiki_nodes),
166
- "dirty_nodes": len(dirty_nodes),
167
- "deleted_nodes": len(deleted_nodes),
168
- "rendered_markdown": int(project_stats.get("rendered", 0)),
169
- "deleted_markdown": int(project_stats.get("deleted", 0)),
170
- "rendered_indexes": int(project_stats.get("indexes", 0)),
171
- "rendered_manifests": int(project_stats.get("manifests", 0)),
172
- "provider_errors": len(provider_errors),
173
- "validation_errors": int(validation_report.get("summary", {}).get("error_count", 0)),
174
- "validation_warnings": int(validation_report.get("summary", {}).get("warning_count", 0)),
175
- "elapsed_ms": elapsed_ms,
176
- }
177
- _append_jsonl(ITERATION_LOG, iteration_event)
178
- _write_routing_event(
179
- env_snapshot=env_snapshot,
180
- dirty_count=len(dirty_nodes),
181
- total_nodes=len(wiki_nodes),
182
- errors=provider_errors,
183
- elapsed_ms=elapsed_ms,
184
- )
116
+ collector = build_telemetry_collector(REPO_ROOT)
117
+
118
+ with collector.start_execution(operation="autodocs-compiler", session_id="autodocs"):
119
+ collector.record_event("ExecutionStarted", {"pipeline": "autodocs", "env_keys": sorted(env_snapshot.keys())})
120
+
121
+ manager = PluginManager(telemetry_collector=collector)
122
+ include_external = str(os.getenv("AUTODOCS_INCLUDE_EXTERNAL_PROVIDERS", "")).strip().lower() in {
123
+ "1",
124
+ "true",
125
+ "yes",
126
+ "on",
127
+ }
128
+
129
+ # Keep CI output deterministic: external providers depend on local intake artifacts that
130
+ # may not exist on clean runners.
131
+ if include_external:
132
+ manager.register_provider(CodeGraphProvider(REPO_ROOT / "repo-intake" / "generated"))
133
+ manager.register_provider(GraphifyProvider(REPO_ROOT / "repo-intake" / "generated"))
134
+
135
+ manager.register_provider(RepoContentProvider(REPO_ROOT))
136
+
137
+ with collector.start_span(name="autodocs.providers", kind="INTERNAL"):
138
+ provider_result = manager.gather_all()
139
+ contracts = provider_result.get("contracts", [])
140
+ provider_errors = provider_result.get("errors", [])
141
+ collector.record_metric("provider_calls", float(len(contracts) + len(provider_errors)), unit="count")
142
+
143
+ consolidator = GraphConsolidator(
144
+ output_graph_path=UNIFIED_GRAPH_PATH,
145
+ markdown_output_dir=MARKDOWN_OUTPUT_DIR,
146
+ telemetry_collector=collector,
147
+ )
148
+ with collector.start_span(name="autodocs.consolidate", kind="INTERNAL"):
149
+ unified_graph = consolidator.consolidate(contracts)
150
+ wiki_nodes = unified_graph.get("wiki_nodes", {})
151
+
152
+ incremental_engine = IncrementalEngine(UNIFIED_GRAPH_PATH, telemetry_collector=collector)
153
+ with collector.start_span(name="autodocs.incremental", kind="INTERNAL"):
154
+ diff = incremental_engine.diff(wiki_nodes)
155
+ dirty_nodes = diff.get("dirty_nodes", {})
156
+ deleted_nodes = diff.get("deleted_nodes", [])
157
+ cached_nodes = diff.get("cached_graph", {}).get("nodes", {})
158
+
159
+ validator = WikiValidator(SCHEMA_PATH, telemetry_collector=collector)
160
+ with collector.start_span(name="autodocs.validate", kind="INTERNAL"):
161
+ validation_report = validator.validate(wiki_nodes)
162
+ validator.write_reports(
163
+ json_path=VALIDATION_REPORT_JSON,
164
+ markdown_path=VALIDATION_REPORT_MD,
165
+ report=validation_report,
166
+ )
167
+
168
+ with collector.start_span(name="autodocs.project", kind="INTERNAL"):
169
+ project_stats = consolidator.project_dirty_nodes(
170
+ dirty_nodes=dirty_nodes,
171
+ deleted_nodes=deleted_nodes,
172
+ all_nodes=wiki_nodes,
173
+ cached_nodes=cached_nodes,
174
+ )
175
+ consolidator.persist_graph(unified_graph)
176
+ consolidator.persist_manifests(unified_graph)
177
+
178
+ elapsed_ms = int((datetime.now(timezone.utc) - start).total_seconds() * 1000)
179
+ iteration_event: Dict[str, Any] = {
180
+ "timestamp": datetime.now(timezone.utc).isoformat(),
181
+ "source_type": "technical-docs",
182
+ "module": "autodocs",
183
+ "total_nodes": len(wiki_nodes),
184
+ "dirty_nodes": len(dirty_nodes),
185
+ "deleted_nodes": len(deleted_nodes),
186
+ "rendered_markdown": int(project_stats.get("rendered", 0)),
187
+ "deleted_markdown": int(project_stats.get("deleted", 0)),
188
+ "rendered_indexes": int(project_stats.get("indexes", 0)),
189
+ "rendered_manifests": int(project_stats.get("manifests", 0)),
190
+ "provider_errors": len(provider_errors),
191
+ "validation_errors": int(validation_report.get("summary", {}).get("error_count", 0)),
192
+ "validation_warnings": int(validation_report.get("summary", {}).get("warning_count", 0)),
193
+ "elapsed_ms": elapsed_ms,
194
+ }
195
+ _append_jsonl(ITERATION_LOG, iteration_event)
196
+ _write_routing_event(
197
+ env_snapshot=env_snapshot,
198
+ dirty_count=len(dirty_nodes),
199
+ total_nodes=len(wiki_nodes),
200
+ errors=provider_errors,
201
+ elapsed_ms=elapsed_ms,
202
+ )
203
+
204
+ collector.record_metric("execution_time_ms", float(elapsed_ms), unit="ms")
205
+ collector.record_metric("warning_count", float(len(provider_errors)), unit="count")
206
+ collector.record_event(
207
+ "KnowledgeGenerated",
208
+ {
209
+ "total_nodes": len(wiki_nodes),
210
+ "dirty_nodes": len(dirty_nodes),
211
+ "deleted_nodes": len(deleted_nodes),
212
+ "elapsed_ms": elapsed_ms,
213
+ },
214
+ )
215
+
216
+ collector.shutdown()
185
217
 
186
218
  if int(validation_report.get("summary", {}).get("error_count", 0)) > 0:
187
219
  return 1
@@ -14,6 +14,7 @@ class RepoContentProvider(BaseWikiProvider):
14
14
 
15
15
  def gather_knowledge(self) -> Dict[str, Any]:
16
16
  entities: List[Dict[str, Any]] = []
17
+ entities.extend(self._collect_core_docs())
17
18
  entities.extend(self._collect_agents())
18
19
  entities.extend(self._collect_skills())
19
20
  entities.extend(self._collect_policies())
@@ -25,6 +26,42 @@ class RepoContentProvider(BaseWikiProvider):
25
26
  self._enrich_relations(entities)
26
27
  return {"provider_id": self.provider_id, "entities": entities}
27
28
 
29
+ def _collect_core_docs(self) -> List[Dict[str, Any]]:
30
+ targets: List[Tuple[Path, str]] = [
31
+ (self.repo_root / "README.md", "Guia principal del engine y sus flujos operativos."),
32
+ (self.repo_root / "README_WIKI.md", "Guia de uso y alcance de la wiki AutoDocs del repositorio."),
33
+ (self.repo_root / "FINAL_USAGE_GUIDE.md", "Guia de uso final con pasos operativos y buenas practicas."),
34
+ (self.repo_root / "FILE_INDEX.md", "Indice del contenido y estructura del repositorio."),
35
+ (self.repo_root / "autodocs" / "README.md", "Referencia de ejecucion y artefactos de AutoDocs."),
36
+ ]
37
+
38
+ entities: List[Dict[str, Any]] = []
39
+ for path, fallback_summary in targets:
40
+ if not path.exists():
41
+ continue
42
+ entities.append(
43
+ self._entity_from_markdown(
44
+ path,
45
+ kind="report",
46
+ section="reports",
47
+ domain="documentation",
48
+ fallback_summary=fallback_summary,
49
+ )
50
+ )
51
+
52
+ package_json = self.repo_root / "package.json"
53
+ if package_json.exists():
54
+ entities.append(
55
+ self._entity_from_json(
56
+ package_json,
57
+ kind="report",
58
+ section="reports",
59
+ domain="packaging",
60
+ )
61
+ )
62
+
63
+ return entities
64
+
28
65
  def _collect_agents(self) -> List[Dict[str, Any]]:
29
66
  agents_dir = self.repo_root / ".github" / "agents"
30
67
  if not agents_dir.exists():
@@ -292,6 +329,18 @@ class RepoContentProvider(BaseWikiProvider):
292
329
  for target_id in ["AGENTS.md", "orchestrator/router.md"]:
293
330
  if target_id in entities_by_id:
294
331
  self._add_relation(entity, target_id, "explains")
332
+ if source_ref == "README.md":
333
+ for target_id in ["AGENTS.md", "ARCHITECTURE.md", "FINAL_USAGE_GUIDE.md", "package.json"]:
334
+ if target_id in entities_by_id:
335
+ self._add_relation(entity, target_id, "documents")
336
+ if source_ref == "FINAL_USAGE_GUIDE.md":
337
+ for target_id in ["README.md", "scripts/README.md"]:
338
+ if target_id in entities_by_id:
339
+ self._add_relation(entity, target_id, "extends")
340
+ if source_ref == "autodocs/README.md":
341
+ for target_id in ["README_WIKI.md", "scripts/wiki/wiki_compiler.py"]:
342
+ if target_id in entities_by_id:
343
+ self._add_relation(entity, target_id, "documents")
295
344
  if source_ref == "autodocs/analysis_mcpee/OPENWIKI_INTERNAL_BLUEPRINT.md":
296
345
  for target_id in ["autodocs/README.md", "README_WIKI.md"]:
297
346
  if target_id in entities_by_id:
@@ -364,6 +413,8 @@ class RepoContentProvider(BaseWikiProvider):
364
413
  stem = path.name
365
414
  if path.name.lower() == "skill.md" and path.parent.name:
366
415
  stem = path.parent.name
416
+ elif path.stem.lower() == "readme" and path.parent != self.repo_root:
417
+ stem = f"{path.parent.name}-{path.name}"
367
418
  tokens = [kind, stem]
368
419
  if kind == "report" and "analysis_mcpee" in relative:
369
420
  tokens.insert(1, "autodocs")
@@ -4,10 +4,11 @@ from pathlib import Path
4
4
  from typing import Any, Dict, List
5
5
 
6
6
  from scripts.wiki.normalizer import section_catalog
7
+ from telemetry import build_telemetry_collector
7
8
 
8
9
 
9
10
  class WikiValidator:
10
- def __init__(self, schema_path: Path) -> None:
11
+ def __init__(self, schema_path: Path, telemetry_collector: Any | None = None) -> None:
11
12
  self.schema_path = schema_path
12
13
  self.allowed_sections = {section["id"] for section in section_catalog()}
13
14
  self.allowed_kinds = {
@@ -20,27 +21,51 @@ class WikiValidator:
20
21
  "report",
21
22
  "capability",
22
23
  }
24
+ self._telemetry = telemetry_collector
25
+
26
+ def _collector(self) -> Any:
27
+ if self._telemetry is None:
28
+ repo_root = Path(__file__).resolve().parents[2]
29
+ self._telemetry = build_telemetry_collector(repo_root)
30
+ return self._telemetry
23
31
 
24
32
  def validate(self, wiki_nodes: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
33
+ collector = self._collector()
25
34
  errors: List[Dict[str, Any]] = []
26
35
  warnings: List[Dict[str, Any]] = []
27
36
  info: List[Dict[str, Any]] = []
28
37
  slug_registry: Dict[str, str] = {}
29
38
 
30
- if not self.schema_path.exists():
31
- warnings.append(self._issue("schema", "schema_missing", "Schema file not found", "warning"))
32
-
33
- for node_key, node in wiki_nodes.items():
34
- self._validate_required(node_key, node, errors)
35
- self._validate_kind(node_key, node, errors)
36
- self._validate_section(node_key, node, errors)
37
- self._validate_slug(node_key, node, slug_registry, errors)
38
- self._validate_sources(node_key, node, warnings)
39
- self._validate_summary(node_key, node, warnings)
40
- self._validate_relations(node_key, node, wiki_nodes, errors)
41
-
42
- quality_score = self._quality_score(total=len(wiki_nodes), errors=len(errors), warnings=len(warnings))
43
- info.append(self._issue("summary", "quality_score", f"quality_score={quality_score}", "info"))
39
+ with collector.start_execution(operation="wiki-validator", session_id="autodocs"):
40
+ with collector.start_span(name="wiki.validate", kind="INTERNAL", attributes={"node_count": len(wiki_nodes)}):
41
+ if not self.schema_path.exists():
42
+ warnings.append(self._issue("schema", "schema_missing", "Schema file not found", "warning"))
43
+ collector.record_event("WarningGenerated", {"warning": "schema_missing", "schema_path": str(self.schema_path)}, level="WARNING")
44
+
45
+ for node_key, node in wiki_nodes.items():
46
+ self._validate_required(node_key, node, errors)
47
+ self._validate_kind(node_key, node, errors)
48
+ self._validate_section(node_key, node, errors)
49
+ self._validate_slug(node_key, node, slug_registry, errors)
50
+ self._validate_sources(node_key, node, warnings)
51
+ self._validate_summary(node_key, node, warnings)
52
+ self._validate_relations(node_key, node, wiki_nodes, errors)
53
+
54
+ quality_score = self._quality_score(total=len(wiki_nodes), errors=len(errors), warnings=len(warnings))
55
+ info.append(self._issue("summary", "quality_score", f"quality_score={quality_score}", "info"))
56
+
57
+ collector.record_metric("warning_count", float(len(warnings)), unit="count")
58
+ collector.record_metric("error_count", float(len(errors)), unit="count")
59
+ collector.record_metric("quality_score", float(quality_score), unit="score")
60
+ collector.record_event(
61
+ "MetricCalculated",
62
+ {
63
+ "node_count": len(wiki_nodes),
64
+ "error_count": len(errors),
65
+ "warning_count": len(warnings),
66
+ "quality_score": quality_score,
67
+ },
68
+ )
44
69
 
45
70
  signature = hashlib.sha256(
46
71
  json.dumps(wiki_nodes, sort_keys=True, ensure_ascii=True, separators=(",", ":")).encode("utf-8")
@@ -0,0 +1,4 @@
1
+ from .bootstrap import build_telemetry_collector
2
+ from .collector.engine import TelemetryCollector
3
+
4
+ __all__ = ["TelemetryCollector", "build_telemetry_collector"]
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from telemetry.collector.engine import TelemetryCollector
6
+ from telemetry.config import load_config
7
+ from telemetry.exporters.console.exporter import ConsoleExporter
8
+ from telemetry.exporters.json.exporter import JsonExporter
9
+ from telemetry.exporters.langsmith.exporter import LangSmithExporter
10
+
11
+
12
+ def build_telemetry_collector(repo_root: Path) -> TelemetryCollector:
13
+ cfg = load_config(repo_root)
14
+ exporters: list[object] = []
15
+
16
+ # Console exporter is always available in runtime.
17
+ if "console" in cfg.exporters:
18
+ exporters.append(ConsoleExporter())
19
+ elif not cfg.exporters:
20
+ exporters.append(ConsoleExporter())
21
+
22
+ if "json" in cfg.exporters:
23
+ exporters.append(JsonExporter((repo_root / cfg.telemetry_dir).resolve()))
24
+
25
+ if "langsmith" in cfg.exporters and cfg.langsmith.enabled:
26
+ has_langsmith_config = bool(cfg.langsmith.api_key.strip()) and bool(cfg.langsmith.project.strip())
27
+ if has_langsmith_config:
28
+ try:
29
+ exporters.append(
30
+ LangSmithExporter(
31
+ api_key=cfg.langsmith.api_key,
32
+ project=cfg.langsmith.project,
33
+ endpoint=cfg.langsmith.endpoint,
34
+ workspace_id=cfg.langsmith.workspace_id,
35
+ high_signal_only=cfg.langsmith.high_signal_only,
36
+ min_span_duration_ms=cfg.langsmith.min_span_duration_ms,
37
+ emit_execution_summary=cfg.langsmith.emit_execution_summary,
38
+ )
39
+ )
40
+ except Exception:
41
+ # LangSmith is optional and must never break startup.
42
+ pass
43
+
44
+ if not exporters:
45
+ exporters.append(ConsoleExporter())
46
+
47
+ return TelemetryCollector(exporters=exporters, enabled=cfg.enabled, batch_size=cfg.batch_size)