@danielblomma/cortex-mcp 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +62 -14
  2. package/package.json +2 -2
  3. package/scaffold/mcp/package-lock.json +3 -7
  4. package/scaffold/mcp/package.json +1 -1
  5. package/scaffold/scripts/dashboard.mjs +15 -1
  6. package/scaffold/scripts/doctor.sh +64 -10
  7. package/scaffold/scripts/ingest.mjs +323 -50
  8. package/scaffold/scripts/parsers/bash-treesitter.mjs +229 -0
  9. package/scaffold/scripts/parsers/cpp-dispatch.mjs +56 -0
  10. package/scaffold/scripts/parsers/cpp-treesitter.mjs +333 -0
  11. package/scaffold/scripts/parsers/csharp.mjs +197 -10
  12. package/scaffold/scripts/parsers/dotnet/CSharpParser/CSharpParser.csproj +1 -0
  13. package/scaffold/scripts/parsers/dotnet/CSharpParser/Program.cs +126 -21
  14. package/scaffold/scripts/parsers/go-treesitter.mjs +283 -0
  15. package/scaffold/scripts/parsers/java-treesitter.mjs +250 -0
  16. package/scaffold/scripts/parsers/javascript/ast.mjs +118 -12
  17. package/scaffold/scripts/parsers/javascript/chunks.mjs +4 -0
  18. package/scaffold/scripts/parsers/javascript/patterns.mjs +6 -0
  19. package/scaffold/scripts/parsers/javascript.mjs +4 -19
  20. package/scaffold/scripts/parsers/node_modules/.package-lock.json +57 -0
  21. package/scaffold/scripts/parsers/node_modules/acorn/CHANGELOG.md +972 -0
  22. package/scaffold/scripts/parsers/node_modules/acorn/LICENSE +21 -0
  23. package/scaffold/scripts/parsers/node_modules/acorn/README.md +301 -0
  24. package/scaffold/scripts/parsers/node_modules/acorn/bin/acorn +4 -0
  25. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.d.mts +883 -0
  26. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.d.ts +883 -0
  27. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.js +6295 -0
  28. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.mjs +6266 -0
  29. package/scaffold/scripts/parsers/node_modules/acorn/dist/bin.js +90 -0
  30. package/scaffold/scripts/parsers/node_modules/acorn/package.json +50 -0
  31. package/scaffold/scripts/parsers/node_modules/acorn-typescript/CHANGELOG.md +421 -0
  32. package/scaffold/scripts/parsers/node_modules/acorn-typescript/LICENSE +21 -0
  33. package/scaffold/scripts/parsers/node_modules/acorn-typescript/README.md +81 -0
  34. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.d.ts +103 -0
  35. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.js +78 -0
  36. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.js.map +1 -0
  37. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.d.ts +167 -0
  38. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.js +75 -0
  39. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.js.map +1 -0
  40. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.d.ts +177 -0
  41. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.js +56 -0
  42. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.js.map +1 -0
  43. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.d.ts +198 -0
  44. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.js +327 -0
  45. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.js.map +1 -0
  46. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.d.ts +256 -0
  47. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.js +256 -0
  48. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.js.map +1 -0
  49. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.d.ts +472 -0
  50. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.js +1 -0
  51. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.js.map +1 -0
  52. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.mjs +1 -0
  53. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.d.ts +159 -0
  54. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.js +2 -0
  55. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.js.map +1 -0
  56. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.d.ts +10 -0
  57. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.js +38 -0
  58. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.js.map +1 -0
  59. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.d.ts +12 -0
  60. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.js +29 -0
  61. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.js.map +1 -0
  62. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.d.ts +2 -0
  63. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.js +118 -0
  64. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.js.map +1 -0
  65. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.d.ts +60 -0
  66. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.js +2 -0
  67. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.js.map +1 -0
  68. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.d.ts +2 -0
  69. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.js +19 -0
  70. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.js.map +1 -0
  71. package/scaffold/scripts/parsers/node_modules/acorn-typescript/package.json +53 -0
  72. package/scaffold/scripts/parsers/node_modules/acorn-typescript/tsconfig.json +19 -0
  73. package/scaffold/scripts/parsers/node_modules/acorn-walk/CHANGELOG.md +209 -0
  74. package/scaffold/scripts/parsers/node_modules/acorn-walk/LICENSE +21 -0
  75. package/scaffold/scripts/parsers/node_modules/acorn-walk/README.md +124 -0
  76. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.d.mts +152 -0
  77. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.d.ts +152 -0
  78. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.js +485 -0
  79. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.mjs +467 -0
  80. package/scaffold/scripts/parsers/node_modules/acorn-walk/package.json +50 -0
  81. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/LICENSE +24 -0
  82. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/README.md +23 -0
  83. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-bash.wasm +0 -0
  84. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-c.wasm +0 -0
  85. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-c_sharp.wasm +0 -0
  86. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-cpp.wasm +0 -0
  87. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-css.wasm +0 -0
  88. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-dart.wasm +0 -0
  89. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elisp.wasm +0 -0
  90. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elixir.wasm +0 -0
  91. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elm.wasm +0 -0
  92. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-embedded_template.wasm +0 -0
  93. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-go.wasm +0 -0
  94. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-html.wasm +0 -0
  95. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-java.wasm +0 -0
  96. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-javascript.wasm +0 -0
  97. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-json.wasm +0 -0
  98. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-kotlin.wasm +0 -0
  99. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-lua.wasm +0 -0
  100. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-objc.wasm +0 -0
  101. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ocaml.wasm +0 -0
  102. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-php.wasm +0 -0
  103. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-python.wasm +0 -0
  104. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ql.wasm +0 -0
  105. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-rescript.wasm +0 -0
  106. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ruby.wasm +0 -0
  107. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-rust.wasm +0 -0
  108. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-scala.wasm +0 -0
  109. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-solidity.wasm +0 -0
  110. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-swift.wasm +0 -0
  111. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-systemrdl.wasm +0 -0
  112. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-tlaplus.wasm +0 -0
  113. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-toml.wasm +0 -0
  114. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-tsx.wasm +0 -0
  115. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-typescript.wasm +0 -0
  116. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-vue.wasm +0 -0
  117. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-yaml.wasm +0 -0
  118. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-zig.wasm +0 -0
  119. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/package.json +64 -0
  120. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/LICENSE +21 -0
  121. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/README.md +198 -0
  122. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/package.json +37 -0
  123. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter-web.d.ts +242 -0
  124. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter.js +1 -0
  125. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
  126. package/scaffold/scripts/parsers/package-lock.json +19 -1
  127. package/scaffold/scripts/parsers/package.json +3 -1
  128. package/scaffold/scripts/parsers/python-treesitter.mjs +271 -0
  129. package/scaffold/scripts/parsers/ruby-treesitter.mjs +271 -0
  130. package/scaffold/scripts/parsers/rust-dispatch.mjs +43 -0
  131. package/scaffold/scripts/parsers/rust-treesitter.mjs +291 -0
  132. package/scaffold/scripts/parsers/tree-sitter/base.mjs +163 -0
  133. package/scaffold/scripts/parsers/tree-sitter/queries/bash.calls.scm +7 -0
  134. package/scaffold/scripts/parsers/tree-sitter/queries/bash.chunks.scm +6 -0
  135. package/scaffold/scripts/parsers/tree-sitter/queries/bash.imports.scm +5 -0
  136. package/scaffold/scripts/parsers/tree-sitter/queries/cpp.calls.scm +17 -0
  137. package/scaffold/scripts/parsers/tree-sitter/queries/cpp.chunks.scm +30 -0
  138. package/scaffold/scripts/parsers/tree-sitter/queries/cpp.imports.scm +6 -0
  139. package/scaffold/scripts/parsers/tree-sitter/queries/go.calls.scm +11 -0
  140. package/scaffold/scripts/parsers/tree-sitter/queries/go.chunks.scm +19 -0
  141. package/scaffold/scripts/parsers/tree-sitter/queries/go.imports.scm +6 -0
  142. package/scaffold/scripts/parsers/tree-sitter/queries/java.calls.scm +6 -0
  143. package/scaffold/scripts/parsers/tree-sitter/queries/java.chunks.scm +23 -0
  144. package/scaffold/scripts/parsers/tree-sitter/queries/java.imports.scm +6 -0
  145. package/scaffold/scripts/parsers/tree-sitter/queries/python.calls.scm +11 -0
  146. package/scaffold/scripts/parsers/tree-sitter/queries/python.chunks.scm +11 -0
  147. package/scaffold/scripts/parsers/tree-sitter/queries/python.imports.scm +13 -0
  148. package/scaffold/scripts/parsers/tree-sitter/queries/ruby.calls.scm +6 -0
  149. package/scaffold/scripts/parsers/tree-sitter/queries/ruby.chunks.scm +16 -0
  150. package/scaffold/scripts/parsers/tree-sitter/queries/ruby.imports.scm +8 -0
  151. package/scaffold/scripts/parsers/tree-sitter/queries/rust.calls.scm +31 -0
  152. package/scaffold/scripts/parsers/tree-sitter/queries/rust.chunks.scm +29 -0
  153. package/scaffold/scripts/parsers/tree-sitter/queries/rust.imports.scm +5 -0
  154. package/scaffold/scripts/parsers/vb6.mjs +395 -0
package/README.md CHANGED
@@ -2,30 +2,78 @@
2
2
  <img src="docs/logo.png" alt="Cortex" width="600" />
3
3
  </p>
4
4
 
5
- # Cortex MCP
5
+ # Cortex
6
+
7
+ **The context layer for AI-assisted software engineering.**
6
8
 
7
9
  [![npm version](https://img.shields.io/npm/v/%40danielblomma%2Fcortex-mcp)](https://www.npmjs.com/package/@danielblomma/cortex-mcp)
8
10
  [![npm downloads](https://img.shields.io/npm/dw/%40danielblomma%2Fcortex-mcp)](https://www.npmjs.com/package/@danielblomma/cortex-mcp)
11
+ [![license](https://img.shields.io/npm/l/%40danielblomma%2Fcortex-mcp)](./LICENSE)
9
12
 
10
- `@danielblomma/cortex-mcp` is a local, repo-scoped context platform for coding assistants.
11
- It indexes your codebase into structured entities (files, rules, ADRs) and exposes that context over MCP (JSON-RPC over stdio).
13
+ ---
12
14
 
13
- ![Cortex install and bootstrap demo](https://raw.githubusercontent.com/DanielBlomma/cortex/main/docs/install-demo.gif)
15
+ ## What Cortex is
14
16
 
15
- ## Why Use Cortex
17
+ Cortex is a local, repository-scoped context engine for coding assistants. It parses your source code with tree-sitter, indexes it into a structured knowledge graph of entities (files, symbols, rules, ADRs) and their relationships (calls, defines, constrains, implements, supersedes), and serves that context to AI assistants over the Model Context Protocol (MCP).
16
18
 
17
- - Semantic search across code and documentation.
18
- - Graph relationships between entities and architectural constraints.
19
- - Local-first: your code and context stay on your machine.
20
- - Incremental updates keep context fresh as the repo changes.
21
- - Works with Claude Code/Desktop and Codex MCP clients.
19
+ Where a general-purpose AI assistant sees your codebase as a pile of text files, Cortex gives it a precise map: what exists, how it is connected, which rules govern it, and which parts are source-of-truth versus deprecated.
20
+
21
+ Cortex runs entirely on the developer's machine. Source code never leaves the host.
22
+
23
+ ## When to use Cortex
24
+
25
+ Cortex is designed for engineering teams that rely on AI assistants for non-trivial work on real codebases. Use it when:
26
+
27
+ - Your codebase is large or fragmented enough that assistants waste context window on irrelevant files.
28
+ - You need assistants to respect architectural rules, deprecations, and source-of-truth decisions already made by the team.
29
+ - You work across multiple languages and want consistent, structured retrieval across all of them.
30
+ - Security or compliance requires that source code stay on-premise and that all AI interactions remain auditable.
31
+ - You want retrieval to surface *existing* functionality before an assistant proposes new code — reducing duplication and drift.
32
+
33
+ Cortex is not a replacement for your editor, your version control, or your coding assistant. It is the grounding layer that makes those assistants act with knowledge of your specific repository.
34
+
35
+ ## Benefits
36
+
37
+ - **Higher-quality suggestions.** Assistants see the right files and rules instead of guessing from filenames.
38
+ - **Lower token cost.** Targeted retrieval replaces broad file reads. Typical sessions use a fraction of the context a raw assistant would consume.
39
+ - **Architectural governance.** Rules and ADRs are surfaced with every answer, so assistants follow the team's established patterns rather than generic best practices.
40
+ - **Multi-language coverage.** A single engine indexes multiple languages through tree-sitter grammars, giving polyglot teams consistent tooling.
41
+ - **Privacy by design.** Your code and its derived index stay on your machine. No upload, no cloud dependency for the core product.
42
+ - **Low friction.** One command (`cortex init --bootstrap`) scaffolds everything: indexing, git hooks, MCP registration for Claude Code, Claude Desktop, and Codex.
43
+
44
+ ## How it works
45
+
46
+ Cortex operates as a five-stage pipeline between your repository and your AI assistant.
47
+
48
+ 1. **Ingestion.** Source files are parsed with tree-sitter, producing structured entities (files, functions, classes, rules, ADRs) and relations (`CALLS`, `DEFINES`, `CONSTRAINS`, `IMPLEMENTS`, `IMPORTS`, `SUPERSEDES`).
49
+ 2. **Storage.** Entities and relations are persisted to a local graph database (RyuGraph). An optional vector index provides semantic search across entity content.
50
+ 3. **Retrieval.** MCP tools combine semantic search with graph traversal to assemble the smallest context package that answers the task.
51
+ 4. **Policy.** Architectural rules and source-of-truth markers filter conflicting or deprecated content before it reaches the assistant.
52
+ 5. **Assembly.** Results are delivered to the assistant as a compact, ranked context package over MCP.
53
+
54
+ Git hooks keep the index fresh on every checkout, pull, commit, and rewrite. A live TUI dashboard (`cortex dashboard`) shows what Cortex adds to the repository in real time.
55
+
56
+ ## Why it works
57
+
58
+ Modern coding assistants are bottlenecked by context, not by model capability. Feeding a model more files rarely helps; feeding it the *right* files almost always does.
59
+
60
+ Cortex is built on one principle: **prefer retrieval quality over analysis completeness.** A smaller, sharper context package outperforms a broad dump of files. Every component — from tree-sitter parsing to graph traversal to rule filtering — exists to raise the signal-to-noise ratio of what the assistant sees.
61
+
62
+ The result is an assistant that behaves as if it already knows your codebase, because — through Cortex — it does.
63
+
64
+ ## Quick demo
65
+
66
+ ![Cortex install and bootstrap demo](https://raw.githubusercontent.com/DanielBlomma/cortex/main/docs/install-demo.gif)
22
67
 
23
- ## Core Features
68
+ ## Core capabilities
24
69
 
25
- - Semantic search across files, rules, and ADRs.
70
+ - Semantic search across code, rules, and ADRs.
26
71
  - Graph relationships between entities and architectural constraints.
27
- - Architectural rules and ADR context for implementation decisions.
28
- - Live TUI dashboard showing what Cortex adds to your repo.
72
+ - Call-graph traversal, caller lookup, and impact analysis.
73
+ - Architectural rules and ADR enforcement at retrieval time.
74
+ - Incremental index updates driven by git hooks.
75
+ - Live TUI dashboard showing what Cortex adds to your repository.
76
+ - First-class integrations with Claude Code, Claude Desktop, and Codex.
29
77
 
30
78
  ## Requirements
31
79
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@danielblomma/cortex-mcp",
3
3
  "mcpName": "io.github.DanielBlomma/cortex",
4
- "version": "1.3.1",
4
+ "version": "1.4.0",
5
5
  "description": "Local, repo-scoped context platform for coding assistants. Semantic search, graph relationships, and architectural rule context.",
6
6
  "type": "module",
7
7
  "author": "Daniel Blomma",
@@ -46,7 +46,7 @@
46
46
  "docs/MCP_MARKETPLACE.md"
47
47
  ],
48
48
  "scripts": {
49
- "test": "node tests/context-regressions.test.mjs && node --test tests/ingest-units.test.mjs tests/javascript-parser.test.mjs tests/sql-parser.test.mjs tests/config-parser.test.mjs tests/resources-parser.test.mjs tests/vbnet-parser.test.mjs tests/cpp-parser.test.mjs tests/multi-level.test.mjs",
49
+ "test": "node tests/context-regressions.test.mjs && node --test tests/ingest-units.test.mjs tests/javascript-parser.test.mjs tests/sql-parser.test.mjs tests/config-parser.test.mjs tests/resources-parser.test.mjs tests/vbnet-parser.test.mjs tests/cpp-parser.test.mjs tests/multi-level.test.mjs tests/no-legacy-paths.test.mjs",
50
50
  "release:sync-version": "node scripts/sync-release-version.mjs",
51
51
  "release:check-version-sync": "node scripts/sync-release-version.mjs --check",
52
52
  "prepublishOnly": "echo 'Ready to publish to npm'"
@@ -236,7 +236,6 @@
236
236
  "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.13.tgz",
237
237
  "integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==",
238
238
  "license": "MIT",
239
- "peer": true,
240
239
  "dependencies": {
241
240
  "undici-types": "~6.21.0"
242
241
  }
@@ -1285,11 +1284,10 @@
1285
1284
  }
1286
1285
  },
1287
1286
  "node_modules/hono": {
1288
- "version": "4.12.12",
1289
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.12.tgz",
1290
- "integrity": "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==",
1287
+ "version": "4.12.14",
1288
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz",
1289
+ "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==",
1291
1290
  "license": "MIT",
1292
- "peer": true,
1293
1291
  "engines": {
1294
1292
  "node": ">=16.9.0"
1295
1293
  }
@@ -2446,7 +2444,6 @@
2446
2444
  "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
2447
2445
  "dev": true,
2448
2446
  "license": "Apache-2.0",
2449
- "peer": true,
2450
2447
  "bin": {
2451
2448
  "tsc": "bin/tsc",
2452
2449
  "tsserver": "bin/tsserver"
@@ -2605,7 +2602,6 @@
2605
2602
  "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
2606
2603
  "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
2607
2604
  "license": "MIT",
2608
- "peer": true,
2609
2605
  "funding": {
2610
2606
  "url": "https://github.com/sponsors/colinhacks"
2611
2607
  }
@@ -20,7 +20,7 @@
20
20
  "overrides": {
21
21
  "cmake-js": "^8.0.0",
22
22
  "express-rate-limit": "^8.3.1",
23
- "hono": "^4.12.12",
23
+ "hono": "^4.12.14",
24
24
  "@hono/node-server": "^1.19.13",
25
25
  "tar": "^7.5.11"
26
26
  },
@@ -543,6 +543,19 @@ function emptyLine(width) {
543
543
  return col("│", C.gray) + " ".repeat(width - 2) + col("│", C.gray);
544
544
  }
545
545
 
546
+ // ── Edition detection ────────────────────────────────────────
547
+ import { createRequire } from "node:module";
548
+ const __require = createRequire(import.meta.url);
549
+
550
+ function detectEdition() {
551
+ try {
552
+ __require.resolve("@danielblomma/cortex-enterprise");
553
+ return "Enterprise";
554
+ } catch {
555
+ return "Community";
556
+ }
557
+ }
558
+
546
559
  // ── Render sections ──────────────────────────────────────────
547
560
  function render(data, isTTY) {
548
561
  const termWidth = process.stdout.columns || 80;
@@ -551,7 +564,8 @@ function render(data, isTTY) {
551
564
 
552
565
  // Header
553
566
  const clock = new Date().toLocaleTimeString("sv-SE", { hour: "2-digit", minute: "2-digit" });
554
- const title = "─ cortex dashboard ";
567
+ const edition = detectEdition();
568
+ const title = `─ cortex dashboard [${edition}] `;
555
569
  const clockPart = ` ${clock} ─`;
556
570
  const fillLen = w - 2 - title.length - clockPart.length;
557
571
  lines.push(col(`┌${title}${"─".repeat(Math.max(0, fillLen))}${clockPart}┐`, C.gray));
@@ -221,19 +221,59 @@ if [[ -n "$ENTERPRISE_CONFIG" ]]; then
221
221
  console.log(fields["policy.endpoint"] || "");
222
222
  ' "$ENTERPRISE_CONFIG" 2>/dev/null || echo "")
223
223
 
224
+ TELEMETRY_API_KEY=$(node -e '
225
+ const fs = require("node:fs");
226
+ const raw = fs.readFileSync(process.argv[1], "utf8");
227
+ let section = "", fields = {};
228
+ for (const line of raw.split("\n")) {
229
+ const t = line.trimEnd();
230
+ if (!t || t.startsWith("#")) continue;
231
+ const sm = t.match(/^(\w+):\s*$/);
232
+ if (sm) { section = sm[1]; continue; }
233
+ const kv = t.match(/^\s+(\w+):\s*(.+?)\s*$/);
234
+ if (kv && section) fields[section + "." + kv[1]] = kv[2].replace(/^["\x27]|["\x27]$/g, "");
235
+ }
236
+ console.log(fields["telemetry.api_key"] || "");
237
+ ' "$ENTERPRISE_CONFIG" 2>/dev/null || echo "")
238
+
239
+ POLICY_API_KEY=$(node -e '
240
+ const fs = require("node:fs");
241
+ const raw = fs.readFileSync(process.argv[1], "utf8");
242
+ let section = "", fields = {};
243
+ for (const line of raw.split("\n")) {
244
+ const t = line.trimEnd();
245
+ if (!t || t.startsWith("#")) continue;
246
+ const sm = t.match(/^(\w+):\s*$/);
247
+ if (sm) { section = sm[1]; continue; }
248
+ const kv = t.match(/^\s+(\w+):\s*(.+?)\s*$/);
249
+ if (kv && section) fields[section + "." + kv[1]] = kv[2].replace(/^["\x27]|["\x27]$/g, "");
250
+ }
251
+ console.log(fields["policy.api_key"] || "");
252
+ ' "$ENTERPRISE_CONFIG" 2>/dev/null || echo "")
253
+
224
254
  # Telemetry
225
255
  if [[ -n "$TELEMETRY_ENDPOINT" ]]; then
226
256
  pass "Telemetry: endpoint configured"
227
- HTTP_CODE=$(curl -so /dev/null -w '%{http_code}' --max-time 5 -X POST \
228
- -H "Content-Type: application/json" \
229
- -d '{}' \
230
- "$TELEMETRY_ENDPOINT" 2>/dev/null | tail -c 3 || echo "000")
257
+ TELEMETRY_CURL_ARGS=(-so /dev/null -w '%{http_code}' --max-time 5 -X POST \
258
+ -H "Content-Type: application/json" -d '{}')
259
+ if [[ -n "$TELEMETRY_API_KEY" ]]; then
260
+ TELEMETRY_CURL_ARGS+=(-H "Authorization: Bearer ${TELEMETRY_API_KEY}")
261
+ fi
262
+ HTTP_CODE=$(curl "${TELEMETRY_CURL_ARGS[@]}" "$TELEMETRY_ENDPOINT" 2>/dev/null | tail -c 3 || echo "000")
231
263
  if [[ "$HTTP_CODE" == "000" ]]; then
232
264
  fail "Telemetry: endpoint not reachable (timeout/DNS)"
233
265
  elif [[ "$HTTP_CODE" =~ ^[23] ]]; then
234
- pass "Telemetry: endpoint reachable (HTTP ${HTTP_CODE})"
235
- elif [[ "$HTTP_CODE" == "401" ]]; then
236
- pass "Telemetry: endpoint reachable (auth required — expected)"
266
+ if [[ -n "$TELEMETRY_API_KEY" ]]; then
267
+ pass "Telemetry: endpoint authenticated (HTTP ${HTTP_CODE})"
268
+ else
269
+ pass "Telemetry: endpoint reachable (HTTP ${HTTP_CODE})"
270
+ fi
271
+ elif [[ "$HTTP_CODE" == "401" || "$HTTP_CODE" == "403" ]]; then
272
+ if [[ -n "$TELEMETRY_API_KEY" ]]; then
273
+ fail "Telemetry: auth rejected (HTTP ${HTTP_CODE}) — check telemetry.api_key in enterprise.yaml"
274
+ else
275
+ pass "Telemetry: endpoint reachable (auth required — expected)"
276
+ fi
237
277
  else
238
278
  warn "Telemetry: endpoint returned HTTP ${HTTP_CODE}"
239
279
  fi
@@ -258,11 +298,25 @@ if [[ -n "$ENTERPRISE_CONFIG" ]]; then
258
298
  fi
259
299
 
260
300
  if [[ -n "$POLICY_ENDPOINT" ]]; then
261
- POLICY_HTTP=$(curl -so /dev/null -w '%{http_code}' --max-time 5 "$POLICY_ENDPOINT" 2>/dev/null | tail -c 3 || echo "000")
301
+ POLICY_CURL_ARGS=(-so /dev/null -w '%{http_code}' --max-time 5)
302
+ if [[ -n "$POLICY_API_KEY" ]]; then
303
+ POLICY_CURL_ARGS+=(-H "Authorization: Bearer ${POLICY_API_KEY}")
304
+ fi
305
+ POLICY_HTTP=$(curl "${POLICY_CURL_ARGS[@]}" "$POLICY_ENDPOINT" 2>/dev/null | tail -c 3 || echo "000")
262
306
  if [[ "$POLICY_HTTP" == "000" ]]; then
263
307
  fail "Policy: endpoint not reachable (timeout/DNS)"
264
- elif [[ "$POLICY_HTTP" =~ ^[23] ]] || [[ "$POLICY_HTTP" == "401" ]]; then
265
- pass "Policy: endpoint reachable (HTTP ${POLICY_HTTP})"
308
+ elif [[ "$POLICY_HTTP" =~ ^[23] ]]; then
309
+ if [[ -n "$POLICY_API_KEY" ]]; then
310
+ pass "Policy: endpoint authenticated (HTTP ${POLICY_HTTP})"
311
+ else
312
+ pass "Policy: endpoint reachable (HTTP ${POLICY_HTTP})"
313
+ fi
314
+ elif [[ "$POLICY_HTTP" == "401" || "$POLICY_HTTP" == "403" ]]; then
315
+ if [[ -n "$POLICY_API_KEY" ]]; then
316
+ fail "Policy: auth rejected (HTTP ${POLICY_HTTP}) — check policy.api_key in enterprise.yaml"
317
+ else
318
+ pass "Policy: endpoint reachable (auth required — expected)"
319
+ fi
266
320
  else
267
321
  warn "Policy: endpoint returned HTTP ${POLICY_HTTP}"
268
322
  fi