@danielblomma/cortex-mcp 2.4.0 → 2.4.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 (214) hide show
  1. package/CHANGELOG.md +226 -0
  2. package/README.md +24 -3
  3. package/bin/cli/arguments.mjs +60 -0
  4. package/bin/cli/context-passthrough.mjs +129 -0
  5. package/bin/cli/daemon.mjs +157 -0
  6. package/bin/cli/enterprise.mjs +516 -0
  7. package/bin/cli/help.mjs +88 -0
  8. package/bin/cli/hooks.mjs +199 -0
  9. package/bin/cli/mcp-command.mjs +87 -0
  10. package/bin/cli/paths.mjs +14 -0
  11. package/bin/cli/process.mjs +49 -0
  12. package/bin/cli/project-commands.mjs +237 -0
  13. package/bin/cli/project-runtime.mjs +34 -0
  14. package/bin/cli/query-command.mjs +18 -0
  15. package/bin/cli/router.mjs +66 -0
  16. package/bin/cli/run-command.mjs +44 -0
  17. package/bin/cli/scaffold-ownership.mjs +936 -0
  18. package/bin/cli/scaffold.mjs +687 -0
  19. package/bin/cli/stage-command.mjs +9 -0
  20. package/bin/cli/telemetry-command.mjs +18 -0
  21. package/bin/cli/trusted-runtime.mjs +18 -0
  22. package/bin/cortex.mjs +12 -1607
  23. package/bin/daemon-control.mjs +162 -0
  24. package/mcp-registry-submission.json +1 -1
  25. package/package.json +8 -3
  26. package/scaffold/mcp/dist/.cortex-build-hash +1 -0
  27. package/scaffold/mcp/dist/cli/enterprise-setup.js +134 -0
  28. package/scaffold/mcp/dist/cli/govern.js +937 -0
  29. package/scaffold/mcp/dist/cli/query.js +409 -0
  30. package/scaffold/mcp/dist/cli/run.js +295 -0
  31. package/scaffold/mcp/dist/cli/stage.js +308 -0
  32. package/scaffold/mcp/dist/cli/telemetry-test.js +141 -0
  33. package/scaffold/mcp/dist/cli/ungoverned-detector.js +133 -0
  34. package/scaffold/mcp/dist/contextEntities.js +282 -0
  35. package/scaffold/mcp/dist/core/audit/query.js +72 -0
  36. package/scaffold/mcp/dist/core/audit/writer.js +28 -0
  37. package/scaffold/mcp/dist/core/config.js +235 -0
  38. package/scaffold/mcp/dist/core/enterprise-host-identity.js +193 -0
  39. package/scaffold/mcp/dist/core/enterprise-identity.js +18 -0
  40. package/scaffold/mcp/dist/core/enterprise-rotation.js +158 -0
  41. package/scaffold/mcp/dist/core/govern-paths.js +21 -0
  42. package/scaffold/mcp/dist/core/index.js +14 -0
  43. package/scaffold/mcp/dist/core/license.js +278 -0
  44. package/scaffold/mcp/dist/core/policy/enforce.js +66 -0
  45. package/scaffold/mcp/dist/core/policy/injection.js +172 -0
  46. package/scaffold/mcp/dist/core/policy/store.js +179 -0
  47. package/scaffold/mcp/dist/core/rbac/check.js +30 -0
  48. package/scaffold/mcp/dist/core/secure-endpoint.js +25 -0
  49. package/scaffold/mcp/dist/core/telemetry/collector.js +285 -0
  50. package/scaffold/mcp/dist/core/telemetry/state-dir.js +31 -0
  51. package/scaffold/mcp/dist/core/validators/builtins.js +632 -0
  52. package/scaffold/mcp/dist/core/validators/config.js +44 -0
  53. package/scaffold/mcp/dist/core/validators/engine.js +120 -0
  54. package/scaffold/mcp/dist/core/validators/evaluators/code_comments.js +236 -0
  55. package/scaffold/mcp/dist/core/validators/evaluators/regex.js +116 -0
  56. package/scaffold/mcp/dist/core/workflow/artifact-io.js +103 -0
  57. package/scaffold/mcp/dist/core/workflow/capabilities.js +88 -0
  58. package/scaffold/mcp/dist/core/workflow/default-workflows.js +102 -0
  59. package/scaffold/mcp/dist/core/workflow/enforcement.js +164 -0
  60. package/scaffold/mcp/dist/core/workflow/envelope.js +132 -0
  61. package/scaffold/mcp/dist/core/workflow/index.js +11 -0
  62. package/scaffold/mcp/dist/core/workflow/mcp-tools.js +175 -0
  63. package/scaffold/mcp/dist/core/workflow/resolution.js +69 -0
  64. package/scaffold/mcp/dist/core/workflow/run-lifecycle.js +123 -0
  65. package/scaffold/mcp/dist/core/workflow/schemas.js +141 -0
  66. package/scaffold/mcp/dist/core/workflow/synced-capability-registry.js +60 -0
  67. package/scaffold/mcp/dist/core/workflow/synced-registry.js +60 -0
  68. package/scaffold/mcp/dist/daemon/capability-sync-checker.js +242 -0
  69. package/scaffold/mcp/dist/daemon/client.js +130 -0
  70. package/scaffold/mcp/dist/daemon/egress-proxy.js +288 -0
  71. package/scaffold/mcp/dist/daemon/global-host-events.js +222 -0
  72. package/scaffold/mcp/dist/daemon/heartbeat-pusher.js +116 -0
  73. package/scaffold/mcp/dist/daemon/heartbeat-tracker.js +165 -0
  74. package/scaffold/mcp/dist/daemon/host-events-pusher.js +249 -0
  75. package/scaffold/mcp/dist/daemon/main.js +449 -0
  76. package/scaffold/mcp/dist/daemon/paths.js +36 -0
  77. package/scaffold/mcp/dist/daemon/project-service-registry.js +78 -0
  78. package/scaffold/mcp/dist/daemon/protocol.js +8 -0
  79. package/scaffold/mcp/dist/daemon/server.js +180 -0
  80. package/scaffold/mcp/dist/daemon/skill-sync-checker.js +557 -0
  81. package/scaffold/mcp/dist/daemon/sync-checker.js +165 -0
  82. package/scaffold/mcp/dist/daemon/ungoverned-scanner.js +136 -0
  83. package/scaffold/mcp/dist/daemon/workflow-sync-checker.js +249 -0
  84. package/scaffold/mcp/dist/defaults.js +6 -0
  85. package/scaffold/mcp/dist/embed.js +627 -0
  86. package/scaffold/mcp/dist/embedScheduler.js +479 -0
  87. package/scaffold/mcp/dist/embeddings.js +167 -0
  88. package/scaffold/mcp/dist/enterprise/audit/push.js +66 -0
  89. package/scaffold/mcp/dist/enterprise/index.js +327 -0
  90. package/scaffold/mcp/dist/enterprise/model/deploy.js +27 -0
  91. package/scaffold/mcp/dist/enterprise/policy/sync.js +129 -0
  92. package/scaffold/mcp/dist/enterprise/privacy/boundary.js +184 -0
  93. package/scaffold/mcp/dist/enterprise/reviews/changed-files.js +33 -0
  94. package/scaffold/mcp/dist/enterprise/reviews/pattern-context.js +202 -0
  95. package/scaffold/mcp/dist/enterprise/reviews/policy-selection.js +46 -0
  96. package/scaffold/mcp/dist/enterprise/reviews/push.js +102 -0
  97. package/scaffold/mcp/dist/enterprise/reviews/trust-state.js +186 -0
  98. package/scaffold/mcp/dist/enterprise/telemetry/sync.js +57 -0
  99. package/scaffold/mcp/dist/enterprise/tools/enterprise.js +826 -0
  100. package/scaffold/mcp/dist/enterprise/tools/harness.js +40 -0
  101. package/scaffold/mcp/dist/enterprise/tools/walk.js +73 -0
  102. package/scaffold/mcp/dist/enterprise/violations/push.js +77 -0
  103. package/scaffold/mcp/dist/enterprise/workflow/push.js +44 -0
  104. package/scaffold/mcp/dist/enterprise/workflow/state.js +329 -0
  105. package/scaffold/mcp/dist/frontmatter.js +33 -0
  106. package/scaffold/mcp/dist/graph.js +769 -0
  107. package/scaffold/mcp/dist/graphCsv.js +55 -0
  108. package/scaffold/mcp/dist/graphMetrics.js +8 -0
  109. package/scaffold/mcp/dist/hooks/permission-request.js +89 -0
  110. package/scaffold/mcp/dist/hooks/post-tool-use.js +105 -0
  111. package/scaffold/mcp/dist/hooks/pre-compact.js +29 -0
  112. package/scaffold/mcp/dist/hooks/pre-tool-use.js +78 -0
  113. package/scaffold/mcp/dist/hooks/session-end.js +43 -0
  114. package/scaffold/mcp/dist/hooks/session-start.js +41 -0
  115. package/scaffold/mcp/dist/hooks/shared.js +194 -0
  116. package/scaffold/mcp/dist/hooks/stop.js +28 -0
  117. package/scaffold/mcp/dist/hooks/user-prompt-submit.js +33 -0
  118. package/scaffold/mcp/dist/impactPresentation.js +137 -0
  119. package/scaffold/mcp/dist/impactRanking.js +191 -0
  120. package/scaffold/mcp/dist/impactResponse.js +30 -0
  121. package/scaffold/mcp/dist/impactResults.js +105 -0
  122. package/scaffold/mcp/dist/impactSeed.js +20 -0
  123. package/scaffold/mcp/dist/impactTraversal.js +64 -0
  124. package/scaffold/mcp/dist/jsonl.js +77 -0
  125. package/scaffold/mcp/dist/loadGraph.js +759 -0
  126. package/scaffold/mcp/dist/lruCache.js +38 -0
  127. package/scaffold/mcp/dist/paths.js +97 -0
  128. package/scaffold/mcp/dist/patternEvidence.js +272 -0
  129. package/scaffold/mcp/dist/plugin.js +81 -0
  130. package/scaffold/mcp/dist/presets.js +78 -0
  131. package/scaffold/mcp/dist/relatedResponse.js +18 -0
  132. package/scaffold/mcp/dist/relatedTraversal.js +78 -0
  133. package/scaffold/mcp/dist/rules.js +23 -0
  134. package/scaffold/mcp/dist/search.js +212 -0
  135. package/scaffold/mcp/dist/searchCore.js +457 -0
  136. package/scaffold/mcp/dist/searchResults.js +230 -0
  137. package/scaffold/mcp/dist/server.js +317 -0
  138. package/scaffold/mcp/dist/types.js +1 -0
  139. package/scaffold/mcp/package-lock.json +321 -200
  140. package/scaffold/mcp/package.json +15 -6
  141. package/scaffold/mcp/src/cli/enterprise-setup.ts +82 -8
  142. package/scaffold/mcp/src/cli/govern.ts +137 -52
  143. package/scaffold/mcp/src/cli/run.ts +53 -19
  144. package/scaffold/mcp/src/cli/stage.ts +8 -3
  145. package/scaffold/mcp/src/core/config.ts +9 -2
  146. package/scaffold/mcp/src/core/enterprise-host-identity.ts +259 -0
  147. package/scaffold/mcp/src/core/enterprise-identity.ts +20 -0
  148. package/scaffold/mcp/src/core/enterprise-rotation.ts +185 -0
  149. package/scaffold/mcp/src/core/govern-paths.ts +30 -0
  150. package/scaffold/mcp/src/core/license.ts +186 -17
  151. package/scaffold/mcp/src/core/secure-endpoint.ts +23 -0
  152. package/scaffold/mcp/src/core/workflow/enforcement.ts +8 -1
  153. package/scaffold/mcp/src/core/workflow/mcp-tools.ts +3 -0
  154. package/scaffold/mcp/src/core/workflow/resolution.ts +9 -1
  155. package/scaffold/mcp/src/core/workflow/synced-capability-registry.ts +15 -0
  156. package/scaffold/mcp/src/core/workflow/synced-registry.ts +15 -0
  157. package/scaffold/mcp/src/daemon/capability-sync-checker.ts +38 -2
  158. package/scaffold/mcp/src/daemon/egress-proxy.ts +14 -8
  159. package/scaffold/mcp/src/daemon/global-host-events.ts +288 -0
  160. package/scaffold/mcp/src/daemon/heartbeat-pusher.ts +4 -0
  161. package/scaffold/mcp/src/daemon/heartbeat-tracker.ts +2 -0
  162. package/scaffold/mcp/src/daemon/host-events-pusher.ts +5 -0
  163. package/scaffold/mcp/src/daemon/main.ts +99 -25
  164. package/scaffold/mcp/src/daemon/project-service-registry.ts +107 -0
  165. package/scaffold/mcp/src/daemon/skill-sync-checker.ts +368 -31
  166. package/scaffold/mcp/src/daemon/sync-checker.ts +4 -0
  167. package/scaffold/mcp/src/daemon/ungoverned-scanner.ts +57 -25
  168. package/scaffold/mcp/src/daemon/workflow-sync-checker.ts +41 -2
  169. package/scaffold/mcp/src/enterprise/audit/push.ts +8 -0
  170. package/scaffold/mcp/src/enterprise/policy/sync.ts +12 -0
  171. package/scaffold/mcp/src/enterprise/reviews/push.ts +9 -0
  172. package/scaffold/mcp/src/enterprise/reviews/trust-state.ts +3 -1
  173. package/scaffold/mcp/src/enterprise/telemetry/sync.ts +9 -0
  174. package/scaffold/mcp/src/enterprise/violations/push.ts +9 -0
  175. package/scaffold/mcp/src/enterprise/workflow/push.ts +7 -0
  176. package/scaffold/mcp/src/plugin.ts +20 -0
  177. package/scaffold/mcp/tests/copilot-shim.test.mjs +19 -1
  178. package/scaffold/mcp/tests/egress-proxy.test.mjs +37 -0
  179. package/scaffold/mcp/tests/enterprise-identity-sync.test.mjs +401 -0
  180. package/scaffold/mcp/tests/enterprise-setup.test.mjs +189 -0
  181. package/scaffold/mcp/tests/global-host-events.test.mjs +81 -0
  182. package/scaffold/mcp/tests/govern-install.test.mjs +95 -2
  183. package/scaffold/mcp/tests/govern-repair.test.mjs +20 -3
  184. package/scaffold/mcp/tests/heartbeat-tracker.test.mjs +26 -0
  185. package/scaffold/mcp/tests/license.test.mjs +367 -0
  186. package/scaffold/mcp/tests/project-service-registry.test.mjs +172 -0
  187. package/scaffold/mcp/tests/review-trust-contract.test.mjs +18 -0
  188. package/scaffold/mcp/tests/secure-enterprise-endpoint.test.mjs +46 -0
  189. package/scaffold/mcp/tests/skill-sync-checker.test.mjs +446 -2
  190. package/scaffold/mcp/tests/ungoverned-scanner.test.mjs +104 -22
  191. package/scaffold/mcp/tests/workflow-cli.test.mjs +14 -1
  192. package/scaffold/mcp/tests/workflow-synced-capabilities.test.mjs +37 -0
  193. package/scaffold/mcp/tests/workflow-synced-registry.test.mjs +40 -1
  194. package/scaffold/ownership/baseline-v2.4.1.json +22 -0
  195. package/scaffold/ownership/current.json +4 -0
  196. package/scaffold/ownership/v1.json +456 -0
  197. package/scaffold/scripts/ingest-parsers.mjs +1 -387
  198. package/scaffold/scripts/ingest-worker.mjs +4 -1
  199. package/scaffold/scripts/ingest.mjs +5 -3899
  200. package/scaffold/scripts/lib/ingest/arguments.mjs +78 -0
  201. package/scaffold/scripts/lib/ingest/chunks.mjs +212 -0
  202. package/scaffold/scripts/lib/ingest/config.mjs +120 -0
  203. package/scaffold/scripts/lib/ingest/constants.mjs +222 -0
  204. package/scaffold/scripts/lib/ingest/files.mjs +387 -0
  205. package/scaffold/scripts/lib/ingest/incremental-state.mjs +131 -0
  206. package/scaffold/scripts/lib/ingest/io.mjs +78 -0
  207. package/scaffold/scripts/lib/ingest/main.mjs +76 -0
  208. package/scaffold/scripts/lib/ingest/parser-composition.mjs +140 -0
  209. package/scaffold/scripts/lib/ingest/parser-registry.mjs +387 -0
  210. package/scaffold/scripts/lib/ingest/pipeline-stages.mjs +1625 -0
  211. package/scaffold/scripts/lib/ingest/projects.mjs +272 -0
  212. package/scaffold/scripts/lib/ingest/relations.mjs +860 -0
  213. package/scaffold/scripts/lib/ingest/runtime-paths.mjs +11 -0
  214. package/scaffold/scripts/lib/ingest/workers.mjs +264 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,226 @@
1
+ # Changelog
2
+
3
+ ## 2.4.2 — 2026-07-30
4
+
5
+ ### Changed
6
+
7
+ - Split the Cortex CLI into cohesive command modules behind the existing
8
+ executable, preserving command names, arguments, streams, exit behavior,
9
+ JSON envelopes, Enterprise trust resolution, and `.context/mcp`
10
+ compatibility.
11
+ - Established `scaffold/scripts/lib/ingest/` as the single canonical ingest
12
+ implementation for development and packaged entrypoints. Deterministic
13
+ output, worker fallback, trace checkpoints, and bounded result retention
14
+ remain unchanged.
15
+ - Added versioned scaffold ownership and installed fingerprints. Forced
16
+ upgrades remove only unmodified obsolete Cortex-managed files, reject
17
+ modified or unsafe collisions, and preserve unknown files, configuration,
18
+ rules, ontology changes, Enterprise secrets, and agent instructions.
19
+ - Extended release synchronization to keep the shipped MCP registry package
20
+ and Node runtime requirement aligned with `package.json`.
21
+
22
+ ### Upgrade
23
+
24
+ - Upgrade the npm package, then run `cortex init --force`, `cortex bootstrap`,
25
+ and `cortex update`. Projects created before ownership state existed are
26
+ migrated only from hash-verified Cortex 2.4.1 scaffold files.
27
+
28
+ ## 2.4.1 — 2026-07-28
29
+
30
+ ### Security
31
+
32
+ - Validated remote enterprise skill names, blocked symlink targets, and
33
+ added Cortex ownership markers so personal skill directories cannot be
34
+ overwritten or recursively deleted. Deletion targets are derived from
35
+ managed CLI roots instead of trusting cached absolute paths.
36
+ - Bound license-cache reuse to the normalized endpoint and a one-way API-key
37
+ fingerprint. Malformed, future-dated, and expired cache assertions fail
38
+ closed; HTTP 401/403 responses reject authorization without grace.
39
+ - Changed enterprise onboarding to read API keys from stdin and atomically
40
+ create `.context/enterprise.yml` with mode `0600`. Remote endpoints require
41
+ HTTPS, with a loopback-only HTTP exception for local development.
42
+ - Bound user-global organization artifacts and host process detection to one
43
+ opaque Enterprise credential identity per OS user. A conflicting endpoint
44
+ is rejected, same-endpoint API-key rotation safely purges old marker-owned
45
+ skills and caches, and only one host-wide process scanner runs.
46
+ - Moved unattributed process findings into a credential-bound, mode-`0600`
47
+ user-global queue instead of the first project's audit directory.
48
+ - Enterprise admin commands now execute only package-owned trusted code.
49
+ Repository runtime modules and project-local state writes never execute with
50
+ root authority; persisted govern paths are not deletion authority.
51
+ - Suppressed shared-proxy project audit events when a connection has no
52
+ trustworthy project attribution.
53
+ - Added verified socket-based daemon stop/restart. Bootstrap now restarts an
54
+ already-running daemon so the upgraded security code replaces the old
55
+ in-memory runtime, and init repairs preserved Enterprise configs to `0600`.
56
+ - Updated the frontend and packaged MCP dependency trees to patched PostCSS,
57
+ SDK, Hono, archive, URI, YAML, protobuf, ONNX ZIP, and Sharp versions. All
58
+ committed npm lockfiles now have a zero-vulnerability audit target.
59
+
60
+ ### Changed
61
+
62
+ - Replace `sudo cortex enterprise <api-key>` with:
63
+
64
+ ```bash
65
+ printf '%s\n' "$CORTEX_API_KEY" |
66
+ sudo cortex enterprise install --api-key-stdin
67
+ ```
68
+
69
+ - After updating the npm package, run `cortex init --force` and
70
+ `cortex bootstrap`. The latter safely restarts a verified running daemon;
71
+ an npm update alone does not activate this fix in an existing process.
72
+ - Existing Enterprise users must then rerun the stdin install to create the
73
+ durable host-identity marker. Confirm
74
+ `cortex enterprise status --json` reports
75
+ `enterprise.host_identity_bound: true`; Cortex never auto-enrolls from a
76
+ repository config.
77
+ - The minimum supported runtime is Node.js 20.9 (the first Node 20 LTS
78
+ release), required by the patched native embedding dependency chain.
79
+ - Before re-enrollment, review legacy `~/.cortex/skills.local.json` records
80
+ without `credential_id`, back up each exact matching Claude/Codex skill
81
+ directory outside the discovery roots, and back up the state file. Ambiguous
82
+ legacy directories are deliberately not adopted or deleted automatically.
83
+
84
+ ### Rollout and emergency containment
85
+
86
+ - Do not downgrade to 2.4.0: that reopens the remote skill traversal boundary.
87
+ Use a forward fix.
88
+ - Before rollout, back up `.context/enterprise.yml` with ownership and mode
89
+ preserved. After restore, verify the correct owner and run
90
+ `chmod 600 .context/enterprise.yml`.
91
+ - If suspicious remote organization content is observed, run
92
+ `cortex daemon stop` and stop Enterprise AI sessions until a forward fix is
93
+ installed. Enforced hooks intentionally fail closed while the daemon is
94
+ unavailable.
95
+ - After rollout, verify `cortex daemon status` reports a verified PID,
96
+ `cortex enterprise status` is healthy, the config mode is `0600`, and a
97
+ canary organization sync cannot overwrite an unmanaged personal skill.
98
+
99
+ ## 2.4.0 — 2026-07-13
100
+
101
+ ### Added
102
+
103
+ - Added a native agent behavior layer: dual plugin manifests (Claude Code +
104
+ Codex), five Cortex skills with trigger descriptions, a cached
105
+ SessionStart bootstrap that survives clear/compaction, and a Claude Code
106
+ marketplace entry.
107
+
108
+ ### Changed
109
+
110
+ - Upgraded the `cortex init` AGENTS.md section from an update reminder to a
111
+ compact using-cortex bootstrap.
112
+
113
+ ## 2.3.0 — 2026-07-13
114
+
115
+ ### Added
116
+
117
+ - Added `cortex pattern-evidence <file-path|entity-id>` for cited, structured
118
+ review evidence ordered by same file, module, feature area, and repository
119
+ fallback.
120
+ - Integrated bounded, non-blocking pattern context into enterprise
121
+ `context.review` without changing policy pass/fail or workflow trust.
122
+
123
+ ### Changed
124
+
125
+ - Made equal-score search ordering deterministic with stable entity/path
126
+ tie-breaks.
127
+ - Added strict numeric validation for CLI query limits.
128
+ - Fixed the enterprise runtime package-version lookup so compiled enterprise
129
+ tools load from the packaged MCP runtime.
130
+ - Made `context.review` scope=changed list staged and untracked files in
131
+ repositories without commits instead of falling back to a full project
132
+ walk that ignores `.gitignore`.
133
+ - Made pattern review context load the Cortex index once per review instead
134
+ of once per target, and cached the ranking reference-time scan per loaded
135
+ index.
136
+ - Unified review path canonicalization and text comparison on the shared
137
+ pattern-evidence and search helpers.
138
+
139
+ ## 2.2.5 — 2026-06-21
140
+
141
+ ### Changed
142
+
143
+ - Made the default embedding token-budget `auto` mode memory-aware: Cortex
144
+ still starts from the embedding model's maximum context, but degrades to a
145
+ safe cap when local memory headroom is unlikely to fit the full context.
146
+
147
+ ## 2.2.4 — 2026-06-20
148
+
149
+ ### Changed
150
+
151
+ - Added an explicit embedding token-budget profile and benchmark support for
152
+ `CORTEX_EMBED_MAX_TOKENS`.
153
+ - Kept the default `auto` token budget quality-preserving: Cortex uses the
154
+ embedding model's own maximum context unless a numeric cap is explicitly set.
155
+ - Reduced embedding memory overhead by avoiding full normalized-text copies for
156
+ cached entities before deciding what needs re-embedding.
157
+
158
+ ## 2.1.0 — 2026-06-11
159
+
160
+ New features and behavior changes, no API breaks.
161
+
162
+ ### Changed
163
+
164
+ - **Default embedding model is now `jinaai/jina-embeddings-v2-base-code`**
165
+ (was `Xenova/all-MiniLM-L6-v2`). The old model truncated input at 512
166
+ tokens, which clipped the majority of file-level embeddings in typical
167
+ repositories and made code-oriented queries miss implementation files.
168
+ The jina code model has an 8192-token window. Override with
169
+ `CORTEX_EMBED_MODEL` as before.
170
+ - **Embedding input text is no longer character-capped.** The previous
171
+ 7000-char entity cap and 2000-char chunk-body preview (and the
172
+ `CORTEX_EMBED_MAX_CHARS` env var) were calibrated for small models. The
173
+ tokenizer's own 8192-token truncation is now the only limit.
174
+ `CORTEX_EMBED_MAX_CHARS` is removed and silently ignored if set.
175
+ - **`graph_score` now uses a midrank percentile of relation degree within
176
+ the entity's own type** instead of `min(1, degree/4)`, which saturated at
177
+ degree >= 4 and made the graph ranking weight a constant for nearly every
178
+ entity. Percentiles are type-neutral (every type averages ~0.5), so
179
+ hub-heavy types such as rules cannot drown out leaf code.
180
+ - **Default ranking weights changed** to `semantic: 0.55, graph: 0.10,
181
+ trust: 0.20, recency: 0.15` (was `0.40 / 0.25 / 0.20 / 0.15`). Graph
182
+ degree mostly measures how many rules constrain an entity, so it gets low
183
+ weight; this reweighting and the percentile graph_score were benchmarked
184
+ as a pair. **Existing projects keep their per-project `config.yaml` —
185
+ ranking weights are NOT updated automatically.** To adopt the new
186
+ defaults, edit `.context/config.yaml`:
187
+
188
+ ```yaml
189
+ ranking:
190
+ semantic: 0.55
191
+ graph: 0.10
192
+ trust: 0.20
193
+ recency: 0.15
194
+ ```
195
+
196
+ ### Added
197
+
198
+ - **Markdown chunking.** `.md`/`.mdx` files are now chunked into H1–H3
199
+ heading-bounded sections (headings inside fenced code blocks are ignored,
200
+ preamble before the first heading is captured, empty sections are
201
+ skipped). Long sections are window-split with overlap, so prose gets
202
+ overlap while code stays symbol-chunked without it. Queries that target a
203
+ specific document section now return that section chunk directly.
204
+ - `rules.yaml` is now preserved on re-scaffold (`cortex init --force`),
205
+ alongside `config.yaml`, so project-specific rules survive upgrades.
206
+
207
+ ### Upgrading an existing project
208
+
209
+ 1. `npm i -g @danielblomma/cortex-mcp@2.1.0`
210
+ 2. In the project: `cortex init --force` (re-scaffolds `.context/mcp` and
211
+ `.context/scripts`; your `config.yaml`, `rules.yaml`, notes and
212
+ decisions are preserved), then `cortex bootstrap`.
213
+ 3. `cortex update` — the stored embedding-model id no longer matches, so
214
+ this triggers a **full re-embed automatically**. Cost: roughly 2 minutes
215
+ per 1000 entities plus a one-time download of the jina ONNX model. The
216
+ embeddings file grows (768-dim vectors vs 384).
217
+ 4. Restart the MCP server (e.g. restart your editor/agent session) — the
218
+ compiled search code only loads on process start.
219
+
220
+ Known quirk: the MCP server lazy-loads the embeddings file, so the first
221
+ search immediately after a re-embed can be served from a stale cache —
222
+ re-run the query.
223
+
224
+ ## 2.0.19 and earlier
225
+
226
+ See git history (`git log --oneline`) and GitHub releases.
package/README.md CHANGED
@@ -79,7 +79,7 @@ The result is an assistant that behaves as if it already knows your codebase, be
79
79
 
80
80
  ## Requirements
81
81
 
82
- - Node.js 20+
82
+ - Node.js 20.9+ (Node 20 LTS or newer)
83
83
  - Git repository
84
84
  - Optional for MCP registration: `claude` and/or `codex` CLI in `PATH`
85
85
 
@@ -96,15 +96,36 @@ To upgrade an already-scaffolded project to a new Cortex version:
96
96
  ```bash
97
97
  npm i -g @danielblomma/cortex-mcp
98
98
  cortex init --force # re-scaffolds .context runtime + .context/scripts
99
- cortex bootstrap
99
+ cortex bootstrap # rebuilds and safely restarts a verified running daemon
100
100
  cortex update
101
101
  ```
102
102
 
103
103
  `cortex init --force` preserves per-project files: `.context/config.yaml`,
104
- `.context/rules.yaml`, and your notes/decisions.
104
+ `.context/rules.yaml`, `.context/enterprise.yml`, and your notes/decisions.
105
+ It repairs existing Enterprise config permissions to `0600` without rewriting
106
+ the file. An npm update alone does not replace code already loaded by the
107
+ per-user daemon; `cortex bootstrap` performs the verified restart.
105
108
 
106
109
  Version-specific notes (see [CHANGELOG.md](CHANGELOG.md) for details):
107
110
 
111
+ - **2.4.2**: `cortex init --force` now uses versioned ownership metadata to
112
+ remove only unmodified obsolete Cortex-managed files. Unknown files and
113
+ protected configuration, rules, ontology, Enterprise, and agent-instruction
114
+ content remain user-owned; modified obsolete files and unsafe collisions
115
+ fail the upgrade instead of being overwritten or deleted.
116
+ - **2.4.1**: enterprise onboarding no longer accepts API keys as positional
117
+ arguments. Pipe the key to
118
+ `sudo cortex enterprise install --api-key-stdin`. Enterprise endpoints must
119
+ use HTTPS (loopback HTTP remains available for local development). Existing
120
+ Enterprise users must rerun that stdin install after `cortex bootstrap`;
121
+ enrollment is deliberately not inferred from repository config. Verify
122
+ `cortex enterprise status --json` reports
123
+ `enterprise.host_identity_bound: true`. One Enterprise endpoint is supported
124
+ per OS user because organization skills and host process detection are
125
+ user-global; an explicit install may rotate its API key. Before upgrading
126
+ legacy organization skills without Cortex ownership markers, back up and
127
+ move the exact reviewed directories listed by
128
+ `~/.cortex/skills.local.json` out of the Claude/Codex discovery roots.
108
129
  - **2.1.0**: the default embedding model changed, so the first
109
130
  `cortex update` after upgrading triggers a full re-embed automatically
110
131
  (~2 min per 1000 entities plus a one-time model download). The
@@ -0,0 +1,60 @@
1
+ import path from "node:path";
2
+
3
+ export function parseInitArgs(args) {
4
+ let target = process.cwd();
5
+ let force = false;
6
+ let bootstrap = false;
7
+ let connect = false;
8
+ let watch = true;
9
+
10
+ for (const arg of args) {
11
+ if (arg === "--force") {
12
+ force = true;
13
+ continue;
14
+ }
15
+ if (arg === "--bootstrap") {
16
+ bootstrap = true;
17
+ continue;
18
+ }
19
+ if (arg === "--connect") {
20
+ connect = true;
21
+ continue;
22
+ }
23
+ if (arg === "--no-connect") {
24
+ connect = false;
25
+ continue;
26
+ }
27
+ if (arg === "--watch") {
28
+ watch = true;
29
+ continue;
30
+ }
31
+ if (arg === "--no-watch") {
32
+ watch = false;
33
+ continue;
34
+ }
35
+ if (arg.startsWith("-")) {
36
+ throw new Error(`Unknown init option: ${arg}`);
37
+ }
38
+ target = path.resolve(arg);
39
+ }
40
+
41
+ return { target, force, bootstrap, connect, watch };
42
+ }
43
+
44
+ export function parseConnectArgs(args) {
45
+ let target = process.cwd();
46
+ let skipBuild = false;
47
+
48
+ for (const arg of args) {
49
+ if (arg === "--skip-build") {
50
+ skipBuild = true;
51
+ continue;
52
+ }
53
+ if (arg.startsWith("-")) {
54
+ throw new Error(`Unknown connect option: ${arg}`);
55
+ }
56
+ target = path.resolve(arg);
57
+ }
58
+
59
+ return { target, skipBuild };
60
+ }
@@ -0,0 +1,129 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { restartDaemonAfterRuntimeUpgrade } from "./daemon.mjs";
4
+ import { CONTEXT_SCRIPTS_REL } from "./paths.mjs";
5
+ import { runCommand } from "./process.mjs";
6
+ import {
7
+ ensureScaffoldExists,
8
+ hardenEnterpriseConfigPermissions,
9
+ initializeScaffold,
10
+ installAssistantHelpers,
11
+ isScaffoldOutOfDate,
12
+ isTruthyEnv,
13
+ maybeInstallGitHooks,
14
+ } from "./scaffold.mjs";
15
+
16
+ export const PASSTHROUGH_COMMANDS = new Set([
17
+ "bootstrap",
18
+ "update",
19
+ "status",
20
+ "ingest",
21
+ "embed",
22
+ "graph-load",
23
+ "dashboard",
24
+ "watch",
25
+ "refresh",
26
+ "memory-compile",
27
+ "memory-lint",
28
+ "doctor",
29
+ ]);
30
+
31
+ const INDEX_MUTATING_COMMANDS = new Set([
32
+ "bootstrap",
33
+ "update",
34
+ "refresh",
35
+ "ingest",
36
+ "embed",
37
+ "graph-load",
38
+ ]);
39
+
40
+ function invalidateSessionStatusCache(cwd) {
41
+ try {
42
+ fs.rmSync(
43
+ path.join(cwd, ".context", "cache", "session-status.json"),
44
+ { force: true },
45
+ );
46
+ } catch {
47
+ // Best effort: a stale cache only delays the status refresh.
48
+ }
49
+ }
50
+
51
+ export async function runContextCommand(cwd, contextArgs) {
52
+ const contextScript = path.join(cwd, CONTEXT_SCRIPTS_REL, "context.sh");
53
+ if (!fs.existsSync(contextScript)) {
54
+ throw new Error(`Missing ${contextScript}. Run 'cortex init' first.`);
55
+ }
56
+ try {
57
+ await runCommand("bash", [contextScript, ...contextArgs], cwd);
58
+ } finally {
59
+ if (INDEX_MUTATING_COMMANDS.has(contextArgs[0])) {
60
+ invalidateSessionStatusCache(cwd);
61
+ }
62
+ }
63
+ }
64
+
65
+ async function confirmPrompt(message) {
66
+ const { createInterface } = await import("node:readline/promises");
67
+ const rl = createInterface({
68
+ input: process.stdin,
69
+ output: process.stderr,
70
+ });
71
+ try {
72
+ const answer = (await rl.question(message)).trim().toLowerCase();
73
+ return answer === "y" || answer === "yes";
74
+ } finally {
75
+ rl.close();
76
+ }
77
+ }
78
+
79
+ export async function maybeMigrateScaffold(targetDir, command) {
80
+ if (!isScaffoldOutOfDate(targetDir)) return;
81
+
82
+ const autoYes = isTruthyEnv(process.env.CORTEX_AUTO_MIGRATE);
83
+ const interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY);
84
+
85
+ console.error(
86
+ `[cortex] scaffold in ${targetDir} is out of date ` +
87
+ `(missing .context/scripts/doctor.sh, context runtime package.json, doctor subcommand in context.sh, ` +
88
+ `or carries a legacy mcp/ directory at the project root).`,
89
+ );
90
+
91
+ let proceed = autoYes;
92
+ if (!autoYes) {
93
+ if (!interactive) {
94
+ throw new Error(
95
+ `Cortex CLI ${process.env.CORTEX_CLI_VERSION ?? ""} needs an updated scaffold to run '${command}'. ` +
96
+ `Run 'cortex init --bootstrap' to upgrade, or re-run with CORTEX_AUTO_MIGRATE=true.`,
97
+ );
98
+ }
99
+ proceed = await confirmPrompt(
100
+ "[cortex] Upgrade scaffold now (runs 'cortex init --bootstrap')? [y/N] ",
101
+ );
102
+ }
103
+
104
+ if (!proceed) {
105
+ throw new Error(
106
+ "Scaffold upgrade declined. Run 'cortex init --bootstrap' manually to continue.",
107
+ );
108
+ }
109
+
110
+ console.error(`[cortex] migrating scaffold in ${targetDir}`);
111
+ ensureScaffoldExists();
112
+ initializeScaffold(targetDir, true);
113
+ installAssistantHelpers(targetDir);
114
+ await maybeInstallGitHooks(targetDir);
115
+ await runContextCommand(targetDir, ["bootstrap"]);
116
+ console.error(`[cortex] scaffold upgraded; continuing with '${command}'`);
117
+ }
118
+
119
+ export async function runPassthroughCommand(command, rest) {
120
+ const cwd = process.cwd();
121
+ await maybeMigrateScaffold(cwd, command);
122
+ if (command === "bootstrap") {
123
+ hardenEnterpriseConfigPermissions(cwd);
124
+ }
125
+ await runContextCommand(cwd, [command, ...rest]);
126
+ if (command === "bootstrap") {
127
+ await restartDaemonAfterRuntimeUpgrade(cwd);
128
+ }
129
+ }
@@ -0,0 +1,157 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { spawn } from "node:child_process";
5
+ import {
6
+ callDaemon,
7
+ probeVerifiedDaemon,
8
+ stopVerifiedDaemon,
9
+ } from "../daemon-control.mjs";
10
+ import { resolveDaemonEntry } from "./project-runtime.mjs";
11
+
12
+ function daemonDirPath() {
13
+ return path.join(process.env.HOME || os.homedir(), ".cortex");
14
+ }
15
+
16
+ function daemonPidFilePath() {
17
+ return path.join(daemonDirPath(), "daemon.pid");
18
+ }
19
+
20
+ function pidFileExists() {
21
+ return fs.existsSync(daemonPidFilePath());
22
+ }
23
+
24
+ function readPid() {
25
+ try {
26
+ const raw = fs.readFileSync(daemonPidFilePath(), "utf8").trim();
27
+ const pid = Number.parseInt(raw, 10);
28
+ return Number.isFinite(pid) && pid > 0 ? pid : null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ function isPidAlive(pid) {
35
+ if (!pid) return false;
36
+ try {
37
+ process.kill(pid, 0);
38
+ return true;
39
+ } catch (err) {
40
+ if (err && typeof err === "object" && err.code === "EPERM") {
41
+ return true;
42
+ }
43
+ return false;
44
+ }
45
+ }
46
+
47
+ async function daemonControlDeps() {
48
+ return {
49
+ readPid,
50
+ isPidAlive,
51
+ call: callDaemon,
52
+ };
53
+ }
54
+
55
+ async function waitForVerifiedDaemon(deps, timeoutMs = 5_000) {
56
+ const deadline = Date.now() + timeoutMs;
57
+ while (Date.now() < deadline) {
58
+ const probe = await probeVerifiedDaemon(deps, 250);
59
+ if (probe.verified) return probe;
60
+ await new Promise((resolve) => setTimeout(resolve, 50));
61
+ }
62
+ return probeVerifiedDaemon(deps, 250);
63
+ }
64
+
65
+ export async function runDaemonCommand(args, options = {}) {
66
+ const sub = args[0] || "status";
67
+ const projectRoot = options.projectRoot || process.cwd();
68
+ const deps = await daemonControlDeps();
69
+ if (sub === "start") {
70
+ const existing = await probeVerifiedDaemon(deps);
71
+ if (existing.verified) {
72
+ console.log("Daemon already running.");
73
+ return;
74
+ }
75
+ if (existing.running) {
76
+ throw new Error(
77
+ `Refusing to replace unverified live pid ${existing.pid} (${existing.reason}).`,
78
+ );
79
+ }
80
+ const daemonDir = daemonDirPath();
81
+ fs.mkdirSync(daemonDir, { recursive: true });
82
+ const entry = resolveDaemonEntry(projectRoot);
83
+ if (!fs.existsSync(entry)) {
84
+ throw new Error(`Daemon entry not found: ${entry}. Build cortex first.`);
85
+ }
86
+ const logFd = fs.openSync(path.join(daemonDir, "daemon.log"), "a");
87
+ const child = spawn(process.execPath, [entry], {
88
+ detached: true,
89
+ stdio: ["ignore", logFd, logFd],
90
+ cwd: projectRoot,
91
+ env: { ...process.env, CORTEX_PROJECT_ROOT: projectRoot },
92
+ });
93
+ child.unref();
94
+ fs.closeSync(logFd);
95
+ const started = await waitForVerifiedDaemon(deps);
96
+ if (!started.verified) {
97
+ throw new Error(
98
+ `Daemon did not complete its verified socket handshake (${started.reason}).`,
99
+ );
100
+ }
101
+ console.log(
102
+ `Daemon started (pid=${started.pid}). Log: ${path.join(daemonDir, "daemon.log")}`,
103
+ );
104
+ return;
105
+ }
106
+ if (sub === "stop") {
107
+ const result = await stopVerifiedDaemon(deps);
108
+ if (!result.stopped) {
109
+ console.log("Daemon not running.");
110
+ return;
111
+ }
112
+ console.log(`Daemon stopped (verified pid=${result.pid}).`);
113
+ return;
114
+ }
115
+ if (sub === "restart") {
116
+ await stopVerifiedDaemon(deps);
117
+ await runDaemonCommand(["start"], { projectRoot });
118
+ return;
119
+ }
120
+ if (sub === "status") {
121
+ const probe = await probeVerifiedDaemon(deps);
122
+ if (probe.verified) {
123
+ console.log(`Daemon running (verified pid=${probe.pid})`);
124
+ } else if (probe.running) {
125
+ console.log(
126
+ `Daemon state unsafe: live pid=${probe.pid}, identity not verified (${probe.reason}).`,
127
+ );
128
+ } else {
129
+ console.log("Daemon not running.");
130
+ if (pidFileExists()) {
131
+ console.log(`(stale pid file at ${daemonPidFilePath()})`);
132
+ }
133
+ }
134
+ return;
135
+ }
136
+ throw new Error(
137
+ `Unknown daemon subcommand: ${sub}. Try start|stop|restart|status`,
138
+ );
139
+ }
140
+
141
+ export async function restartDaemonAfterRuntimeUpgrade(projectRoot) {
142
+ const daemonEntry = resolveDaemonEntry(projectRoot);
143
+ if (!fs.existsSync(daemonEntry)) return;
144
+ const deps = await daemonControlDeps();
145
+ const probe = await probeVerifiedDaemon(deps);
146
+ if (!probe.running) return;
147
+ if (!probe.verified) {
148
+ throw new Error(
149
+ `Runtime upgraded, but live pid ${probe.pid} could not be verified. ` +
150
+ "Refusing to signal it; stop it manually after confirming ownership.",
151
+ );
152
+ }
153
+ console.log(
154
+ `[cortex] restarting verified daemon pid=${probe.pid} to activate the upgraded runtime`,
155
+ );
156
+ await runDaemonCommand(["restart"], { projectRoot });
157
+ }