@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.
- package/CHANGELOG.md +226 -0
- package/README.md +24 -3
- package/bin/cli/arguments.mjs +60 -0
- package/bin/cli/context-passthrough.mjs +129 -0
- package/bin/cli/daemon.mjs +157 -0
- package/bin/cli/enterprise.mjs +516 -0
- package/bin/cli/help.mjs +88 -0
- package/bin/cli/hooks.mjs +199 -0
- package/bin/cli/mcp-command.mjs +87 -0
- package/bin/cli/paths.mjs +14 -0
- package/bin/cli/process.mjs +49 -0
- package/bin/cli/project-commands.mjs +237 -0
- package/bin/cli/project-runtime.mjs +34 -0
- package/bin/cli/query-command.mjs +18 -0
- package/bin/cli/router.mjs +66 -0
- package/bin/cli/run-command.mjs +44 -0
- package/bin/cli/scaffold-ownership.mjs +936 -0
- package/bin/cli/scaffold.mjs +687 -0
- package/bin/cli/stage-command.mjs +9 -0
- package/bin/cli/telemetry-command.mjs +18 -0
- package/bin/cli/trusted-runtime.mjs +18 -0
- package/bin/cortex.mjs +12 -1607
- package/bin/daemon-control.mjs +162 -0
- package/mcp-registry-submission.json +1 -1
- package/package.json +8 -3
- package/scaffold/mcp/dist/.cortex-build-hash +1 -0
- package/scaffold/mcp/dist/cli/enterprise-setup.js +134 -0
- package/scaffold/mcp/dist/cli/govern.js +937 -0
- package/scaffold/mcp/dist/cli/query.js +409 -0
- package/scaffold/mcp/dist/cli/run.js +295 -0
- package/scaffold/mcp/dist/cli/stage.js +308 -0
- package/scaffold/mcp/dist/cli/telemetry-test.js +141 -0
- package/scaffold/mcp/dist/cli/ungoverned-detector.js +133 -0
- package/scaffold/mcp/dist/contextEntities.js +282 -0
- package/scaffold/mcp/dist/core/audit/query.js +72 -0
- package/scaffold/mcp/dist/core/audit/writer.js +28 -0
- package/scaffold/mcp/dist/core/config.js +235 -0
- package/scaffold/mcp/dist/core/enterprise-host-identity.js +193 -0
- package/scaffold/mcp/dist/core/enterprise-identity.js +18 -0
- package/scaffold/mcp/dist/core/enterprise-rotation.js +158 -0
- package/scaffold/mcp/dist/core/govern-paths.js +21 -0
- package/scaffold/mcp/dist/core/index.js +14 -0
- package/scaffold/mcp/dist/core/license.js +278 -0
- package/scaffold/mcp/dist/core/policy/enforce.js +66 -0
- package/scaffold/mcp/dist/core/policy/injection.js +172 -0
- package/scaffold/mcp/dist/core/policy/store.js +179 -0
- package/scaffold/mcp/dist/core/rbac/check.js +30 -0
- package/scaffold/mcp/dist/core/secure-endpoint.js +25 -0
- package/scaffold/mcp/dist/core/telemetry/collector.js +285 -0
- package/scaffold/mcp/dist/core/telemetry/state-dir.js +31 -0
- package/scaffold/mcp/dist/core/validators/builtins.js +632 -0
- package/scaffold/mcp/dist/core/validators/config.js +44 -0
- package/scaffold/mcp/dist/core/validators/engine.js +120 -0
- package/scaffold/mcp/dist/core/validators/evaluators/code_comments.js +236 -0
- package/scaffold/mcp/dist/core/validators/evaluators/regex.js +116 -0
- package/scaffold/mcp/dist/core/workflow/artifact-io.js +103 -0
- package/scaffold/mcp/dist/core/workflow/capabilities.js +88 -0
- package/scaffold/mcp/dist/core/workflow/default-workflows.js +102 -0
- package/scaffold/mcp/dist/core/workflow/enforcement.js +164 -0
- package/scaffold/mcp/dist/core/workflow/envelope.js +132 -0
- package/scaffold/mcp/dist/core/workflow/index.js +11 -0
- package/scaffold/mcp/dist/core/workflow/mcp-tools.js +175 -0
- package/scaffold/mcp/dist/core/workflow/resolution.js +69 -0
- package/scaffold/mcp/dist/core/workflow/run-lifecycle.js +123 -0
- package/scaffold/mcp/dist/core/workflow/schemas.js +141 -0
- package/scaffold/mcp/dist/core/workflow/synced-capability-registry.js +60 -0
- package/scaffold/mcp/dist/core/workflow/synced-registry.js +60 -0
- package/scaffold/mcp/dist/daemon/capability-sync-checker.js +242 -0
- package/scaffold/mcp/dist/daemon/client.js +130 -0
- package/scaffold/mcp/dist/daemon/egress-proxy.js +288 -0
- package/scaffold/mcp/dist/daemon/global-host-events.js +222 -0
- package/scaffold/mcp/dist/daemon/heartbeat-pusher.js +116 -0
- package/scaffold/mcp/dist/daemon/heartbeat-tracker.js +165 -0
- package/scaffold/mcp/dist/daemon/host-events-pusher.js +249 -0
- package/scaffold/mcp/dist/daemon/main.js +449 -0
- package/scaffold/mcp/dist/daemon/paths.js +36 -0
- package/scaffold/mcp/dist/daemon/project-service-registry.js +78 -0
- package/scaffold/mcp/dist/daemon/protocol.js +8 -0
- package/scaffold/mcp/dist/daemon/server.js +180 -0
- package/scaffold/mcp/dist/daemon/skill-sync-checker.js +557 -0
- package/scaffold/mcp/dist/daemon/sync-checker.js +165 -0
- package/scaffold/mcp/dist/daemon/ungoverned-scanner.js +136 -0
- package/scaffold/mcp/dist/daemon/workflow-sync-checker.js +249 -0
- package/scaffold/mcp/dist/defaults.js +6 -0
- package/scaffold/mcp/dist/embed.js +627 -0
- package/scaffold/mcp/dist/embedScheduler.js +479 -0
- package/scaffold/mcp/dist/embeddings.js +167 -0
- package/scaffold/mcp/dist/enterprise/audit/push.js +66 -0
- package/scaffold/mcp/dist/enterprise/index.js +327 -0
- package/scaffold/mcp/dist/enterprise/model/deploy.js +27 -0
- package/scaffold/mcp/dist/enterprise/policy/sync.js +129 -0
- package/scaffold/mcp/dist/enterprise/privacy/boundary.js +184 -0
- package/scaffold/mcp/dist/enterprise/reviews/changed-files.js +33 -0
- package/scaffold/mcp/dist/enterprise/reviews/pattern-context.js +202 -0
- package/scaffold/mcp/dist/enterprise/reviews/policy-selection.js +46 -0
- package/scaffold/mcp/dist/enterprise/reviews/push.js +102 -0
- package/scaffold/mcp/dist/enterprise/reviews/trust-state.js +186 -0
- package/scaffold/mcp/dist/enterprise/telemetry/sync.js +57 -0
- package/scaffold/mcp/dist/enterprise/tools/enterprise.js +826 -0
- package/scaffold/mcp/dist/enterprise/tools/harness.js +40 -0
- package/scaffold/mcp/dist/enterprise/tools/walk.js +73 -0
- package/scaffold/mcp/dist/enterprise/violations/push.js +77 -0
- package/scaffold/mcp/dist/enterprise/workflow/push.js +44 -0
- package/scaffold/mcp/dist/enterprise/workflow/state.js +329 -0
- package/scaffold/mcp/dist/frontmatter.js +33 -0
- package/scaffold/mcp/dist/graph.js +769 -0
- package/scaffold/mcp/dist/graphCsv.js +55 -0
- package/scaffold/mcp/dist/graphMetrics.js +8 -0
- package/scaffold/mcp/dist/hooks/permission-request.js +89 -0
- package/scaffold/mcp/dist/hooks/post-tool-use.js +105 -0
- package/scaffold/mcp/dist/hooks/pre-compact.js +29 -0
- package/scaffold/mcp/dist/hooks/pre-tool-use.js +78 -0
- package/scaffold/mcp/dist/hooks/session-end.js +43 -0
- package/scaffold/mcp/dist/hooks/session-start.js +41 -0
- package/scaffold/mcp/dist/hooks/shared.js +194 -0
- package/scaffold/mcp/dist/hooks/stop.js +28 -0
- package/scaffold/mcp/dist/hooks/user-prompt-submit.js +33 -0
- package/scaffold/mcp/dist/impactPresentation.js +137 -0
- package/scaffold/mcp/dist/impactRanking.js +191 -0
- package/scaffold/mcp/dist/impactResponse.js +30 -0
- package/scaffold/mcp/dist/impactResults.js +105 -0
- package/scaffold/mcp/dist/impactSeed.js +20 -0
- package/scaffold/mcp/dist/impactTraversal.js +64 -0
- package/scaffold/mcp/dist/jsonl.js +77 -0
- package/scaffold/mcp/dist/loadGraph.js +759 -0
- package/scaffold/mcp/dist/lruCache.js +38 -0
- package/scaffold/mcp/dist/paths.js +97 -0
- package/scaffold/mcp/dist/patternEvidence.js +272 -0
- package/scaffold/mcp/dist/plugin.js +81 -0
- package/scaffold/mcp/dist/presets.js +78 -0
- package/scaffold/mcp/dist/relatedResponse.js +18 -0
- package/scaffold/mcp/dist/relatedTraversal.js +78 -0
- package/scaffold/mcp/dist/rules.js +23 -0
- package/scaffold/mcp/dist/search.js +212 -0
- package/scaffold/mcp/dist/searchCore.js +457 -0
- package/scaffold/mcp/dist/searchResults.js +230 -0
- package/scaffold/mcp/dist/server.js +317 -0
- package/scaffold/mcp/dist/types.js +1 -0
- package/scaffold/mcp/package-lock.json +321 -200
- package/scaffold/mcp/package.json +15 -6
- package/scaffold/mcp/src/cli/enterprise-setup.ts +82 -8
- package/scaffold/mcp/src/cli/govern.ts +137 -52
- package/scaffold/mcp/src/cli/run.ts +53 -19
- package/scaffold/mcp/src/cli/stage.ts +8 -3
- package/scaffold/mcp/src/core/config.ts +9 -2
- package/scaffold/mcp/src/core/enterprise-host-identity.ts +259 -0
- package/scaffold/mcp/src/core/enterprise-identity.ts +20 -0
- package/scaffold/mcp/src/core/enterprise-rotation.ts +185 -0
- package/scaffold/mcp/src/core/govern-paths.ts +30 -0
- package/scaffold/mcp/src/core/license.ts +186 -17
- package/scaffold/mcp/src/core/secure-endpoint.ts +23 -0
- package/scaffold/mcp/src/core/workflow/enforcement.ts +8 -1
- package/scaffold/mcp/src/core/workflow/mcp-tools.ts +3 -0
- package/scaffold/mcp/src/core/workflow/resolution.ts +9 -1
- package/scaffold/mcp/src/core/workflow/synced-capability-registry.ts +15 -0
- package/scaffold/mcp/src/core/workflow/synced-registry.ts +15 -0
- package/scaffold/mcp/src/daemon/capability-sync-checker.ts +38 -2
- package/scaffold/mcp/src/daemon/egress-proxy.ts +14 -8
- package/scaffold/mcp/src/daemon/global-host-events.ts +288 -0
- package/scaffold/mcp/src/daemon/heartbeat-pusher.ts +4 -0
- package/scaffold/mcp/src/daemon/heartbeat-tracker.ts +2 -0
- package/scaffold/mcp/src/daemon/host-events-pusher.ts +5 -0
- package/scaffold/mcp/src/daemon/main.ts +99 -25
- package/scaffold/mcp/src/daemon/project-service-registry.ts +107 -0
- package/scaffold/mcp/src/daemon/skill-sync-checker.ts +368 -31
- package/scaffold/mcp/src/daemon/sync-checker.ts +4 -0
- package/scaffold/mcp/src/daemon/ungoverned-scanner.ts +57 -25
- package/scaffold/mcp/src/daemon/workflow-sync-checker.ts +41 -2
- package/scaffold/mcp/src/enterprise/audit/push.ts +8 -0
- package/scaffold/mcp/src/enterprise/policy/sync.ts +12 -0
- package/scaffold/mcp/src/enterprise/reviews/push.ts +9 -0
- package/scaffold/mcp/src/enterprise/reviews/trust-state.ts +3 -1
- package/scaffold/mcp/src/enterprise/telemetry/sync.ts +9 -0
- package/scaffold/mcp/src/enterprise/violations/push.ts +9 -0
- package/scaffold/mcp/src/enterprise/workflow/push.ts +7 -0
- package/scaffold/mcp/src/plugin.ts +20 -0
- package/scaffold/mcp/tests/copilot-shim.test.mjs +19 -1
- package/scaffold/mcp/tests/egress-proxy.test.mjs +37 -0
- package/scaffold/mcp/tests/enterprise-identity-sync.test.mjs +401 -0
- package/scaffold/mcp/tests/enterprise-setup.test.mjs +189 -0
- package/scaffold/mcp/tests/global-host-events.test.mjs +81 -0
- package/scaffold/mcp/tests/govern-install.test.mjs +95 -2
- package/scaffold/mcp/tests/govern-repair.test.mjs +20 -3
- package/scaffold/mcp/tests/heartbeat-tracker.test.mjs +26 -0
- package/scaffold/mcp/tests/license.test.mjs +367 -0
- package/scaffold/mcp/tests/project-service-registry.test.mjs +172 -0
- package/scaffold/mcp/tests/review-trust-contract.test.mjs +18 -0
- package/scaffold/mcp/tests/secure-enterprise-endpoint.test.mjs +46 -0
- package/scaffold/mcp/tests/skill-sync-checker.test.mjs +446 -2
- package/scaffold/mcp/tests/ungoverned-scanner.test.mjs +104 -22
- package/scaffold/mcp/tests/workflow-cli.test.mjs +14 -1
- package/scaffold/mcp/tests/workflow-synced-capabilities.test.mjs +37 -0
- package/scaffold/mcp/tests/workflow-synced-registry.test.mjs +40 -1
- package/scaffold/ownership/baseline-v2.4.1.json +22 -0
- package/scaffold/ownership/current.json +4 -0
- package/scaffold/ownership/v1.json +456 -0
- package/scaffold/scripts/ingest-parsers.mjs +1 -387
- package/scaffold/scripts/ingest-worker.mjs +4 -1
- package/scaffold/scripts/ingest.mjs +5 -3899
- package/scaffold/scripts/lib/ingest/arguments.mjs +78 -0
- package/scaffold/scripts/lib/ingest/chunks.mjs +212 -0
- package/scaffold/scripts/lib/ingest/config.mjs +120 -0
- package/scaffold/scripts/lib/ingest/constants.mjs +222 -0
- package/scaffold/scripts/lib/ingest/files.mjs +387 -0
- package/scaffold/scripts/lib/ingest/incremental-state.mjs +131 -0
- package/scaffold/scripts/lib/ingest/io.mjs +78 -0
- package/scaffold/scripts/lib/ingest/main.mjs +76 -0
- package/scaffold/scripts/lib/ingest/parser-composition.mjs +140 -0
- package/scaffold/scripts/lib/ingest/parser-registry.mjs +387 -0
- package/scaffold/scripts/lib/ingest/pipeline-stages.mjs +1625 -0
- package/scaffold/scripts/lib/ingest/projects.mjs +272 -0
- package/scaffold/scripts/lib/ingest/relations.mjs +860 -0
- package/scaffold/scripts/lib/ingest/runtime-paths.mjs +11 -0
- 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
|
+
}
|