@halofy/agent-connect 0.12.1 → 0.13.1

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 (253) hide show
  1. package/README.md +249 -10
  2. package/bin/halofy-agent.mjs +96 -11
  3. package/node_modules/yaml/LICENSE +13 -0
  4. package/node_modules/yaml/README.md +172 -0
  5. package/node_modules/yaml/bin.mjs +11 -0
  6. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  7. package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  8. package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  9. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  10. package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  11. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  12. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  13. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  14. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  15. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  16. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +226 -0
  17. package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  18. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  19. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  20. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  21. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  22. package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  23. package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  24. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  25. package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  26. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  27. package/node_modules/yaml/browser/dist/errors.js +57 -0
  28. package/node_modules/yaml/browser/dist/index.js +17 -0
  29. package/node_modules/yaml/browser/dist/log.js +11 -0
  30. package/node_modules/yaml/browser/dist/nodes/Alias.js +118 -0
  31. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  32. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  33. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  34. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  35. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  36. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  37. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  38. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  39. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  40. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  41. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  42. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  43. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  44. package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  45. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  46. package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  47. package/node_modules/yaml/browser/dist/public-api.js +102 -0
  48. package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  49. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  50. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  51. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  52. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  53. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  54. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  55. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  56. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  57. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  58. package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  59. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  60. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  61. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  62. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  63. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  64. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  65. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  66. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  67. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  68. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  69. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  70. package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  71. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  72. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  73. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  74. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  75. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  76. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  77. package/node_modules/yaml/browser/dist/util.js +11 -0
  78. package/node_modules/yaml/browser/dist/visit.js +233 -0
  79. package/node_modules/yaml/browser/index.js +5 -0
  80. package/node_modules/yaml/browser/package.json +3 -0
  81. package/node_modules/yaml/dist/cli.d.ts +8 -0
  82. package/node_modules/yaml/dist/cli.mjs +201 -0
  83. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  84. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  85. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  86. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  87. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  88. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  89. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  90. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  91. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  92. package/node_modules/yaml/dist/compose/composer.js +224 -0
  93. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  94. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  95. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  96. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  97. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  98. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  99. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  100. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  101. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  102. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  103. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  104. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +228 -0
  105. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  106. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  107. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  108. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  109. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  110. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  111. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  112. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  113. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  114. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  115. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  116. package/node_modules/yaml/dist/doc/Document.js +337 -0
  117. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  118. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  119. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  120. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  121. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  122. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  123. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  124. package/node_modules/yaml/dist/doc/directives.js +178 -0
  125. package/node_modules/yaml/dist/errors.d.ts +21 -0
  126. package/node_modules/yaml/dist/errors.js +62 -0
  127. package/node_modules/yaml/dist/index.d.ts +25 -0
  128. package/node_modules/yaml/dist/index.js +50 -0
  129. package/node_modules/yaml/dist/log.d.ts +3 -0
  130. package/node_modules/yaml/dist/log.js +19 -0
  131. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  132. package/node_modules/yaml/dist/nodes/Alias.js +120 -0
  133. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  134. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  135. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  136. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  137. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  138. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  139. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  140. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  141. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  142. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  143. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  144. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  145. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  146. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  147. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  148. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  149. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  150. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  151. package/node_modules/yaml/dist/options.d.ts +350 -0
  152. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  153. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  154. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  155. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  156. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  157. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  158. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  159. package/node_modules/yaml/dist/parse/cst.js +112 -0
  160. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  161. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  162. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  163. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  164. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  165. package/node_modules/yaml/dist/parse/parser.js +980 -0
  166. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  167. package/node_modules/yaml/dist/public-api.js +107 -0
  168. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  169. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  170. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  171. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  172. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  173. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  174. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  175. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  176. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  177. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  178. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  179. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  180. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  181. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  182. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  183. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  184. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  185. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  186. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  187. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  188. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  189. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  190. package/node_modules/yaml/dist/schema/tags.js +99 -0
  191. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  192. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  193. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  194. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  195. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  196. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  197. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  198. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  199. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  200. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  201. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  202. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  203. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  204. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  205. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  206. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  207. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  208. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  209. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  210. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  211. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  212. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  213. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  214. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  215. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  216. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  217. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  218. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  219. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  220. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  221. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  222. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  223. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  224. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  225. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  226. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  227. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  228. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  229. package/node_modules/yaml/dist/test-events.js +134 -0
  230. package/node_modules/yaml/dist/util.d.ts +16 -0
  231. package/node_modules/yaml/dist/util.js +28 -0
  232. package/node_modules/yaml/dist/visit.d.ts +102 -0
  233. package/node_modules/yaml/dist/visit.js +236 -0
  234. package/node_modules/yaml/package.json +97 -0
  235. package/node_modules/yaml/util.js +2 -0
  236. package/package.json +8 -2
  237. package/src/claude-config.mjs +60 -2
  238. package/src/claude-hook.mjs +8 -1
  239. package/src/client-registry.mjs +13 -0
  240. package/src/delivery-sync.mjs +14 -0
  241. package/src/health.mjs +26 -4
  242. package/src/hermes-config.mjs +283 -0
  243. package/src/hermes-health.mjs +45 -0
  244. package/src/hermes-hook.mjs +86 -0
  245. package/src/hermes-plugin.py +67 -0
  246. package/src/host-hook.mjs +6 -8
  247. package/src/install.mjs +8 -0
  248. package/src/installer-cli.mjs +25 -3
  249. package/src/instructions.mjs +5 -1
  250. package/src/runtime.mjs +33 -22
  251. package/src/skill-guard.mjs +171 -0
  252. package/src/skills-sync.mjs +32 -16
  253. package/src/version.mjs +3 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Halofy agent lifecycle installer
2
2
 
3
- Status: source for `@halofy/agent-connect@0.12.1`; publication and deployment
3
+ Status: source for `@halofy/agent-connect@0.13.1`; publication and deployment
4
4
  require separate verification. The production console supplies the command for
5
5
  the verified published package pinned by the deployment workflow. Host loading
6
6
  requires separate verification.
@@ -24,14 +24,80 @@ conversations and serves the agent-invoked MCP memory tools, but does not push
24
24
  recalled memory into host sessions on session start or prompt submit. The
25
25
  bounded recall block formats stay in place and tested for when it returns.
26
26
 
27
+ ## Headless host limits and explicit refresh
28
+
29
+ Codex `exec` lifecycle hooks are not verified. A local Codex CLI 0.154.0
30
+ probe reached session/model dispatch without invoking configured SessionStart
31
+ or UserPromptSubmit hooks. Do not infer startup delivery, capture or complete
32
+ conversation coverage from the presence of `hooks.json`. This source adds an
33
+ explicit refresh command for an existing installation:
34
+
35
+ ```bash
36
+ node "/absolute/path/to/runtime/0.13.1/bin/halofy-agent.mjs" sync --connection <installation-id>
37
+ ```
38
+
39
+ The installer prints `syncCommand` with the exact executable, argument array
40
+ and `HALOFY_AGENT_HOME` environment for this installation. Use those values
41
+ (the example path above is a placeholder); an `npx` installation does not put
42
+ `halofy-agent` on your shell PATH. Run it before starting headless work. It
43
+ refreshes instructions, policies, knowledge references and assigned skills through the same signed, authorized delivery path without creating a
44
+ host session or capturing messages. It exits nonzero if instructions or
45
+ acknowledged file delivery are unavailable. A successful refresh proves file
46
+ delivery only; start a new host session to load changes. It does not add hooks
47
+ to `codex exec` or enable headless capture. Existing 0.12.1 installations do
48
+ not acquire this command until the new package is published and installed.
49
+
50
+ Claude installation adds a read-only permission for the exact installation's
51
+ `halofy-context-<hash>` directory, never the whole skills tree, runtime keys,
52
+ shell commands or MCP tools. Existing ask/deny rules remain authoritative.
53
+ Project allow rules require a trusted workspace; `claude -p` in an untrusted
54
+ folder may ignore them. Assigned skill folders and MCP tools may still need
55
+ separate host permission. No trust markers or permission-bypass flags are set.
56
+ See [Claude permissions](https://code.claude.com/docs/en/permissions).
57
+
58
+ Guarded Claude installations give managed skills immutable version aliases and
59
+ check current eligibility before native `Skill` expansion. Approved calls keep
60
+ normal host permissions; retired, replaced or unverifiable managed versions are
61
+ denied, including bodies Claude cached before its startup sync. Unrelated
62
+ employee skills outside reserved `halofy-managed-*` aliases and legacy tombstone
63
+ names remain unchanged when ownership history is intact. This requires
64
+ the installed trusted hook to execute and a reachable Halofy server. It cannot
65
+ recall earlier conversation content, downloaded copies or arbitrary file reads.
66
+ Other trusted hooks that rewrite `Skill` input are incompatible with this guard:
67
+ Claude can apply their rewritten input after Halofy's check.
68
+ Installer compatibility diagnostics inspect project, project-local and user
69
+ settings. An empty overlap list does not verify plugin, managed or command-line
70
+ hooks, or hooks introduced after installation.
71
+
72
+ If ownership history is missing or corrupt, all native Skill calls pause because
73
+ the runtime cannot safely distinguish employee skills from legacy managed names.
74
+ An administrator must restore verified `claude-skill-guard` ownership state or
75
+ review a reconnect migration that preserves legacy tombstones. Do not delete or
76
+ recreate an empty history to bypass the pause. Ordinary reinstall does not reset
77
+ initialized history.
78
+
79
+ The isolated real-host regression is opt-in (no global configuration or real
80
+ credentials): `HALOFY_CLAUDE_HOST_TEST=1 node --test test/claude-host-skills.test.mjs`.
81
+ Set `HALOFY_CLAUDE_BINARY` if `claude` is not on PATH. It verifies current managed
82
+ and employee skill expansion, native deny preservation and cached retired-body
83
+ denial, including whitespace around legacy names. It also reproduces the trusted
84
+ input-rewrite limitation in both hook registration orders.
85
+
86
+ For Codex, `HALOFY_CODEX_HOST_TEST=1 node --test test/codex-host-skills.test.mjs`
87
+ verifies signed explicit synchronization removes a retired skill's catalog and
88
+ explicitly requested body from the first fresh host request while preserving an
89
+ employee skill. Set `HALOFY_CODEX_BINARY` if needed. A running conversation can
90
+ retain already-loaded content; publication alone does not refresh installed
91
+ runtimes or their managed copies.
92
+
27
93
  ## Browser sign-in
28
94
 
29
95
  Users assigned to a team can run the installer without a manually copied badge.
30
- Use the production console’s verified command. After 0.12.1 is published and
96
+ Use the production console’s verified command. After 0.13.1 is published and
31
97
  verified, the command for this source version is:
32
98
 
33
99
  ```bash
34
- npx @halofy/agent-connect@0.12.1 install claude-code --server https://app.halofy.ai
100
+ npx @halofy/agent-connect@0.13.1 install claude-code --server https://app.halofy.ai
35
101
  ```
36
102
 
37
103
  `login <client-kind> --server <origin>` is an alias for the same installation
@@ -45,11 +111,11 @@ pending key survives retries. Installation still requires the terminal's
45
111
  explicit CONNECT disclosure before changing host configuration.
46
112
 
47
113
  Browser sign-in requires the matching server enrollment endpoints. The example
48
- above does not establish that 0.12.1 is published or enabled in production. The
49
- manual claim path remains supported; after publication, its 0.12.1 form is:
114
+ above does not establish that 0.13.1 is published or enabled in production. The
115
+ manual claim path remains supported; after publication, its 0.13.1 form is:
50
116
 
51
117
  ```bash
52
- npx --yes @halofy/agent-connect@0.12.1 install <client-kind> \
118
+ npx --yes @halofy/agent-connect@0.13.1 install <client-kind> \
53
119
  --server https://app.halofy.ai \
54
120
  --claim '<one-time-claim>'
55
121
  ```
@@ -66,6 +132,7 @@ permits only these reviewed client kinds:
66
132
  | `codex` | partial | assistant responses, tool failures, session end, binary bodies |
67
133
  | `vscode` | partial | assistant responses, binary bodies, context-use evidence |
68
134
  | `cline` | partial | assistant responses, tool failures, subagents, compaction, session end, binary bodies |
135
+ | `hermes-agents` | partial; Hermes 0.21.3 (2026.9.14) only | interrupted/intermediate assistant output, compaction, tokens/thinking, subagents, binary bodies, managed instructions/skills/context |
69
136
 
70
137
  Other catalog entries remain `Not supported yet` or `Not observed`; the
71
138
  installer refuses them before claim consumption. A knowledge connector,
@@ -126,16 +193,52 @@ npm test
126
193
  npm run check
127
194
  ```
128
195
 
129
- Content-free local queue/version evidence is available without decrypting or
130
- printing any pending event body:
196
+ Content-free local queue/version evidence is available without printing any
197
+ pending event body or proof key:
131
198
 
132
199
  ```bash
133
200
  node kernel/integrations/agent-runtime/bin/halofy-agent.mjs diagnostics
134
201
  ```
135
202
 
203
+ Pass `--connection <installation-id>` to inspect a specific installation.
204
+ Diagnostics shows installed and running runtime versions, local hook/pause
205
+ health, frozen capture capabilities, queue depth, oldest pending time and expired
206
+ batch count. It makes no server request, and neither active local hooks nor an
207
+ empty queue proves that a particular conversation reached the archive.
208
+
209
+ ## Conversation return reliability (0.13.1 source)
210
+
211
+ Append acknowledgement is now mandatory and bounded to the submitted batch.
212
+ An empty, non-JSON or malformed success response cannot discard queued events.
213
+ Only explicitly accepted or duplicate events advance the cursor; a server
214
+ sequence ahead of an event conflict cannot acknowledge the rejected local body.
215
+ An unchanged transcript retries its already durable queue, including after a
216
+ lost append response, without requiring another user message. Hook messages
217
+ without a native event id receive an id per invocation, so multiple prompts in
218
+ one Cline task and repeated identical prompts remain separate events. Queue
219
+ retries preserve that id; native event ids still deduplicate host retries.
220
+
221
+ Retries run at supported hooks, explicit runtime replay and the existing MCP
222
+ proxy's 60-second health tick. Each background tick attempts at most one pending
223
+ batch, with the proxy's five-second request timeout and cancellation on exit.
224
+ Heartbeat reporting continues when replay fails. Paused or replaced installations
225
+ skip background replay; resume permits queued work to retry. The pause result
226
+ reports an incomplete flush while any unacknowledged batch remains. No new monitoring
227
+ process is installed. Abrupt host shutdown can leave pending data until the next
228
+ proxy start or supported hook, subject to the existing seven-day queue limit.
229
+ This release does not widen host capabilities or add assistant
230
+ responses to the partial adapters listed above. Hosts without native event ids
231
+ cannot distinguish two host invocations from a duplicated host callback.
232
+
233
+ The npm `0.12.1` tarball was downloaded and matched the deployment workflow's
234
+ SHA-256 pin on 2026-09-17. These `0.13.1` fixes require a new reviewed publication,
235
+ server pin promotion and a recipient-confirmed reinstall. Existing runtimes do
236
+ not auto-upgrade. Public health responses and package integrity do not verify
237
+ authenticated production conversation capture.
238
+
136
239
  Version 0.8.0 additionally refreshes authorized organization and team policy and
137
- knowledge-base references at installation and SessionStart for all seven hosts
138
- above. Each installation gets a private `halofy-context-*` skill folder containing
240
+ knowledge-base references at installation and SessionStart for the seven pre-Hermes hosts
241
+ above. Hermes does not support this managed delivery. Each installation gets a private `halofy-context-*` skill folder containing
139
242
  `SKILL.md` and canonical content references. The content is extracted directives
140
243
  and ingested knowledge, not original uploaded files or live backend rows. Host
141
244
  skill discovery makes the references available; copying files is not evidence
@@ -251,6 +354,91 @@ precedence, context limits, project configuration and exclusion settings still
251
354
  apply. Receipts say `pending_restart`, never loaded or obeyed. Other local OS
252
355
  accounts, containers and remote/cloud profiles require their own installation.
253
356
 
357
+ ### Codex instruction delivery verification
358
+
359
+ On 2026-09-17, source runtime 0.12.2 was tested against Codex CLI 0.154.0 on
360
+ Linux with disposable profiles and a loopback model endpoint. The actual host's
361
+ outgoing request contained the published instruction after signed prelaunch
362
+ sync, then its replacement, then no managed instruction after authorized
363
+ removal. Personal instruction bytes survived. This verifies that tested host's
364
+ loading path, not model obedience or delivery to an existing employee device.
365
+ The protocol server in this test is synthetic; it does not replace the kernel's
366
+ signed HTTP, scope, publication, or receipt tests.
367
+
368
+ The probe also runs the actual installer in a second fresh disposable profile:
369
+ organization disclosure and fixture confirmation, claim exchange, generated
370
+ installation proof, signed heartbeat, profile configuration, instruction write,
371
+ ownership manifest, and receipt. The first real Codex request loads that
372
+ instruction. Executing the returned `syncCommand` from the installed runtime
373
+ then replaces it in the first following fresh session. This uses synthetic
374
+ claim authority and confirmation; it is not production enrollment or employee
375
+ consent evidence.
376
+
377
+ The same probe established two independent startup limits:
378
+
379
+ - With trusted hooks, `SessionStart` refreshed the file and sent a receipt,
380
+ but Codex had already discovered the instructions for that session. The new
381
+ text appeared on the following fresh launch. `pending_restart` is accurate
382
+ even when the startup fetch succeeded.
383
+ - Without trust for the hook definition, Codex skipped the hook and made no
384
+ instruction request. Installing hook configuration does not establish that
385
+ the host executes it. Review and trust the installed hooks through Codex's
386
+ own workflow; do not disable the host's trust checks as a production remedy.
387
+
388
+ For a published instruction with no verified host delivery:
389
+
390
+ 1. Where authorized evidence is available, correlate the device, OS account,
391
+ Codex profile (`CODEX_HOME`), badge namespace, active installation, and
392
+ executable runtime version. A newer staged package or a different signed-in
393
+ console workspace proves none of
394
+ these. Never share private keys, claims, or complete connection files.
395
+ 2. If the installation predates instruction support or lacks the consented
396
+ `instructionProfile`, have its recipient complete the currently verified
397
+ setup/reconnect command for that host and badge. Do not manufacture a
398
+ profile by editing the connection JSON. A release must publish and activate
399
+ a reviewed runtime before using capabilities absent from the current pin.
400
+ 3. For a reviewed installed version that provides `syncCommand` (0.12.2 source
401
+ and later), run its exact executable, arguments, and `HALOFY_AGENT_HOME`
402
+ environment **before** starting Codex. Check successful exit and `ready:true`.
403
+ This performs signed file refresh; it neither starts capture nor upgrades
404
+ an older installed runtime. Source 0.12.2 alone is not publication evidence.
405
+ 4. Start a fresh session in the intended profile and workspace. Correlate the
406
+ effective instruction digest, owned-file manifest, server receipt, and host
407
+ load evidence. A receipt alone does not establish that the model loaded or
408
+ followed the instruction. Keep representative workflow verification separate
409
+ from claims about an affected installation that has not been inspected.
410
+
411
+ Release acceptance requires the coordinator to verify the reviewed package's
412
+ published version and integrity, the deployed installer pin, and the exact
413
+ installed version. In an authorized disposable installation, use normal scoped
414
+ publication and enrollment to repeat the first-fresh-session check, then the
415
+ replacement and removal checks through the installed `syncCommand`. Retain only
416
+ the installation/version/scope identifiers, effective bundle digest, owned-file
417
+ manifest metadata, receipt outcome, and host-load assertion. Personal content
418
+ must survive each change. A content SHA is not the effective bundle digest.
419
+ These checks can establish a supported delivery remedy without access to an
420
+ end user's device; historical incident repair remains unconfirmed until that
421
+ device's delivery is observed.
422
+
423
+ The opt-in smoke test requires a local Codex executable, uses no model API key,
424
+ and leaves user profiles untouched. It exercises the real source hook and
425
+ explicit CLI `sync`, fresh installer, and installed runtime with synthetic signed
426
+ responses. The hook-trust bypass is limited to the disposable fixture; a separate
427
+ run verifies untrusted hooks
428
+ are skipped. No raw model requests or private fixture keys are retained.
429
+
430
+ ```sh
431
+ cd kernel/integrations/agent-runtime
432
+ HALOFY_CODEX_HOST_TEST=1 node --test test/codex-host-instructions.test.mjs
433
+ ```
434
+
435
+ Set `HALOFY_CODEX_BINARY` to select another executable. The test reports its
436
+ version and observed startup timing; it is skipped in the default hermetic
437
+ suite. See the official [Codex instruction discovery](https://learn.chatgpt.com/docs/agent-configuration/agents-md),
438
+ [hook trust](https://learn.chatgpt.com/docs/hooks), and
439
+ [provider configuration](https://learn.chatgpt.com/docs/config-file/config-reference)
440
+ references for the host mechanisms used by the fixture.
441
+
254
442
  Sync validates exact content and bundle digests, scope ancestry/order and size
255
443
  before writing. Personal bytes outside a managed block are preserved exactly.
256
444
  An isolated ownership manifest, exclusive profile lock, no-follow reads,
@@ -271,3 +459,54 @@ selected profile. Local filesystem errors and receipt failures do not interrupt
271
459
  capture or MCP. Neither instruction text, filesystem paths nor backups are sent
272
460
  in status receipts. Existing policy/knowledge/skill operations and runtime queue
273
461
  files are not changed by instruction sync.
462
+
463
+
464
+ ## Hermes pinned adapter (since 0.13.0)
465
+
466
+ This source supports [Hermes Agent v2026.9.14](https://github.com/NousResearch/hermes-agent/releases/tag/v2026.9.14),
467
+ package version `0.21.3`, upstream commit
468
+ `345cd2b057a452236de401d3534b8502a7465e8d`. The installer executes
469
+ `hermes --version` and rejects other versions before consuming a claim. The
470
+ server offers Hermes only with a verified stable installer at least `0.13.0`.
471
+ Publication, server activation and each employee installation require separate
472
+ verification. Existing runtimes do not upgrade automatically.
473
+
474
+ Installation targets the selected `HERMES_HOME`, otherwise `~/.hermes`, after
475
+ explicit CONNECT consent. One owned `plugins/halofy-lifecycle` directory contains
476
+ a native Python observer (`capture`) and a portable MCP plugin (`memory`).
477
+ Both exact discovery keys are enabled. Unrelated YAML/comments/plugins remain;
478
+ ambiguous YAML, symlinks, disabled plugins, namespace collisions and edited owned
479
+ files stop installation. A known conflict is checked before claim consumption.
480
+ The portable plugin uses the native namespaced server key, not a generic
481
+ `mcp_servers.halofy` command. No credentials are stored in either plugin.
482
+
483
+ The capture plugin records submitted user text, final uninterrupted assistant
484
+ text and native tool call/results. Native end-of-turn commits a checkpoint;
485
+ only finalize closes the session. Missing, multimodal, oversized or interrupted
486
+ content produces explicit gaps. No transcript files are read. Recall remains
487
+ agent-invoked through signed MCP tools; no recalled context is injected. Managed
488
+ instructions, skills and knowledge references remain unsupported.
489
+
490
+ Before starting a new MCP proxy, the runtime validates native portable
491
+ `PLUGIN_ROOT`, independently profile-derived `PLUGIN_DATA`, the working
492
+ directory, the exact host version and owned configuration. Config-only copies
493
+ have no executable memory plugin. Profile clones, moves and symlinked plugin
494
+ subtrees must reconnect explicitly. A whole-home alias to the same canonical
495
+ directory is the same profile, not a newly enrolled profile. These checks prevent
496
+ accidental authority inheritance; they are not attestation against a process
497
+ that deliberately forges its environment and command under the same OS account
498
+ that can already read the installation proof.
499
+
500
+ The package bundles `yaml@2.9.1` under its original ISC license. Release CI installs
501
+ locked dependencies with scripts disabled; the durable runtime copy includes the
502
+ bundled dependency and license so it works after the transient package directory
503
+ is removed. `test/hermes-package.test.mjs` packs the real artifact and verifies
504
+ that offline copy. Setting `HALOFY_HERMES_PYTHON` to an isolated pinned Hermes
505
+ interpreter additionally runs native discovery and synthetic local-model turns,
506
+ checks signed lifecycle/MCP requests, and exercises rejected profile copies.
507
+ This is host/protocol verification, not real-provider inference or production
508
+ connection evidence.
509
+
510
+ Manual bearer MCP remains a separate existing memory-tools-only alternative;
511
+ see the [official Hermes MCP configuration reference](https://hermes-agent.nousresearch.com/docs/reference/mcp-config-reference).
512
+ A manual MCP connection is not lifecycle capture evidence.
@@ -1,13 +1,32 @@
1
1
  #!/usr/bin/env node
2
+ import { skillInvocationDenial } from "../src/skill-guard.mjs";
2
3
  import { ConnectionStore, defaultRuntimeDirectory } from "../src/storage.mjs";
3
4
  import { loadActiveConnection } from "../src/active.mjs";
4
5
  import { runStdioMcpProxy } from "../src/mcp-proxy.mjs";
5
6
  import { BoundedEncryptedQueue } from "../src/queue.mjs";
6
7
  import { runClaudeLifecycleHook } from "../src/claude-hook.mjs";
7
8
  import { HOST_HOOK_EVENTS, runHostLifecycleHook } from "../src/host-hook.mjs";
9
+ import { HERMES_HOOK_EVENTS, runHermesLifecycleHook } from "../src/hermes-hook.mjs";
8
10
  import { LifecycleRuntime } from "../src/runtime.mjs";
9
- import { setCapturePaused } from "../src/health.mjs";
10
- import { join } from "node:path";
11
+ import { inspectCaptureHealth, setCapturePaused } from "../src/health.mjs";
12
+ import { refreshManagedConfiguration } from "../src/delivery-sync.mjs";
13
+ import { RUNTIME_VERSION } from "../src/version.mjs";
14
+ import { join, resolve } from "node:path";
15
+ import { realpath } from "node:fs/promises";
16
+ import { readJson, safeDirectory } from "../src/storage.mjs";
17
+ import { createHash } from "node:crypto";
18
+ import { readPrivateJson } from "../src/context-sync.mjs";
19
+
20
+ async function loadGuardConnection(installationId) {
21
+ const root = defaultRuntimeDirectory();
22
+ const id = installationId || process.env.HALOFY_INSTALLATION_ID
23
+ || (await readPrivateJson(join(root, "active-claude-code.json")))?.installationId;
24
+ const connection = await readPrivateJson(new ConnectionStore(root).path(id));
25
+ if (connection?.clientKind !== "claude-code" || connection.installationId !== id) {
26
+ throw new Error("Claude skill guard connection identity is unavailable");
27
+ }
28
+ return connection;
29
+ }
11
30
 
12
31
  function option(name) {
13
32
  const index = process.argv.indexOf(name);
@@ -15,44 +34,110 @@ function option(name) {
15
34
  }
16
35
 
17
36
  const command = process.argv[2];
18
- const hookEvent = command === "hook" ? process.argv[3] : null;
37
+ const hookEvent = command === "hook" || command === "hermes-hook" ? process.argv[3] : null;
38
+ // Bound connection/input loading as well as the guard itself below Claude's
39
+ // eight-second timeout. Fail closed with a flushed native decision.
40
+ const guardDeadline = command === "hook" && hookEvent === "PreToolUse" ? setTimeout(() => {
41
+ process.stdout.write(`${JSON.stringify(skillInvocationDenial())}\n`, () => process.exit(0));
42
+ }, 6000) : null;
19
43
  const claudeHookEvents = new Set([
20
- "SessionStart", "UserPromptSubmit", "Stop", "PreCompact", "SessionEnd",
44
+ "PreToolUse", "SessionStart", "UserPromptSubmit", "Stop", "PreCompact", "SessionEnd",
21
45
  "SubagentStart", "SubagentStop", "PostToolUse", "PostToolUseFailure", "PostToolBatch",
22
46
  ]);
23
- if (!["mcp", "diagnostics", "hook", "pause", "resume"].includes(command) ||
47
+ if (!["mcp", "hermes-mcp", "diagnostics", "hook", "hermes-hook", "pause", "resume", "sync"].includes(command) ||
48
+ (command === "hermes-hook" && !HERMES_HOOK_EVENTS.has(hookEvent)) ||
24
49
  (command === "hook" && !claudeHookEvents.has(hookEvent) && !HOST_HOOK_EVENTS.has(hookEvent))) {
25
- process.stderr.write("Usage: halofy-agent <mcp|diagnostics|hook EVENT|pause|resume> [--connection <installation-id>]\n");
50
+ process.stderr.write("Usage: halofy-agent <mcp|diagnostics|hook EVENT|pause|resume|sync> [--connection <installation-id>]\n");
26
51
  process.exitCode = 2;
27
52
  } else {
28
53
  try {
54
+ if (command === "hermes-mcp") {
55
+ const expected = option("--hermes-home");
56
+ const actual = process.env.PLUGIN_ROOT;
57
+ const enrolledPlugin = expected && join(resolve(expected), "plugins", "halofy-lifecycle", "memory");
58
+ const namespace = `agent-plugin-halofy-lifecycle-memory-${createHash("sha256").update("halofy-lifecycle/memory").digest("hex").slice(0, 8)}`;
59
+ const enrolledData = expected && join(resolve(expected), "plugin-data", namespace);
60
+ const actualData = process.env.PLUGIN_DATA;
61
+ // The pinned native portable loader supplies PLUGIN_ROOT and defaults cwd
62
+ // to the discovered package. HERMES_HOME is intentionally stripped from
63
+ // MCP children; a copied descriptor must not authenticate its old profile.
64
+ if (!expected || !actual || !actualData || !process.env.HALOFY_AGENT_HOME ||
65
+ resolve(actual) !== enrolledPlugin || await realpath(actual) !== enrolledPlugin ||
66
+ resolve(actualData) !== enrolledData || await realpath(actualData) !== enrolledData ||
67
+ process.cwd() !== enrolledPlugin) {
68
+ throw new Error("this Hermes profile is not enrolled; connect it explicitly");
69
+ }
70
+ await safeDirectory(enrolledPlugin);
71
+ await safeDirectory(enrolledData);
72
+ // A host upgrade can make Hermes skip the plugin while retaining its
73
+ // MCP config. Verify the reviewed host before any new proxy heartbeat.
74
+ const { detectHermes } = await import("../src/hermes-config.mjs");
75
+ detectHermes();
76
+ const id = option("--connection");
77
+ if (!id || !/^[A-Za-z0-9_-]{1,160}$/.test(id)) throw new Error("invalid Hermes installation");
78
+ const metadata = await readJson(join(defaultRuntimeDirectory(), id, "health-targets.json"));
79
+ const target = metadata?.targets?.find((entry) => entry.kind === "hermes");
80
+ const { inspectHermesCaptureHealth } = await import("../src/hermes-health.mjs");
81
+ if (!target || target.configPath !== join(resolve(expected), "config.yaml") ||
82
+ target.pluginPath !== join(resolve(expected), "plugins", "halofy-lifecycle") ||
83
+ (await inspectHermesCaptureHealth(target)).captureState !== "active") {
84
+ throw new Error("managed Hermes profile configuration changed; reconnect explicitly");
85
+ }
86
+ }
29
87
  const installationId = option("--connection");
30
- const connection = installationId
88
+ const connection = hookEvent === "PreToolUse" ? await loadGuardConnection(installationId) : installationId
31
89
  ? await new ConnectionStore(defaultRuntimeDirectory()).load(installationId)
32
90
  : await loadActiveConnection("claude-code");
33
91
  if (!connection) throw new Error("no active installation-bound connection");
34
- if (command === "mcp") {
92
+ if (command === "mcp" || command === "hermes-mcp") {
93
+ if (command === "hermes-mcp" && connection.clientKind !== "hermes-agents") {
94
+ throw new Error("Hermes profile requires a Hermes installation");
95
+ }
35
96
  await runStdioMcpProxy(connection);
97
+ } else if (command === "sync") {
98
+ const root = defaultRuntimeDirectory();
99
+ const result = await refreshManagedConfiguration(new LifecycleRuntime(connection, { root }), connection, root);
100
+ process.stdout.write(`${JSON.stringify(result)}\n`);
101
+ if (!result.ready) process.exitCode = 1;
36
102
  } else if (command === "pause" || command === "resume") {
37
103
  const root = defaultRuntimeDirectory();
38
104
  const runtime = new LifecycleRuntime(connection, { root });
39
105
  process.stdout.write(`${JSON.stringify(await setCapturePaused(runtime, root, command === "pause"))}\n`);
106
+ } else if (command === "hermes-hook") {
107
+ const result = await runHermesLifecycleHook(connection, hookEvent);
108
+ if (result.degraded || result.unavailable) process.exitCode = 1;
40
109
  } else if (command === "hook") {
41
110
  if (connection.clientKind === "claude-code") await runClaudeLifecycleHook(connection, hookEvent);
42
111
  else await runHostLifecycleHook(connection, hookEvent);
112
+ if (hookEvent === "PreToolUse") {
113
+ await new Promise(resolve => process.stdout.write("", resolve));
114
+ process.exit(0);
115
+ }
43
116
  } else {
44
- const queue = new BoundedEncryptedQueue(join(defaultRuntimeDirectory(), connection.installationId));
117
+ const root = defaultRuntimeDirectory();
118
+ const queue = new BoundedEncryptedQueue(join(root, connection.installationId));
45
119
  process.stdout.write(`${JSON.stringify({
46
120
  installationId: connection.installationId,
47
121
  clientKind: connection.clientKind,
48
122
  protocolVersion: connection.protocolVersion,
49
123
  pluginVersion: connection.pluginVersion,
124
+ runtimeVersion: RUNTIME_VERSION,
50
125
  proofStorage: connection.proofStorage,
126
+ health: await inspectCaptureHealth(connection, root),
127
+ declaredCapabilities: Object.fromEntries([
128
+ "userMessages", "assistantMessages", "toolInputs", "toolOutputs", "toolFailures",
129
+ "sessionEnd", "tokenUsage", "sessionMetadata", "images", "artifactBodies",
130
+ ].map((name) => [name, connection.capabilities?.[name] === true])),
131
+ serverCheck: "not_performed",
51
132
  queue: await queue.diagnostics(),
52
133
  }, null, 2)}\n`);
53
134
  }
54
135
  } catch (error) {
55
- process.stderr.write(`${error?.message || "Halofy MCP proxy unavailable"}\n`);
56
- process.exitCode = 1;
136
+ if (hookEvent === "PreToolUse") process.stdout.write(`${JSON.stringify(skillInvocationDenial())}\n`);
137
+ process.stderr.write(`${command === "diagnostics" ? "Halofy diagnostics unavailable" :
138
+ error?.message || "Halofy MCP proxy unavailable"}\n`);
139
+ process.exitCode = hookEvent === "PreToolUse" ? 0 : 1;
57
140
  }
58
141
  }
142
+
143
+ if (guardDeadline) clearTimeout(guardDeadline);
@@ -0,0 +1,13 @@
1
+ Copyright Eemeli Aro <eemeli@gmail.com>
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose
4
+ with or without fee is hereby granted, provided that the above copyright notice
5
+ and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
9
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
11
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
12
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
13
+ THIS SOFTWARE.
@@ -0,0 +1,172 @@
1
+ # YAML <a href="https://www.npmjs.com/package/yaml"><img align="right" src="https://badge.fury.io/js/yaml.svg" title="npm package" /></a>
2
+
3
+ `yaml` is a definitive library for [YAML](https://yaml.org/), the human friendly data serialization standard.
4
+ This library:
5
+
6
+ - Supports both YAML 1.1 and YAML 1.2 and all common data schemas,
7
+ - Passes all of the [yaml-test-suite](https://github.com/yaml/yaml-test-suite) tests,
8
+ - Can accept any string as input without throwing, parsing as much YAML out of it as it can, and
9
+ - Supports parsing, modifying, and writing YAML comments and blank lines.
10
+
11
+ The library is released under the ISC open source license, and the code is [available on GitHub](https://github.com/eemeli/yaml/).
12
+ It has no external dependencies and runs on Node.js as well as modern browsers.
13
+
14
+ For the purposes of versioning, any changes that break any of the documented endpoints or APIs will be considered semver-major breaking changes.
15
+ Undocumented library internals may change between minor versions, and previous APIs may be deprecated (but not removed).
16
+
17
+ The minimum supported TypeScript version of the included typings is 3.9;
18
+ for use in earlier versions you may need to set `skipLibCheck: true` in your config.
19
+ This requirement may be updated between minor versions of the library.
20
+
21
+ For more information, see the project's documentation site: [**eemeli.org/yaml**](https://eemeli.org/yaml/)
22
+
23
+ For build instructions and contribution guidelines, see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
24
+
25
+ To install:
26
+
27
+ ```sh
28
+ npm install yaml
29
+ # or
30
+ deno add jsr:@eemeli/yaml
31
+ ```
32
+
33
+ **Note:** These docs are for `yaml@2`. For v1, see the [v1.10.0 tag](https://github.com/eemeli/yaml/tree/v1.10.0) for the source and [eemeli.org/yaml/v1](https://eemeli.org/yaml/v1/) for the documentation.
34
+
35
+ ## API Overview
36
+
37
+ The API provided by `yaml` has three layers, depending on how deep you need to go: [Parse & Stringify](https://eemeli.org/yaml/#parse-amp-stringify), [Documents](https://eemeli.org/yaml/#documents), and the underlying [Lexer/Parser/Composer](https://eemeli.org/yaml/#parsing-yaml).
38
+ The first has the simplest API and "just works", the second gets you all the bells and whistles supported by the library along with a decent [AST](https://eemeli.org/yaml/#content-nodes), and the third lets you get progressively closer to YAML source, if that's your thing.
39
+
40
+ A [command-line tool](https://eemeli.org/yaml/#command-line-tool) is also included.
41
+
42
+ ### Parse & Stringify
43
+
44
+ ```js
45
+ import { parse, stringify } from 'yaml'
46
+ ```
47
+
48
+ - [`parse(str, reviver?, options?): value`](https://eemeli.org/yaml/#yaml-parse)
49
+ - [`stringify(value, replacer?, options?): string`](https://eemeli.org/yaml/#yaml-stringify)
50
+
51
+ ### Documents
52
+
53
+ <!-- prettier-ignore -->
54
+ ```js
55
+ import {
56
+ Document,
57
+ isDocument,
58
+ parseAllDocuments,
59
+ parseDocument
60
+ } from 'yaml'
61
+ ```
62
+
63
+ - [`Document`](https://eemeli.org/yaml/#documents)
64
+ - [`constructor(value, replacer?, options?)`](https://eemeli.org/yaml/#creating-documents)
65
+ - [`#contents`](https://eemeli.org/yaml/#content-nodes)
66
+ - [`#directives`](https://eemeli.org/yaml/#stream-directives)
67
+ - [`#errors`](https://eemeli.org/yaml/#errors)
68
+ - [`#warnings`](https://eemeli.org/yaml/#errors)
69
+ - [`isDocument(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
70
+ - [`parseAllDocuments(str, options?): Document[]`](https://eemeli.org/yaml/#parsing-documents)
71
+ - [`parseDocument(str, options?): Document`](https://eemeli.org/yaml/#parsing-documents)
72
+
73
+ ### Content Nodes
74
+
75
+ <!-- prettier-ignore -->
76
+ ```js
77
+ import {
78
+ isAlias, isCollection, isMap, isNode,
79
+ isPair, isScalar, isSeq, Scalar,
80
+ visit, visitAsync, YAMLMap, YAMLSeq
81
+ } from 'yaml'
82
+ ```
83
+
84
+ - [`isAlias(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
85
+ - [`isCollection(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
86
+ - [`isMap(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
87
+ - [`isNode(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
88
+ - [`isPair(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
89
+ - [`isScalar(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
90
+ - [`isSeq(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
91
+ - [`new Scalar(value)`](https://eemeli.org/yaml/#scalar-values)
92
+ - [`new YAMLMap()`](https://eemeli.org/yaml/#collections)
93
+ - [`new YAMLSeq()`](https://eemeli.org/yaml/#collections)
94
+ - [`doc.createAlias(node, name?): Alias`](https://eemeli.org/yaml/#creating-nodes)
95
+ - [`doc.createNode(value, options?): Node`](https://eemeli.org/yaml/#creating-nodes)
96
+ - [`doc.createPair(key, value): Pair`](https://eemeli.org/yaml/#creating-nodes)
97
+ - [`visit(node, visitor)`](https://eemeli.org/yaml/#finding-and-modifying-nodes)
98
+ - [`visitAsync(node, visitor)`](https://eemeli.org/yaml/#finding-and-modifying-nodes)
99
+
100
+ ### Parsing YAML
101
+
102
+ ```js
103
+ import { Composer, Lexer, Parser } from 'yaml'
104
+ ```
105
+
106
+ - [`new Lexer().lex(src)`](https://eemeli.org/yaml/#lexer)
107
+ - [`new Parser(onNewLine?).parse(src)`](https://eemeli.org/yaml/#parser)
108
+ - [`new Composer(options?).compose(tokens)`](https://eemeli.org/yaml/#composer)
109
+
110
+ ## YAML.parse
111
+
112
+ ```yaml
113
+ # file.yml
114
+ YAML:
115
+ - A human-readable data serialization language
116
+ - https://en.wikipedia.org/wiki/YAML
117
+ yaml:
118
+ - A complete JavaScript implementation
119
+ - https://www.npmjs.com/package/yaml
120
+ ```
121
+
122
+ ```js
123
+ import fs from 'fs'
124
+ import YAML from 'yaml'
125
+
126
+ YAML.parse('3.14159')
127
+ // 3.14159
128
+
129
+ YAML.parse('[ true, false, maybe, null ]\n')
130
+ // [ true, false, 'maybe', null ]
131
+
132
+ const file = fs.readFileSync('./file.yml', 'utf8')
133
+ YAML.parse(file)
134
+ // { YAML:
135
+ // [ 'A human-readable data serialization language',
136
+ // 'https://en.wikipedia.org/wiki/YAML' ],
137
+ // yaml:
138
+ // [ 'A complete JavaScript implementation',
139
+ // 'https://www.npmjs.com/package/yaml' ] }
140
+ ```
141
+
142
+ ## YAML.stringify
143
+
144
+ ```js
145
+ import YAML from 'yaml'
146
+
147
+ YAML.stringify(3.14159)
148
+ // '3.14159\n'
149
+
150
+ YAML.stringify([true, false, 'maybe', null])
151
+ // `- true
152
+ // - false
153
+ // - maybe
154
+ // - null
155
+ // `
156
+
157
+ YAML.stringify({ number: 3, plain: 'string', block: 'two\nlines\n' })
158
+ // `number: 3
159
+ // plain: string
160
+ // block: |
161
+ // two
162
+ // lines
163
+ // `
164
+ ```
165
+
166
+ ---
167
+
168
+ Browser testing provided by:
169
+
170
+ <a href="https://www.browserstack.com/open-source">
171
+ <img width=200 src="https://eemeli.org/yaml/images/browserstack.svg" alt="BrowserStack" />
172
+ </a>