@mycodemap/mycodemap 0.4.2 → 0.5.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 (288) hide show
  1. package/CHANGELOG.md +105 -3
  2. package/README.md +192 -53
  3. package/dist/ai/claude.d.ts +38 -0
  4. package/dist/ai/claude.d.ts.map +1 -0
  5. package/dist/ai/claude.js +169 -0
  6. package/dist/ai/claude.js.map +1 -0
  7. package/dist/ai/codex.d.ts +38 -0
  8. package/dist/ai/codex.d.ts.map +1 -0
  9. package/dist/ai/codex.js +169 -0
  10. package/dist/ai/codex.js.map +1 -0
  11. package/dist/ai/factory.d.ts +48 -0
  12. package/dist/ai/factory.d.ts.map +1 -0
  13. package/dist/ai/factory.js +95 -0
  14. package/dist/ai/factory.js.map +1 -0
  15. package/dist/ai/index.d.ts +12 -0
  16. package/dist/ai/index.d.ts.map +1 -0
  17. package/dist/ai/index.js +29 -0
  18. package/dist/ai/index.js.map +1 -0
  19. package/dist/ai/provider.d.ts +70 -0
  20. package/dist/ai/provider.d.ts.map +1 -0
  21. package/dist/ai/provider.js +31 -0
  22. package/dist/ai/provider.js.map +1 -0
  23. package/dist/ai/subagent-caller.d.ts +90 -0
  24. package/dist/ai/subagent-caller.d.ts.map +1 -0
  25. package/dist/ai/subagent-caller.js +280 -0
  26. package/dist/ai/subagent-caller.js.map +1 -0
  27. package/dist/ai/types.d.ts +70 -0
  28. package/dist/ai/types.d.ts.map +1 -0
  29. package/dist/ai/types.js +5 -0
  30. package/dist/ai/types.js.map +1 -0
  31. package/dist/cli/commands/analyze.d.ts +18 -0
  32. package/dist/cli/commands/analyze.d.ts.map +1 -1
  33. package/dist/cli/commands/analyze.js +239 -6
  34. package/dist/cli/commands/analyze.js.map +1 -1
  35. package/dist/cli/commands/check.d.ts +22 -0
  36. package/dist/cli/commands/check.d.ts.map +1 -0
  37. package/dist/cli/commands/check.js +168 -0
  38. package/dist/cli/commands/check.js.map +1 -0
  39. package/dist/cli/commands/ci.d.ts +25 -0
  40. package/dist/cli/commands/ci.d.ts.map +1 -1
  41. package/dist/cli/commands/ci.js +139 -36
  42. package/dist/cli/commands/ci.js.map +1 -1
  43. package/dist/cli/commands/complexity.d.ts.map +1 -1
  44. package/dist/cli/commands/complexity.js +6 -0
  45. package/dist/cli/commands/complexity.js.map +1 -1
  46. package/dist/cli/commands/design.d.ts +52 -0
  47. package/dist/cli/commands/design.d.ts.map +1 -0
  48. package/dist/cli/commands/design.js +274 -0
  49. package/dist/cli/commands/design.js.map +1 -0
  50. package/dist/cli/commands/generate.d.ts +1 -0
  51. package/dist/cli/commands/generate.d.ts.map +1 -1
  52. package/dist/cli/commands/generate.js +121 -8
  53. package/dist/cli/commands/generate.js.map +1 -1
  54. package/dist/cli/commands/history.d.ts +26 -0
  55. package/dist/cli/commands/history.d.ts.map +1 -0
  56. package/dist/cli/commands/history.js +92 -0
  57. package/dist/cli/commands/history.js.map +1 -0
  58. package/dist/cli/commands/mcp.d.ts +13 -0
  59. package/dist/cli/commands/mcp.d.ts.map +1 -0
  60. package/dist/cli/commands/mcp.js +108 -0
  61. package/dist/cli/commands/mcp.js.map +1 -0
  62. package/dist/cli/commands/server.d.ts +9 -0
  63. package/dist/cli/commands/server.d.ts.map +1 -0
  64. package/dist/cli/commands/server.js +65 -0
  65. package/dist/cli/commands/server.js.map +1 -0
  66. package/dist/cli/commands/ship/pipeline.d.ts.map +1 -1
  67. package/dist/cli/commands/ship/pipeline.js +8 -1
  68. package/dist/cli/commands/ship/pipeline.js.map +1 -1
  69. package/dist/cli/commands/ship/publisher.d.ts +9 -1
  70. package/dist/cli/commands/ship/publisher.d.ts.map +1 -1
  71. package/dist/cli/commands/ship/publisher.js +149 -6
  72. package/dist/cli/commands/ship/publisher.js.map +1 -1
  73. package/dist/cli/commands/workflow.d.ts.map +1 -1
  74. package/dist/cli/commands/workflow.js +22 -2
  75. package/dist/cli/commands/workflow.js.map +1 -1
  76. package/dist/cli/config-loader.d.ts.map +1 -1
  77. package/dist/cli/config-loader.js +3 -2
  78. package/dist/cli/config-loader.js.map +1 -1
  79. package/dist/cli/contract-checker.d.ts +33 -0
  80. package/dist/cli/contract-checker.d.ts.map +1 -0
  81. package/dist/cli/contract-checker.js +719 -0
  82. package/dist/cli/contract-checker.js.map +1 -0
  83. package/dist/cli/contract-diff-scope.d.ts +14 -0
  84. package/dist/cli/contract-diff-scope.d.ts.map +1 -0
  85. package/dist/cli/contract-diff-scope.js +127 -0
  86. package/dist/cli/contract-diff-scope.js.map +1 -0
  87. package/dist/cli/contract-gate-thresholds.d.ts +14 -0
  88. package/dist/cli/contract-gate-thresholds.d.ts.map +1 -0
  89. package/dist/cli/contract-gate-thresholds.js +19 -0
  90. package/dist/cli/contract-gate-thresholds.js.map +1 -0
  91. package/dist/cli/design-contract-loader.d.ts +15 -0
  92. package/dist/cli/design-contract-loader.d.ts.map +1 -0
  93. package/dist/cli/design-contract-loader.js +527 -0
  94. package/dist/cli/design-contract-loader.js.map +1 -0
  95. package/dist/cli/design-contract-schema.d.ts +11 -0
  96. package/dist/cli/design-contract-schema.d.ts.map +1 -0
  97. package/dist/cli/design-contract-schema.js +75 -0
  98. package/dist/cli/design-contract-schema.js.map +1 -0
  99. package/dist/cli/design-handoff-builder.d.ts +15 -0
  100. package/dist/cli/design-handoff-builder.d.ts.map +1 -0
  101. package/dist/cli/design-handoff-builder.js +345 -0
  102. package/dist/cli/design-handoff-builder.js.map +1 -0
  103. package/dist/cli/design-scope-resolver.d.ts +8 -0
  104. package/dist/cli/design-scope-resolver.d.ts.map +1 -0
  105. package/dist/cli/design-scope-resolver.js +760 -0
  106. package/dist/cli/design-scope-resolver.js.map +1 -0
  107. package/dist/cli/design-verification-builder.d.ts +8 -0
  108. package/dist/cli/design-verification-builder.d.ts.map +1 -0
  109. package/dist/cli/design-verification-builder.js +369 -0
  110. package/dist/cli/design-verification-builder.js.map +1 -0
  111. package/dist/cli/index.js +20 -6
  112. package/dist/cli/index.js.map +1 -1
  113. package/dist/cli/paths.d.ts.map +1 -1
  114. package/dist/cli/paths.js +30 -7
  115. package/dist/cli/paths.js.map +1 -1
  116. package/dist/cli-new/commands/server.d.ts +13 -0
  117. package/dist/cli-new/commands/server.d.ts.map +1 -0
  118. package/dist/cli-new/commands/server.js +90 -0
  119. package/dist/cli-new/commands/server.js.map +1 -0
  120. package/dist/core/analyzer.d.ts.map +1 -1
  121. package/dist/core/analyzer.js +16 -0
  122. package/dist/core/analyzer.js.map +1 -1
  123. package/dist/domain/entities/CodeGraph.d.ts +5 -1
  124. package/dist/domain/entities/CodeGraph.d.ts.map +1 -1
  125. package/dist/domain/entities/CodeGraph.js +29 -12
  126. package/dist/domain/entities/CodeGraph.js.map +1 -1
  127. package/dist/domain/entities/Dependency.d.ts +8 -1
  128. package/dist/domain/entities/Dependency.d.ts.map +1 -1
  129. package/dist/domain/entities/Dependency.js +19 -4
  130. package/dist/domain/entities/Dependency.js.map +1 -1
  131. package/dist/domain/entities/Symbol.d.ts +2 -1
  132. package/dist/domain/entities/Symbol.d.ts.map +1 -1
  133. package/dist/domain/entities/Symbol.js +6 -3
  134. package/dist/domain/entities/Symbol.js.map +1 -1
  135. package/dist/generator/ai-overview.d.ts +51 -0
  136. package/dist/generator/ai-overview.d.ts.map +1 -0
  137. package/dist/generator/ai-overview.js +160 -0
  138. package/dist/generator/ai-overview.js.map +1 -0
  139. package/dist/infrastructure/storage/StorageFactory.d.ts +13 -5
  140. package/dist/infrastructure/storage/StorageFactory.d.ts.map +1 -1
  141. package/dist/infrastructure/storage/StorageFactory.js +62 -16
  142. package/dist/infrastructure/storage/StorageFactory.js.map +1 -1
  143. package/dist/infrastructure/storage/adapters/FileSystemStorage.d.ts +3 -1
  144. package/dist/infrastructure/storage/adapters/FileSystemStorage.d.ts.map +1 -1
  145. package/dist/infrastructure/storage/adapters/FileSystemStorage.js +10 -2
  146. package/dist/infrastructure/storage/adapters/FileSystemStorage.js.map +1 -1
  147. package/dist/infrastructure/storage/adapters/KuzuDBStorage.d.ts +3 -1
  148. package/dist/infrastructure/storage/adapters/KuzuDBStorage.d.ts.map +1 -1
  149. package/dist/infrastructure/storage/adapters/KuzuDBStorage.js +9 -1
  150. package/dist/infrastructure/storage/adapters/KuzuDBStorage.js.map +1 -1
  151. package/dist/infrastructure/storage/adapters/MemoryStorage.d.ts +3 -1
  152. package/dist/infrastructure/storage/adapters/MemoryStorage.d.ts.map +1 -1
  153. package/dist/infrastructure/storage/adapters/MemoryStorage.js +9 -1
  154. package/dist/infrastructure/storage/adapters/MemoryStorage.js.map +1 -1
  155. package/dist/infrastructure/storage/adapters/Neo4jStorage.d.ts +41 -0
  156. package/dist/infrastructure/storage/adapters/Neo4jStorage.d.ts.map +1 -0
  157. package/dist/infrastructure/storage/adapters/Neo4jStorage.js +162 -0
  158. package/dist/infrastructure/storage/adapters/Neo4jStorage.js.map +1 -0
  159. package/dist/infrastructure/storage/adapters/SQLiteStorage.d.ts +53 -0
  160. package/dist/infrastructure/storage/adapters/SQLiteStorage.d.ts.map +1 -0
  161. package/dist/infrastructure/storage/adapters/SQLiteStorage.js +879 -0
  162. package/dist/infrastructure/storage/adapters/SQLiteStorage.js.map +1 -0
  163. package/dist/infrastructure/storage/graph-helpers.d.ts +3 -1
  164. package/dist/infrastructure/storage/graph-helpers.d.ts.map +1 -1
  165. package/dist/infrastructure/storage/graph-helpers.js +90 -0
  166. package/dist/infrastructure/storage/graph-helpers.js.map +1 -1
  167. package/dist/infrastructure/storage/index.d.ts +1 -1
  168. package/dist/infrastructure/storage/index.d.ts.map +1 -1
  169. package/dist/infrastructure/storage/interfaces/StorageBase.d.ts +3 -1
  170. package/dist/infrastructure/storage/interfaces/StorageBase.d.ts.map +1 -1
  171. package/dist/infrastructure/storage/interfaces/StorageBase.js.map +1 -1
  172. package/dist/infrastructure/storage/sqlite/GovernanceGraphCache.d.ts +27 -0
  173. package/dist/infrastructure/storage/sqlite/GovernanceGraphCache.d.ts.map +1 -0
  174. package/dist/infrastructure/storage/sqlite/GovernanceGraphCache.js +246 -0
  175. package/dist/infrastructure/storage/sqlite/GovernanceGraphCache.js.map +1 -0
  176. package/dist/infrastructure/storage/sqlite/perf-thresholds.d.ts +25 -0
  177. package/dist/infrastructure/storage/sqlite/perf-thresholds.d.ts.map +1 -0
  178. package/dist/infrastructure/storage/sqlite/perf-thresholds.js +25 -0
  179. package/dist/infrastructure/storage/sqlite/perf-thresholds.js.map +1 -0
  180. package/dist/infrastructure/storage/sqlite/schema.d.ts +4 -0
  181. package/dist/infrastructure/storage/sqlite/schema.d.ts.map +1 -0
  182. package/dist/infrastructure/storage/sqlite/schema.js +111 -0
  183. package/dist/infrastructure/storage/sqlite/schema.js.map +1 -0
  184. package/dist/interface/types/design-check.d.ts +73 -0
  185. package/dist/interface/types/design-check.d.ts.map +1 -0
  186. package/dist/interface/types/design-check.js +4 -0
  187. package/dist/interface/types/design-check.js.map +1 -0
  188. package/dist/interface/types/design-contract.d.ts +123 -0
  189. package/dist/interface/types/design-contract.d.ts.map +1 -0
  190. package/dist/interface/types/design-contract.js +7 -0
  191. package/dist/interface/types/design-contract.js.map +1 -0
  192. package/dist/interface/types/design-handoff.d.ts +68 -0
  193. package/dist/interface/types/design-handoff.d.ts.map +1 -0
  194. package/dist/interface/types/design-handoff.js +4 -0
  195. package/dist/interface/types/design-handoff.js.map +1 -0
  196. package/dist/interface/types/design-mapping.d.ts +51 -0
  197. package/dist/interface/types/design-mapping.d.ts.map +1 -0
  198. package/dist/interface/types/design-mapping.js +4 -0
  199. package/dist/interface/types/design-mapping.js.map +1 -0
  200. package/dist/interface/types/design-verification.d.ts +49 -0
  201. package/dist/interface/types/design-verification.d.ts.map +1 -0
  202. package/dist/interface/types/design-verification.js +4 -0
  203. package/dist/interface/types/design-verification.js.map +1 -0
  204. package/dist/interface/types/history-risk.d.ts +90 -0
  205. package/dist/interface/types/history-risk.d.ts.map +1 -0
  206. package/dist/interface/types/history-risk.js +4 -0
  207. package/dist/interface/types/history-risk.js.map +1 -0
  208. package/dist/interface/types/index.d.ts +20 -1
  209. package/dist/interface/types/index.d.ts.map +1 -1
  210. package/dist/interface/types/storage.d.ts +28 -1
  211. package/dist/interface/types/storage.d.ts.map +1 -1
  212. package/dist/orchestrator/adapters/ast-grep-adapter.d.ts +10 -0
  213. package/dist/orchestrator/adapters/ast-grep-adapter.d.ts.map +1 -1
  214. package/dist/orchestrator/adapters/ast-grep-adapter.js +46 -17
  215. package/dist/orchestrator/adapters/ast-grep-adapter.js.map +1 -1
  216. package/dist/orchestrator/adapters/codemap-adapter.d.ts.map +1 -1
  217. package/dist/orchestrator/adapters/codemap-adapter.js +2 -22
  218. package/dist/orchestrator/adapters/codemap-adapter.js.map +1 -1
  219. package/dist/orchestrator/ai-feed-generator.d.ts +210 -0
  220. package/dist/orchestrator/ai-feed-generator.d.ts.map +1 -0
  221. package/dist/orchestrator/ai-feed-generator.js +377 -0
  222. package/dist/orchestrator/ai-feed-generator.js.map +1 -0
  223. package/dist/orchestrator/history-risk-service.d.ts +55 -0
  224. package/dist/orchestrator/history-risk-service.d.ts.map +1 -0
  225. package/dist/orchestrator/history-risk-service.js +680 -0
  226. package/dist/orchestrator/history-risk-service.js.map +1 -0
  227. package/dist/orchestrator/types.d.ts +19 -1
  228. package/dist/orchestrator/types.d.ts.map +1 -1
  229. package/dist/orchestrator/types.js +19 -0
  230. package/dist/orchestrator/types.js.map +1 -1
  231. package/dist/server/mcp/index.d.ts +4 -0
  232. package/dist/server/mcp/index.d.ts.map +1 -0
  233. package/dist/server/mcp/index.js +5 -0
  234. package/dist/server/mcp/index.js.map +1 -0
  235. package/dist/server/mcp/server.d.ts +17 -0
  236. package/dist/server/mcp/server.d.ts.map +1 -0
  237. package/dist/server/mcp/server.js +84 -0
  238. package/dist/server/mcp/server.js.map +1 -0
  239. package/dist/server/mcp/service.d.ts +22 -0
  240. package/dist/server/mcp/service.d.ts.map +1 -0
  241. package/dist/server/mcp/service.js +177 -0
  242. package/dist/server/mcp/service.js.map +1 -0
  243. package/dist/server/mcp/types.d.ts +56 -0
  244. package/dist/server/mcp/types.d.ts.map +1 -0
  245. package/dist/server/mcp/types.js +4 -0
  246. package/dist/server/mcp/types.js.map +1 -0
  247. package/docs/AI_ASSISTANT_SETUP.md +1 -1
  248. package/docs/SETUP_GUIDE.md +6 -6
  249. package/docs/ai-guide/COMMANDS.md +171 -4
  250. package/docs/ai-guide/INTEGRATION.md +137 -433
  251. package/docs/ai-guide/OUTPUT.md +890 -5
  252. package/docs/ai-guide/PATTERNS.md +54 -14
  253. package/docs/ai-guide/PROMPTS.md +17 -6
  254. package/docs/archive/test-report-symbol-search.md +384 -0
  255. package/docs/archive/test-scenario-4-complexity-analysis.md +460 -0
  256. package/docs/archive/test_report_scenario5.md +615 -0
  257. package/docs/archive/test_scenario_3_impact_analysis_report.md +520 -0
  258. package/docs/backlog.md +177 -0
  259. package/docs/eatdogfood-reports/2026-04-17-eatdogfood-agent-experience.md +231 -0
  260. package/docs/exec-plans/completed/2026-04-17-eatdogfood-codemap-cli.md +103 -0
  261. package/docs/ideation/2026-04-15-executable-architecture-constitution-ideation.md +102 -0
  262. package/docs/product-specs/DESIGN_CONTRACT_TEMPLATE.md +126 -0
  263. package/docs/product-specs/MVP3-ARCHITECTURE-COMPARISON.md +11 -10
  264. package/docs/product-specs/MVP3-ARCHITECTURE-REDESIGN-PRD.md +10 -10
  265. package/docs/product-specs/MVP3-ARCHITECTURE-REDESIGN-TECH-PRD.md +17 -12
  266. package/docs/product-specs/README.md +2 -1
  267. package/docs/rules/README.md +16 -11
  268. package/docs/rules/architecture-guardrails.md +24 -336
  269. package/docs/rules/code-quality-redlines.md +25 -311
  270. package/docs/rules/engineering-with-codex-openai.md +20 -3
  271. package/docs/rules/validation.md +90 -37
  272. package/mycodemap.config.schema.json +3 -3
  273. package/package.json +7 -2
  274. package/scripts/benchmark-governance-graph.mjs +132 -0
  275. package/scripts/calibrate-contract-gate.mjs +221 -0
  276. package/scripts/capability-report.py +255 -0
  277. package/scripts/experiments/arcadedb-http-smoke.mjs +90 -0
  278. package/scripts/qa-rule-control.sh +254 -0
  279. package/scripts/report-high-risk-files.mjs +395 -0
  280. package/scripts/rule-context.mjs +155 -0
  281. package/scripts/smoke-sqlite-impact.mjs +85 -0
  282. package/scripts/sync-analyze-docs.js +1 -0
  283. package/scripts/tests/test_capability_report.py +89 -0
  284. package/scripts/tests/test_rule_control_workflow.py +51 -0
  285. package/scripts/tests/test_validate_rules.py +81 -0
  286. package/scripts/validate-ai-docs.js +283 -1
  287. package/scripts/validate-docs.js +479 -25
  288. package/scripts/validate-rules.py +254 -0
@@ -0,0 +1,132 @@
1
+ import { mkdtempSync, rmSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import path from 'node:path';
4
+ import { fileURLToPath, pathToFileURL } from 'node:url';
5
+
6
+ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
7
+ const loadModule = async (relativePath) => import(pathToFileURL(path.join(repoRoot, relativePath)).href);
8
+ const { SQLiteStorage } = await loadModule('dist/infrastructure/storage/adapters/SQLiteStorage.js');
9
+ const {
10
+ CONTRACT_GATE_MAX_CHANGED_FILES_FOR_HARD_GATE,
11
+ CONTRACT_GATE_MAX_FALSE_POSITIVE_RATE,
12
+ CONTRACT_GATE_PERF_BUDGET,
13
+ } = await loadModule('dist/cli/contract-gate-thresholds.js');
14
+
15
+ function parseArgs(argv) {
16
+ const args = {
17
+ maxFiles: CONTRACT_GATE_PERF_BUDGET.maxFiles,
18
+ maxLoadMs: CONTRACT_GATE_PERF_BUDGET.maxLoadMs,
19
+ maxRssMb: CONTRACT_GATE_PERF_BUDGET.maxRssMb,
20
+ };
21
+
22
+ for (let index = 0; index < argv.length; index += 1) {
23
+ const current = argv[index];
24
+ const next = argv[index + 1];
25
+
26
+ if (current === '--max-files' && next) {
27
+ args.maxFiles = Number(next);
28
+ }
29
+ if (current === '--max-load-ms' && next) {
30
+ args.maxLoadMs = Number(next);
31
+ }
32
+ if (current === '--max-rss-mb' && next) {
33
+ args.maxRssMb = Number(next);
34
+ }
35
+ }
36
+
37
+ return args;
38
+ }
39
+
40
+ function createLinearGraph(moduleCount) {
41
+ const modules = Array.from({ length: moduleCount }, (_, index) => ({
42
+ id: `mod-${index + 1}`,
43
+ projectId: 'proj-benchmark',
44
+ path: `src/mod-${index + 1}.ts`,
45
+ language: 'ts',
46
+ stats: {
47
+ lines: 10,
48
+ codeLines: 8,
49
+ commentLines: 1,
50
+ blankLines: 1,
51
+ },
52
+ }));
53
+ const dependencies = modules.slice(1).map((module, index) => ({
54
+ id: `dep-${index + 1}`,
55
+ sourceId: module.id,
56
+ targetId: modules[index]?.id ?? module.id,
57
+ type: 'import',
58
+ }));
59
+
60
+ return {
61
+ project: {
62
+ id: 'proj-benchmark',
63
+ name: 'governance-benchmark',
64
+ rootPath: '/fixture',
65
+ createdAt: new Date('2026-04-15T00:00:00Z'),
66
+ updatedAt: new Date('2026-04-15T00:00:00Z'),
67
+ },
68
+ modules,
69
+ symbols: [],
70
+ dependencies,
71
+ };
72
+ }
73
+
74
+ async function runCase(moduleCount, thresholds) {
75
+ const rootDir = mkdtempSync(path.join(tmpdir(), 'codemap-governance-benchmark-'));
76
+ const storage = new SQLiteStorage(
77
+ {
78
+ type: 'sqlite',
79
+ databasePath: '.codemap/governance.sqlite',
80
+ },
81
+ {
82
+ governanceGraphThresholds: thresholds,
83
+ }
84
+ );
85
+
86
+ try {
87
+ await storage.initialize(rootDir);
88
+ await storage.saveCodeGraph(createLinearGraph(moduleCount));
89
+ return storage.getGovernanceGraphRuntimeStats();
90
+ } finally {
91
+ await storage.close();
92
+ rmSync(rootDir, { recursive: true, force: true });
93
+ }
94
+ }
95
+
96
+ const thresholds = parseArgs(process.argv.slice(2));
97
+ const benchmarkModuleCount = Math.min(Math.max(32, thresholds.maxFiles - 1), 512);
98
+ const benchmarkStats = await runCase(benchmarkModuleCount, thresholds);
99
+ const fallbackStats = await runCase(thresholds.maxFiles + 1, thresholds);
100
+
101
+ if (benchmarkStats.cacheMode !== 'memory-eager') {
102
+ throw new Error(
103
+ `benchmark graph should stay memory-eager, got ${benchmarkStats.cacheMode} (${benchmarkStats.warning ?? 'no warning'})`
104
+ );
105
+ }
106
+
107
+ if (benchmarkStats.loadMs > thresholds.maxLoadMs) {
108
+ throw new Error(
109
+ `benchmark load time ${benchmarkStats.loadMs.toFixed(2)}ms exceeds maxLoadMs=${thresholds.maxLoadMs}`
110
+ );
111
+ }
112
+
113
+ if (benchmarkStats.rssDeltaMb > thresholds.maxRssMb) {
114
+ throw new Error(
115
+ `benchmark rss delta ${benchmarkStats.rssDeltaMb.toFixed(2)}MB exceeds maxRssMb=${thresholds.maxRssMb}`
116
+ );
117
+ }
118
+
119
+ if (fallbackStats.cacheMode !== 'sqlite-direct') {
120
+ throw new Error(`oversize rehearsal should fall back to sqlite-direct, got ${fallbackStats.cacheMode}`);
121
+ }
122
+
123
+ console.log(JSON.stringify({
124
+ ok: true,
125
+ thresholds,
126
+ contractGate: {
127
+ maxChangedFilesForHardGate: CONTRACT_GATE_MAX_CHANGED_FILES_FOR_HARD_GATE,
128
+ maxFalsePositiveRate: CONTRACT_GATE_MAX_FALSE_POSITIVE_RATE,
129
+ },
130
+ benchmark: benchmarkStats,
131
+ failureRehearsal: fallbackStats,
132
+ }, null, 2));
@@ -0,0 +1,221 @@
1
+ import { readdirSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { performance } from 'node:perf_hooks';
4
+ import { fileURLToPath, pathToFileURL } from 'node:url';
5
+
6
+ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
7
+ const loadModule = async (relativePath) => import(pathToFileURL(path.join(repoRoot, relativePath)).href);
8
+ const { runContractCheck } = await loadModule('dist/cli/contract-checker.js');
9
+ const { resolveContractDiffScope } = await loadModule('dist/cli/contract-diff-scope.js');
10
+ const { renderGitHubAnnotations } = await loadModule('dist/cli/commands/check.js');
11
+ const {
12
+ CONTRACT_GATE_MAX_CHANGED_FILES_FOR_HARD_GATE,
13
+ CONTRACT_GATE_MAX_FALSE_POSITIVE_RATE,
14
+ CONTRACT_GATE_PERF_BUDGET,
15
+ } = await loadModule('dist/cli/contract-gate-thresholds.js');
16
+
17
+ function parseArgs(argv) {
18
+ const args = {
19
+ maxChangedFiles: CONTRACT_GATE_MAX_CHANGED_FILES_FOR_HARD_GATE,
20
+ maxFalsePositiveRate: CONTRACT_GATE_MAX_FALSE_POSITIVE_RATE,
21
+ };
22
+
23
+ for (let index = 0; index < argv.length; index += 1) {
24
+ const current = argv[index];
25
+ const next = argv[index + 1];
26
+ if (current === '--max-changed-files' && next) {
27
+ args.maxChangedFiles = Number(next);
28
+ }
29
+ if (current === '--max-false-positive-rate' && next) {
30
+ args.maxFalsePositiveRate = Number(next);
31
+ }
32
+ }
33
+
34
+ return args;
35
+ }
36
+
37
+ function collectTsFiles(rootDir) {
38
+ const files = [];
39
+ const queue = [rootDir];
40
+
41
+ while (queue.length > 0) {
42
+ const currentDir = queue.shift();
43
+ for (const entry of readdirSync(currentDir, { withFileTypes: true })) {
44
+ const entryPath = path.join(currentDir, entry.name);
45
+ if (entry.isDirectory()) {
46
+ if (entry.name === '__tests__') {
47
+ continue;
48
+ }
49
+ queue.push(entryPath);
50
+ continue;
51
+ }
52
+
53
+ if (/\.[cm]?[jt]sx?$/u.test(entry.name) && !/\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(entry.name)) {
54
+ files.push(entryPath);
55
+ }
56
+ }
57
+ }
58
+
59
+ return files.sort();
60
+ }
61
+
62
+ async function runCalibrationCase(testCase) {
63
+ const startedAt = performance.now();
64
+ const diffScope = await resolveContractDiffScope({
65
+ againstPath: testCase.againstPath,
66
+ rootDir: repoRoot,
67
+ changedFiles: testCase.changedFiles,
68
+ base: testCase.base,
69
+ });
70
+ const result = await runContractCheck({
71
+ contractPath: testCase.contractPath,
72
+ againstPath: testCase.againstPath,
73
+ rootDir: repoRoot,
74
+ scanMode: diffScope.scanMode,
75
+ changedFiles: diffScope.changedFiles,
76
+ warnings: diffScope.warnings,
77
+ });
78
+ const durationMs = performance.now() - startedAt;
79
+
80
+ return {
81
+ name: testCase.name,
82
+ kind: testCase.kind,
83
+ durationMs: Math.round(durationMs * 100) / 100,
84
+ scanMode: diffScope.scanMode,
85
+ changedFiles: diffScope.changedFiles,
86
+ warnings: result.warnings,
87
+ errorCount: result.summary.error_count,
88
+ warningCount: result.summary.warn_count,
89
+ annotationCount: renderGitHubAnnotations(result)
90
+ .split('\n')
91
+ .map((line) => line.trim())
92
+ .filter(Boolean).length,
93
+ };
94
+ }
95
+
96
+ const args = parseArgs(process.argv.slice(2));
97
+ const designFixturesDir = path.join(repoRoot, 'tests', 'fixtures', 'design-contracts');
98
+ const contractFixturesDir = path.join(repoRoot, 'tests', 'fixtures', 'contract-check');
99
+ const repoSourceFiles = collectTsFiles(path.join(repoRoot, 'src')).slice(0, args.maxChangedFiles + 1);
100
+
101
+ if (repoSourceFiles.length < args.maxChangedFiles + 1) {
102
+ throw new Error(`无法收集足够的 repo source files 来验证 hard-gate window,至少需要 ${args.maxChangedFiles + 1} 个文件`);
103
+ }
104
+
105
+ const calibrationCases = [
106
+ {
107
+ name: 'good-valid-core-service',
108
+ kind: 'good',
109
+ contractPath: path.join(designFixturesDir, 'valid-frontmatter.design.md'),
110
+ againstPath: path.join(contractFixturesDir, 'valid-project'),
111
+ changedFiles: [path.join(contractFixturesDir, 'valid-project', 'src', 'core', 'service.ts')],
112
+ },
113
+ {
114
+ name: 'good-valid-reader',
115
+ kind: 'good',
116
+ contractPath: path.join(designFixturesDir, 'valid-frontmatter.design.md'),
117
+ againstPath: path.join(contractFixturesDir, 'valid-project'),
118
+ changedFiles: [path.join(contractFixturesDir, 'valid-project', 'src', 'infrastructure', 'parser', 'reader.ts')],
119
+ },
120
+ {
121
+ name: 'good-valid-domain-public-api',
122
+ kind: 'good',
123
+ contractPath: path.join(designFixturesDir, 'valid-frontmatter.design.md'),
124
+ againstPath: path.join(contractFixturesDir, 'valid-project'),
125
+ changedFiles: [path.join(contractFixturesDir, 'valid-project', 'src', 'app', 'use-domain.ts')],
126
+ },
127
+ {
128
+ name: 'bad-invalid-core-layer',
129
+ kind: 'bad',
130
+ contractPath: path.join(designFixturesDir, 'valid-frontmatter.design.md'),
131
+ againstPath: path.join(contractFixturesDir, 'invalid-project'),
132
+ changedFiles: [path.join(contractFixturesDir, 'invalid-project', 'src', 'core', 'bad.ts')],
133
+ },
134
+ {
135
+ name: 'bad-barrel-downstream',
136
+ kind: 'bad',
137
+ contractPath: path.join(designFixturesDir, 'contract-barrel.design.md'),
138
+ againstPath: path.join(contractFixturesDir, 'barrel-project'),
139
+ changedFiles: [path.join(contractFixturesDir, 'barrel-project', 'src', 'domain', 'index.ts')],
140
+ },
141
+ ];
142
+
143
+ const caseResults = [];
144
+ for (const testCase of calibrationCases) {
145
+ caseResults.push(await runCalibrationCase(testCase));
146
+ }
147
+
148
+ const windowScope = await resolveContractDiffScope({
149
+ againstPath: path.join(repoRoot, 'src'),
150
+ rootDir: repoRoot,
151
+ changedFiles: repoSourceFiles,
152
+ });
153
+ const fallbackScope = await resolveContractDiffScope({
154
+ againstPath: path.join(contractFixturesDir, 'invalid-project'),
155
+ rootDir: repoRoot,
156
+ base: 'not-a-real-base-ref',
157
+ });
158
+
159
+ const goodCases = caseResults.filter((entry) => entry.kind === 'good');
160
+ const badCases = caseResults.filter((entry) => entry.kind === 'bad');
161
+ const falsePositives = goodCases.filter((entry) => entry.errorCount > 0);
162
+ const falseNegatives = badCases.filter((entry) => entry.errorCount === 0);
163
+ const missingAnnotations = badCases.filter((entry) => entry.annotationCount === 0);
164
+ const falsePositiveRate = goodCases.length === 0 ? 0 : falsePositives.length / goodCases.length;
165
+ const maxObservedDurationMs = caseResults.reduce((max, entry) => Math.max(max, entry.durationMs), 0);
166
+
167
+ const failures = [];
168
+ if (falsePositiveRate > args.maxFalsePositiveRate) {
169
+ failures.push(`false-positive rate ${falsePositiveRate.toFixed(2)} exceeds max ${args.maxFalsePositiveRate.toFixed(2)}`);
170
+ }
171
+ if (falseNegatives.length > 0) {
172
+ failures.push(`false negatives detected: ${falseNegatives.map((entry) => entry.name).join(', ')}`);
173
+ }
174
+ if (missingAnnotations.length > 0) {
175
+ failures.push(`annotation output missing for bad cases: ${missingAnnotations.map((entry) => entry.name).join(', ')}`);
176
+ }
177
+ if (maxObservedDurationMs > CONTRACT_GATE_PERF_BUDGET.maxLoadMs) {
178
+ failures.push(`max case duration ${maxObservedDurationMs.toFixed(2)}ms exceeds perf budget ${CONTRACT_GATE_PERF_BUDGET.maxLoadMs}ms`);
179
+ }
180
+ if (!windowScope.warnings.some((warning) => warning.code === 'hard-gate-window-exceeded')) {
181
+ failures.push('hard-gate window overrun did not emit hard-gate-window-exceeded warning');
182
+ }
183
+ if (!fallbackScope.warnings.some((warning) => warning.code === 'diff-scope-fallback')) {
184
+ failures.push('invalid diff base did not emit diff-scope-fallback warning');
185
+ }
186
+
187
+ const recommendation = failures.length === 0
188
+ ? 'hard-gate-ok'
189
+ : failures.some((failure) => failure.includes('false-positive rate') || failure.includes('false negatives') || failure.includes('annotation output'))
190
+ ? 'warn-only'
191
+ : 're-scope';
192
+
193
+ const output = {
194
+ ok: failures.length === 0,
195
+ thresholds: {
196
+ maxChangedFiles: args.maxChangedFiles,
197
+ maxFalsePositiveRate: args.maxFalsePositiveRate,
198
+ perfBudget: CONTRACT_GATE_PERF_BUDGET,
199
+ },
200
+ summary: {
201
+ goodCaseCount: goodCases.length,
202
+ badCaseCount: badCases.length,
203
+ falsePositiveCount: falsePositives.length,
204
+ falseNegativeCount: falseNegatives.length,
205
+ falsePositiveRate: Math.round(falsePositiveRate * 1000) / 1000,
206
+ maxObservedDurationMs,
207
+ recommendation,
208
+ },
209
+ warnings: {
210
+ windowScope: windowScope.warnings,
211
+ fallbackScope: fallbackScope.warnings,
212
+ },
213
+ cases: caseResults,
214
+ failures,
215
+ };
216
+
217
+ console.log(JSON.stringify(output, null, 2));
218
+
219
+ if (failures.length > 0) {
220
+ process.exitCode = 1;
221
+ }
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env python3
2
+ """Generate a repo-local capability baseline report without gating workflows."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import subprocess
9
+ import sys
10
+ import time
11
+ from datetime import datetime, timezone
12
+ from pathlib import Path
13
+ from typing import Any, Callable, Sequence
14
+
15
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent
16
+
17
+ CommandRunner = Callable[[Sequence[str], Path, int], dict[str, Any]]
18
+
19
+
20
+ def iso_utc_now() -> str:
21
+ return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
22
+
23
+
24
+ def trim_output(value: str | bytes | None, limit: int = 400) -> str:
25
+ if value is None:
26
+ return ""
27
+ if isinstance(value, bytes):
28
+ value = value.decode("utf-8", errors="replace")
29
+ text = value.strip()
30
+ return text[:limit]
31
+
32
+
33
+ def run_command(command: Sequence[str], cwd: Path, timeout: int) -> dict[str, Any]:
34
+ started = time.perf_counter()
35
+ try:
36
+ completed = subprocess.run(
37
+ command,
38
+ cwd=cwd,
39
+ check=False,
40
+ capture_output=True,
41
+ text=True,
42
+ timeout=timeout,
43
+ )
44
+ duration_ms = round((time.perf_counter() - started) * 1000)
45
+ return {
46
+ "available": True,
47
+ "returncode": completed.returncode,
48
+ "stdout": trim_output(completed.stdout),
49
+ "stderr": trim_output(completed.stderr),
50
+ "duration_ms": duration_ms,
51
+ }
52
+ except FileNotFoundError as error:
53
+ duration_ms = round((time.perf_counter() - started) * 1000)
54
+ return {
55
+ "available": False,
56
+ "returncode": None,
57
+ "stdout": "",
58
+ "stderr": str(error),
59
+ "duration_ms": duration_ms,
60
+ }
61
+ except subprocess.TimeoutExpired as error:
62
+ duration_ms = round((time.perf_counter() - started) * 1000)
63
+ return {
64
+ "available": True,
65
+ "returncode": None,
66
+ "stdout": trim_output(error.stdout),
67
+ "stderr": trim_output(error.stderr) or f"timeout after {timeout}s",
68
+ "duration_ms": duration_ms,
69
+ }
70
+
71
+
72
+ def classify_status(kind: str, available: bool, returncode: int | None) -> str:
73
+ if kind == "required":
74
+ return "PASS" if available and returncode == 0 else "REQUIRED_FAIL"
75
+ if kind == "optional":
76
+ return "PASS" if available and returncode == 0 else "OPTIONAL_DISABLED"
77
+ if kind == "strategy":
78
+ return "STRATEGY_PASS" if available and returncode == 0 else "STRATEGY_FAIL"
79
+ raise ValueError(f"unsupported capability kind: {kind}")
80
+
81
+
82
+ def build_item(
83
+ name: str,
84
+ kind: str,
85
+ command: Sequence[str],
86
+ *,
87
+ cwd: Path,
88
+ timeout: int,
89
+ runner: CommandRunner = run_command,
90
+ notes: list[str] | None = None,
91
+ ) -> dict[str, Any]:
92
+ outcome = runner(command, cwd, timeout)
93
+ item: dict[str, Any] = {
94
+ "name": name,
95
+ "kind": kind,
96
+ "command": " ".join(command),
97
+ "status": classify_status(kind, outcome["available"], outcome["returncode"]),
98
+ "duration_ms": outcome["duration_ms"],
99
+ "returncode": outcome["returncode"],
100
+ "stdout": outcome["stdout"],
101
+ "stderr": outcome["stderr"],
102
+ }
103
+ if notes:
104
+ item["notes"] = notes
105
+ return item
106
+
107
+
108
+ def build_git_hooks_item(project_root: Path, runner: CommandRunner = run_command) -> dict[str, Any]:
109
+ item = build_item(
110
+ "git_hooks",
111
+ "required",
112
+ ["git", "config", "core.hooksPath"],
113
+ cwd=project_root,
114
+ timeout=10,
115
+ runner=runner,
116
+ )
117
+ configured_path = item["stdout"].strip()
118
+ if item["returncode"] == 0 and configured_path:
119
+ item["notes"] = [f"core.hooksPath={configured_path}"]
120
+ return item
121
+
122
+ fallback_dir = project_root / ".githooks"
123
+ if fallback_dir.is_dir():
124
+ item["status"] = "PASS"
125
+ item["notes"] = ["core.hooksPath unset; fallback .githooks directory exists"]
126
+ return item
127
+
128
+ item["status"] = "REQUIRED_FAIL"
129
+ item["notes"] = ["core.hooksPath unset and .githooks directory missing"]
130
+ return item
131
+
132
+
133
+ def build_optional_validator_item(project_root: Path, runner: CommandRunner = run_command) -> dict[str, Any]:
134
+ validator_path = project_root / "scripts" / "validate-rules.py"
135
+ if not validator_path.is_file():
136
+ return {
137
+ "name": "validate_rules",
138
+ "kind": "optional",
139
+ "command": "python3 scripts/validate-rules.py code --report-only",
140
+ "status": "OPTIONAL_DISABLED",
141
+ "duration_ms": None,
142
+ "returncode": None,
143
+ "stdout": "",
144
+ "stderr": "",
145
+ "notes": ["scripts/validate-rules.py is unavailable"],
146
+ }
147
+
148
+ item = build_item(
149
+ "validate_rules",
150
+ "optional",
151
+ ["python3", "scripts/validate-rules.py", "code", "--report-only"],
152
+ cwd=project_root,
153
+ timeout=180,
154
+ runner=runner,
155
+ )
156
+ if item["status"] == "OPTIONAL_DISABLED" and not item.get("notes"):
157
+ item["notes"] = ["validator exists but report-only command is unavailable"]
158
+ return item
159
+
160
+
161
+ def summarize(items: list[dict[str, Any]]) -> dict[str, dict[str, int]]:
162
+ summary = {
163
+ "required": {"passed": 0, "failed": 0, "total": 0},
164
+ "optional": {"passed": 0, "disabled": 0, "total": 0},
165
+ "strategy": {"passed": 0, "failed": 0, "total": 0},
166
+ }
167
+
168
+ for item in items:
169
+ kind = item["kind"]
170
+ status = item["status"]
171
+ summary[kind]["total"] += 1
172
+ if kind == "required":
173
+ summary[kind]["passed" if status == "PASS" else "failed"] += 1
174
+ elif kind == "optional":
175
+ summary[kind]["passed" if status == "PASS" else "disabled"] += 1
176
+ else:
177
+ summary[kind]["passed" if status == "STRATEGY_PASS" else "failed"] += 1
178
+ return summary
179
+
180
+
181
+ def build_report(project_root: Path = PROJECT_ROOT, runner: CommandRunner = run_command) -> dict[str, Any]:
182
+ items = [
183
+ build_item("python3", "required", ["python3", "--version"], cwd=project_root, timeout=10, runner=runner),
184
+ build_item("node", "required", ["node", "--version"], cwd=project_root, timeout=10, runner=runner),
185
+ build_git_hooks_item(project_root, runner=runner),
186
+ build_item(
187
+ "typecheck",
188
+ "strategy",
189
+ ["npm", "run", "typecheck"],
190
+ cwd=project_root,
191
+ timeout=300,
192
+ runner=runner,
193
+ ),
194
+ build_item(
195
+ "tests",
196
+ "strategy",
197
+ ["npm", "test"],
198
+ cwd=project_root,
199
+ timeout=300,
200
+ runner=runner,
201
+ ),
202
+ build_item(
203
+ "lint",
204
+ "strategy",
205
+ ["npm", "run", "lint"],
206
+ cwd=project_root,
207
+ timeout=300,
208
+ runner=runner,
209
+ ),
210
+ build_item(
211
+ "codemap_cli",
212
+ "optional",
213
+ ["node", "dist/cli/index.js", "--version"],
214
+ cwd=project_root,
215
+ timeout=30,
216
+ runner=runner,
217
+ ),
218
+ build_optional_validator_item(project_root, runner=runner),
219
+ ]
220
+
221
+ return {
222
+ "version": 1,
223
+ "generated_at": iso_utc_now(),
224
+ "summary": summarize(items),
225
+ "items": items,
226
+ }
227
+
228
+
229
+ def write_report(report: dict[str, Any], output_path: Path) -> None:
230
+ output_path.parent.mkdir(parents=True, exist_ok=True)
231
+ output_path.write_text(json.dumps(report, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
232
+
233
+
234
+ def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
235
+ parser = argparse.ArgumentParser(description="Generate a capability baseline report for repo-local rule control.")
236
+ parser.add_argument("--output", type=Path, help="Optional path to write the JSON report.")
237
+ return parser.parse_args(argv)
238
+
239
+
240
+ def main(
241
+ argv: Sequence[str] | None = None,
242
+ *,
243
+ report_builder: Callable[[], dict[str, Any]] | None = None,
244
+ ) -> int:
245
+ args = parse_args(argv)
246
+ report = (report_builder or build_report)()
247
+ if args.output is not None:
248
+ write_report(report, args.output)
249
+ json.dump(report, sys.stdout, indent=2, ensure_ascii=False)
250
+ sys.stdout.write("\n")
251
+ return 0
252
+
253
+
254
+ if __name__ == "__main__":
255
+ raise SystemExit(main())
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+
3
+ const HELP_TEXT = `
4
+ ArcadeDB HTTP smoke test
5
+
6
+ Required environment variables:
7
+ ARCADEDB_HTTP_URL Base URL, for example http://localhost:2480
8
+ ARCADEDB_DATABASE Database name used in /api/v1/command/{database}
9
+ ARCADEDB_USERNAME Basic auth username
10
+ ARCADEDB_PASSWORD Basic auth password
11
+
12
+ Optional:
13
+ ARCADEDB_CYPHER Cypher query to run
14
+
15
+ Request:
16
+ POST {ARCADEDB_HTTP_URL}/api/v1/command/{database}
17
+ Body: {"language":"cypher","command":"MATCH (n) RETURN count(n) AS total LIMIT 1"}
18
+ Auth: Authorization: Basic ...
19
+
20
+ This script is intentionally isolated from shipped runtime code.
21
+ Use --help for offline validation when no ArcadeDB server is available.
22
+ `.trim();
23
+
24
+ function printHelp() {
25
+ console.log(HELP_TEXT);
26
+ }
27
+
28
+ function getRequiredEnv(name) {
29
+ const value = process.env[name];
30
+ if (!value || value.trim().length === 0) {
31
+ throw new Error(`Missing required environment variable: ${name}`);
32
+ }
33
+ return value.trim();
34
+ }
35
+
36
+ async function main() {
37
+ if (process.argv.includes("--help")) {
38
+ printHelp();
39
+ return;
40
+ }
41
+
42
+ let baseUrl;
43
+ let database;
44
+ let username;
45
+ let password;
46
+
47
+ try {
48
+ baseUrl = getRequiredEnv("ARCADEDB_HTTP_URL").replace(/\/+$/, "");
49
+ database = getRequiredEnv("ARCADEDB_DATABASE");
50
+ username = getRequiredEnv("ARCADEDB_USERNAME");
51
+ password = getRequiredEnv("ARCADEDB_PASSWORD");
52
+ } catch (error) {
53
+ console.error(String(error instanceof Error ? error.message : error));
54
+ console.error("Run with --help to see the required contract.");
55
+ process.exitCode = 1;
56
+ return;
57
+ }
58
+
59
+ const command = (process.env.ARCADEDB_CYPHER || "MATCH (n) RETURN count(n) AS total LIMIT 1").trim();
60
+ const endpoint = `${baseUrl}/api/v1/command/${database}`;
61
+ const authHeader = Buffer.from(`${username}:${password}`, "utf8").toString("base64");
62
+
63
+ const response = await fetch(endpoint, {
64
+ method: "POST",
65
+ headers: {
66
+ "content-type": "application/json",
67
+ authorization: `Basic ${authHeader}`,
68
+ },
69
+ body: JSON.stringify({
70
+ language: "cypher",
71
+ command,
72
+ }),
73
+ });
74
+
75
+ const text = await response.text();
76
+
77
+ if (!response.ok) {
78
+ console.error(`ArcadeDB HTTP smoke failed: ${response.status} ${response.statusText}`);
79
+ console.error(text);
80
+ process.exitCode = 1;
81
+ return;
82
+ }
83
+
84
+ console.log("ArcadeDB HTTP smoke succeeded");
85
+ if (text.trim().length > 0) {
86
+ console.log(text);
87
+ }
88
+ }
89
+
90
+ await main();