@sentropic/h2a 0.98.5 → 0.98.7-rc.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 (225) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/dist/cli-command-map.d.ts.map +1 -1
  4. package/dist/cli-command-map.js +1 -0
  5. package/dist/cli-command-map.js.map +1 -1
  6. package/dist/cli-contract.js +2 -2
  7. package/dist/cli-contract.js.map +1 -1
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +224 -16
  10. package/dist/cli.js.map +1 -1
  11. package/dist/hosts/agy.js +1 -1
  12. package/dist/hosts/agy.js.map +1 -1
  13. package/dist/hosts/installation-doctor.d.ts +1 -0
  14. package/dist/hosts/installation-doctor.d.ts.map +1 -1
  15. package/dist/hosts/installation-doctor.js +1 -1
  16. package/dist/hosts/installation-doctor.js.map +1 -1
  17. package/dist/hosts/muse.d.ts.map +1 -1
  18. package/dist/hosts/muse.js +2 -4
  19. package/dist/hosts/muse.js.map +1 -1
  20. package/dist/hosts/native-artifacts.d.ts +33 -0
  21. package/dist/hosts/native-artifacts.d.ts.map +1 -0
  22. package/dist/hosts/native-artifacts.js +104 -0
  23. package/dist/hosts/native-artifacts.js.map +1 -0
  24. package/dist/hosts/native-catalog.d.ts +19 -0
  25. package/dist/hosts/native-catalog.d.ts.map +1 -0
  26. package/dist/hosts/native-catalog.js +14 -0
  27. package/dist/hosts/native-catalog.js.map +1 -0
  28. package/dist/hosts/native-convergence.d.ts +132 -0
  29. package/dist/hosts/native-convergence.d.ts.map +1 -0
  30. package/dist/hosts/native-convergence.js +86 -0
  31. package/dist/hosts/native-convergence.js.map +1 -0
  32. package/dist/hosts/native-files.d.ts +40 -0
  33. package/dist/hosts/native-files.d.ts.map +1 -0
  34. package/dist/hosts/native-files.js +131 -0
  35. package/dist/hosts/native-files.js.map +1 -0
  36. package/dist/hosts/native-inspection.d.ts +31 -0
  37. package/dist/hosts/native-inspection.d.ts.map +1 -0
  38. package/dist/hosts/native-inspection.js +79 -0
  39. package/dist/hosts/native-inspection.js.map +1 -0
  40. package/dist/hosts/native-paths.d.ts +11 -0
  41. package/dist/hosts/native-paths.d.ts.map +1 -0
  42. package/dist/hosts/native-paths.js +21 -0
  43. package/dist/hosts/native-paths.js.map +1 -0
  44. package/dist/hosts/native-proof.d.ts +32 -0
  45. package/dist/hosts/native-proof.d.ts.map +1 -0
  46. package/dist/hosts/native-proof.js +31 -0
  47. package/dist/hosts/native-proof.js.map +1 -0
  48. package/dist/hosts/native-runtime-record.d.ts +3 -0
  49. package/dist/hosts/native-runtime-record.d.ts.map +1 -0
  50. package/dist/hosts/native-runtime-record.js +60 -0
  51. package/dist/hosts/native-runtime-record.js.map +1 -0
  52. package/dist/hosts/native-skills.d.ts +24 -0
  53. package/dist/hosts/native-skills.d.ts.map +1 -0
  54. package/dist/hosts/native-skills.js +56 -0
  55. package/dist/hosts/native-skills.js.map +1 -0
  56. package/dist/hosts/native-toml.d.ts +18 -0
  57. package/dist/hosts/native-toml.d.ts.map +1 -0
  58. package/dist/hosts/native-toml.js +91 -0
  59. package/dist/hosts/native-toml.js.map +1 -0
  60. package/dist/hosts/operator-notices.d.ts +3 -0
  61. package/dist/hosts/operator-notices.d.ts.map +1 -0
  62. package/dist/hosts/operator-notices.js +31 -0
  63. package/dist/hosts/operator-notices.js.map +1 -0
  64. package/dist/hosts/plugin.d.ts.map +1 -1
  65. package/dist/hosts/plugin.js +3 -2
  66. package/dist/hosts/plugin.js.map +1 -1
  67. package/dist/hosts/upgrade-equipment.d.ts +42 -0
  68. package/dist/hosts/upgrade-equipment.d.ts.map +1 -0
  69. package/dist/hosts/upgrade-equipment.js +26 -0
  70. package/dist/hosts/upgrade-equipment.js.map +1 -0
  71. package/dist/hosts/vibe-discovery.d.ts +12 -0
  72. package/dist/hosts/vibe-discovery.d.ts.map +1 -0
  73. package/dist/hosts/vibe-discovery.js +33 -0
  74. package/dist/hosts/vibe-discovery.js.map +1 -0
  75. package/dist/hosts/vibe-equipment.d.ts +71 -0
  76. package/dist/hosts/vibe-equipment.d.ts.map +1 -0
  77. package/dist/hosts/vibe-equipment.js +162 -0
  78. package/dist/hosts/vibe-equipment.js.map +1 -0
  79. package/dist/hosts/vibe-mcp.d.ts +32 -0
  80. package/dist/hosts/vibe-mcp.d.ts.map +1 -0
  81. package/dist/hosts/vibe-mcp.js +210 -0
  82. package/dist/hosts/vibe-mcp.js.map +1 -0
  83. package/dist/hosts/vibe.d.ts +12 -3
  84. package/dist/hosts/vibe.d.ts.map +1 -1
  85. package/dist/hosts/vibe.js +15 -7
  86. package/dist/hosts/vibe.js.map +1 -1
  87. package/dist/index.d.ts +2 -1
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +2 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/runtime/drive/consent.d.ts +1 -1
  92. package/dist/runtime/drive/consent.d.ts.map +1 -1
  93. package/dist/runtime/drive/consent.js +2 -2
  94. package/dist/runtime/drive/consent.js.map +1 -1
  95. package/dist/runtime/drive/index.d.ts +1 -1
  96. package/dist/runtime/drive/index.d.ts.map +1 -1
  97. package/dist/runtime/drive/index.js +3 -1
  98. package/dist/runtime/drive/index.js.map +1 -1
  99. package/dist/runtime/drumbeat/relaunchers.d.ts +1 -1
  100. package/dist/runtime/drumbeat/relaunchers.d.ts.map +1 -1
  101. package/dist/runtime/drumbeat/relaunchers.js +2 -1
  102. package/dist/runtime/drumbeat/relaunchers.js.map +1 -1
  103. package/dist/runtime/identity/binding-commit.d.ts +31 -0
  104. package/dist/runtime/identity/binding-commit.d.ts.map +1 -0
  105. package/dist/runtime/identity/binding-commit.js +211 -0
  106. package/dist/runtime/identity/binding-commit.js.map +1 -0
  107. package/dist/runtime/identity/bindings.d.ts +6 -30
  108. package/dist/runtime/identity/bindings.d.ts.map +1 -1
  109. package/dist/runtime/identity/bindings.js +85 -96
  110. package/dist/runtime/identity/bindings.js.map +1 -1
  111. package/dist/runtime/identity/durable.d.ts +7 -0
  112. package/dist/runtime/identity/durable.d.ts.map +1 -0
  113. package/dist/runtime/identity/durable.js +68 -0
  114. package/dist/runtime/identity/durable.js.map +1 -0
  115. package/dist/runtime/identity/live.d.ts +4 -1
  116. package/dist/runtime/identity/live.d.ts.map +1 -1
  117. package/dist/runtime/identity/live.js +59 -6
  118. package/dist/runtime/identity/live.js.map +1 -1
  119. package/dist/runtime/identity/possession.d.ts +34 -0
  120. package/dist/runtime/identity/possession.d.ts.map +1 -0
  121. package/dist/runtime/identity/possession.js +162 -0
  122. package/dist/runtime/identity/possession.js.map +1 -0
  123. package/dist/runtime/identity/worker.js +16 -5
  124. package/dist/runtime/identity/worker.js.map +1 -1
  125. package/dist/runtime/live/contracts.d.ts +55 -0
  126. package/dist/runtime/live/contracts.d.ts.map +1 -0
  127. package/dist/runtime/live/contracts.js +59 -0
  128. package/dist/runtime/live/contracts.js.map +1 -0
  129. package/dist/runtime/local-files/identity-fence.d.ts +164 -0
  130. package/dist/runtime/local-files/identity-fence.d.ts.map +1 -0
  131. package/dist/runtime/local-files/identity-fence.js +1338 -0
  132. package/dist/runtime/local-files/identity-fence.js.map +1 -0
  133. package/dist/runtime/local-files/index.d.ts +1 -0
  134. package/dist/runtime/local-files/index.d.ts.map +1 -1
  135. package/dist/runtime/local-files/index.js +1 -0
  136. package/dist/runtime/local-files/index.js.map +1 -1
  137. package/dist/runtime/local-files/legacy-identity-evidence.d.ts +26 -0
  138. package/dist/runtime/local-files/legacy-identity-evidence.d.ts.map +1 -0
  139. package/dist/runtime/local-files/legacy-identity-evidence.js +234 -0
  140. package/dist/runtime/local-files/legacy-identity-evidence.js.map +1 -0
  141. package/dist/runtime/local-files/locks.d.ts +3 -0
  142. package/dist/runtime/local-files/locks.d.ts.map +1 -1
  143. package/dist/runtime/local-files/locks.js +6 -5
  144. package/dist/runtime/local-files/locks.js.map +1 -1
  145. package/dist/runtime/local-files/orphan-gc.d.ts +3 -0
  146. package/dist/runtime/local-files/orphan-gc.d.ts.map +1 -0
  147. package/dist/runtime/local-files/orphan-gc.js +69 -0
  148. package/dist/runtime/local-files/orphan-gc.js.map +1 -0
  149. package/dist/runtime/local-files/presence.d.ts +5 -2
  150. package/dist/runtime/local-files/presence.d.ts.map +1 -1
  151. package/dist/runtime/local-files/presence.js +32 -29
  152. package/dist/runtime/local-files/presence.js.map +1 -1
  153. package/dist/runtime/local-files/recipient-hints.d.ts +10 -0
  154. package/dist/runtime/local-files/recipient-hints.d.ts.map +1 -0
  155. package/dist/runtime/local-files/recipient-hints.js +156 -0
  156. package/dist/runtime/local-files/recipient-hints.js.map +1 -0
  157. package/dist/runtime/local-files/store.d.ts +1 -1
  158. package/dist/runtime/local-files/store.d.ts.map +1 -1
  159. package/dist/runtime/local-files/store.js +12 -1
  160. package/dist/runtime/local-files/store.js.map +1 -1
  161. package/dist/runtime/local-files/succession-lock.d.ts +71 -6
  162. package/dist/runtime/local-files/succession-lock.d.ts.map +1 -1
  163. package/dist/runtime/local-files/succession-lock.js +226 -31
  164. package/dist/runtime/local-files/succession-lock.js.map +1 -1
  165. package/dist/runtime/mcp/handlers.d.ts +1 -0
  166. package/dist/runtime/mcp/handlers.d.ts.map +1 -1
  167. package/dist/runtime/mcp/handlers.js +7 -4
  168. package/dist/runtime/mcp/handlers.js.map +1 -1
  169. package/dist/runtime/mcp/identity-blocker-snapshot.d.ts +2 -0
  170. package/dist/runtime/mcp/identity-blocker-snapshot.d.ts.map +1 -0
  171. package/dist/runtime/mcp/identity-blocker-snapshot.js +98 -0
  172. package/dist/runtime/mcp/identity-blocker-snapshot.js.map +1 -0
  173. package/dist/runtime/mcp/identity-state.d.ts +20 -3
  174. package/dist/runtime/mcp/identity-state.d.ts.map +1 -1
  175. package/dist/runtime/mcp/identity-state.js +98 -13
  176. package/dist/runtime/mcp/identity-state.js.map +1 -1
  177. package/dist/runtime/mcp/notifications.d.ts +2 -1
  178. package/dist/runtime/mcp/notifications.d.ts.map +1 -1
  179. package/dist/runtime/mcp/notifications.js +16 -2
  180. package/dist/runtime/mcp/notifications.js.map +1 -1
  181. package/dist/runtime/mcp/server.d.ts +3 -0
  182. package/dist/runtime/mcp/server.d.ts.map +1 -1
  183. package/dist/runtime/mcp/server.js +31 -15
  184. package/dist/runtime/mcp/server.js.map +1 -1
  185. package/dist/runtime/mcp/sessions.d.ts +6 -6
  186. package/dist/runtime/mcp/sessions.d.ts.map +1 -1
  187. package/dist/runtime/mcp/sessions.js +18 -6
  188. package/dist/runtime/mcp/sessions.js.map +1 -1
  189. package/dist/runtime/mcp/stdio.d.ts.map +1 -1
  190. package/dist/runtime/mcp/stdio.js +11 -0
  191. package/dist/runtime/mcp/stdio.js.map +1 -1
  192. package/dist/runtime/mcp/tools.js +1 -1
  193. package/dist/runtime/mcp/tools.js.map +1 -1
  194. package/dist/runtime/remote/client.d.ts +1 -1
  195. package/dist/runtime/remote/client.d.ts.map +1 -1
  196. package/dist/runtime/remote/client.js +1 -1
  197. package/dist/runtime/remote/client.js.map +1 -1
  198. package/dist/runtime/send.d.ts +10 -0
  199. package/dist/runtime/send.d.ts.map +1 -1
  200. package/dist/runtime/send.js +80 -5
  201. package/dist/runtime/send.js.map +1 -1
  202. package/dist/runtime/upgrade/index.d.ts +1 -0
  203. package/dist/runtime/upgrade/index.d.ts.map +1 -1
  204. package/dist/runtime/upgrade/index.js +1 -0
  205. package/dist/runtime/upgrade/index.js.map +1 -1
  206. package/dist/vendor/engram-live/contracts.d.ts +208 -0
  207. package/dist/vendor/engram-live/contracts.js +558 -0
  208. package/fixtures/native-host-catalog.json +1 -0
  209. package/fixtures/native-host-history.json +1261 -0
  210. package/fixtures/native-host-renderers.json +1 -0
  211. package/hooks/deny-manual-h2a-cli.mjs +38 -0
  212. package/hooks/hooks.json +17 -0
  213. package/hooks/vibe-post-agent.mjs +29 -0
  214. package/hooks/vibe-pre-tool.mjs +40 -0
  215. package/package.json +9 -6
  216. package/scripts/qualification-budget.mjs +56 -0
  217. package/scripts/qualification-cleanup.mjs +15 -0
  218. package/scripts/qualification-oracles.mjs +44 -0
  219. package/scripts/qualification-patch.mjs +21 -0
  220. package/scripts/qualification-poll-hosts.mjs +19 -0
  221. package/scripts/qualification-probe.mjs +63 -0
  222. package/scripts/qualification-rpc.mjs +59 -0
  223. package/scripts/qualification-vibe.mjs +159 -0
  224. package/scripts/qualify-host.mjs +143 -0
  225. package/skills/h2a/SKILL.md +6 -2
package/dist/cli.js CHANGED
@@ -62,6 +62,13 @@ import { runHarnessCli, HARNESS_SKILLS } from "./vendor/harness/index.js";
62
62
  import { buildLaunchIndex } from "./runtime/local-files/launch-index.js";
63
63
  import { renderCommandMap } from "./cli-command-map.js";
64
64
  import { resolveHostConfigRoot } from "./runtime/host-config-root.js";
65
+ import { isNativeHost, NATIVE_HOSTS, REGISTRY_WAITING, stateRoot, vibeHome } from "./hosts/native-paths.js";
66
+ import { convergeNativeHost } from "./hosts/native-convergence.js";
67
+ import { nativeSkillArtifacts } from "./hosts/native-skills.js";
68
+ import { assertNativePath, atomicNativeWrite, snapshot as snapshotNativeFile } from "./hosts/native-files.js";
69
+ import { clearVibeDirectRemoved, editVibeMcpServers, setVibeDirectRemoved, VIBE_MCP_NAME } from "./hosts/vibe-mcp.js";
70
+ import { convergeAfterExplicitUpgrade } from "./hosts/upgrade-equipment.js";
71
+ import { captureHostOperatorNotices } from "./hosts/operator-notices.js";
65
72
  import { H2A_ATTESTER_COMPREHENSION_RIGHT, H2A_COMPREHENSION_ATTESTATION_BODY_KIND, H2A_DECLARATION_INTERET_BODY_KIND, H2A_ORG_MANIFEST_FILENAME, H2A_ORG_PROPOSAL_BODY_KIND, H2A_ORG_RATIFIED_BODY_KIND, H2A_ROLES, H2A_WORK_STATUSES, auditNhiPosture, buildComprehensionAttestation, canAttestComprehension, checkEnvelopeFreshness, computeHash, createEnvelope, deriveWorkspaceId, diffOrgManifest, effectiveOrgInstances, isComprehensionAttestation, nhiAttestationEnvelope, nhiInventory, deriveConnectionConfidence, nhiTrustBundle, orgAssignmentEnvelope, parseOrgManifest, signCanonical, signEnvelope, subagentAddress, validateOrgManifest, verifyComprehensionAttestation } from "@sentropic/h2a";
66
73
  import { H2A_CLAUDE_HOST } from "./hosts/claude.js";
67
74
  import { H2A_CODEX_HOST } from "./hosts/codex.js";
@@ -263,9 +270,9 @@ export function renderCliHelp() {
263
270
  " h2a drumbeat escalations [--root <path>]",
264
271
  " h2a drumbeat relance-inbox [--instance <id>] [--relauncher logging|local-tmux|headless|auto] [--root <path>]",
265
272
  " h2a drumbeat watch [--interval-ms <n>] [--max-relances <n>] [--relauncher logging|local-tmux|remote|headless|auto] [--instance <signer> --private-key <pem>] [--decider logging|<command>] [--decider-after <k>] [--decider-enforce] [--root <path>]",
266
- " h2a host setup --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe> [--endpoint local|remote] [--url <https://…/mcp>] [--root <path>] [--print | --write <file>] [--force] [--no-wake] (selects exactly one h2a endpoint; local renders mcp-serve --auto-open --auto-upgrade --wake auto by default)",
273
+ " h2a host setup --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe> [--endpoint local|remote] [--url <https://…/mcp>] [--root <path>] [--print | --write <file>] [--force] [--no-wake] (selects one endpoint; Muse/agy render nonrecommended historical direct paths pending registry bootstrap; Vibe --write installs the interim direct entry pending registry bootstrap (--remove clears it for migration))",
267
274
  " h2a host status [--host <name>]",
268
- " h2a host plugin --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe> --instance <id> [--status <work-status>] [--root <path>] [--write <settings.json> [--force]] [--scaffold <dir>] (--write installs the Stop hook for claude|gemini|codex|hermes|opencode; --scaffold writes codex's full local marketplace + trust step; vibe records via a post_agent hook in ~/.vibe/hooks.toml; agy and muse are poll-only)",
275
+ " h2a host plugin --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe> --instance <id> [--status <work-status>] [--root <path>] [--write <settings.json|hooks.toml> [--force]] [--scaffold <dir>] (--write installs the Stop hook for claude|gemini|codex|hermes|opencode; --scaffold writes codex's full local marketplace + trust step; vibe writes its explicit parent-only wrapper to VIBE_HOME/hooks.toml; agy and muse have no qualified native hooks)",
269
276
  " h2a store migrate [--from <v>] [--to <v>] [--sanitize-paths] [--dry-run] [--root <path>]",
270
277
  " h2a store index-launch --root <absolute-path> (derived indexes; original logs retained)",
271
278
  "",
@@ -274,7 +281,7 @@ export function renderCliHelp() {
274
281
  " h2a conductor [--workspace <id|path>] [--root <path>] (who is the live conductor/owner of a workspace — derived from presence; conductor=role CONDUCTOR if set, else null; candidates=in-workspace live agents)",
275
282
  " h2a conductor-launch-check [--workspace <id|path>] [--root <path>] [--idle-ms <ms>] (DRY-RUN: polls track workspace-activity; recommends launching a conductor if work is stalled and none is live — h2a does NOT spawn; launch parked pending spawn policy + remote)",
276
283
  " h2a conductor-launch --workspace <id|path> [--root <path>] [--idle-ms <ms>] [--confirm] [--remote <instance>] [--instance <self>] (D3 EMIT: if stalled+no conductor, emits a launch-REQUEST envelope to a live remote agent — gated by --confirm + 1/30min/workspace cap; h2a NEVER spawns; remote does the actual spawn)",
277
- " h2a doctor [--root <path>] [--scan <dir>] [--prune] [--repair] [--dry-run] (--repair converges Claude/Codex plugin installs; --repair --dry-run reports host findings/actions without changing them; --prune deletes host-less/phantom/orphan inbox dirs + stray buses; dry-run by default)",
284
+ " h2a doctor [--root <path>] [--scan <dir>] [--prune] [--repair] [--dry-run] [--host <name>] [--skip-hosts] [--guard on|off] [--lifecycle on|off] (--repair converges detected host components; --repair --dry-run reports host findings/actions without changing them; --prune deletes host-less/phantom/orphan inbox dirs + stray buses; dry-run by default)",
278
285
  " h2a keepalive [--root <path>] [--interval <ms>] [--once] (external keepalive prober — refreshes presence for agents whose tmux pane is still alive)",
279
286
  " h2a rename --instance <id> --name <name> [--root <path>] (set a live session's display name so peers can find it via discover --name)",
280
287
  " h2a status [--root <path>] [--scope <s>] [--instance <i>]",
@@ -1486,19 +1493,20 @@ export function cmdUpgrade(flags, streams, runtime) {
1486
1493
  // the boot auto-upgrade (bounded — no infinite terminal wait). No cachePath is
1487
1494
  // passed, so it always checks fresh and is never throttled for an explicit run.
1488
1495
  const result = performAutoUpgrade(current, { ...(runtime ? { runtime } : {}) });
1496
+ const hosts = convergeAfterExplicitUpgrade(result, flags);
1489
1497
  if (result.outcome === "upgraded") {
1490
- streams.stdout.write(`${JSON.stringify({ ok: true, current, latest: result.target, upgraded: true, verified: result.verifiedVersion, package: H2A_CLI_PACKAGE, ...(result.logPath ? { log: result.logPath } : {}) }, null, 2)}\n`);
1498
+ streams.stdout.write(`${JSON.stringify({ ok: true, current, latest: result.target, upgraded: true, verified: result.verifiedVersion, package: H2A_CLI_PACKAGE, hosts, ...(result.logPath ? { log: result.logPath } : {}) }, null, 2)}\n`);
1491
1499
  return 0;
1492
1500
  }
1493
1501
  if (result.outcome === "already-current") {
1494
- streams.stdout.write(`${JSON.stringify({ ok: true, current, latest: result.target ?? current, upgraded: false, reason: "already current or registry unreachable" }, null, 2)}\n`);
1502
+ streams.stdout.write(`${JSON.stringify({ ok: true, current, latest: result.target ?? current, upgraded: false, hosts, reason: "already current or registry unreachable" }, null, 2)}\n`);
1495
1503
  return 0;
1496
1504
  }
1497
1505
  // The target is published but not yet installable (propagation delay). A full
1498
1506
  // `npm i -g` would hit the same registry and fail too, so we do not force it;
1499
1507
  // the staged path retries on a later run. Nothing was mutated.
1500
1508
  if (result.outcome === "deferred-propagation") {
1501
- streams.stdout.write(`${JSON.stringify({ ok: true, current, latest: result.target, upgraded: false, reason: "update published but not yet installable; retry later", ...(result.logPath ? { log: result.logPath } : {}) }, null, 2)}\n`);
1509
+ streams.stdout.write(`${JSON.stringify({ ok: true, current, latest: result.target, upgraded: false, hosts, reason: "update published but not yet installable; retry later", ...(result.logPath ? { log: result.logPath } : {}) }, null, 2)}\n`);
1502
1510
  return 0;
1503
1511
  }
1504
1512
  // skipped-locked / failed.
@@ -3625,6 +3633,105 @@ function driveLineFromHookInput(raw) {
3625
3633
  }
3626
3634
  return driveLineFromText(raw);
3627
3635
  }
3636
+ function resolveVibeSetupTarget(flags) {
3637
+ if (flags.write && flags.write !== "true")
3638
+ return flags.write;
3639
+ return join(vibeHome(), "config.toml");
3640
+ }
3641
+ function vibeWantedEntry(snippet) {
3642
+ const incoming = snippet.config.mcpServers.h2a;
3643
+ if (typeof incoming.url === "string")
3644
+ return { name: VIBE_MCP_NAME, transport: "streamable-http", url: incoming.url };
3645
+ return { name: VIBE_MCP_NAME, transport: "stdio", command: incoming.command ?? "h2a", args: [...(incoming.args ?? ["mcp-serve"])] };
3646
+ }
3647
+ function vibeStateForTarget(targetPath) {
3648
+ return stateRoot("vibe", dirname(resolvePath(targetPath)));
3649
+ }
3650
+ function cmdVibeSetupWrite(flags, streams, snippet, endpoint) {
3651
+ const targetPath = resolveVibeSetupTarget(flags);
3652
+ if (!targetPath.toLowerCase().endsWith(".toml")) {
3653
+ streams.stderr.write(`h2a host setup: --write for Vibe MCP supports TOML only and will not rewrite ${targetPath}. Use the default <VIBE_HOME>/config.toml.\n`);
3654
+ return 1;
3655
+ }
3656
+ const wanted = vibeWantedEntry(snippet);
3657
+ let original;
3658
+ try {
3659
+ if (!existsSync(targetPath))
3660
+ original = "";
3661
+ else
3662
+ original = readFileSync(targetPath, "utf8");
3663
+ }
3664
+ catch (error) {
3665
+ streams.stderr.write(`h2a host setup: cannot read ${targetPath} (${error.message})\n`);
3666
+ return 3;
3667
+ }
3668
+ let edited;
3669
+ try {
3670
+ edited = editVibeMcpServers(original, wanted);
3671
+ }
3672
+ catch (error) {
3673
+ streams.stderr.write(`h2a host setup: ${targetPath} refused (${error.message}); invalid or incompatible TOML is never overwritten, even with --force.\n`);
3674
+ return 2;
3675
+ }
3676
+ if (!edited.changed) {
3677
+ clearVibeDirectRemoved(vibeStateForTarget(targetPath));
3678
+ streams.stdout.write(`${JSON.stringify({ ok: true, host: "vibe", endpoint, path: targetPath, merged: false, replacedH2a: false, removedH2aMcpServers: [], migration: "voie directe — non migrée" }, null, 2)}\n`);
3679
+ return 0;
3680
+ }
3681
+ try {
3682
+ atomicNativeWrite(targetPath, edited.text, { state: vibeStateForTarget(targetPath), expected: snapshotNativeFile(targetPath) });
3683
+ }
3684
+ catch (error) {
3685
+ streams.stderr.write(`h2a host setup: cannot write ${targetPath} (${error.message})\n`);
3686
+ return 3;
3687
+ }
3688
+ clearVibeDirectRemoved(vibeStateForTarget(targetPath));
3689
+ streams.stdout.write(`${JSON.stringify({ ok: true, host: "vibe", endpoint, path: targetPath, merged: true, replacedH2a: edited.replacedH2a, removedH2aMcpServers: edited.removed, migration: "voie directe — non migrée" }, null, 2)}\n`);
3690
+ streams.stderr.write(`# wrote the interim direct mcp_servers.h2a endpoint for host=vibe to ${targetPath} (owner 16/10, derogation O7.2; migration R5/R7: h2a host setup --host vibe --remove)\n# disabled duplicate h2a MCP entries: ${edited.removed.join(", ") || "none"}\n# ${snippet.path.hint}\n`);
3691
+ return 0;
3692
+ }
3693
+ function cmdVibeSetupRemove(flags, streams) {
3694
+ const targetPath = resolveVibeSetupTarget(flags);
3695
+ if (!targetPath.toLowerCase().endsWith(".toml")) {
3696
+ streams.stderr.write(`h2a host setup: --remove for Vibe MCP supports TOML only and will not rewrite ${targetPath}. Use the default <VIBE_HOME>/config.toml.\n`);
3697
+ return 1;
3698
+ }
3699
+ let original;
3700
+ try {
3701
+ if (!existsSync(targetPath))
3702
+ original = "";
3703
+ else
3704
+ original = readFileSync(targetPath, "utf8");
3705
+ }
3706
+ catch (error) {
3707
+ streams.stderr.write(`h2a host setup: cannot read ${targetPath} (${error.message})\n`);
3708
+ return 3;
3709
+ }
3710
+ let edited;
3711
+ try {
3712
+ edited = editVibeMcpServers(original, null);
3713
+ }
3714
+ catch (error) {
3715
+ streams.stderr.write(`h2a host setup: ${targetPath} refused (${error.message}); invalid or incompatible TOML is never overwritten, even with --force.\n`);
3716
+ return 2;
3717
+ }
3718
+ if (!edited.changed) {
3719
+ setVibeDirectRemoved(vibeStateForTarget(targetPath));
3720
+ streams.stdout.write(`${JSON.stringify({ ok: true, host: "vibe", path: targetPath, removed: false, migration: REGISTRY_WAITING }, null, 2)}\n`);
3721
+ return 0;
3722
+ }
3723
+ try {
3724
+ atomicNativeWrite(targetPath, edited.text, { state: vibeStateForTarget(targetPath), expected: snapshotNativeFile(targetPath) });
3725
+ }
3726
+ catch (error) {
3727
+ streams.stderr.write(`h2a host setup: cannot write ${targetPath} (${error.message})\n`);
3728
+ return 3;
3729
+ }
3730
+ setVibeDirectRemoved(vibeStateForTarget(targetPath));
3731
+ streams.stdout.write(`${JSON.stringify({ ok: true, host: "vibe", path: targetPath, removed: true, removedH2aMcpServers: edited.removed, migration: REGISTRY_WAITING }, null, 2)}\n`);
3732
+ streams.stderr.write(`# removed the interim direct mcp_servers.h2a endpoint for host=vibe from ${targetPath}; registry bootstrap expected.\n`);
3733
+ return 0;
3734
+ }
3628
3735
  function cmdHostSetup(flags, streams, options) {
3629
3736
  const host = flags.host;
3630
3737
  if (!host) {
@@ -3714,9 +3821,16 @@ function cmdHostSetup(flags, streams, options) {
3714
3821
  }
3715
3822
  const targetPath = flags.write;
3716
3823
  const printMode = flags.print === "true" || !targetPath;
3824
+ if (host === "vibe" && flags.remove === "true") {
3825
+ return cmdVibeSetupRemove(flags, streams);
3826
+ }
3827
+ if (host === "vibe" && targetPath) {
3828
+ return cmdVibeSetupWrite(flags, streams, snippet, endpoint);
3829
+ }
3717
3830
  if (printMode && !targetPath) {
3718
- streams.stdout.write(`${JSON.stringify(snippet.config, null, 2)}\n`);
3719
- streams.stderr.write(`# ${host} — selected ${endpoint} h2a endpoint; paste this snippet under \`mcpServers\` in:\n# ${snippet.path.hint}\n# example path: ${snippet.path.example}\n`);
3831
+ streams.stdout.write(`${JSON.stringify(isNativeHost(host) ? { ...snippet.config, migration: REGISTRY_WAITING, hint: snippet.path.hint } : snippet.config, null, 2)}\n`);
3832
+ streams.stderr.write(isNativeHost(host) ? `# ${host}: rendu historique non recommandé; ${REGISTRY_WAITING}.\n# ${snippet.path.hint}\n` :
3833
+ `# ${host} — selected ${endpoint} h2a endpoint; paste this snippet under \`mcpServers\` in:\n# ${snippet.path.hint}\n# example path: ${snippet.path.example}\n`);
3720
3834
  return reportHostSetupCoherence(host, streams, options) ? 0 : 2;
3721
3835
  }
3722
3836
  if (isUnsupportedHostWritePath(host, targetPath)) {
@@ -3803,6 +3917,7 @@ function cmdHostSetup(flags, streams, options) {
3803
3917
  replacedH2a,
3804
3918
  removedH2aMcpServers,
3805
3919
  removedTrackMcpServers,
3920
+ ...(isNativeHost(host) ? { migration: "voie directe — non migrée" } : {}),
3806
3921
  ...(coherent ? {} : { next: "h2a doctor --repair" })
3807
3922
  }, null, 2)}\n`);
3808
3923
  streams.stderr.write(`# wrote the selected ${endpoint} mcpServers.h2a endpoint for host=${host} to ${targetPath}\n# disabled duplicate h2a MCP entries: ${removedH2aMcpServers.join(", ") || "none"}\n# disabled standalone Track MCP entries: ${removedTrackMcpServers.join(", ") || "none"}\n# ${snippet.path.hint}\n`);
@@ -3865,7 +3980,17 @@ function cmdHostStatus(flags, streams) {
3865
3980
  mcpAdapterShipped,
3866
3981
  hostSetupShipped,
3867
3982
  hostScenarioShipped,
3868
- summary
3983
+ summary: hostScenarioShipped ? summary.replace('scenario shipped', 'rendu testé') : summary,
3984
+ ...(isNativeHost(descriptor.host) ? { native: (() => {
3985
+ try {
3986
+ return nativeHostReport(descriptor.host, flags, false, false, undefined, streams.cwd?.());
3987
+ }
3988
+ catch (error) {
3989
+ return { ok: false, installation: 'inspection impossible', error: error.message };
3990
+ }
3991
+ })() } : {
3992
+ convergence: ['claude', 'codex'].includes(descriptor.host) ? 'historical doctor convergence; native parity unverified; registry non migré' : 'non couvert'
3993
+ })
3869
3994
  };
3870
3995
  });
3871
3996
  streams.stdout.write(`${JSON.stringify({ ok: true, hosts }, null, 2)}\n`);
@@ -3885,6 +4010,24 @@ function cmdHostPlugin(flags, streams) {
3885
4010
  streams.stderr.write("h2a host plugin: --instance <id> is required\n");
3886
4011
  return 1;
3887
4012
  }
4013
+ if (flags.host === 'vibe') {
4014
+ try {
4015
+ if (flags.instance === 'auto')
4016
+ throw new Error('non disponible — interface B non livrée');
4017
+ if (flags.write && resolvePath(flags.write) !== join(vibeHome(), 'hooks.toml')) {
4018
+ streams.stderr.write('h2a host plugin: this target is not available for vibe; post_agent requires the effective <VIBE_HOME>/hooks.toml TOML file.\n');
4019
+ return 1;
4020
+ }
4021
+ const result = nativeHostReport('vibe', flags, !!flags.write, false, undefined, streams.cwd?.());
4022
+ streams.stdout.write(`${JSON.stringify({ ...result, push: true, mechanism: 'vibe-hooks', record: 'rendered' in result ? result.rendered : '',
4023
+ receive: 'N-A', hint: 'post_agent in <VIBE_HOME>/hooks.toml; ' + ('lifecycleScope' in result ? result.lifecycleScope : 'hôte absent') }, null, 2)}\n`);
4024
+ return result.ok ? 0 : 2;
4025
+ }
4026
+ catch (error) {
4027
+ streams.stderr.write(`h2a host plugin: ${error.message}\n`);
4028
+ return 2;
4029
+ }
4030
+ }
3888
4031
  const render = renderStopHook(flags.host, {
3889
4032
  instance: flags.instance,
3890
4033
  ...(flags.root ? { root: flags.root } : {}),
@@ -4715,6 +4858,14 @@ export function cmdConductorLaunch(argv, streams, opts) {
4715
4858
  return 0;
4716
4859
  }
4717
4860
  function cmdDoctor(flags, streams, options = {}) {
4861
+ if (flags.host && !isNativeHost(flags.host) && !['claude', 'codex'].includes(flags.host)) {
4862
+ streams.stderr.write('h2a doctor: --host must be claude|codex|vibe|muse|agy\n');
4863
+ return 1;
4864
+ }
4865
+ if ((flags.guard || flags.lifecycle) && flags.host !== 'vibe') {
4866
+ streams.stderr.write('h2a doctor: --guard/--lifecycle require --host vibe\n');
4867
+ return 1;
4868
+ }
4718
4869
  const cwd = streams.cwd ?? (() => process.cwd());
4719
4870
  const root = resolveRoot(flags, cwd);
4720
4871
  const report = {
@@ -4793,9 +4944,10 @@ function cmdDoctor(flags, streams, options = {}) {
4793
4944
  // is allowed to touch host configuration/caches and invoke native host CLIs.
4794
4945
  // That keeps an ordinary isolated-bus probe independent of the operator's
4795
4946
  // personal Claude/Codex setup while retaining a fail-closed repair surface.
4796
- if (flags.repair === "true") {
4947
+ if (flags.repair === "true" && (!flags.host || ['claude', 'codex'].includes(flags.host))) {
4797
4948
  const dryRun = flags["dry-run"] === "true";
4798
- const hostInstallations = (options.doctorHostInstallations ?? doctorHostInstallations)({ repair: true, dryRun });
4949
+ const hostInstallations = (options.doctorHostInstallations ?? doctorHostInstallations)({ repair: true, dryRun,
4950
+ ...(flags.host ? { hosts: [flags.host] } : {}) });
4799
4951
  checks.hostInstallations = hostInstallations;
4800
4952
  if (!hostInstallations.ok) {
4801
4953
  report.ok = false;
@@ -4844,6 +4996,21 @@ function cmdDoctor(flags, streams, options = {}) {
4844
4996
  message: "pass --repair to detect and converge Claude/Codex host installation drift"
4845
4997
  };
4846
4998
  }
4999
+ if (flags['skip-hosts'] !== 'true') {
5000
+ const selection = flags.host ? isNativeHost(flags.host) ? [flags.host] : [] : NATIVE_HOSTS;
5001
+ const hosts = selection.map(host => {
5002
+ try {
5003
+ const { instance, ...nativeFlags } = flags;
5004
+ return nativeHostReport(host, nativeFlags, flags.repair === 'true', false, undefined, cwd());
5005
+ }
5006
+ catch (error) {
5007
+ return { host, ok: false, installation: 'inspection impossible', error: error.message };
5008
+ }
5009
+ });
5010
+ checks.nativeHostInstallations = { ok: hosts.every(host => host.ok), hosts };
5011
+ if (!hosts.every(host => host.ok))
5012
+ report.ok = false;
5013
+ }
4847
5014
  // ── Warning checks (do NOT flip report.ok) ──────────────────────────────
4848
5015
  // (a) rootSource: record where the root came from
4849
5016
  const rootInfo = resolveRootInfo(flags, cwd);
@@ -5453,7 +5620,9 @@ function cmdConnect(flags, streams) {
5453
5620
  const followUp = [
5454
5621
  flags.host === "remote"
5455
5622
  ? "Use the bridge-provided environment in the remote session Pod"
5456
- : `Merge the snippet above under \`mcpServers\` in ${steps[1].pathExample}`,
5623
+ : flags.host === "vibe" ? `Entrée directe intérimaire (décision owner 16/10, dérogation O7.2) : h2a host setup --host vibe --write ; migration registre R5/R7 : h2a host setup --host vibe --remove puis bootstrap.`
5624
+ : isNativeHost(flags.host) ? `Rendu historique non recommandé — ${REGISTRY_WAITING}; installation et activation par l’intégrateur registre.`
5625
+ : `Merge the snippet above under \`mcpServers\` in ${steps[1].pathExample}`,
5457
5626
  identity.privateKeyPath
5458
5627
  ? `keypair ready: ${identity.privateKeyPath}`
5459
5628
  : `legacy override: run h2a keys generate --instance ${instance} --root ${root} if needed`,
@@ -5565,7 +5734,7 @@ function targetSpecFor(host, cwd) {
5565
5734
  // installed skills are listed at session open.
5566
5735
  return {
5567
5736
  host: "vibe",
5568
- userBase: join(homedir(), ".vibe", "skills"),
5737
+ userBase: join(vibeHome(), "skills"),
5569
5738
  projectBase: join(cwd, ".vibe", "skills"),
5570
5739
  extension: "SKILL.md",
5571
5740
  write: (base, skillName, _parsed, raw) => {
@@ -5704,7 +5873,7 @@ function readSkillFrom(srcDir, dirName, source, renameTo) {
5704
5873
  raw = raw.replace(/^(name:[ \t]*).*$/m, `$1${installName}`);
5705
5874
  parsed = { ...parsed, name: installName };
5706
5875
  }
5707
- return { kind: "skill", skill: { installName, parsed, raw, source } };
5876
+ return { kind: "skill", skill: { installName, parsed, raw, source, resourceDir: join(srcDir, dirName) } };
5708
5877
  }
5709
5878
  /**
5710
5879
  * Resolve the on-disk `skills/` directory of an installed dependency package
@@ -5812,6 +5981,15 @@ function collectInstallableSkills() {
5812
5981
  return { skills, sources, error: harnessRes.error };
5813
5982
  return { skills, sources };
5814
5983
  }
5984
+ function nativeHostReport(host, flags, repair, explicitInstall = false, root, cwd) {
5985
+ const collection = collectInstallableSkills();
5986
+ if (collection.error)
5987
+ throw new Error(collection.error.message);
5988
+ return convergeNativeHost({ host, root, cwd, version: currentCliVersion(), skills: collection.skills, renderGemini: renderSkillAsGeminiToml,
5989
+ sourcesComplete: collection.sources.every(s => s.dir !== null && s.count > 0), repair, explicitInstall,
5990
+ dryRun: flags['dry-run'] === 'true', force: flags.force === 'true', guard: flags.guard, lifecycle: flags.lifecycle,
5991
+ instance: flags.instance, busRoot: flags.root, status: flags.status });
5992
+ }
5815
5993
  function cmdInstallSkills(flags, streams) {
5816
5994
  const host = flags.host;
5817
5995
  if (!host) {
@@ -5841,8 +6019,23 @@ function cmdInstallSkills(flags, streams) {
5841
6019
  return collection.error.exit;
5842
6020
  }
5843
6021
  const targetBase = scope === "user" ? spec.userBase : spec.projectBase;
6022
+ if (scope === 'user' && (isNativeHost(host) || host === 'gemini')) {
6023
+ try {
6024
+ const result = nativeHostReport(host, flags, true, true, dirname(targetBase), cwd());
6025
+ streams.stdout.write(`${JSON.stringify({ ...result, scope, targetBase, installed: 'changed' in result ? result.changed : [], sources: collection.sources,
6026
+ prunedLegacy: [], skipped: 'conflicts' in result ? result.conflicts.map(path => ({ path, reason: 'customized or unknown provenance; preserved' })) : [],
6027
+ ...(host === 'muse' ? { verifyHint: 'muse skills list # project scope requires workspace trust' } : {}),
6028
+ ...(host === 'vibe' ? { verifyHint: 'vibe # skills load at session open; nouvelle session ou reprise propre' } : {}),
6029
+ ...(host === 'agy' ? { importHint: 'agy plugin import gemini # then: agy plugin enable h2a' } : {}) }, null, 2)}\n`);
6030
+ return result.ok ? 0 : 2;
6031
+ }
6032
+ catch (error) {
6033
+ streams.stderr.write(`h2a install-skills: ${error.message}\n`);
6034
+ return 3;
6035
+ }
6036
+ }
5844
6037
  // DEC-057: prune the pre-consolidation skill names if they linger on disk.
5845
- const prunedLegacy = pruneLegacy(spec, targetBase);
6038
+ const prunedLegacy = isNativeHost(host) || host === 'gemini' ? [] : pruneLegacy(spec, targetBase);
5846
6039
  const installed = [];
5847
6040
  const skipped = [];
5848
6041
  for (const skill of collection.skills) {
@@ -5860,7 +6053,18 @@ function cmdInstallSkills(flags, streams) {
5860
6053
  continue;
5861
6054
  }
5862
6055
  try {
5863
- const targetPath = spec.write(targetBase, skillName, skill.parsed, skill.raw);
6056
+ let targetPath;
6057
+ if (scope === 'project' && (isNativeHost(host) || host === 'gemini')) {
6058
+ const artifacts = nativeSkillArtifacts({ host, root: dirname(targetBase), project: true, version: currentCliVersion(), skills: [skill], renderGemini: renderSkillAsGeminiToml, historicalHashes: () => [] });
6059
+ for (const artifact of artifacts) {
6060
+ assertNativePath(artifact.path);
6061
+ mkdirSync(dirname(artifact.path), { recursive: true });
6062
+ writeFileSync(artifact.path, artifact.bytes);
6063
+ }
6064
+ targetPath = probeTarget;
6065
+ }
6066
+ else
6067
+ targetPath = spec.write(targetBase, skillName, skill.parsed, skill.raw);
5864
6068
  installed.push(targetPath);
5865
6069
  }
5866
6070
  catch (error) {
@@ -6268,6 +6472,10 @@ export function runCli(argv = process.argv.slice(2), streams = {
6268
6472
  stderr: process.stderr
6269
6473
  }, options = {}) {
6270
6474
  const { command, flags } = parseFlags(argv);
6475
+ if (streams.stderr === process.stderr && process.stderr.isTTY) {
6476
+ for (const notice of captureHostOperatorNotices())
6477
+ streams.stderr.write(`${notice}\n`);
6478
+ }
6271
6479
  if (command && TRACK_FACADE_VERBS.has(command)) {
6272
6480
  // ④: read-only + sync-write verbs run in-process; `focus` (async) keeps
6273
6481
  // shelling out. Same `.track`, same lock. A native WRITE never falls back to