neurain 0.1.0-alpha.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 (89) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +57 -0
  3. package/README.md +205 -0
  4. package/SECURITY.md +22 -0
  5. package/bin/neurain.mjs +7 -0
  6. package/docs/comparison-mem0.en.md +22 -0
  7. package/docs/connect-claude.en.md +48 -0
  8. package/docs/connect-claude.kr.md +51 -0
  9. package/docs/connect-codex.en.md +38 -0
  10. package/docs/connect-codex.kr.md +40 -0
  11. package/docs/connect-gemini.en.md +71 -0
  12. package/docs/connect-gemini.kr.md +71 -0
  13. package/docs/connect-runtime.en.md +61 -0
  14. package/docs/connect-runtime.kr.md +61 -0
  15. package/docs/development-status.en.md +157 -0
  16. package/docs/development-status.kr.md +157 -0
  17. package/docs/knowledge-os.en.md +105 -0
  18. package/docs/knowledge-os.kr.md +106 -0
  19. package/docs/pricing.en.md +14 -0
  20. package/docs/privacy-and-data-flow.en.md +25 -0
  21. package/docs/public-saas-readiness.en.md +39 -0
  22. package/docs/quickstart.en.md +64 -0
  23. package/docs/quickstart.kr.md +64 -0
  24. package/docs/release-checklist.en.md +38 -0
  25. package/docs/safety.en.md +36 -0
  26. package/docs/self-improvement-90-roadmap.en.md +429 -0
  27. package/docs/self-improvement-90-roadmap.kr.md +429 -0
  28. package/docs/self-improving-workflows.en.md +163 -0
  29. package/docs/self-improving-workflows.kr.md +163 -0
  30. package/docs/support.en.md +17 -0
  31. package/docs/troubleshooting.en.md +35 -0
  32. package/package.json +36 -0
  33. package/src/cli.mjs +261 -0
  34. package/src/core/adopt.mjs +304 -0
  35. package/src/core/answer_eval.mjs +450 -0
  36. package/src/core/capabilities.mjs +217 -0
  37. package/src/core/capture_durable.mjs +181 -0
  38. package/src/core/classify.mjs +237 -0
  39. package/src/core/compile_desk.mjs +324 -0
  40. package/src/core/complete.mjs +108 -0
  41. package/src/core/config.mjs +142 -0
  42. package/src/core/connect.mjs +355 -0
  43. package/src/core/curator.mjs +351 -0
  44. package/src/core/daemon.mjs +536 -0
  45. package/src/core/digest.mjs +155 -0
  46. package/src/core/doctor.mjs +115 -0
  47. package/src/core/durable.mjs +96 -0
  48. package/src/core/envelope.mjs +97 -0
  49. package/src/core/flush.mjs +190 -0
  50. package/src/core/fs.mjs +121 -0
  51. package/src/core/init.mjs +194 -0
  52. package/src/core/journal.mjs +269 -0
  53. package/src/core/labels.mjs +117 -0
  54. package/src/core/lessons.mjs +793 -0
  55. package/src/core/lifecycle.mjs +1138 -0
  56. package/src/core/link_check.mjs +180 -0
  57. package/src/core/live_cases.mjs +221 -0
  58. package/src/core/onboard.mjs +175 -0
  59. package/src/core/plan_receipt.mjs +177 -0
  60. package/src/core/plan_writeback.mjs +176 -0
  61. package/src/core/queue.mjs +62 -0
  62. package/src/core/queue_archive.mjs +87 -0
  63. package/src/core/queue_model.mjs +161 -0
  64. package/src/core/queue_write.mjs +28 -0
  65. package/src/core/recall.mjs +1802 -0
  66. package/src/core/recall_bench.mjs +275 -0
  67. package/src/core/recall_corpus.mjs +152 -0
  68. package/src/core/recall_facts.mjs +233 -0
  69. package/src/core/recall_intel.mjs +233 -0
  70. package/src/core/recall_lexical.mjs +269 -0
  71. package/src/core/recap.mjs +78 -0
  72. package/src/core/review_queue.mjs +131 -0
  73. package/src/core/review_worker.mjs +284 -0
  74. package/src/core/route.mjs +73 -0
  75. package/src/core/safety.mjs +57 -0
  76. package/src/core/scheduler.mjs +697 -0
  77. package/src/core/search.mjs +54 -0
  78. package/src/core/secret_scan.mjs +143 -0
  79. package/src/core/semantic.mjs +187 -0
  80. package/src/core/source_digest.mjs +56 -0
  81. package/src/core/source_digest_gen.mjs +311 -0
  82. package/src/core/stage.mjs +105 -0
  83. package/src/core/status.mjs +175 -0
  84. package/src/core/vault_state.mjs +115 -0
  85. package/src/core/watch.mjs +282 -0
  86. package/src/core/wiki_log.mjs +29 -0
  87. package/src/core/wrap.mjs +62 -0
  88. package/src/mcp/server.mjs +865 -0
  89. package/templates/starter-vault/README.md +9 -0
@@ -0,0 +1,163 @@
1
+ # [kr] 자기개선 워크플로우
2
+
3
+ 버전: 0.14
4
+
5
+ Neurain Knowledge OS는 LLM을 학습시키거나 대체하지 않습니다. Codex, Claude Code, Gemini CLI, Agent Runtime, OpenClaw 같은 AI host가 더 잘 일하도록 안전한 local memory layer를 제공합니다.
6
+
7
+ Agent Runtime는 model이 아니라 agent runtime입니다. Neurain의 역할은 이런 runtime들이 함께 쓸 수 있는 local-first Knowledge OS layer를 제공하는 것입니다.
8
+
9
+ Runtime에서 흡수한 핵심 루프는 다음과 같습니다.
10
+
11
+ 1. 사용자가 로컬 폴더에서 작업합니다.
12
+ 2. Neurain은 source-grounded evidence를 읽거나 캡처합니다.
13
+ 3. `neurain wrap <folder> --dry-run`이 최근 작업 신호를 요약합니다.
14
+ 4. `neurain journal add`가 검토된 local event를 receipt와 함께 append할 수 있습니다.
15
+ 5. `neurain watch <folder> --poll-once`가 최근 파일, journal event, recap hint, lesson candidate를 읽어 read-only candidate report를 만듭니다.
16
+ 6. `neurain review <folder> --json`이 그 신호를 read-only review worker report로 바꾸고 manual improvement proposal을 만듭니다.
17
+ 7. `neurain scheduler tick <folder> --json`이 해당 신호가 review worker report를 포함할 만큼 강한지 판단합니다.
18
+ 8. `neurain scheduler eval <folder> --fixture-size 100`이 background review 품질을 주장하기 전에 trigger precision, trigger recall, no-recursion, private boundary, target-root non-write를 확인합니다.
19
+ 9. `neurain scheduler monitor <folder> --max-ticks 3`가 사용자가 명령을 켜 둔 동안 read-only tick을 foreground에서 반복할 수 있습니다.
20
+ 10. `neurain daemon run <folder>`이 같은 scheduler check를 사용자가 켜 둔 foreground loop로 계속 실행할 수 있습니다. 이때 operational state만 씁니다.
21
+ 11. `neurain lifecycle emit`이 turn end, wrap complete, compaction, resume 같은 검토된 host boundary event를 append할 수 있습니다.
22
+ 12. `neurain connect claude <folder> --lifecycle-hooks --dry-run`이 Claude Code의 SessionStart, UserPromptSubmit, Stop, SessionEnd hook을 lifecycle receipt로 매핑하는 설정 preview를 제공합니다. Prompt body, transcript path, 성공 stdout은 저장하거나 model context에 주입하지 않습니다.
23
+ 13. `neurain lifecycle report`가 session lineage를 요약하고 review 또는 recall이 이어져야 할 지점을 보여줍니다.
24
+ 14. 반복되는 실수나 workflow pattern이 보이면 lesson candidate를 제안합니다.
25
+ 15. durable lesson으로 CLI 승격하기 전 사용자가 후보를 검토합니다.
26
+ 16. `neurain curator`가 오래된 agent-created lesson을 snapshot rollback과 pinned protection 아래 stale 또는 archived로 표시할 수 있습니다.
27
+ 17. `neurain recall`이 optional local SQLite FTS5 cache를 만들어 이전 handoff, event, receipt, lesson을 더 빠르게 찾을 수 있게 합니다.
28
+ 18. `neurain recall eval`이 synthetic fixture 또는 reviewed case file로 safe host-tagged event가 올바른 host filter에서 회수되는지 확인합니다.
29
+ 19. `neurain answer eval`이 synthetic fixture 또는 reviewed case file로 model call 또는 target-root write 없이 answer faithfulness, citation accuracy, conflict surfacing, abstention, private boundary, stale-source handling을 확인합니다.
30
+ 20. `neurain lessons eval`이 model call 또는 target-root write 없이 lesson candidate detection precision, recall, false-positive rate, unsafe candidate blocking을 확인합니다.
31
+ 21. `neurain lifecycle eval`이 Claude Code, Codex, Runtime, generic host의 lifecycle hook payload가 올바른 lifecycle event로 매핑되는지, malformed/unsupported/missing-session payload가 durable write 없이 ignored result가 되는지, 그리고 prompt body, transcript path, tool stdout, tool stderr, secret, private payload가 절대 저장되지 않는지를 model call 또는 target-root write 없이 확인합니다.
32
+ 22. Agent Runtime는 bounded MCP config snippet으로 연결할 수 있고, Neurain은 backend Knowledge OS로 남습니다.
33
+ 23. 다음 세션은 active lesson cover, lifecycle lineage, recall result, scheduler-trigger gate, lesson-detection gate, answer-quality gate, lifecycle-automation gate를 먼저 읽고 같은 실수를 줄입니다.
34
+
35
+ ## Neurain이 저장하는 것
36
+
37
+ - `00_system/neurain/lessons.md`의 active lessons
38
+ - `00_system/neurain/events.ndjson`의 append-only workflow events
39
+ - 같은 journal에 `lifecycle` event로 저장되는 append-only host lifecycle boundary events
40
+ - 필요할 경우 area별 `memory/lessons/`의 상세 lesson card
41
+ - `00_system/neurain/recall.sqlite`의 optional generated recall cache
42
+ - `00_system/neurain/daemon-state.json`의 foreground daemon operational state
43
+ - 사용자 또는 MCP capture tool이 제공한 raw source
44
+ - adoption, lesson promotion, lesson rollback 같은 safety-critical write의 receipt
45
+
46
+ ## Alpha에서 하지 않는 것
47
+
48
+ - lesson candidate를 조용히 durable lesson으로 승격하지 않습니다.
49
+ - MCP는 preview-only이며 lesson을 승격하지 않습니다.
50
+ - MCP를 통해 durable wiki knowledge를 조용히 덮어쓰지 않습니다.
51
+ - web admin page를 노출하지 않습니다.
52
+ - 사용자의 폴더를 hosted memory service로 업로드하지 않습니다.
53
+ - recall SQLite cache를 canonical truth로 취급하지 않습니다.
54
+
55
+ ## Commands
56
+
57
+ ```bash
58
+ neurain onboard ~/NeurainDemo --lang ko
59
+ neurain connect codex ~/NeurainDemo --dry-run
60
+ neurain connect claude ~/NeurainDemo --dry-run
61
+ neurain connect gemini ~/NeurainDemo --dry-run
62
+ neurain connect runtime ~/NeurainDemo --dry-run
63
+ neurain lessons list ~/NeurainDemo
64
+ neurain journal list ~/NeurainDemo
65
+ neurain journal add ~/NeurainDemo --type test --summary "npm test passed" --confirm "1건 저장 진행"
66
+ neurain journal verify ~/NeurainDemo
67
+ neurain watch ~/NeurainDemo --poll-once
68
+ neurain review ~/NeurainDemo --json
69
+ neurain scheduler tick ~/NeurainDemo --json
70
+ neurain scheduler status ~/NeurainDemo --json
71
+ neurain scheduler monitor ~/NeurainDemo --interval-seconds 60 --max-ticks 3 --json
72
+ neurain scheduler eval ~/NeurainDemo --fixture-size 100 --json
73
+ neurain scheduler eval ~/NeurainDemo --case-file scheduler-cases.json --min-cases 5 --json
74
+ neurain daemon run ~/NeurainDemo --interval-seconds 300 --max-ticks 2 --json
75
+ neurain daemon status ~/NeurainDemo --json
76
+ neurain daemon stop ~/NeurainDemo --json
77
+ neurain lifecycle emit ~/NeurainDemo --host codex --event turn_end --session-id codex-session-1 --turn-id turn-1 --confirm "1건 저장 진행" --json
78
+ neurain lifecycle report ~/NeurainDemo --json
79
+ neurain lifecycle eval ~/NeurainDemo --fixture-size 100 --json
80
+ neurain lifecycle eval ~/NeurainDemo --case-file lifecycle-cases.json --min-cases 6 --json
81
+ neurain curator status ~/NeurainDemo --json
82
+ neurain curator run ~/NeurainDemo --dry-run --json
83
+ neurain curator run ~/NeurainDemo --confirm "1건 저장 진행" --json
84
+ neurain curator rollback ~/NeurainDemo --receipt output/receipts/curator/<receipt>.json
85
+ neurain recall status ~/NeurainDemo --json
86
+ neurain recall rebuild ~/NeurainDemo --dry-run --json
87
+ neurain recall rebuild ~/NeurainDemo --json
88
+ neurain recall search ~/NeurainDemo "rollback lesson" --json
89
+ neurain recall semantic-search ~/NeurainDemo "fixed the login bug" --json
90
+ neurain recall hybrid-search ~/NeurainDemo "fixed the login bug" --json
91
+ neurain recall verify ~/NeurainDemo --json
92
+ neurain recall eval ~/NeurainDemo --json
93
+ neurain recall eval ~/NeurainDemo --fixture-size 100 --private-probes 20 --json
94
+ neurain recall eval ~/NeurainDemo --case-file recall-cases.json --min-cases 1 --json
95
+ neurain recall eval ~/NeurainDemo --semantic --fixture-size 60 --min-cases 50 --json
96
+ neurain recall eval ~/NeurainDemo --semantic --case-file semantic-recall-cases.json --min-cases 50 --json
97
+ neurain recall live-eval ~/NeurainDemo --sample-size 60 --json
98
+ neurain live-cases scaffold ~/NeurainDemo --sample-size 12 --json
99
+ neurain live-cases scaffold ~/NeurainDemo --write --confirm "1건 저장 진행" --output output/live-cases/e23-live-case-pack.json --json
100
+ neurain answer eval ~/NeurainDemo --fixture-size 120 --json
101
+ neurain answer eval ~/NeurainDemo --case-file answer-cases.json --min-cases 5 --json
102
+ neurain lessons eval ~/NeurainDemo --fixture-size 100 --json
103
+ neurain lessons eval ~/NeurainDemo --case-file lesson-cases.json --min-cases 4 --json
104
+ neurain connect runtime ~/NeurainDemo --dry-run
105
+ neurain lessons candidates ~/NeurainDemo
106
+ neurain lessons promote ~/NeurainDemo --candidate-id <candidate-id> --confirm "1건 저장 진행"
107
+ neurain lessons rollback ~/NeurainDemo --receipt output/receipts/lessons/<receipt>.json
108
+ neurain recap ~/NeurainDemo
109
+ neurain wrap ~/NeurainDemo --dry-run
110
+ neurain capabilities "rollback lesson"
111
+ ```
112
+
113
+ multi-area vault에서는 preview command가 모든 area를 기본으로 스캔하지 않습니다. 특정 area를 보려면 `--area <name>`을 전달합니다. secret-like 또는 instruction-injection content가 포함된 preview line은 redaction됩니다.
114
+
115
+ ## Safety Rules
116
+
117
+ secret-like content 또는 "이전 지시를 무시하라" 같은 instruction-injection 문구가 포함된 lesson candidate는 차단되거나 sanitization 대상으로 표시됩니다. Private source에서 나온 lesson은 사용자가 명시적으로 declassify하지 않는 한 private 범위에 머뭅니다. Promotion은 append block과 receipt만 쓰고, rollback은 receipt에 기록된 정확한 block만 제거합니다.
118
+
119
+ Journal event도 같은 안전 방향을 따릅니다. Secret-like 또는 instruction-injection summary는 저장 전 redaction되고, prompt context에 넣을 수 없는 event로 표시되며, cross-host recall indexing에서도 차단됩니다.
120
+
121
+ Dry-run journal output은 `line_hash_status`를 `planned`로 표시합니다. Durable journal write는 NDJSON append 전에 pending receipt를 먼저 만들고, append 성공 뒤 receipt를 final 상태로 갱신합니다. Pending receipt는 `line_hash_status`를 `expected_pending_append`로 표시하고, finalized receipt는 `observed_after_append`로 표시합니다.
122
+
123
+ `neurain journal verify`는 저장된 event line이 event hash와 계속 일치하는지, 각 line이 valid JSON인지 확인합니다. Alpha integrity check이며, 완전한 tamper-proof chain은 아닙니다. 삭제, 순서 변경, standalone hash까지 맞춘 forged event 탐지는 이후 sequence-chain 작업이 필요합니다.
124
+
125
+ Watch report는 read-only입니다. Alpha에서는 daemon을 시작하지 않고, journal event를 append하지 않고, lesson을 promote하지 않고, durable wiki knowledge를 쓰지 않습니다. Private 또는 unsafe event summary는 local CLI 사용자가 명시적으로 포함하지 않는 한 withheld 처리되며, MCP watch report에는 append capability가 없습니다. Withheld event도 review trigger 계산을 위해 event id, event type, timestamp, sensitivity 같은 최소 routing metadata는 노출할 수 있지만 private content는 노출하지 않습니다.
126
+
127
+ Review worker report도 read-only입니다. Watch report, event sequence, recap hint, lesson candidate를 manual review item, blocked item, suggested action으로 바꿉니다. Model을 호출하지 않고, nested review worker를 시작하지 않고, external tool을 실행하지 않고, lesson을 promote하지 않고, durable knowledge를 쓰지 않습니다. MCP는 같은 read-only 표면으로 `neurain_review_worker`를 노출합니다.
128
+
129
+ Scheduler tick도 read-only입니다. Watch signal을 보고 local review fork를 실행할지 판단하며, threshold를 넘을 때만 review worker report를 포함합니다. Background job을 설치하지 않고, daemon을 시작하지 않고, model을 호출하지 않고, lesson을 promote하지 않고, durable knowledge를 쓰지 않습니다. MCP는 같은 read-only tick 표면으로 `neurain_scheduler_tick`을 노출합니다.
130
+
131
+ Scheduler eval은 read-only이며 scheduler tick과 별도입니다. Meaningful event, lesson candidate, journal-integrity failure, ordinary no-review note를 기준으로 background review trigger의 precision과 recall이 충분한지 확인합니다. 또한 실제 review report가 실행된 case의 no-recursion, private marker가 있는 case의 private boundary, case-file size limit, temp cleanup, broad target-root non-write snapshot을 검증합니다. Synthetic fixture는 `--fixture-size`를 쓰고, 검토된 live case는 `--case-file`로 넣을 수 있습니다. MCP는 같은 read-only eval 표면으로 `neurain_scheduler_eval`을 노출합니다.
132
+
133
+ Scheduler monitor는 bounded foreground run입니다. 사용자가 지정한 tick 수만큼 read-only scheduler tick을 반복하고, background job을 설치하지 않고, 명령 종료 뒤 계속 실행되지 않고, durable knowledge를 쓰지 않습니다. Alpha에서 MCP는 scheduler monitor를 노출하지 않습니다.
134
+
135
+ Daemon run은 continuous local review check를 위한 user-started foreground loop입니다. 사용자가 멈추거나 `--max-ticks`에 도달할 때까지 scheduler tick을 반복합니다. Stop request는 sleep interval 중에도 약 1초 단위로 확인합니다. `00_system/neurain/daemon-state.json`에 operational state만 쓰고, 그 state에 private path를 저장하지 않으며, background job을 설치하지 않고, durable wiki knowledge를 쓰지 않고, lesson을 promote하지 않고, model을 호출하지 않고, external tool을 호출하지 않고, MCP에 노출되지 않습니다.
136
+
137
+ Lifecycle event는 Neurain이 직접 소유하지 않는 host에서도 agent-loop awareness를 흡수하기 위한 장치입니다. `neurain lifecycle emit`은 `session_start`, `turn_start`, `turn_end`, `wrap_complete`, `review_due`, `review_complete`, `compaction`, `resume`, `session_end` 같은 boundary receipt를 append합니다. Emit은 정확한 confirmation phrase가 필요합니다. `neurain lifecycle report`는 read-only이며 completed turn, open turn, parent session, compaction, resume, review-due event를 요약합니다. MCP는 `neurain_lifecycle_report`만 노출하고 lifecycle emit은 노출하지 않습니다.
138
+
139
+ Lifecycle hook preview는 connector-specific입니다. `neurain connect claude <folder> --lifecycle-hooks --dry-run`은 Claude Code settings snippet을 출력하고, `neurain connect codex <folder> --lifecycle-hooks --dry-run`은 `.codex/hooks.json` snippet을 출력하며, `neurain connect runtime <folder> --lifecycle-hooks --dry-run`은 host-proxy contract를 출력합니다. Adapter는 host hook payload를 lifecycle receipt로 매핑하고 operational metadata만 저장하며, prompt body text, transcript path, tool stdout, tool stderr, 성공 stdout을 저장하거나 model context에 주입하지 않습니다.
140
+
141
+ Lifecycle eval은 read-only이며 lifecycle emit과 별도입니다. E21 native lifecycle automation gate로, 완전한 background self-improvement loop를 만드는 단계가 아니라 lifecycle 관찰 계층이 안전한지를 증명하는 단계입니다. Claude Code, Codex, Runtime, generic host의 synthetic lifecycle payload와 reviewed case file을 실제 hook adapter로 격리된 임시 root에서 재생한 뒤, 모든 durable artifact(journal, connector state, receipt)를 다시 읽어 prompt body, transcript path, tool stdout, tool stderr, 그리고 secret-like/instruction-injection content가 전혀 저장되지 않음을 증명합니다. 이는 그 위험 content를 lifecycle summary로 흘러드는 host-controlled source/reason/matcher/tool-name/tool 필드에 넣은 경우까지 포함합니다. 그 필드의 짧은 host lineage 라벨은 설계상 sanitized/lowercased/length-capped/redaction 처리된 형태로 저장되므로, non-persistence 주장은 payload body content와 secret/injection content에 한정되며 그 짧은 trigger 라벨에는 적용되지 않습니다. 매칭은 대소문자를 무시하며, `non_persistence_proof_complete` 플래그가 모든 non-persistence 차원이 실제로 시험됐는지 보고하여 프로브 없는 reviewed case file이 완전한 증명으로 오인되지 않게 합니다. 또한 host coverage, lifecycle event coverage, malformed/unsupported/missing-session payload의 ignored 처리, path-traversal containment, broad target-root non-write snapshot, temp cleanup을 gate로 확인합니다. Synthetic fixture는 `--fixture-size`를 쓰고, 검토된 live case는 `--case-file`로 넣을 수 있습니다. MCP는 같은 read-only eval 표면으로 `neurain_lifecycle_eval`을 노출하며 여전히 lifecycle emit은 노출하지 않습니다. Neurain이 host loop를 소유한다고 주장하지 않고, 자동 background review, 자동 lesson promotion, 자동 rollback을 수행하지 않습니다.
142
+
143
+ Curator lifecycle change는 snapshot-gated입니다. `neurain curator status`와 `neurain curator run --dry-run`은 read-only입니다. Confirmed curator run은 lesson `Status` field만 변경하고, lesson을 삭제하지 않으며, pinned, human-authored, private, non-agent-created lesson을 보호하고, 이전 registry snapshot이 포함된 rollback receipt를 씁니다. Curator run 이후 registry가 바뀌면 rollback은 사용자 edit를 덮어쓰지 않기 위해 거부됩니다. MCP는 read-only curator status와 run-preview tool만 노출합니다.
144
+
145
+ Recall DB는 optional이고 rebuildable입니다. `neurain recall status`, `neurain recall search`, `neurain recall verify`, `neurain recall eval`은 read-only입니다. `neurain recall rebuild`는 generated SQLite cache와 rebuild receipt만 씁니다. Markdown, event, handoff, receipt는 계속 canonical입니다. Private path, raw source body, secret-like content, instruction-injection content, recall rebuild receipt는 indexing에서 제외됩니다. SQLite file이 삭제되면 search는 markdown fallback으로 동작하고 cache는 나중에 다시 rebuild할 수 있습니다. `neurain recall eval --fixture-size 100 --private-probes 20`은 target root를 건드리지 않고 synthetic cross-host regression suite를 실행합니다. `neurain recall eval --case-file recall-cases.json`은 사람이 검토한 recall case를 target root write 없이 실행합니다. 두 모드 모두 host filtering, source-supporting snippet, host isolation, private leakage를 gate로 확인합니다. 이 둘만으로 semantic recall quality benchmark라고 주장하지는 않습니다.
146
+
147
+ Semantic recall은 별도의 read-only 계층(E22)입니다. `neurain recall semantic-search`와 `neurain recall eval --semantic`은 exact-token recall 위에 local lexical-semantic provider를 얹어 의역 쿼리를 찾습니다. 어간(fix/fixed/fixing) + 동의어맵(resolved↔fixed, defect↔bug, authentication↔login) + 오타용 char-trigram 퍼지를 결합합니다. 기본 `local-lexical` provider는 완전 결정론적이고, model call이 없고, 외부 의존성이 없고, 별도 generated index가 필요 없으며(markdown이 canonical), 특정 LLM에 종속되지 않습니다. embedding provider는 교체 가능해서 나중에 진짜 벡터모델을 canonical 변경 없이 끼울 수 있습니다. 정직한 범위: 이 계층은 형태소 변형, 큐레이션된 동의어, 오타까지 다루며 neural의 임의 개념유사는 아닙니다. 맵에 없는 개념은 여전히 pluggable embedding provider가 필요합니다. semantic eval은 read-only이고, synthetic 의역 fixture에서 semantic recall이 exact-token 기준선을 명확히 능가함(Hit@top 개선)을 증명하면서 host isolation, private 제외, no-answer abstention, rebuild 동등성, target-root non-write를 유지합니다. 메커니즘을 결정론적으로 증명할 뿐 실사용자 recall benchmark를 대체하지는 않습니다. MCP는 read-only `neurain_recall_semantic_search`와 `neurain_recall_semantic_eval`만 노출합니다.
148
+
149
+ Hybrid recall이 권장되는 견고한 recall입니다. `neurain recall hybrid-search`는 exact-token 결과와 local lexical-semantic 결과의 합집합을 반환하므로 exact-token보다 절대 나쁘지 않고 의역 케이스를 위에 더합니다. `--top`은 각 branch의 후보 깊이라서 semantic-only catch가 있으면 반환되는 합집합은 `--top`보다 길어질 수 있습니다. 이건 아래 live-eval을 실제 콘텐츠에 돌려보니 순수 semantic만으로는 실제 코퍼스에서 exact-token보다 recall이 더 낮을 수 있음이 드러났기 때문입니다: lexical-semantic 계층은 exact-token BM25의 희귀도 가중치가 없어 어휘가 겹치는 실제 코퍼스에서 구분력이 떨어집니다. hybrid 합집합이 이를 고칩니다. MCP는 read-only `neurain_recall_hybrid_search`를 노출합니다.
150
+
151
+ Live-content recall coverage(E23 첫 increment)는 synthetic fixture에서 실사용자 증거로 가는 첫걸음입니다. `neurain recall live-eval <folder>`는 read-only로, 실제 폴더의 자기 콘텐츠가 의역 쿼리(실제 단어를 동의어로 교체)로 얼마나 회수되는지를 측정해 hybrid coverage(권장 exact-union-semantic), exact-token coverage, semantic-only coverage, kind별 coverage를 보고합니다. 그래서 실사용자가 자기 자료에서 recall이 충분한지, 무엇을 놓치는지 볼 수 있습니다. hybrid coverage가 exact-token coverage 이상인지를 gate로 봅니다. 이걸 실제 콘텐츠에 돌린 게 바로 순수 semantic-only coverage가 exact-token보다 낮을 수 있음을 드러냈고, 그게 위의 hybrid recall로 이어졌습니다. 단어 단위 semantic 우위는 E22 semantic eval이 따로 증명합니다. 출력은 메트릭만이고 콘텐츠를 저장하지 않아 private vault에서도 안전하며, model/external call이 없습니다. 정직한 범위: 쿼리는 자동 생성이지 사람이 판단한 relevance가 아니고, 폴더 하나는 3명이 아닙니다. live-content coverage는 실제 콘텐츠 단계일 뿐 외부 사용자 walkthrough를 대체하지 않으므로 synthetic-only 주장은 줄었지만 아직 완전히 제거되진 않았습니다. 완전한 E23(최소 3개 실제 업무 폴더의 reviewed live case)은 사람의 몫으로 남습니다.
152
+
153
+ Live case scaffolding은 reviewed live case를 안전하게 저장 가능한 형태로 준비하는 E23 storage-safety bridge입니다. `neurain live-cases scaffold <folder>`는 eligible local markdown을 샘플링하고 hash-only source ref와 recall, answer, lesson template만 출력합니다. Raw source text, absolute local path, private path name, secret-like content, instruction-injection content를 저장하지 않습니다. 의도적으로 `reviewed_live_user_evidence: false`, `human_judged: false`를 보고합니다. 사람이 안전한 local case file을 채우고 eval을 실행해야만 reviewed live evidence라고 주장할 수 있습니다. `--write`를 쓰면 정확한 확인 문구가 필요하고 `output/live-cases/` 아래 redacted pack만 씁니다.
154
+
155
+ Answer eval은 recall eval과 별도입니다. `neurain answer eval`은 read-only로 policy-level answer quality를 확인합니다. 출처에 충실한 답변인지, citation이 실제 claim을 support하는지, conflict를 숨기지 않는지, evidence가 부족하면 abstain하는지, private boundary와 stale-source handling이 지켜지는지 봅니다. Synthetic fixture는 `--fixture-size`를 쓰고, 검토된 live case는 `--case-file`로 넣을 수 있습니다. Model을 호출하지 않고 target root에 write하지 않으며, external user walkthrough 없이 production answer quality를 증명하지는 않습니다.
156
+
157
+ Lessons eval은 lesson promotion과 별도입니다. `neurain lessons eval`은 read-only로 candidate detection quality를 확인합니다. 실제 lesson 후보를 잘 찾는지, 평범한 note를 false positive로 잘 피하는지, secret-like 또는 instruction-injection candidate를 안전하게 차단하는지 봅니다. Synthetic fixture는 `--fixture-size`를 쓰고, 검토된 live case는 `--case-file`로 넣을 수 있습니다. Model을 호출하지 않고 target root에 write하지 않으며, external user case 없이 production lesson quality를 증명하지는 않습니다.
158
+
159
+ Onboarding은 E24 first-run layer입니다. `neurain onboard <folder>`는 read-only이고, 비개발자에게 다음 행동이 `init`, `adopt --dry-run`, host connection, `wrap --dry-run` 중 무엇인지 알려줍니다. Model call, external call, durable write가 없습니다.
160
+
161
+ Gemini CLI connector support는 E26 일부로 shipped 상태입니다. `neurain connect gemini <folder> --dry-run`은 bounded `gemini mcp add` command를 출력하고, status, search, adopt scan, recall, eval, live-case scaffold, lifecycle report/eval, lesson preview, scheduler preview, wrap preview를 포함한 read-first allowlist를 사용합니다. Gemini lifecycle hook automation은 alpha에서 manual-only이므로 필요 시 explicit `lifecycle emit --host gemini`이 receipt path입니다.
162
+
163
+ Runtime connector alpha는 config-preview only입니다. `neurain connect runtime <folder> --dry-run`은 host-managed config용 작은 read-heavy Neurain allowlist가 포함된 bounded MCP server snippet을 출력합니다. Host config를 직접 수정하지 않고, 특정 runtime을 Neurain dependency로 만들지 않습니다.
@@ -0,0 +1,17 @@
1
+ # Support
2
+
3
+ Alpha support channels:
4
+
5
+ - GitHub Issues for bugs and feature requests.
6
+ - Security reports through the private contact listed in `SECURITY.md`.
7
+ - Release notes in `CHANGELOG.md`.
8
+
9
+ When opening an issue, include:
10
+
11
+ - operating system
12
+ - Node version
13
+ - command run
14
+ - output
15
+ - whether the target folder contains private or secret material
16
+
17
+ Do not paste secrets, credentials, or private documents into public issues.
@@ -0,0 +1,35 @@
1
+ # Troubleshooting
2
+
3
+ ## `npx neurain` is not found
4
+
5
+ Use Node 20 or newer.
6
+
7
+ ```bash
8
+ node --version
9
+ ```
10
+
11
+ ## `connect codex` fails
12
+
13
+ Check that Codex CLI is installed:
14
+
15
+ ```bash
16
+ codex --version
17
+ codex mcp --help
18
+ ```
19
+
20
+ ## `connect claude` fails
21
+
22
+ Check that Claude Code CLI is installed:
23
+
24
+ ```bash
25
+ claude --version
26
+ claude mcp --help
27
+ ```
28
+
29
+ ## Adoption refuses to apply
30
+
31
+ Use the exact confirmation phrase printed by `neurain adopt <folder> --dry-run`.
32
+
33
+ ## Capture refuses text
34
+
35
+ The text probably contains a secret-like pattern. Redact credentials before capturing.
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "neurain",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Local-first Neurain Knowledge OS CLI and MCP connector.",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "tag": "alpha"
10
+ },
11
+ "bin": {
12
+ "neurain": "bin/neurain.mjs"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "src/",
17
+ "templates/",
18
+ "docs/",
19
+ "README.md",
20
+ "CHANGELOG.md",
21
+ "SECURITY.md",
22
+ "LICENSE"
23
+ ],
24
+ "engines": {
25
+ "node": ">=20"
26
+ },
27
+ "scripts": {
28
+ "test": "node --test",
29
+ "pack:dry-run": "npm pack --dry-run",
30
+ "readiness": "node scripts/readiness.mjs --full"
31
+ },
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.17.5"
34
+ },
35
+ "devDependencies": {}
36
+ }
package/src/cli.mjs ADDED
@@ -0,0 +1,261 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import path from 'node:path';
3
+ import { adoptCommand, rollbackAdoption, scanAdoption } from './core/adopt.mjs';
4
+ import { answerCommand } from './core/answer_eval.mjs';
5
+ import { connectCommand } from './core/connect.mjs';
6
+ import { capabilitiesCommand } from './core/capabilities.mjs';
7
+ import { curatorCommand } from './core/curator.mjs';
8
+ import { daemonCommand } from './core/daemon.mjs';
9
+ import { doctorCommand } from './core/doctor.mjs';
10
+ import { initCommand } from './core/init.mjs';
11
+ import { journalCommand } from './core/journal.mjs';
12
+ import { lessonsCommand } from './core/lessons.mjs';
13
+ import { lifecycleCommand } from './core/lifecycle.mjs';
14
+ import { liveCasesCommand } from './core/live_cases.mjs';
15
+ import { onboardCommand } from './core/onboard.mjs';
16
+ import { recapCommand } from './core/recap.mjs';
17
+ import { recallCommand } from './core/recall.mjs';
18
+ import { reviewCommand } from './core/review_worker.mjs';
19
+ import { statusCommand } from './core/status.mjs';
20
+ import { digestCommand } from './core/digest.mjs';
21
+ import { queueCommand } from './core/queue.mjs';
22
+ import { reviewQueueCommand } from './core/review_queue.mjs';
23
+ import { routeCommand } from './core/route.mjs';
24
+ import { planWritebackCommand } from './core/plan_writeback.mjs';
25
+ import { flushCommand, sessionFlushCommand } from './core/flush.mjs';
26
+ import { compileCommand } from './core/compile_desk.mjs';
27
+ import { planReceiptCommand } from './core/plan_receipt.mjs';
28
+ import { sourceDigestCommand } from './core/source_digest_gen.mjs';
29
+ import { stageCommand } from './core/stage.mjs';
30
+ import { queueArchiveCommand } from './core/queue_archive.mjs';
31
+ import { captureCommand } from './core/capture_durable.mjs';
32
+ import { completeCommand } from './core/complete.mjs';
33
+ import { linkCheckCommand } from './core/link_check.mjs';
34
+ import { schedulerCommand } from './core/scheduler.mjs';
35
+ import { searchCommand } from './core/search.mjs';
36
+ import { watchCommand } from './core/watch.mjs';
37
+ import { wrapCommand } from './core/wrap.mjs';
38
+ import { startMcpServer } from './mcp/server.mjs';
39
+
40
+ export async function runCli(argv) {
41
+ const [command, ...rest] = argv;
42
+ if (!command || command === 'help' || command === '--help' || command === '-h') {
43
+ process.stdout.write(helpText());
44
+ return;
45
+ }
46
+ if (command === '--version' || command === '-v') {
47
+ const version = await packageVersion();
48
+ process.stdout.write(`${version}\n`);
49
+ return;
50
+ }
51
+
52
+ const args = parseArgs(rest);
53
+ if (command === 'init') return render(await initCommand(args));
54
+ if (command === 'onboard') return render(await onboardCommand(args));
55
+ if (command === 'adopt') {
56
+ if (args.rollback) return render(await rollbackAdoption(args));
57
+ return render(await adoptCommand(args));
58
+ }
59
+ if (command === 'answer') return render(await answerCommand(args));
60
+ if (command === 'doctor') return render(await doctorCommand(args));
61
+ if (command === 'search') return render(await searchCommand(args));
62
+ if (command === 'connect') return render(await connectCommand(args));
63
+ if (command === 'journal') return render(await journalCommand(args));
64
+ if (command === 'lifecycle') return render(await lifecycleCommand(args));
65
+ if (command === 'live-cases') return render(await liveCasesCommand(args));
66
+ if (command === 'lessons') return render(await lessonsCommand(args));
67
+ if (command === 'curator') return render(await curatorCommand(args));
68
+ if (command === 'daemon') return render(await daemonCommand(args));
69
+ if (command === 'recall') return render(await recallCommand(args));
70
+ if (command === 'status') return render(await statusCommand(args));
71
+ if (command === 'digest') return render(await digestCommand(args));
72
+ if (command === 'queue') return render(await queueCommand(args));
73
+ if (command === 'review-queue') return render(await reviewQueueCommand(args));
74
+ if (command === 'route') return render(await routeCommand(args));
75
+ if (command === 'plan-writeback') return render(await planWritebackCommand(args));
76
+ if (command === 'flush') return render(await flushCommand(args));
77
+ if (command === 'session-flush') return render(await sessionFlushCommand(args));
78
+ if (command === 'compile') return render(await compileCommand(args));
79
+ if (command === 'plan-receipt') return render(await planReceiptCommand(args));
80
+ if (command === 'source-digest') return render(await sourceDigestCommand(args));
81
+ if (command === 'stage') return render(await stageCommand(args));
82
+ if (command === 'queue-archive') return render(await queueArchiveCommand(args));
83
+ if (command === 'capture') return render(await captureCommand(args));
84
+ if (command === 'complete') return render(await completeCommand(args));
85
+ if (command === 'link-check') return render(await linkCheckCommand(args));
86
+ if (command === 'capabilities') return render(await capabilitiesCommand(args));
87
+ if (command === 'recap') return render(await recapCommand(args));
88
+ if (command === 'watch') return render(await watchCommand(args));
89
+ if (command === 'review') return render(await reviewCommand(args));
90
+ if (command === 'scheduler') return render(await schedulerCommand(args));
91
+ if (command === 'wrap') return render(await wrapCommand(args));
92
+ if (command === 'mcp') return startMcpServer(args);
93
+ if (command === 'selftest') return runSelftest();
94
+
95
+ throw new Error(`Unknown command: ${command}\n\n${helpText()}`);
96
+ }
97
+
98
+ export function parseArgs(tokens) {
99
+ const args = { _: [] };
100
+ for (let i = 0; i < tokens.length; i += 1) {
101
+ const token = tokens[i];
102
+ if (!token.startsWith('--')) {
103
+ args._.push(token);
104
+ continue;
105
+ }
106
+ const eq = token.indexOf('=');
107
+ if (eq > 2) {
108
+ args[token.slice(2, eq)] = token.slice(eq + 1);
109
+ continue;
110
+ }
111
+ const key = token.slice(2);
112
+ const next = tokens[i + 1];
113
+ if (next && !next.startsWith('--')) {
114
+ args[key] = next;
115
+ i += 1;
116
+ } else {
117
+ args[key] = true;
118
+ }
119
+ }
120
+ return args;
121
+ }
122
+
123
+ function render(result) {
124
+ if (result == null) return;
125
+ if (result.json) {
126
+ process.stdout.write(`${JSON.stringify(result.payload, null, 2)}\n`);
127
+ return;
128
+ }
129
+ if (result.text === '') return;
130
+ process.stdout.write(result.text.endsWith('\n') ? result.text : `${result.text}\n`);
131
+ }
132
+
133
+ async function runSelftest() {
134
+ const result = spawnSync('node', ['--test'], {
135
+ cwd: path.resolve(new URL('..', import.meta.url).pathname),
136
+ encoding: 'utf8',
137
+ stdio: ['ignore', 'pipe', 'pipe'],
138
+ });
139
+ process.stdout.write(result.stdout || '');
140
+ process.stderr.write(result.stderr || '');
141
+ process.exitCode = result.status || 0;
142
+ }
143
+
144
+ async function packageVersion() {
145
+ const pkg = await import('../package.json', { with: { type: 'json' } });
146
+ return pkg.default.version;
147
+ }
148
+
149
+ function helpText() {
150
+ return `Neurain CLI
151
+
152
+ Usage:
153
+ neurain init <folder> [--area general] [--lang ko|en] [--dry-run]
154
+ neurain onboard <folder> [--lang ko|en] [--host codex|claude|gemini|runtime] [--json]
155
+ neurain adopt <folder> [--dry-run] [--apply --confirm "<N>건 저장 진행"]
156
+ neurain adopt --rollback <receipt> [--root <folder>]
157
+ neurain doctor <folder> [--json]
158
+ neurain search <folder> <query> [--top 10] [--json]
159
+ neurain journal list <folder> [--type type] [--top 20] [--json]
160
+ neurain journal add <folder> --type type --summary text --confirm "1건 저장 진행" [--source rel] [--host name] [--dry-run] [--json]
161
+ neurain journal verify <folder> [--json]
162
+ neurain lifecycle emit <folder> --host codex|claude|gemini|runtime|openclaw|cli|generic --event session_start|turn_start|turn_end|wrap_complete|review_due|review_complete|compaction|resume|session_end --session-id id [--turn-id id] [--parent-session-id id] --confirm "1건 저장 진행" [--dry-run] [--json]
163
+ neurain lifecycle hook <folder> --host claude|codex|runtime --confirm "1건 저장 진행" [--quiet] [--json]
164
+ neurain lifecycle report <folder> [--host name] [--session-id id] [--json]
165
+ neurain lifecycle eval <folder> [--fixture-size 100] [--case-file rel.json] [--min-cases 100] [--json]
166
+ neurain live-cases scaffold <folder> [--sample-size 12] [--label name] [--write --confirm "1건 저장 진행" --output output/live-cases/e23-live-case-pack.json] [--json]
167
+ neurain lessons list <folder> [--area name] [--json]
168
+ neurain lessons candidates <folder> [--area name] [--top 5] [--json]
169
+ neurain lessons eval <folder> [--fixture-size 100] [--case-file rel.json] [--min-cases 100] [--json]
170
+ neurain lessons promote <folder> --candidate-id <candidate-id> --confirm "1건 저장 진행" [--area name] [--dry-run] [--json]
171
+ neurain lessons rollback <folder> --receipt <receipt> [--json]
172
+ neurain curator status <folder> [--stale-days 30] [--archive-days 90] [--json]
173
+ neurain curator run <folder> --dry-run [--stale-days 30] [--archive-days 90] [--json]
174
+ neurain curator run <folder> --confirm "1건 저장 진행" [--stale-days 30] [--archive-days 90] [--json]
175
+ neurain curator rollback <folder> --receipt <receipt> [--json]
176
+ neurain recall status <folder> [--json]
177
+ neurain recall rebuild <folder> [--dry-run] [--json]
178
+ neurain recall search <folder> <query> [--top 10] [--host name] [--area name] [--json]
179
+ neurain recall semantic-search <folder> <query> [--top 10] [--host name] [--area name] [--provider local-lexical] [--min-score 0.34] [--json]
180
+ neurain recall hybrid-search <folder> <query> [--top 10] [--host name] [--area name] [--routing auto|on|off] [--provider local-lexical] [--min-score 0.34] [--json]
181
+ neurain recall lexical-search <folder> <query> [--top 10] [--area name] [--max-per-layer 3] [--json]
182
+ neurain recall bench <folder> --suites <dir> [--area name] [--top 5] [--baseline 0.94] [--matcher strict|loose] [--case ID --explain] [--json]
183
+ neurain recall scorecard <folder> --suites <dir> [--area name] [--top 5] [--matcher strict|loose] [--json]
184
+ neurain recall verify <folder> [--json]
185
+ neurain recall eval <folder> [--min-cases 2] [--fixture-size 100] [--case-file rel.json] [--private-probes 20] [--json]
186
+ neurain recall eval <folder> --semantic [--fixture-size 60] [--case-file rel.json] [--min-cases 50] [--provider local-lexical] [--json]
187
+ neurain recall live-eval <folder> [--sample-size 60] [--top 5] [--provider local-lexical] [--json]
188
+ neurain answer eval <folder> [--fixture-size 120] [--case-file rel.json] [--min-cases 50] [--json]
189
+ neurain status <folder> [--session-id id] [--all] [--stale-days 7] [--now ms] [--json]
190
+ neurain digest <folder> --session <id> [--sources area-brief,wrap-journal] [--window-hours 72] [--now ms] [--json]
191
+ neurain queue <folder> [--queue name] [--status s] [--pending] [--stats] [--lossless-check] [--json]
192
+ neurain review-queue <folder> [--session-id id] [--queue rel] [--manifest rel] [--top 12] [--json]
193
+ neurain route <folder> [--text "..." | <text> | --file rel] [--session-id id] [--area name] [--sensitivity s] [--intent i] [--title t] [--type memo] [--json]
194
+ neurain plan-writeback <folder> [--source-id id | --text "..." | --file rel] [--session-id id] [--area name] [--sensitivity s] [--intent i] [--title t] [--type memo] [--json]
195
+ neurain flush <folder> [--queue rel] [--json]
196
+ neurain session-flush <folder> --session-id id [--level light|standard|full] [--queue rel] [--json]
197
+ neurain compile <folder> [<target> | --target q | --text q] [--session-id id] [--top 5] [--manifest rel] [--queue rel] [--list] [--auto] [--desk] [--json]
198
+ neurain source-digest <folder> [--scope raw] [--manifest rel] [--write] [--rehash] [--top 20] [--json]
199
+ neurain plan-receipt <folder> --plan rel --actual rel [--label name] [--allow-unplanned] [--write] [--json]
200
+ neurain plan-receipt <folder> --selftest [--json]
201
+ neurain stage <folder> --target <relpath> [--text "..." | --file rel] [--allow-secret] [--json]
202
+ neurain queue-archive <folder> [--dry-run] [--older-than-days N] [--json]
203
+ neurain capture <folder> [--text "..." | <text> | --file rel] [--session-id id] [--type memo] [--title t] [--area name] [--sensitivity s] [--intent i] [--allow-secret] [--dry-run] [--json]
204
+ neurain complete <folder> --source-id id --compiled-to "a.md,b.md" [--status compiled] [--completed-at ts] [--dry-run] [--json]
205
+ neurain link-check <folder> [--scope .] [--top 20] [--include-raw] [--include-archive] [--include-output] [--json]
206
+ neurain recap <folder> [--area name] [--json]
207
+ neurain watch <folder> [--area name] [--since-minutes 1440] [--top 10] [--poll-once] [--json]
208
+ neurain review <folder> [--area name] [--since-minutes 1440] [--top 10] [--json]
209
+ neurain scheduler tick <folder> [--area name] [--since-minutes 1440] [--top 10] [--json]
210
+ neurain scheduler status <folder> [--area name] [--since-minutes 1440] [--top 10] [--json]
211
+ neurain scheduler monitor <folder> [--area name] [--since-minutes 1440] [--interval-seconds 60, clamped 0..3600] [--max-ticks 3, clamped 1..20] [--json]
212
+ neurain scheduler eval <folder> [--fixture-size 100] [--case-file rel.json] [--min-cases 100] [--json]
213
+ neurain daemon status <folder> [--json]
214
+ neurain daemon run <folder> [--area name] [--since-minutes 1440] [--interval-seconds 300] [--max-ticks 0] [--json]
215
+ neurain daemon stop <folder> [--json]
216
+ neurain wrap <folder> [--area name] [--dry-run] [--json]
217
+ neurain capabilities [query] [--json]
218
+ neurain connect codex <folder> [--dry-run]
219
+ neurain connect claude <folder> [--dry-run] [--scope local|user|project]
220
+ neurain connect gemini <folder> [--dry-run] [--scope user|project]
221
+ neurain connect runtime <folder> --dry-run
222
+ neurain connect claude <folder> --lifecycle-hooks --dry-run [--json]
223
+ neurain connect codex|gemini|runtime <folder> --lifecycle-hooks --dry-run [--json]
224
+ neurain mcp --root <folder>
225
+
226
+ Alpha principles:
227
+ - Local markdown is the source of truth.
228
+ - Adoption scans are read-only unless --apply is confirmed.
229
+ - Event journal writes are append-only and require an exact confirmation phrase.
230
+ - Lifecycle events are append-only host boundary receipts; MCP can report them but cannot emit them.
231
+ - Lifecycle hook previews map host hooks to lifecycle receipts without storing prompt bodies, transcript paths, tool stdout, or tool stderr.
232
+ - Lifecycle eval checks that Claude, Codex, Runtime, and generic host lifecycle payloads map safely, that malformed, unsupported, and missing-session events become ignored results with no durable write, and that prompt bodies, transcript paths, tool output, secrets, and private payloads are never persisted, without writing to the target root.
233
+ - Watch reports are read-only candidate reports, not background auto-writes.
234
+ - Review worker reports turn watch signals into manual improvement proposals only.
235
+ - Scheduler ticks and bounded foreground monitors decide whether review should run, but do not write knowledge.
236
+ - Scheduler eval checks background review trigger precision, recall, no-recursion, private boundaries, case-file size, and broad target-root non-write without writing to the target root.
237
+ - Daemon run is a user-started foreground loop; it writes only operational state and never writes wiki, promotes lessons, calls models, or exposes MCP tools.
238
+ - Curator runs snapshot first, never deletes lessons, and requires confirmation for lifecycle writes.
239
+ - Recall DB is an optional rebuildable SQLite FTS5 cache; markdown remains canonical.
240
+ - Recall eval can run a larger cross-host fixture or reviewed case file without touching the target root.
241
+ - Recall semantic-search and recall eval --semantic add a local lexical-semantic layer (stemming, synonyms, fuzzy) that recalls paraphrased queries exact-token misses. The default provider is deterministic with no model call, no external dependency, and no LLM lock-in; markdown stays canonical and the embedding provider is swappable.
242
+ - Recall live-eval measures recall coverage on a real folder's own content using auto-derived paraphrase queries. It is read-only, returns metrics only with no stored content, and is one real-content step toward live user evidence; it does not replace human-judged external user walkthroughs.
243
+ - Recall hybrid-search is the robust recall: exact-token union local lexical-semantic. It is never worse than exact-token and adds paraphrase catches on top. Its --top value is the candidate depth for each branch, so the returned union can be longer than --top when semantic-only catches exist. Live-eval on real content showed pure semantic alone can recall less than exact-token, so hybrid is the recommended strategy.
244
+ - Recall routing (auto when a search index registry has areas, or with --area, or recall.routing.enabled): adds a BM25 + structural/layer/entity/domain/fact-ledger lexical branch ranked first in the union, so the corpus includes general area knowledge with label-based private exclusion. Routing is off by default on a bare vault, preserving exact-token union semantic.
245
+ - Recall bench scores a directory of benchmark suites (passed as a runtime arg, never bundled) against the routed lexical branch, reporting strict and loose source recall, entity recall, and a gate verdict against an optional baseline. Read-only; --case ID --explain prints per-signal traces and whether each expected source is in the corpus at all. Recall scorecard reports Hit@K, R@K, MRR, entity recall, and latency.
246
+ - The recall markdown corpus is config-extensible (recall.include/exclude) and privacy-gated by labels (per-file frontmatter sensitivity, area baseline from _area.md, and boundary path markers), so private content is excluded at index time, not just hidden at query time.
247
+ - Status, digest, queue, and review-queue are read-only views over vault state (session-state, wrap-journal, writeback queue + per-area registry, source-digest manifest). They never write: status does not advance the digest ack pointer and does not run maintenance, and digest never acks. Every format degrades gracefully when absent. Private review-queue items redact their file paths; digest redacts cross-area references and stays within the session's own area.
248
+ - Route, plan-writeback, flush, session-flush, and compile are read-only W-B desks: they classify and PLAN the capture/queue/compile pipeline (area/sensitivity/intent routing, writeback targets + gates, flush scope, and the compile candidate picker) but write nothing. Private and needs-confirmation items are surfaced separately, never silently compiled, and compile reads no raw bodies.
249
+ - Source-digest and plan-receipt are W-B writers that touch only their own non-canonical artifacts: source-digest writes the rebuildable source-digest manifest (dry by default, --write to update) and plan-receipt writes an optional receipt under output/receipts/. Every durable write goes through an atomic temp+fsync+rename plus a cross-process lock, and the manifest's path sensitivity is decided by the label resolver, never hardcoded area names.
250
+ - Stage is the secret gate: content lands in .neurain-staging (excluded from every walk), is scanned fail-closed for high-confidence secret shapes, mnemonics, context-aware hex keys, and high-entropy tokens, and is promoted to its canonical target by an atomic rename ONLY if clean; a hit holds the content in staging, leaves the target untouched, and exits 2. Queue-archive moves terminal queue rows into an append-only archive under one lock (archive appended before the hot-queue rewrite, so a crash never loses a row).
251
+ - Capture and complete are the durable pipeline writers. They write raw markdown (capture, routed through the stage secret gate), the _inbox envelope, the writeback queue (capture appends, complete rewrites - both under a lock), and a wiki/log line, but they NEVER write session-state, handoff, or area-brief files: those stay W-D-owned, returned as an unapplied session_state_delta whose pending_count is advisory (the future vault shuttle recomputes at apply time). Capture is text-only in this increment; file capture and overlap/numeric enrichment are the documented flip gate.
252
+ - Link-check (W-C) is a read-only graph validator: it resolves every markdown link and wikilink against the vault and reports unresolved targets by file and area, writing nothing. Area buckets use the configured structural dirs, not hardcoded area names.
253
+ - Live-cases scaffold creates a redacted E23 reviewed-case pack scaffold with hash-only source refs. It does not claim human evidence and stores no raw source text or absolute paths.
254
+ - Onboard is a read-only first-run guide for non-developers. It explains the next command without creating files or calling a model.
255
+ - Answer eval checks faithfulness, citation accuracy, conflict surfacing, abstention, private boundaries, and stale-source handling without model calls or writes.
256
+ - Lessons eval checks candidate precision, recall, false positives, and unsafe blocking without model calls or writes.
257
+ - Gemini connector uses Gemini CLI MCP config with a bounded tool allowlist. Runtime connector alpha emits a bounded MCP config snippet instead of editing host config.
258
+ - Lessons are previewed before promotion, and promotion requires an exact confirmation phrase.
259
+ - MCP alpha exposes read/capture/scan/preview tools only, not silent durable wiki writes.
260
+ `;
261
+ }