@remnic/core 9.7.12 → 9.7.14

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 (285) hide show
  1. package/dist/access-admin-ops-surface.d.ts +6 -6
  2. package/dist/access-admin-ops-surface.js +7 -7
  3. package/dist/access-boundary.d.ts +6 -6
  4. package/dist/access-boundary.js +8 -8
  5. package/dist/access-cli.js +34 -34
  6. package/dist/access-http.d.ts +6 -6
  7. package/dist/access-http.js +12 -12
  8. package/dist/access-identity-continuity-surface.d.ts +5 -5
  9. package/dist/access-identity-continuity-surface.js +7 -7
  10. package/dist/access-lcm-surface.d.ts +6 -6
  11. package/dist/access-lcm-surface.js +7 -7
  12. package/dist/access-mcp.d.ts +6 -6
  13. package/dist/access-mcp.js +11 -11
  14. package/dist/access-observe-write-surface.d.ts +6 -6
  15. package/dist/access-observe-write-surface.js +7 -7
  16. package/dist/access-operations-batch.js +9 -9
  17. package/dist/access-operations.d.ts +6 -6
  18. package/dist/access-operations.js +10 -10
  19. package/dist/access-recall-surface.d.ts +6 -6
  20. package/dist/access-recall-surface.js +7 -7
  21. package/dist/{access-service-tHd3eQpd.d.ts → access-service-CPhSnLOH.d.ts} +4 -4
  22. package/dist/access-service.d.ts +6 -6
  23. package/dist/access-service.js +7 -7
  24. package/dist/access-surface-catalog.d.ts +6 -6
  25. package/dist/action-confidence.d.ts +1 -1
  26. package/dist/active-memory-bridge.d.ts +1 -1
  27. package/dist/active-recall.d.ts +1 -1
  28. package/dist/active-recall.js +1 -1
  29. package/dist/behavior-learner.d.ts +1 -1
  30. package/dist/behavior-signals.d.ts +1 -1
  31. package/dist/bootstrap.d.ts +5 -5
  32. package/dist/briefing.d.ts +2 -2
  33. package/dist/briefing.js +3 -3
  34. package/dist/buffer-surprise-report.d.ts +1 -1
  35. package/dist/buffer.d.ts +2 -2
  36. package/dist/bulk-import/index.d.ts +3 -3
  37. package/dist/calibration.d.ts +1 -1
  38. package/dist/capabilities.d.ts +1 -1
  39. package/dist/{catalog-DEMiw6HZ.d.ts → catalog-uX9sT9ws.d.ts} +1 -1
  40. package/dist/causal-behavior.d.ts +1 -1
  41. package/dist/causal-consolidation.d.ts +1 -1
  42. package/dist/causal-consolidation.js +4 -4
  43. package/dist/causal-trajectory-graph.d.ts +1 -1
  44. package/dist/{chunk-2RSL6YRA.js → chunk-2E6G7FCE.js} +2 -2
  45. package/dist/{chunk-JKLJ6A7W.js → chunk-3D6AFGQR.js} +2 -2
  46. package/dist/{chunk-BQTSGK5Y.js → chunk-4B4MUS5D.js} +2 -2
  47. package/dist/{chunk-NVXQTRBL.js → chunk-4LEF6XWJ.js} +2 -2
  48. package/dist/{chunk-TMGK6YE7.js → chunk-5UNWK7KU.js} +2 -2
  49. package/dist/{chunk-OIFZII6J.js → chunk-67ZCJLJY.js} +2 -2
  50. package/dist/{chunk-ZRXSHGXT.js → chunk-6CALL5VN.js} +2 -2
  51. package/dist/{chunk-TRH533CA.js → chunk-7ICYQUOL.js} +2 -2
  52. package/dist/{chunk-I3GKTDM2.js → chunk-7LFXDGLH.js} +3 -3
  53. package/dist/{chunk-OCY3CRPG.js → chunk-A7B4RMQG.js} +3 -3
  54. package/dist/{chunk-2ZPQUTMW.js → chunk-AD6AMF2N.js} +4 -4
  55. package/dist/{chunk-TITSEN2M.js → chunk-ANADNYWK.js} +19 -5
  56. package/dist/chunk-ANADNYWK.js.map +1 -0
  57. package/dist/{chunk-YI7XUXLX.js → chunk-ASKEM4AR.js} +18 -18
  58. package/dist/{chunk-G5PVJJRA.js → chunk-B3F4CWQR.js} +1 -1
  59. package/dist/chunk-B3F4CWQR.js.map +1 -0
  60. package/dist/{chunk-675YU5IK.js → chunk-DDGV7NAX.js} +2 -2
  61. package/dist/{chunk-CE3GMHT4.js → chunk-EEARRVZ2.js} +2 -2
  62. package/dist/{chunk-AOWPZ7TM.js → chunk-F7AU34FC.js} +17 -17
  63. package/dist/{chunk-T6U7HDIY.js → chunk-FBNWOMCE.js} +2 -2
  64. package/dist/{chunk-QPZCAVDC.js → chunk-GMSDQUCR.js} +7 -7
  65. package/dist/{chunk-6N7R7TR2.js → chunk-IFJ23BHU.js} +6 -1
  66. package/dist/chunk-IFJ23BHU.js.map +1 -0
  67. package/dist/{chunk-IQULRIZM.js → chunk-IKSELOIV.js} +2 -2
  68. package/dist/{chunk-ZC3HG22I.js → chunk-JMBVCAR4.js} +2 -2
  69. package/dist/{chunk-CLFY35ED.js → chunk-KGWXHWAH.js} +3 -3
  70. package/dist/{chunk-RT7IP3D3.js → chunk-KSNVDPDF.js} +2 -2
  71. package/dist/{chunk-TWGGNUWJ.js → chunk-MKDRQAA3.js} +2 -2
  72. package/dist/{chunk-ZASJ53ML.js → chunk-ND5M64JJ.js} +41 -9
  73. package/dist/chunk-ND5M64JJ.js.map +1 -0
  74. package/dist/{chunk-XUQUBZ7O.js → chunk-NUWYOKS6.js} +2 -2
  75. package/dist/{chunk-VY6LKKVN.js → chunk-NWTGD4AN.js} +6 -1
  76. package/dist/chunk-NWTGD4AN.js.map +1 -0
  77. package/dist/{chunk-D4TLWDYR.js → chunk-PK5XBDA6.js} +2 -2
  78. package/dist/{chunk-2AL7N3BH.js → chunk-RBQLJSJ7.js} +2 -2
  79. package/dist/{chunk-FUUF7FMX.js → chunk-TXVD7PLT.js} +2 -2
  80. package/dist/{chunk-UTZW3X2R.js → chunk-UN3CH3CO.js} +2 -2
  81. package/dist/{chunk-PA6DMYEK.js → chunk-VYOFVVNK.js} +6 -6
  82. package/dist/{chunk-3SIC3E65.js → chunk-W5NKDU24.js} +2 -2
  83. package/dist/{cli-D8Tsa4Sh.d.ts → cli-_Y2Bmt6A.d.ts} +5 -5
  84. package/dist/cli.d.ts +8 -8
  85. package/dist/cli.js +25 -25
  86. package/dist/compounding/engine.d.ts +2 -2
  87. package/dist/compounding/engine.js +3 -3
  88. package/dist/compounding/preference-consolidator.d.ts +1 -1
  89. package/dist/compression-optimizer.d.ts +1 -1
  90. package/dist/config.d.ts +1 -1
  91. package/dist/config.js +1 -1
  92. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  93. package/dist/connectors/codex-materialize-runner.js +3 -3
  94. package/dist/connectors/codex-materialize.d.ts +1 -1
  95. package/dist/connectors/index.d.ts +1 -1
  96. package/dist/connectors/index.js +3 -3
  97. package/dist/consolidation-provenance-check.d.ts +2 -2
  98. package/dist/consolidation-undo.d.ts +2 -2
  99. package/dist/contradiction/index.d.ts +2 -2
  100. package/dist/conversation-index/backend.d.ts +1 -1
  101. package/dist/conversation-index/chunker.d.ts +1 -1
  102. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  103. package/dist/conversation-index/indexer.d.ts +1 -1
  104. package/dist/conversation-index/search.d.ts +1 -1
  105. package/dist/day-summary.d.ts +1 -1
  106. package/dist/delinearize.d.ts +1 -1
  107. package/dist/direct-answer-wiring.d.ts +1 -1
  108. package/dist/direct-answer.d.ts +1 -1
  109. package/dist/embedding-fallback.d.ts +1 -1
  110. package/dist/enrichment/index.d.ts +1 -1
  111. package/dist/entity-retrieval.d.ts +2 -2
  112. package/dist/entity-retrieval.js +3 -3
  113. package/dist/entity-schema.d.ts +1 -1
  114. package/dist/explicit-capture.d.ts +5 -5
  115. package/dist/extraction-faithfulness.d.ts +1 -1
  116. package/dist/extraction-judge-telemetry.d.ts +1 -1
  117. package/dist/extraction-judge-training.d.ts +1 -1
  118. package/dist/extraction-judge.d.ts +1 -1
  119. package/dist/extraction.d.ts +1 -1
  120. package/dist/extraction.js +2 -2
  121. package/dist/fallback-llm.d.ts +1 -1
  122. package/dist/graph-dashboard-diff.d.ts +1 -1
  123. package/dist/graph-dashboard-key.d.ts +1 -1
  124. package/dist/graph-dashboard-parser.d.ts +1 -1
  125. package/dist/graph-edge-reinforcement.d.ts +1 -1
  126. package/dist/graph-snapshot.d.ts +1 -1
  127. package/dist/graph.d.ts +1 -1
  128. package/dist/identity-continuity.d.ts +1 -1
  129. package/dist/importance.d.ts +1 -1
  130. package/dist/importers/index.d.ts +1 -1
  131. package/dist/in-flight-reads.d.ts +1 -1
  132. package/dist/index.d.ts +14 -14
  133. package/dist/index.js +34 -34
  134. package/dist/intent.d.ts +1 -1
  135. package/dist/lcm/engine.d.ts +1 -1
  136. package/dist/lcm/index.d.ts +1 -1
  137. package/dist/lcm/tools.d.ts +1 -1
  138. package/dist/lifecycle.d.ts +1 -1
  139. package/dist/live-connectors-runner.d.ts +1 -1
  140. package/dist/local-llm.d.ts +1 -1
  141. package/dist/local-llm.js +1 -1
  142. package/dist/local-model-endpoint.d.ts +1 -1
  143. package/dist/maintenance/memory-governance.d.ts +1 -1
  144. package/dist/maintenance/memory-governance.js +3 -3
  145. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  146. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  147. package/dist/mcp-memory-inspector-app.d.ts +6 -6
  148. package/dist/memory-action-policy.d.ts +1 -1
  149. package/dist/memory-cache.d.ts +1 -1
  150. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  151. package/dist/memory-projection-store.d.ts +1 -1
  152. package/dist/memory-provenance.d.ts +1 -1
  153. package/dist/memory-worth-outcomes.d.ts +2 -2
  154. package/dist/models-json.d.ts +1 -1
  155. package/dist/namespaces/migrate.d.ts +3 -3
  156. package/dist/namespaces/migrate.js +4 -4
  157. package/dist/namespaces/principal.d.ts +1 -1
  158. package/dist/namespaces/search.d.ts +1 -1
  159. package/dist/namespaces/storage.d.ts +3 -3
  160. package/dist/namespaces/storage.js +3 -3
  161. package/dist/native-knowledge.d.ts +1 -1
  162. package/dist/operator-toolkit.d.ts +2 -2
  163. package/dist/operator-toolkit.js +8 -8
  164. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  165. package/dist/orchestration/maintenance.d.ts +2 -2
  166. package/dist/orchestration/maintenance.js +5 -5
  167. package/dist/{orchestrator-B_WXBmuE.d.ts → orchestrator-BbZ_dQSU.d.ts} +4 -4
  168. package/dist/orchestrator.d.ts +5 -5
  169. package/dist/orchestrator.js +34 -34
  170. package/dist/patterns-cli.d.ts +1 -1
  171. package/dist/{pipeline-Dvtvt141.d.ts → pipeline-FRMDb1fn.d.ts} +1 -1
  172. package/dist/policy-runtime.d.ts +1 -1
  173. package/dist/provenance.d.ts +1 -1
  174. package/dist/qmd-preflight.d.ts +2 -2
  175. package/dist/qmd-recall-cache.d.ts +1 -1
  176. package/dist/{qmd-DwBLh_hl.d.ts → qmd-xJRrHFbA.d.ts} +1 -1
  177. package/dist/qmd.d.ts +2 -2
  178. package/dist/recall-disclosure-escalation.d.ts +1 -1
  179. package/dist/recall-explain-renderer.d.ts +1 -1
  180. package/dist/recall-explain-renderer.js +3 -3
  181. package/dist/recall-planner-llm.d.ts +1 -1
  182. package/dist/recall-state.d.ts +1 -1
  183. package/dist/recall-tag-filter.d.ts +1 -1
  184. package/dist/recall-timings.d.ts +1 -1
  185. package/dist/recall-xray-cli.d.ts +1 -1
  186. package/dist/recall-xray-cli.js +4 -4
  187. package/dist/recall-xray-renderer.d.ts +1 -1
  188. package/dist/recall-xray-renderer.js +3 -3
  189. package/dist/recall-xray.d.ts +1 -1
  190. package/dist/recall-xray.js +2 -2
  191. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  192. package/dist/replay/normalizers/claude.d.ts +1 -1
  193. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  194. package/dist/replay/normalizers/shared.d.ts +1 -1
  195. package/dist/replay/runner.d.ts +1 -1
  196. package/dist/replay/types.d.ts +1 -1
  197. package/dist/resolve-auth-token.d.ts +1 -1
  198. package/dist/resume-bundles.js +2 -2
  199. package/dist/retrieval-agents.d.ts +2 -2
  200. package/dist/retrieval-tiers.d.ts +1 -1
  201. package/dist/routing/engine.d.ts +1 -1
  202. package/dist/routing/store.d.ts +1 -1
  203. package/dist/search/embed-helper.d.ts +1 -1
  204. package/dist/search/factory.d.ts +1 -1
  205. package/dist/search/index.d.ts +1 -1
  206. package/dist/search/lancedb-backend.d.ts +1 -1
  207. package/dist/search/meilisearch-backend.d.ts +1 -1
  208. package/dist/search/noop-backend.d.ts +1 -1
  209. package/dist/search/orama-backend.d.ts +1 -1
  210. package/dist/search/port.d.ts +1 -1
  211. package/dist/search/remote-backend.d.ts +1 -1
  212. package/dist/{semantic-consolidation-Dia_6FOn.d.ts → semantic-consolidation-fvdZRa5Z.d.ts} +1 -1
  213. package/dist/semantic-consolidation.d.ts +2 -2
  214. package/dist/semantic-consolidation.js +4 -4
  215. package/dist/semantic-rule-promotion.js +3 -3
  216. package/dist/semantic-rule-verifier.d.ts +1 -1
  217. package/dist/semantic-rule-verifier.js +3 -3
  218. package/dist/session-observer-bands.d.ts +1 -1
  219. package/dist/session-observer-state.d.ts +1 -1
  220. package/dist/shared-context/manager.d.ts +1 -1
  221. package/dist/signal.d.ts +1 -1
  222. package/dist/{storage-RshM7i8-.d.ts → storage-CrvzaM9C.d.ts} +1 -1
  223. package/dist/storage.d.ts +2 -2
  224. package/dist/storage.js +2 -2
  225. package/dist/summarizer.d.ts +1 -1
  226. package/dist/summarizer.js +2 -2
  227. package/dist/summary-snapshot.d.ts +1 -1
  228. package/dist/temporal-supersession.d.ts +2 -2
  229. package/dist/temporal-timeline-recall.d.ts +1 -1
  230. package/dist/temporal-validity.d.ts +1 -1
  231. package/dist/threading.d.ts +1 -1
  232. package/dist/tier-migration.d.ts +2 -2
  233. package/dist/tier-routing.d.ts +1 -1
  234. package/dist/topics.d.ts +1 -1
  235. package/dist/transcript.d.ts +1 -1
  236. package/dist/trust-score-stage.d.ts +1 -1
  237. package/dist/trust-score.d.ts +1 -1
  238. package/dist/{types-CHSXOq7s.d.ts → types-Bl4BWDM8.d.ts} +6 -0
  239. package/dist/types.d.ts +1 -1
  240. package/dist/types.js +1 -1
  241. package/dist/utility-runtime.d.ts +1 -1
  242. package/dist/verified-recall.js +3 -3
  243. package/package.json +2 -2
  244. package/src/access-http.ts +40 -2
  245. package/src/config.ts +9 -0
  246. package/src/local-llm-thinking.test.ts +55 -1
  247. package/src/local-llm.ts +14 -0
  248. package/src/relay/mission-access.test.ts +58 -3
  249. package/src/relay/mission-access.ts +17 -3
  250. package/src/relay/mission-ui.test.ts +90 -0
  251. package/src/types.ts +6 -0
  252. package/dist/chunk-6N7R7TR2.js.map +0 -1
  253. package/dist/chunk-G5PVJJRA.js.map +0 -1
  254. package/dist/chunk-TITSEN2M.js.map +0 -1
  255. package/dist/chunk-VY6LKKVN.js.map +0 -1
  256. package/dist/chunk-ZASJ53ML.js.map +0 -1
  257. /package/dist/{chunk-2RSL6YRA.js.map → chunk-2E6G7FCE.js.map} +0 -0
  258. /package/dist/{chunk-JKLJ6A7W.js.map → chunk-3D6AFGQR.js.map} +0 -0
  259. /package/dist/{chunk-BQTSGK5Y.js.map → chunk-4B4MUS5D.js.map} +0 -0
  260. /package/dist/{chunk-NVXQTRBL.js.map → chunk-4LEF6XWJ.js.map} +0 -0
  261. /package/dist/{chunk-TMGK6YE7.js.map → chunk-5UNWK7KU.js.map} +0 -0
  262. /package/dist/{chunk-OIFZII6J.js.map → chunk-67ZCJLJY.js.map} +0 -0
  263. /package/dist/{chunk-ZRXSHGXT.js.map → chunk-6CALL5VN.js.map} +0 -0
  264. /package/dist/{chunk-TRH533CA.js.map → chunk-7ICYQUOL.js.map} +0 -0
  265. /package/dist/{chunk-I3GKTDM2.js.map → chunk-7LFXDGLH.js.map} +0 -0
  266. /package/dist/{chunk-OCY3CRPG.js.map → chunk-A7B4RMQG.js.map} +0 -0
  267. /package/dist/{chunk-2ZPQUTMW.js.map → chunk-AD6AMF2N.js.map} +0 -0
  268. /package/dist/{chunk-YI7XUXLX.js.map → chunk-ASKEM4AR.js.map} +0 -0
  269. /package/dist/{chunk-675YU5IK.js.map → chunk-DDGV7NAX.js.map} +0 -0
  270. /package/dist/{chunk-CE3GMHT4.js.map → chunk-EEARRVZ2.js.map} +0 -0
  271. /package/dist/{chunk-AOWPZ7TM.js.map → chunk-F7AU34FC.js.map} +0 -0
  272. /package/dist/{chunk-T6U7HDIY.js.map → chunk-FBNWOMCE.js.map} +0 -0
  273. /package/dist/{chunk-QPZCAVDC.js.map → chunk-GMSDQUCR.js.map} +0 -0
  274. /package/dist/{chunk-IQULRIZM.js.map → chunk-IKSELOIV.js.map} +0 -0
  275. /package/dist/{chunk-ZC3HG22I.js.map → chunk-JMBVCAR4.js.map} +0 -0
  276. /package/dist/{chunk-CLFY35ED.js.map → chunk-KGWXHWAH.js.map} +0 -0
  277. /package/dist/{chunk-RT7IP3D3.js.map → chunk-KSNVDPDF.js.map} +0 -0
  278. /package/dist/{chunk-TWGGNUWJ.js.map → chunk-MKDRQAA3.js.map} +0 -0
  279. /package/dist/{chunk-XUQUBZ7O.js.map → chunk-NUWYOKS6.js.map} +0 -0
  280. /package/dist/{chunk-D4TLWDYR.js.map → chunk-PK5XBDA6.js.map} +0 -0
  281. /package/dist/{chunk-2AL7N3BH.js.map → chunk-RBQLJSJ7.js.map} +0 -0
  282. /package/dist/{chunk-FUUF7FMX.js.map → chunk-TXVD7PLT.js.map} +0 -0
  283. /package/dist/{chunk-UTZW3X2R.js.map → chunk-UN3CH3CO.js.map} +0 -0
  284. /package/dist/{chunk-PA6DMYEK.js.map → chunk-VYOFVVNK.js.map} +0 -0
  285. /package/dist/{chunk-3SIC3E65.js.map → chunk-W5NKDU24.js.map} +0 -0
package/src/local-llm.ts CHANGED
@@ -999,6 +999,20 @@ export class LocalLlmClient {
999
999
  THINKING_COMPATIBLE_BACKENDS.has(this.detectedType)
1000
1000
  ) {
1001
1001
  requestBody.chat_template_kwargs = { enable_thinking: false };
1002
+ } else if (shouldSuppressThinking && this.detectedType === "ollama") {
1003
+ // Ollama's /v1 endpoint silently drops `chat_template_kwargs` AND
1004
+ // `enable_thinking` — the ONLY field it maps to think-off is
1005
+ // `reasoning_effort` ("none" → ThinkValue{false} in openai.go;
1006
+ // verified against Ollama 0.32.0 source and live probes,
1007
+ // issue #1996). Without this, thinking-capable models (Gemma 4,
1008
+ // Qwen 3.5+) burn 1,700-2,000 reasoning tokens per extraction on
1009
+ // Ollama, exceed the client timeout, and retry forever. The effort
1010
+ // is configurable via `localLlmReasoningEffort` (default "none");
1011
+ // an empty value disables injection (pre-#1996 behavior).
1012
+ const effort = this.config.localLlmReasoningEffort;
1013
+ if (effort) {
1014
+ requestBody.reasoning_effort = effort;
1015
+ }
1002
1016
  }
1003
1017
 
1004
1018
  // Normalize URL (use 127.0.0.1 instead of localhost)
@@ -60,13 +60,33 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
60
60
  service: fakeService(root, calls),
61
61
  port: 0,
62
62
  authToken: "relay-token",
63
- principal: "relay-operator",
63
+ principal: "operator-build-week",
64
64
  adminConsoleEnabled: false,
65
65
  });
66
66
  const status = await server.start();
67
67
  const base = `http://127.0.0.1:${status.port}/engram/v1/relay/missions/${RELAY_DEMO_MISSION_ID}`;
68
68
  try {
69
69
  const fixture = createRelayMissionFixture();
70
+ const approval = fixture.find((event) => event.payload.kind === "correction_approved");
71
+ assert.ok(approval && approval.payload.kind === "correction_approved");
72
+ const mismatchedApproval = await fetch(`${base}/events`, {
73
+ method: "POST",
74
+ headers: authHeaders(),
75
+ body: JSON.stringify({
76
+ namespace: RELAY_DEMO_NAMESPACE,
77
+ event: {
78
+ ...approval,
79
+ idempotencyKey: "mismatched-human-approval",
80
+ payload: {
81
+ ...approval.payload,
82
+ approvedBy: { ...approval.payload.approvedBy, id: "different-operator" },
83
+ },
84
+ },
85
+ }),
86
+ });
87
+ assert.equal(mismatchedApproval.status, 400);
88
+ assert.equal(((await mismatchedApproval.json()) as { code: string }).code, "input_error");
89
+
70
90
  const blankNamespace = await fetch(`${base}/events`, {
71
91
  method: "POST",
72
92
  headers: authHeaders(),
@@ -91,7 +111,7 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
91
111
  assert.equal(response.status, 201, responseBody);
92
112
  assert.equal(
93
113
  (JSON.parse(responseBody) as { event: { authenticatedPrincipal?: string } }).event.authenticatedPrincipal,
94
- "relay-operator"
114
+ "operator-build-week"
95
115
  );
96
116
  }
97
117
 
@@ -108,6 +128,7 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
108
128
  });
109
129
  assert.equal(response.status, 200);
110
130
  assert.equal(response.headers.get("cache-control"), "no-store");
131
+ assert.equal(response.headers.get("x-remnic-authenticated-principal"), "operator-build-week");
111
132
  const snapshot = (await response.json()) as RelayMissionSnapshot;
112
133
  assert.equal(snapshot.receipt.complete, true);
113
134
  assert.deepEqual(snapshot.receipt.activeDecisionIds, ["decision-refresh-after-expiry"]);
@@ -115,7 +136,40 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
115
136
  assert.equal(snapshot.agents.length, 3);
116
137
  assert.equal(snapshot.tests.at(-1)?.status, "passed");
117
138
  assert.ok(calls.every((call) => call.namespace === RELAY_DEMO_NAMESPACE));
118
- assert.ok(calls.every((call) => call.principal === "relay-operator"));
139
+ assert.ok(calls.every((call) => call.principal === "operator-build-week"));
140
+ } finally {
141
+ await server.stop();
142
+ }
143
+ });
144
+ });
145
+
146
+ test("HTTP Relay rejects human approval without a server-resolved principal before persistence", async () => {
147
+ await withTempRoot(async (root) => {
148
+ const server = new EngramAccessHttpServer({
149
+ service: fakeService(root, []),
150
+ port: 0,
151
+ authToken: "relay-token",
152
+ adminConsoleEnabled: false,
153
+ });
154
+ const status = await server.start();
155
+ const base = `http://127.0.0.1:${status.port}/engram/v1/relay/missions/${RELAY_DEMO_MISSION_ID}`;
156
+ try {
157
+ const approval = createRelayMissionFixture().find((event) => event.payload.kind === "correction_approved");
158
+ assert.ok(approval);
159
+ const rejected = await fetch(`${base}/events`, {
160
+ method: "POST",
161
+ headers: authHeaders(),
162
+ body: JSON.stringify({ namespace: RELAY_DEMO_NAMESPACE, event: approval }),
163
+ });
164
+ assert.equal(rejected.status, 400);
165
+ assert.equal(((await rejected.json()) as { code: string }).code, "input_error");
166
+
167
+ const snapshotResponse = await fetch(`${base}?namespace=${RELAY_DEMO_NAMESPACE}`, {
168
+ headers: authHeaders(),
169
+ });
170
+ assert.equal(snapshotResponse.status, 200);
171
+ assert.equal(snapshotResponse.headers.get("x-remnic-authenticated-principal"), null);
172
+ assert.equal(((await snapshotResponse.json()) as RelayMissionSnapshot).found, false);
119
173
  } finally {
120
174
  await server.stop();
121
175
  }
@@ -150,6 +204,7 @@ test("HTTP Relay surface distinguishes empty, invalid, unauthorized, and backend
150
204
 
151
205
  const empty = await fetch(emptyUrl, { headers: authHeaders("read-token") });
152
206
  assert.equal(empty.status, 200);
207
+ assert.equal(empty.headers.get("x-remnic-authenticated-principal"), null);
153
208
  assert.deepEqual(await empty.json(), assertEmptyMissionShape());
154
209
 
155
210
  const badLimit = await fetch(`${emptyUrl}&limit=501`, {
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
 
3
3
  import { type OperationContext, defineOperation } from "../access-boundary.js";
4
- import type { EngramAccessService } from "../access-service.js";
4
+ import { EngramAccessInputError, type EngramAccessService } from "../access-service.js";
5
5
  import {
6
6
  RELAY_MISSION_MAX_EVENT_LIMIT,
7
7
  RelayIsoDateTimeSchema,
@@ -76,12 +76,26 @@ export async function appendRelayMissionEvent(
76
76
  authenticatedPrincipal?: string,
77
77
  beforeAppend?: () => void | Promise<void>
78
78
  ): Promise<RelayMissionAppendResult> {
79
- const resolved = await service.getWritableStorageForNamespace(input.namespace ?? undefined, authenticatedPrincipal);
79
+ const event = RelayMissionEventInputSchema.parse(input.event);
80
+ const approvalPrincipal = authenticatedPrincipal?.trim() || undefined;
81
+ if (event.payload.kind === "correction_approved" && event.payload.approvedBy.kind === "human") {
82
+ if (!approvalPrincipal) {
83
+ throw new EngramAccessInputError(
84
+ "Relay human approval requires a server-resolved authenticated principal"
85
+ );
86
+ }
87
+ if (event.payload.approvedBy.id !== approvalPrincipal) {
88
+ throw new EngramAccessInputError(
89
+ "Relay human approval identity must match the server-resolved authenticated principal"
90
+ );
91
+ }
92
+ }
93
+ const resolved = await service.getWritableStorageForNamespace(input.namespace ?? undefined, approvalPrincipal);
80
94
  const store = new RelayMissionStore({
81
95
  rootDir: resolved.storage.dir,
82
96
  namespace: resolved.namespace,
83
97
  });
84
- return store.append(input.missionId, input.event, { authenticatedPrincipal, beforeAppend });
98
+ return store.append(input.missionId, event, { authenticatedPrincipal: approvalPrincipal, beforeAppend });
85
99
  }
86
100
 
87
101
  /** Namespace-authorized, bounded Relay snapshot read shared by HTTP and UI. */
@@ -0,0 +1,90 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtemp, rm } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import test from "node:test";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ import { EngramAccessHttpServer } from "../access-http.js";
9
+ import type { EngramAccessService } from "../access-service.js";
10
+ import type { StorageManager } from "../storage.js";
11
+
12
+ const adminConsolePublicDir = path.resolve(
13
+ path.dirname(fileURLToPath(import.meta.url)),
14
+ "../../../../admin-console/public"
15
+ );
16
+
17
+ async function withTempRoot(run: (root: string) => Promise<void>): Promise<void> {
18
+ const root = await mkdtemp(path.join(os.tmpdir(), "remnic-relay-ui-"));
19
+ try {
20
+ await run(root);
21
+ } finally {
22
+ await rm(root, { recursive: true, force: true });
23
+ }
24
+ }
25
+
26
+ function fakeService(root: string): EngramAccessService {
27
+ const storage = { dir: root } as StorageManager;
28
+ return {
29
+ configRef: { defaultNamespace: "relay-build-week", namespacesEnabled: true },
30
+ getReadableStorageForNamespace: async (namespace?: string) => ({ namespace: namespace ?? "relay-build-week", storage }),
31
+ getWritableStorageForNamespace: async (namespace?: string) => ({ namespace: namespace ?? "relay-build-week", storage }),
32
+ } as unknown as EngramAccessService;
33
+ }
34
+
35
+ test("Relay Mission Control serves both aliases from one exact static allow-list", async () => {
36
+ await withTempRoot(async (root) => {
37
+ const server = new EngramAccessHttpServer({
38
+ service: fakeService(root),
39
+ host: "127.0.0.1",
40
+ port: 0,
41
+ authToken: "relay-token",
42
+ principal: "relay-operator",
43
+ adminConsoleEnabled: true,
44
+ adminConsolePublicDir,
45
+ adminConsolePrefillToken: true,
46
+ });
47
+ const status = await server.start();
48
+ const origin = `http://127.0.0.1:${status.port}`;
49
+ try {
50
+ for (const prefix of ["remnic", "engram"]) {
51
+ const redirect = await fetch(`${origin}/${prefix}/ui/relay`, { redirect: "manual" });
52
+ assert.equal(redirect.status, 301);
53
+ assert.equal(redirect.headers.get("location"), `/${prefix}/ui/relay/`);
54
+
55
+ const shell = await fetch(`${origin}/${prefix}/ui/relay/`);
56
+ assert.equal(shell.status, 200);
57
+ assert.match(shell.headers.get("content-type") ?? "", /^text\/html/);
58
+ assert.doesNotMatch(await shell.text(), /__REMNIC_ADMIN_CONSOLE_PREFILL_TOKEN__/);
59
+
60
+ const authorizedShell = await fetch(`${origin}/${prefix}/ui/relay/`, {
61
+ headers: { authorization: "Bearer relay-token" },
62
+ });
63
+ assert.equal(authorizedShell.status, 200);
64
+ assert.equal(authorizedShell.headers.get("cache-control"), "private, no-store");
65
+ assert.match(await authorizedShell.text(), /__REMNIC_ADMIN_CONSOLE_PREFILL_TOKEN__="relay-token"/);
66
+
67
+ const expectedAssets = new Map([
68
+ ["relay.css", /^text\/css/],
69
+ ["relay-model.js", /^application\/javascript/],
70
+ ["relay.js", /^application\/javascript/],
71
+ ["replay.json", /^application\/json/],
72
+ ]);
73
+ for (const [fileName, contentType] of expectedAssets) {
74
+ const asset = await fetch(`${origin}/${prefix}/ui/relay/${fileName}`);
75
+ assert.equal(asset.status, 200, `${prefix}/${fileName}`);
76
+ assert.match(asset.headers.get("content-type") ?? "", contentType);
77
+ assert.ok((await asset.text()).length > 100);
78
+ }
79
+
80
+ const auth = { authorization: "Bearer relay-token" };
81
+ const unknown = await fetch(`${origin}/${prefix}/ui/relay/not-allowed.js`, { headers: auth });
82
+ assert.equal(unknown.status, 404);
83
+ const nested = await fetch(`${origin}/${prefix}/ui/relay/relay.js/extra`, { headers: auth });
84
+ assert.equal(nested.status, 404);
85
+ }
86
+ } finally {
87
+ await server.stop();
88
+ }
89
+ });
90
+ });
package/src/types.ts CHANGED
@@ -1595,6 +1595,12 @@ export interface PluginConfig {
1595
1595
  localLlmRetryBackoffMs: number;
1596
1596
  localLlm400TripThreshold: number;
1597
1597
  localLlm400CooldownMs: number;
1598
+ /** Ollama-backend thinking suppression: `reasoning_effort` value injected on
1599
+ * `/v1/chat/completions` for THINKING_SUPPRESSED_OPERATIONS ("none" | "low" |
1600
+ * "medium" | "high" | "max"; "" disables injection). Ollama ignores
1601
+ * `chat_template_kwargs`, so this is the only think-off dialect it honors.
1602
+ * Issue #1996. */
1603
+ localLlmReasoningEffort: string;
1598
1604
  // Extraction retry/backoff + circuit breaker (extraction hot-loop hardening)
1599
1605
  /** Master gate. When false, restores pre-change behavior (extractor called on every triggered observe; no gate). */
1600
1606
  extractionRetryEnabled: boolean;