ctxora 6.2.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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +441 -0
  3. package/README.vi.md +441 -0
  4. package/bin/ctxora.mjs +147 -0
  5. package/package.json +45 -0
  6. package/pyproject.toml +59 -0
  7. package/src/chunking/compressor.py +104 -0
  8. package/src/chunking/treesitter_chunker.py +240 -0
  9. package/src/compact/anthropic.py +98 -0
  10. package/src/compact/gemini.py +88 -0
  11. package/src/compact/handoff.py +179 -0
  12. package/src/compact/openai.py +318 -0
  13. package/src/compact/summarizer.py +186 -0
  14. package/src/context/assembler.py +298 -0
  15. package/src/context/budgeting.py +137 -0
  16. package/src/context/sanitizer.py +23 -0
  17. package/src/evaluation/__init__.py +1 -0
  18. package/src/evaluation/gates.py +172 -0
  19. package/src/evaluation/metrics.py +41 -0
  20. package/src/harness_context/__init__.py +5 -0
  21. package/src/harness_context/adapters/__init__.py +1 -0
  22. package/src/harness_context/adapters/clients/__init__.py +4 -0
  23. package/src/harness_context/adapters/clients/formatters.py +47 -0
  24. package/src/harness_context/adapters/clients/profiles.py +29 -0
  25. package/src/harness_context/adapters/ecc/__init__.py +4 -0
  26. package/src/harness_context/adapters/ecc/detection.py +41 -0
  27. package/src/harness_context/adapters/ecc/mapping.py +32 -0
  28. package/src/harness_context/adapters/ecc/memory_reader.py +162 -0
  29. package/src/harness_context/adapters/ecc/provenance.py +16 -0
  30. package/src/harness_context/api/__init__.py +1 -0
  31. package/src/harness_context/api/v2/__init__.py +12 -0
  32. package/src/harness_context/api/v2/contracts.py +119 -0
  33. package/src/harness_context/api/v2/diagnostics.py +13 -0
  34. package/src/harness_context/api/v2/enums.py +17 -0
  35. package/src/harness_context/api/v2/errors.py +32 -0
  36. package/src/harness_context/api/v2/models.py +4 -0
  37. package/src/harness_context/api/v2/requests.py +17 -0
  38. package/src/harness_context/api/v2/responses.py +22 -0
  39. package/src/harness_context/application/__init__.py +3 -0
  40. package/src/harness_context/application/container.py +31 -0
  41. package/src/harness_context/application/context_service.py +51 -0
  42. package/src/harness_context/application/ecc_service.py +7 -0
  43. package/src/harness_context/application/handoff_service.py +11 -0
  44. package/src/harness_context/application/memory_service.py +9 -0
  45. package/src/harness_context/application/protocols.py +46 -0
  46. package/src/harness_context/application/refresh_service.py +25 -0
  47. package/src/harness_context/application/retrieval_service.py +22 -0
  48. package/src/harness_context/application/services.py +4 -0
  49. package/src/harness_context/application/workspace_service.py +18 -0
  50. package/src/harness_context/bootstrap.py +47 -0
  51. package/src/harness_context/branding.py +16 -0
  52. package/src/harness_context/cli/__init__.py +1 -0
  53. package/src/harness_context/cli/app.py +239 -0
  54. package/src/harness_context/cli/exit_codes.py +25 -0
  55. package/src/harness_context/domain/__init__.py +9 -0
  56. package/src/harness_context/domain/cag.py +18 -0
  57. package/src/harness_context/domain/chunking.py +17 -0
  58. package/src/harness_context/domain/planning.py +30 -0
  59. package/src/harness_context/domain/ports.py +24 -0
  60. package/src/harness_context/domain/retrieval.py +46 -0
  61. package/src/harness_context/engine.py +10 -0
  62. package/src/harness_context/free_tools.py +143 -0
  63. package/src/harness_context/infrastructure/__init__.py +10 -0
  64. package/src/harness_context/infrastructure/graph.py +26 -0
  65. package/src/harness_context/infrastructure/indexes.py +33 -0
  66. package/src/harness_context/infrastructure/local_engine.py +296 -0
  67. package/src/harness_context/infrastructure/parsing.py +38 -0
  68. package/src/harness_context/infrastructure/scanning.py +51 -0
  69. package/src/harness_context/installer/__init__.py +4 -0
  70. package/src/harness_context/installer/models.py +22 -0
  71. package/src/harness_context/installer/service.py +168 -0
  72. package/src/harness_context/mcp/__init__.py +3 -0
  73. package/src/harness_context/mcp/capabilities.py +11 -0
  74. package/src/harness_context/mcp/errors.py +8 -0
  75. package/src/harness_context/mcp/lifecycle.py +72 -0
  76. package/src/harness_context/mcp/middleware.py +57 -0
  77. package/src/harness_context/mcp/server.py +3 -0
  78. package/src/harness_context/mcp/tool_handlers/__init__.py +7 -0
  79. package/src/harness_context/mcp/tool_handlers/context.py +16 -0
  80. package/src/harness_context/mcp/tool_handlers/ecc.py +8 -0
  81. package/src/harness_context/mcp/tool_handlers/handoffs.py +20 -0
  82. package/src/harness_context/mcp/tool_handlers/memory.py +16 -0
  83. package/src/harness_context/mcp/tool_handlers/workspace.py +12 -0
  84. package/src/harness_context/mcp/tools.py +15 -0
  85. package/src/harness_context/observability/__init__.py +6 -0
  86. package/src/harness_context/observability/events.py +25 -0
  87. package/src/harness_context/observability/metrics.py +20 -0
  88. package/src/harness_context/paths.py +35 -0
  89. package/src/harness_context/runtime.py +127 -0
  90. package/src/harness_context/schemas.py +38 -0
  91. package/src/harness_context/security/__init__.py +3 -0
  92. package/src/harness_context/security/secret_patterns.py +15 -0
  93. package/src/harness_context/server.py +1077 -0
  94. package/src/harness_context/storage/__init__.py +6 -0
  95. package/src/harness_context/storage/migrations.py +24 -0
  96. package/src/harness_context/storage/pins.py +10 -0
  97. package/src/harness_context/storage/snapshots.py +149 -0
  98. package/src/harness_context/tokenize.py +12 -0
  99. package/src/harness_context/topology.py +65 -0
  100. package/src/harness_context/watcher/__init__.py +3 -0
  101. package/src/harness_context/watcher/service.py +32 -0
  102. package/src/harness_context/workspace/__init__.py +13 -0
  103. package/src/harness_context/workspace/identity.py +9 -0
  104. package/src/harness_context/workspace/lock.py +24 -0
  105. package/src/harness_context/workspace/policy.py +3 -0
  106. package/src/harness_context/workspace/roots.py +84 -0
  107. package/src/harness_context/workspace/state.py +35 -0
  108. package/src/memory/episodic.py +257 -0
  109. package/src/memory/vector_store.py +104 -0
  110. package/src/retrieval/bm25.py +23 -0
  111. package/src/retrieval/cache.py +76 -0
  112. package/src/retrieval/embeddings.py +75 -0
  113. package/src/retrieval/graph.py +45 -0
  114. package/src/retrieval/reranker.py +78 -0
  115. package/src/retrieval/tokenize.py +11 -0
package/README.vi.md ADDED
@@ -0,0 +1,441 @@
1
+ <div align="center">
2
+
3
+ # CTXORA Engine
4
+
5
+ ### Index once. Ground every agent.
6
+
7
+ **Context engine local-first dành cho coding agent.**
8
+
9
+ [![CI](https://github.com/nguyentrunghieutcu/ctxora-engine/actions/workflows/ci.yml/badge.svg)](https://github.com/nguyentrunghieutcu/ctxora-engine/actions/workflows/ci.yml)
10
+ [![npm](https://img.shields.io/npm/v/ctxora?logo=npm)](https://www.npmjs.com/package/ctxora)
11
+ [![skills.sh](https://skills.sh/b/nguyentrunghieutcu/ctxora-engine)](https://skills.sh/nguyentrunghieutcu/ctxora-engine)
12
+ [![Python](https://img.shields.io/badge/Python-3.10--3.13-3776AB?logo=python&logoColor=white)](https://www.python.org/)
13
+ [![License](https://img.shields.io/badge/License-MIT-22c55e.svg)](LICENSE)
14
+ [![Local first](https://img.shields.io/badge/Context-local--first-7c3aed)](#quyền-riêng-tư-và-bảo-mật)
15
+ [![Plan](https://img.shields.io/badge/CTXORA_Free-không_giới_hạn-0ea5e9)](docs/PRICING.md)
16
+
17
+ [English](README.md) · **Tiếng Việt**
18
+
19
+ [Bắt đầu nhanh](#bắt-đầu-nhanh) · [Cài đặt](#cài-đặt) · [Agent skills](#agent-skills) · [CLI](#tham-chiếu-cli) · [MCP](#mcp-tools) · [Bảo mật](#quyền-riêng-tư-và-bảo-mật)
20
+
21
+ </div>
22
+
23
+ > [!IMPORTANT]
24
+ > **Nguồn chính thức:** dùng package `ctxora` trên npm hoặc GitHub repository này. Gói `ctxora-engine` không được phát hành trên PyPI. Các package bên thứ ba sử dụng tên CTXORA không được dự án duy trì hoặc kiểm duyệt.
25
+
26
+ CTXORA Engine xây dựng biểu diễn local có thể tái sử dụng của repository và cung cấp đúng evidence cho Codex, Claude Code, Cursor, GitHub Copilot hoặc bất kỳ agent hỗ trợ MCP nào. Source code, index, embedding, graph, memory và handoff đều nằm trên máy của bạn.
27
+
28
+ ## Bắt đầu nhanh
29
+
30
+ ```bash
31
+ npx ctxora setup --workspace /duong-dan/toi/project
32
+ npx ctxora index --workspace /duong-dan/toi/project
33
+ npx ctxora explain --workspace /duong-dan/toi/project \
34
+ "Authentication được triển khai ở đâu?"
35
+ ```
36
+
37
+ Kết quả là JSON có cấu trúc, gồm file liên quan, symbol, tín hiệu dependency, provenance, coverage diagnostics và test hoặc convention được đề xuất khi có thể xác định.
38
+
39
+ ## Vì sao cần CTXORA?
40
+
41
+ Coding agent thường tốn token để khám phá lại repository, chọn sai layer, bỏ sót convention hoặc mất context giữa các phiên. Instruction file tĩnh giúp định hướng, nhưng không tự chọn evidence phù hợp với từng task.
42
+
43
+ CTXORA bổ sung một lớp context local:
44
+
45
+ ```text
46
+ Repository
47
+ ↓ scan, parse, chunk
48
+ Immutable local snapshot
49
+ ↓ lexical + semantic + symbol + path + graph indexes
50
+ Context planner
51
+ ↓ CAG / RAG / long context / graph-augmented retrieval
52
+ Codex · Claude Code · Cursor · Copilot · MCP clients
53
+ ```
54
+
55
+ - **Giảm sửa sai file** — tìm module, dependency path và test liên quan.
56
+ - **Giảm prompt lặp lại** — tái sử dụng kiến thức repository giữa nhiều phiên agent.
57
+ - **Không khóa vào một agent** — một engine phục vụ nhiều coding tool.
58
+ - **Riêng tư mặc định** — không hosted index, remote telemetry hoặc cloud account bắt buộc.
59
+ - **Evidence có thể kiểm tra** — mỗi kết quả đều có source path và provenance.
60
+
61
+ ## Bạn nhận được gì
62
+
63
+ ### Local context engine
64
+
65
+ - AST-aware chunking cho Python, JavaScript và TypeScript; fallback chunking có giới hạn cho định dạng text khác.
66
+ - Hybrid lexical và local semantic retrieval bằng BM25, TF-IDF/LSA, keyword overlap, symbol và path.
67
+ - Code dependency graph và graph-augmented context selection.
68
+ - Các strategy CAG, RAG, hybrid CAG/RAG, long context và graph augmented.
69
+ - Immutable snapshot với candidate validation, atomic promotion, recovery và incremental refresh.
70
+ - SQLite memory và raw conversation handoff theo workspace.
71
+ - Token budgeting cho context window của OpenAI, Anthropic và Gemini.
72
+
73
+ ### Onboarding coding agent
74
+
75
+ ```bash
76
+ ctxora repo-map --workspace .
77
+ ctxora context-score --workspace .
78
+ ctxora generate-agents-md --workspace .
79
+ ctxora generate-copilot-instructions --workspace .
80
+ ctxora generate-cursor-rules --workspace .
81
+ ```
82
+
83
+ Các instruction file được sinh theo cách deterministic và không ghi đè file hiện có nếu thiếu `--force`.
84
+
85
+ ### An toàn và vận hành
86
+
87
+ - Authorization theo canonical workspace root và chặn symlink thoát khỏi root.
88
+ - Loại secret-like file, binary, dependency, VCS, generated state và file quá lớn.
89
+ - Nội dung repository được retrieve luôn là untrusted evidence, không phải agent instruction.
90
+ - Machine-readable diagnostics, context health report, evaluation gate và CLI exit code ổn định.
91
+ - `ctxora ci` local để index file thay đổi giữa hai Git ref.
92
+
93
+ ## Cài đặt
94
+
95
+ ### npm / npx — khuyến nghị
96
+
97
+ ```bash
98
+ npx ctxora setup --workspace /duong-dan/toi/project
99
+ npx ctxora doctor --workspace /duong-dan/toi/project
100
+ ```
101
+
102
+ Npm launcher không có dependency ngoài, đóng gói source Python MIT và cài CTXORA Engine vào environment local theo version. Không cần cài Python package global hoặc tạo cloud account. Máy cần có sẵn Python 3.10–3.13.
103
+
104
+ Nếu muốn có shell command lâu dài:
105
+
106
+ ```bash
107
+ npm install --global ctxora
108
+ ctxora setup --workspace /duong-dan/toi/project
109
+ ```
110
+
111
+ ### Cài trực tiếp từ GitHub
112
+
113
+ ```bash
114
+ python3 -m pip install \
115
+ "git+https://github.com/nguyentrunghieutcu/ctxora-engine.git"
116
+ ```
117
+
118
+ ### Cài từ source clone
119
+
120
+ ```bash
121
+ git clone https://github.com/nguyentrunghieutcu/ctxora-engine.git
122
+ cd ctxora-engine
123
+ python3 -m pip install .
124
+ ctxora doctor --workspace .
125
+ ```
126
+
127
+ ### Môi trường phát triển
128
+
129
+ ```bash
130
+ python3 -m venv .venv
131
+ source .venv/bin/activate
132
+ python -m pip install -e '.[dev]'
133
+ ```
134
+
135
+ Yêu cầu: Python 3.10–3.13 và Git. Runtime state nằm trong `.ctxora/`; state `.harness/` cũ vẫn đọc được trong giai đoạn migration.
136
+
137
+ ## Agent skills
138
+
139
+ Cài toàn bộ CTXORA skills từ repository này:
140
+
141
+ ```bash
142
+ npx skills add nguyentrunghieutcu/ctxora-engine
143
+ ```
144
+
145
+ Liệt kê hoặc chỉ cài một skill:
146
+
147
+ ```bash
148
+ npx skills add nguyentrunghieutcu/ctxora-engine --list
149
+ npx skills add nguyentrunghieutcu/ctxora-engine --skill ctxora-setup
150
+ ```
151
+
152
+ Pack gồm các workflow setup, grounded repository context và context health. Phiên bản hiện tại của `skills` CLI yêu cầu Node.js 22.20 trở lên.
153
+
154
+ ## Kết nối coding agent
155
+
156
+ CTXORA có thể cập nhật an toàn cấu hình client được hỗ trợ và giữ nguyên các entry không liên quan:
157
+
158
+ ```bash
159
+ ctxora profile --workspace .
160
+ ctxora install --workspace . --profile codex
161
+ ctxora install --workspace . --profile claude-code
162
+ ctxora install --workspace . --profile cursor
163
+ ctxora install --workspace . --profile generic-mcp
164
+ ```
165
+
166
+ Dùng `--dry-run` để xem trước và `--client-config` để chọn file cấu hình khác mặc định.
167
+
168
+ | Profile | Cấu hình mặc định |
169
+ |---|---|
170
+ | Codex | `~/.codex/config.toml` |
171
+ | Claude Code | `~/.claude.json` |
172
+ | Cursor | `~/.cursor/mcp.json` |
173
+ | Generic MCP | `~/.config/mcp/servers.json` |
174
+
175
+ Cấu hình MCP thủ công:
176
+
177
+ ```json
178
+ {
179
+ "mcpServers": {
180
+ "ctxora": {
181
+ "command": "ctxora",
182
+ "args": ["run", "--workspace", "/absolute/path/to/project", "--transport", "stdio"],
183
+ "env": {
184
+ "CTXORA_ALLOWED_ROOTS": "/absolute/path/to/project",
185
+ "PYTHONUTF8": "1"
186
+ }
187
+ }
188
+ }
189
+ }
190
+ ```
191
+
192
+ Không commit cấu hình client chứa đường dẫn cá nhân.
193
+
194
+ ## Workflow chính
195
+
196
+ ### Tìm hiểu repository
197
+
198
+ ```bash
199
+ ctxora setup --workspace .
200
+ ctxora index --workspace .
201
+ ctxora query --workspace . "Luồng xác thực request hoạt động thế nào?"
202
+ ctxora explain --workspace . "Nên sửa token rotation ở đâu?"
203
+ ctxora inspect --workspace . snapshot
204
+ ```
205
+
206
+ ### Refresh file thay đổi
207
+
208
+ ```bash
209
+ ctxora index --workspace . --incremental
210
+ ctxora ci --workspace . --base origin/main --head HEAD
211
+ ```
212
+
213
+ ### Chạy MCP server
214
+
215
+ ```bash
216
+ # Transport local được khuyến nghị
217
+ ctxora run --workspace . --transport stdio
218
+
219
+ # HTTP local
220
+ ctxora run --workspace . --transport streamable-http \
221
+ --host 127.0.0.1 --port 8765
222
+ ```
223
+
224
+ Bind HTTP ra ngoài loopback cần `--allow-external` và phải được bảo vệ bằng authorization layer trước khi dùng production.
225
+
226
+ ### Export và sửa local state
227
+
228
+ ```bash
229
+ ctxora export --workspace . --output ./ctxora-snapshot.json
230
+ ctxora doctor --workspace .
231
+ ctxora repair --workspace .
232
+ ```
233
+
234
+ ## Tham chiếu CLI
235
+
236
+ | Command | Mục đích |
237
+ |---|---|
238
+ | `setup` | Tạo cấu hình local cho workspace. |
239
+ | `register` | Đăng ký và authorize workspace. |
240
+ | `run` | Chạy CTXORA MCP foreground. |
241
+ | `start`, `status`, `stop` | Quản lý background process local. |
242
+ | `index` | Build hoặc refresh local snapshot. |
243
+ | `query` | Trả về context package có cấu trúc. |
244
+ | `explain` | Giải thích vị trí và cách thực hiện thay đổi. |
245
+ | `context-score` | Chấm điểm độ sẵn sàng của repository context. |
246
+ | `repo-map` | Tạo repository map cô đọng. |
247
+ | `inspect` | Xem workspace, snapshot, bundle hoặc ECC state. |
248
+ | `doctor`, `repair` | Chẩn đoán hoặc build lại local state. |
249
+ | `export` | Export snapshot ra JSON. |
250
+ | `profile` | Liệt kê coding-agent profile được hỗ trợ. |
251
+ | `install`, `uninstall` | Thêm hoặc gỡ cấu hình MCP client an toàn. |
252
+ | `ci` | Refresh file thay đổi giữa hai Git ref. |
253
+ | `generate-agents-md` | Sinh repository instructions cho agent. |
254
+ | `generate-copilot-instructions` | Sinh GitHub Copilot instructions. |
255
+ | `generate-cursor-rules` | Sinh Cursor rules. |
256
+ | `pro` | Hiển thị trạng thái waitlist, không cài paid feature. |
257
+
258
+ Mọi command đều hỗ trợ `--workspace`. Chạy `ctxora <command> --help` để xem option cụ thể.
259
+
260
+ ## MCP tools
261
+
262
+ CTXORA MCP hiện cung cấp 24 tools.
263
+
264
+ ### Context và workspace
265
+
266
+ | Tool | Mục đích |
267
+ |---|---|
268
+ | `register_workspace` | Đăng ký repository root được phép. |
269
+ | `refresh_workspace` | Build hoặc incremental refresh snapshot. |
270
+ | `plan_context` | Chọn retrieval strategy cho task. |
271
+ | `retrieve_context` | Trả ranked evidence và coverage diagnostics. |
272
+ | `prepare_context` | Tạo context package theo token budget. |
273
+ | `context_stats` | Xem thống kê index và snapshot. |
274
+ | `invalidate_context` | Invalidate index hoặc cached state. |
275
+ | `retrieve_context_legacy` | Compatibility entry point cho client cũ. |
276
+
277
+ ### Memory và handoff
278
+
279
+ | Tool | Mục đích |
280
+ |---|---|
281
+ | `memory_save`, `memory_search`, `memory_inject` | Lưu, tìm và inject knowledge theo scope. |
282
+ | `memory_list`, `memory_delete`, `memory_evict`, `memory_stats` | Quản lý vòng đời local memory. |
283
+ | `handoff_conversation` | Lưu raw provider-format conversation handoff. |
284
+ | `restore_conversation_handoff` | Khôi phục handoff được chọn rõ ràng. |
285
+ | `list_conversation_handoffs` | Liệt kê handoff còn lưu. |
286
+ | `delete_conversation_handoff`, `purge_expired_handoffs` | Xóa handoff được chọn hoặc đã hết hạn. |
287
+
288
+ ### Tiện ích
289
+
290
+ | Tool | Mục đích |
291
+ |---|---|
292
+ | `estimate_tokens` | Ước tính token cho text. |
293
+ | `get_token_budget` | Trả context budget và reserved headroom của model. |
294
+ | `invalidate_cache` | Xóa retrieval cache. |
295
+ | `reindex_paths` | Force reindex các path được chọn. |
296
+
297
+ JSON Schema API v2 nằm tại [`schemas/mcp-v2/`](schemas/mcp-v2/).
298
+
299
+ ## Retrieval strategies
300
+
301
+ | Strategy | Phù hợp với |
302
+ |---|---|
303
+ | `cag` | Instruction ổn định và repository knowledge cô đọng. |
304
+ | `hybrid_rag` | Câu hỏi code cần ranked evidence tập trung. |
305
+ | `long_context` | Repository nhỏ nằm trong token budget. |
306
+ | `hybrid_cag_rag` | Guidance ổn định kết hợp evidence theo task. |
307
+ | `graph_augmented` | Kiến trúc, call path, dependency và impact analysis. |
308
+
309
+ Planner deterministic và có thể override khi caller cần strategy cụ thể.
310
+
311
+ ## Tích hợp ECC
312
+
313
+ CTXORA có thể đọc vault format [`ecc.memory.v1`](https://github.com/affaan-m/ECC) như external context tùy chọn. CTXORA không cài, clone, gọi hoặc sửa ECC.
314
+
315
+ ```bash
316
+ ctxora run --workspace . --transport stdio --ecc
317
+ ctxora inspect --workspace . --ecc ecc
318
+ ```
319
+
320
+ Project memory tại `.ecc/memory` chỉ được đọc. User memory tại `~/.ecc/memory` bị tắt trừ khi bật `--ecc-user-scope` hoặc `ecc_allow_user_scope = true`. Memory import có external provenance và trạng thái unreviewed trust.
321
+
322
+ ## Kiến trúc
323
+
324
+ ```text
325
+ CLI / MCP / CI transports
326
+
327
+ Application services
328
+
329
+ Domain contracts and planning
330
+
331
+ Local scanners · parsers · indexes · graph · snapshots · SQLite
332
+ ```
333
+
334
+ Production package dùng `src/` layout. `harness_context` vẫn là internal Python namespace để tương thích; branding và command public dùng CTXORA. Xem [Architecture](docs/ARCHITECTURE.md) và [OSS release scope](docs/OSS-IMPLEMENTATION-PLAN.md).
335
+
336
+ ## Quyền riêng tư và bảo mật
337
+
338
+ - Không remote telemetry mặc định.
339
+ - Không yêu cầu cloud account hoặc hosted index.
340
+ - Workspace root được authorize và canonicalize rõ ràng.
341
+ - Symlink không thể thoát khỏi root được phép.
342
+ - Secret-like và binary file bị loại trước indexing.
343
+ - Retrieved source là untrusted evidence và không thể ghi đè agent instruction.
344
+ - External HTTP là opt-in và cần authorization layer do bạn quản lý.
345
+
346
+ Báo cáo lỗ hổng qua [GitHub Private Vulnerability Reporting](https://github.com/nguyentrunghieutcu/ctxora-engine/security/advisories/new). Nếu kênh đó không dùng được, gửi email tới `nguyentrunghieutcu@gmail.com`. Xem [SECURITY.md](SECURITY.md).
347
+
348
+ ## Free và Pro
349
+
350
+ ### CTXORA Free — đã có
351
+
352
+ Toàn bộ local engine trong repository MIT này miễn phí và không giới hạn: manual indexing, CAG/RAG/graph retrieval, MCP, local memory, handoff, health tools, repository map và instruction generation.
353
+
354
+ ### CTXORA Pro — waitlist
355
+
356
+ Phạm vi trả phí dự kiến chỉ gồm managed repository automation, private workflow operations và shared team context. Billing, entitlement, hosted automation và team service chưa được triển khai trong repository này. `ctxora pro` chỉ trả thông tin waitlist.
357
+
358
+ Xem [product boundary](docs/PRICING.md).
359
+
360
+ ## Cấu trúc project
361
+
362
+ ```text
363
+ src/harness_context/ Runtime, domain, application, MCP, CLI, storage
364
+ src/chunking/ AST-aware và fallback chunking
365
+ src/context/ Assembly, sanitization, token budgeting
366
+ src/retrieval/ BM25, local embeddings, graph, reranking, cache
367
+ src/memory/ Local episodic và vector memory
368
+ src/compact/ Provider handoff và compaction helpers
369
+ src/evaluation/ Quality metrics và release gates
370
+ bin/ npm/npx launcher không có dependency ngoài
371
+ skills/ Coding-agent skills có thể cài đặt
372
+ schemas/mcp-v2/ API v2 JSON Schemas công khai
373
+ tests/ Unit, security, evaluation, E2E, packaging tests
374
+ scripts/ Install, uninstall, migration, topology audit
375
+ ```
376
+
377
+ ## Phát triển và kiểm tra
378
+
379
+ ```bash
380
+ npm test
381
+ npm pack --dry-run
382
+ ruff check .
383
+ python scripts/audit_topology.py
384
+ python -m unittest discover -s tests -t . -v
385
+ python -m evaluation.gates
386
+ python -m compileall -q src tests scripts
387
+ git diff --check
388
+ ```
389
+
390
+ CI matrix chạy Python 3.10, 3.11, 3.12 và 3.13. Evaluation fixture bao gồm Python, TypeScript, Flutter, monorepo, tiếng Việt, malicious prompt-like file, long document và duplicate symbol.
391
+
392
+ ## Xử lý sự cố
393
+
394
+ ### Không tìm thấy `ctxora`
395
+
396
+ Dùng npm launcher mà không cần cài global command:
397
+
398
+ ```bash
399
+ npx ctxora --version
400
+ npx ctxora doctor --workspace .
401
+ ```
402
+
403
+ ### Workspace bị từ chối
404
+
405
+ Dùng đường dẫn tuyệt đối đang tồn tại và bảo đảm nó nằm trong `CTXORA_ALLOWED_ROOTS` nếu MCP client thiết lập allowlist.
406
+
407
+ ### Instruction file hiện có không được thay thế
408
+
409
+ Đây là hành vi chủ động để bảo vệ dữ liệu. Kiểm tra output hoặc chỉ chạy lại với `--force` khi thật sự muốn ghi đè.
410
+
411
+ ### HTTP binding bị từ chối
412
+
413
+ Loopback là security boundary mặc định. Chỉ dùng `--allow-external` phía sau authentication và network-access layer do bạn kiểm soát.
414
+
415
+ ### Cần build lại local state
416
+
417
+ ```bash
418
+ ctxora doctor --workspace .
419
+ ctxora repair --workspace .
420
+ ```
421
+
422
+ ## Tài liệu
423
+
424
+ - [OSS release scope](docs/OSS-IMPLEMENTATION-PLAN.md)
425
+ - [Architecture](docs/ARCHITECTURE.md)
426
+ - [Operations](docs/OPERATIONS.md)
427
+ - [Free và Pro boundary](docs/PRICING.md)
428
+ - [Security policy](SECURITY.md)
429
+ - [Support policy](SUPPORT.md)
430
+ - [Contributing](CONTRIBUTING.md)
431
+ - [Changelog](CHANGELOG.md)
432
+
433
+ ## Cộng đồng
434
+
435
+ - Mở [GitHub issue](https://github.com/nguyentrunghieutcu/ctxora-engine/issues) cho bug tái hiện được và feature request.
436
+ - Dùng private vulnerability reporting cho vấn đề bảo mật.
437
+ - Chào đón contribution giữ nguyên local-first và paid-control-plane independence boundary.
438
+
439
+ ## License
440
+
441
+ CTXORA Engine được phát hành theo [MIT License](LICENSE).
package/bin/ctxora.mjs ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { dirname, join, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { spawnSync } from "node:child_process";
8
+
9
+ const PACKAGE_VERSION = "6.2.0";
10
+ const PYTHON_RANGE = "3.10-3.13";
11
+ const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
12
+
13
+ function fail(message) {
14
+ console.error(`ctxora: ${message}`);
15
+ process.exitCode = 1;
16
+ }
17
+
18
+ function run(command, args, options = {}) {
19
+ return spawnSync(command, args, {
20
+ encoding: "utf8",
21
+ stdio: options.capture ? "pipe" : "inherit",
22
+ env: options.env ?? process.env,
23
+ });
24
+ }
25
+
26
+ export function parsePythonVersion(output) {
27
+ const match = output.match(/Python\s+(\d+)\.(\d+)\.(\d+)/);
28
+ return match ? match.slice(1).map(Number) : null;
29
+ }
30
+
31
+ export function isSupportedPython(version) {
32
+ return Boolean(version && version[0] === 3 && version[1] >= 10 && version[1] <= 13);
33
+ }
34
+
35
+ function pythonCandidates() {
36
+ if (process.env.CTXORA_PYTHON) {
37
+ return [{ command: process.env.CTXORA_PYTHON, prefix: [] }];
38
+ }
39
+ return process.platform === "win32"
40
+ ? [{ command: "py", prefix: ["-3"] }, { command: "python", prefix: [] }, { command: "python3", prefix: [] }]
41
+ : [{ command: "python3", prefix: [] }, { command: "python", prefix: [] }];
42
+ }
43
+
44
+ export function findPython() {
45
+ for (const candidate of pythonCandidates()) {
46
+ const result = run(candidate.command, [...candidate.prefix, "--version"], { capture: true });
47
+ const version = parsePythonVersion(`${result.stdout ?? ""}${result.stderr ?? ""}`);
48
+ if (!result.error && result.status === 0 && isSupportedPython(version)) {
49
+ return candidate;
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+
55
+ export function runtimeRoot(environment = process.env) {
56
+ if (environment.CTXORA_HOME) return resolve(environment.CTXORA_HOME);
57
+ if (process.platform === "win32") {
58
+ return join(environment.LOCALAPPDATA || join(homedir(), "AppData", "Local"), "CTXORA");
59
+ }
60
+ return join(environment.XDG_DATA_HOME || join(homedir(), ".local", "share"), "ctxora");
61
+ }
62
+
63
+ export function runtimePython(runtimeDirectory) {
64
+ return process.platform === "win32"
65
+ ? join(runtimeDirectory, "venv", "Scripts", "python.exe")
66
+ : join(runtimeDirectory, "venv", "bin", "python");
67
+ }
68
+
69
+ function markerMatches(markerPath) {
70
+ try {
71
+ const marker = JSON.parse(readFileSync(markerPath, "utf8"));
72
+ return marker.packageVersion === PACKAGE_VERSION;
73
+ } catch {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ function installRuntime(systemPython, runtimeDirectory) {
79
+ const parent = dirname(runtimeDirectory);
80
+ mkdirSync(parent, { recursive: true });
81
+ const staging = join(parent, `.install-${process.pid}-${Date.now()}`);
82
+ rmSync(staging, { recursive: true, force: true });
83
+
84
+ const create = run(systemPython.command, [...systemPython.prefix, "-m", "venv", join(staging, "venv")]);
85
+ if (create.error || create.status !== 0) {
86
+ rmSync(staging, { recursive: true, force: true });
87
+ throw new Error("could not create the managed Python environment");
88
+ }
89
+
90
+ const python = runtimePython(staging);
91
+ const install = run(python, [
92
+ "-m", "pip", "install", "--disable-pip-version-check", "--upgrade", PACKAGE_ROOT,
93
+ ]);
94
+ if (install.error || install.status !== 0) {
95
+ rmSync(staging, { recursive: true, force: true });
96
+ throw new Error("could not install CTXORA Engine into the managed environment");
97
+ }
98
+
99
+ writeFileSync(join(staging, "install.json"), `${JSON.stringify({ packageVersion: PACKAGE_VERSION }, null, 2)}\n`);
100
+ rmSync(runtimeDirectory, { recursive: true, force: true });
101
+ renameSync(staging, runtimeDirectory);
102
+ }
103
+
104
+ export function ensureRuntime() {
105
+ const runtimeDirectory = join(runtimeRoot(), "runtime", PACKAGE_VERSION);
106
+ const python = runtimePython(runtimeDirectory);
107
+ if (existsSync(python) && markerMatches(join(runtimeDirectory, "install.json"))) return python;
108
+
109
+ const systemPython = findPython();
110
+ if (!systemPython) throw new Error(`Python ${PYTHON_RANGE} is required`);
111
+ installRuntime(systemPython, runtimeDirectory);
112
+ return runtimePython(runtimeDirectory);
113
+ }
114
+
115
+ function printHelp() {
116
+ console.log(`CTXORA Engine ${PACKAGE_VERSION}\n\nUsage:\n npx ctxora setup --workspace <path>\n npx ctxora <command> [options]\n\nThe npm launcher installs CTXORA Engine into a versioned local Python environment.\nRun \"npx ctxora setup --help\" for engine command help.`);
117
+ }
118
+
119
+ export function main(args = process.argv.slice(2)) {
120
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
121
+ printHelp();
122
+ return 0;
123
+ }
124
+ if (args[0] === "--version" || args[0] === "-V") {
125
+ console.log(PACKAGE_VERSION);
126
+ return 0;
127
+ }
128
+
129
+ try {
130
+ const python = ensureRuntime();
131
+ const environment = {
132
+ ...process.env,
133
+ CTXORA_MCP_COMMAND: python,
134
+ CTXORA_MCP_ARGS_PREFIX: JSON.stringify(["-m", "harness_context.cli.app"]),
135
+ };
136
+ const result = run(python, ["-m", "harness_context.cli.app", ...args], { env: environment });
137
+ if (result.error) throw result.error;
138
+ return result.status ?? 1;
139
+ } catch (error) {
140
+ fail(error instanceof Error ? error.message : String(error));
141
+ return 1;
142
+ }
143
+ }
144
+
145
+ if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
146
+ process.exitCode = main();
147
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "ctxora",
3
+ "version": "6.2.0",
4
+ "description": "Local-first context engine for coding agents.",
5
+ "type": "module",
6
+ "bin": {
7
+ "ctxora": "bin/ctxora.mjs"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src/**/*.py",
12
+ "pyproject.toml",
13
+ "README.md",
14
+ "README.vi.md",
15
+ "LICENSE"
16
+ ],
17
+ "scripts": {
18
+ "test": "node --test tests/npm/*.test.mjs"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "keywords": [
24
+ "ai-agents",
25
+ "coding-agents",
26
+ "context-engineering",
27
+ "mcp",
28
+ "rag",
29
+ "codex",
30
+ "claude-code",
31
+ "cursor"
32
+ ],
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/nguyentrunghieutcu/ctxora-engine.git"
36
+ },
37
+ "homepage": "https://github.com/nguyentrunghieutcu/ctxora-engine#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/nguyentrunghieutcu/ctxora-engine/issues"
40
+ },
41
+ "license": "MIT",
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }
package/pyproject.toml ADDED
@@ -0,0 +1,59 @@
1
+ [build-system]
2
+ requires = ["setuptools>=75", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ctxora-engine"
7
+ version = "6.2.0"
8
+ description = "Local-first context engine for coding agents."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "mcp>=1.0,<2",
13
+ "networkx>=3.2,<4",
14
+ "numpy>=1.26,<3",
15
+ "rank-bm25>=0.2.2,<0.3",
16
+ "scikit-learn>=1.4,<2",
17
+ "tiktoken>=0.7,<1",
18
+ "tomli>=2,<3; python_version < '3.11'",
19
+ "tree-sitter>=0.22,<0.26",
20
+ "tree-sitter-javascript>=0.23,<0.24",
21
+ "tree-sitter-python>=0.23,<0.24",
22
+ "tree-sitter-typescript>=0.23,<0.24",
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ dev = ["pytest>=8,<9", "ruff>=0.12,<1", "mypy>=1.17,<2"]
27
+
28
+ [project.scripts]
29
+ ctxora-mcp = "harness_context.server:main"
30
+ ctxora = "harness_context.cli.app:main"
31
+
32
+ [tool.setuptools]
33
+ package-dir = {"" = "src"}
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+ include = ["harness_context*", "chunking*", "compact*", "context*", "memory*", "retrieval*", "evaluation*"]
38
+
39
+ [tool.pytest.ini_options]
40
+ testpaths = ["tests"]
41
+
42
+ [tool.mypy]
43
+ python_version = "3.10"
44
+ check_untyped_defs = true
45
+ ignore_missing_imports = true
46
+
47
+ [tool.ruff]
48
+ target-version = "py310"
49
+ line-length = 100
50
+
51
+ [tool.ruff.lint.per-file-ignores]
52
+ "src/chunking/treesitter_chunker.py" = ["BLE001"]
53
+ "src/compact/gemini.py" = ["SIM102"]
54
+ "src/compact/openai.py" = ["BLE001"]
55
+ "src/harness_context/domain/planning.py" = ["RUF012"]
56
+ "src/harness_context/server.py" = ["BLE001", "G201"]
57
+ "src/harness_context/watcher/service.py" = ["BLE001", "S112"]
58
+ "tests/packaging/test_clean_environment.py" = ["ISC004", "PLW1510"]
59
+ "tests/test_phase_b_workspace_storage.py" = ["BLE001", "SIM117"]