@sentropic/h2a 0.85.16 → 0.85.17
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.
- package/.claude-plugin/plugin.json +29 -0
- package/.codex-plugin/plugin.json +35 -0
- package/.mcp.json +19 -0
- package/README.md +3 -0
- package/dist/bin-routing.d.ts +14 -3
- package/dist/bin-routing.d.ts.map +1 -1
- package/dist/bin-routing.js +31 -6
- package/dist/bin-routing.js.map +1 -1
- package/dist/bin.js +45 -14
- package/dist/bin.js.map +1 -1
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli-contract.js +41 -1
- package/dist/cli-contract.js.map +1 -1
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +146 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +1 -0
- package/dist/mcp.js.map +1 -1
- package/dist/runtime/focus/serve.d.ts +42 -0
- package/dist/runtime/focus/serve.d.ts.map +1 -0
- package/dist/runtime/focus/serve.js +366 -0
- package/dist/runtime/focus/serve.js.map +1 -0
- package/dist/runtime/loop/engine/adapters.d.ts +62 -6
- package/dist/runtime/loop/engine/adapters.d.ts.map +1 -1
- package/dist/runtime/loop/engine/adapters.js +272 -36
- package/dist/runtime/loop/engine/adapters.js.map +1 -1
- package/dist/runtime/loop/engine/decision.d.ts.map +1 -1
- package/dist/runtime/loop/engine/decision.js +20 -2
- package/dist/runtime/loop/engine/decision.js.map +1 -1
- package/dist/runtime/loop/engine/execute.d.ts +13 -4
- package/dist/runtime/loop/engine/execute.d.ts.map +1 -1
- package/dist/runtime/loop/engine/execute.js +17 -7
- package/dist/runtime/loop/engine/execute.js.map +1 -1
- package/dist/runtime/loop/index.d.ts +16 -0
- package/dist/runtime/loop/index.d.ts.map +1 -1
- package/dist/runtime/loop/index.js +146 -13
- package/dist/runtime/loop/index.js.map +1 -1
- package/dist/runtime/mcp/agent-launch.d.ts +33 -0
- package/dist/runtime/mcp/agent-launch.d.ts.map +1 -0
- package/dist/runtime/mcp/agent-launch.js +250 -0
- package/dist/runtime/mcp/agent-launch.js.map +1 -0
- package/dist/runtime/mcp/handlers.d.ts +8 -0
- package/dist/runtime/mcp/handlers.d.ts.map +1 -1
- package/dist/runtime/mcp/handlers.js +34 -4
- package/dist/runtime/mcp/handlers.js.map +1 -1
- package/dist/runtime/mcp/index.d.ts +2 -1
- package/dist/runtime/mcp/index.d.ts.map +1 -1
- package/dist/runtime/mcp/index.js +2 -1
- package/dist/runtime/mcp/index.js.map +1 -1
- package/dist/runtime/mcp/server.d.ts +5 -0
- package/dist/runtime/mcp/server.d.ts.map +1 -1
- package/dist/runtime/mcp/server.js +3 -0
- package/dist/runtime/mcp/server.js.map +1 -1
- package/dist/runtime/mcp/stdio.d.ts +17 -0
- package/dist/runtime/mcp/stdio.d.ts.map +1 -1
- package/dist/runtime/mcp/stdio.js +65 -13
- package/dist/runtime/mcp/stdio.js.map +1 -1
- package/dist/runtime/mcp/tools.d.ts.map +1 -1
- package/dist/runtime/mcp/tools.js +96 -5
- package/dist/runtime/mcp/tools.js.map +1 -1
- package/dist/runtime/path-safety.d.ts +3 -0
- package/dist/runtime/path-safety.d.ts.map +1 -0
- package/dist/runtime/path-safety.js +12 -0
- package/dist/runtime/path-safety.js.map +1 -0
- package/dist/runtime/reporting/config.d.ts +21 -0
- package/dist/runtime/reporting/config.d.ts.map +1 -0
- package/dist/runtime/reporting/config.js +76 -0
- package/dist/runtime/reporting/config.js.map +1 -0
- package/dist/runtime/reporting/context.d.ts +27 -0
- package/dist/runtime/reporting/context.d.ts.map +1 -0
- package/dist/runtime/reporting/context.js +265 -0
- package/dist/runtime/reporting/context.js.map +1 -0
- package/dist/runtime/reporting/index.d.ts +4 -0
- package/dist/runtime/reporting/index.d.ts.map +1 -0
- package/dist/runtime/reporting/index.js +4 -0
- package/dist/runtime/reporting/index.js.map +1 -0
- package/dist/runtime/reporting/report-ai.d.ts +49 -0
- package/dist/runtime/reporting/report-ai.d.ts.map +1 -0
- package/dist/runtime/reporting/report-ai.js +325 -0
- package/dist/runtime/reporting/report-ai.js.map +1 -0
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css +1 -0
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.br +2 -0
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css +1 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js +2 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js +1 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js +2 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js +1 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js +1 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js +2 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js +1 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js +1 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/wbPk3Yxo.js +81 -0
- package/focus-app/client/_app/immutable/chunks/wbPk3Yxo.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/wbPk3Yxo.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js +2 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js +1 -0
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.br +2 -0
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js +5 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js +1 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js +1 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.gz +0 -0
- package/focus-app/client/_app/version.json +1 -0
- package/focus-app/client/_app/version.json.br +0 -0
- package/focus-app/client/_app/version.json.gz +0 -0
- package/focus-app/env.js +70 -0
- package/focus-app/env.js.map +1 -0
- package/focus-app/h2a-focus.json +114 -0
- package/focus-app/handler.js +24 -0
- package/focus-app/handler.js.map +1 -0
- package/focus-app/index.js +147 -0
- package/focus-app/index.js.map +1 -0
- package/focus-app/server/chunks/chunks/exports.js-DUTkELZq.js +217 -0
- package/focus-app/server/chunks/chunks/exports.js-DUTkELZq.js.map +1 -0
- package/focus-app/server/chunks/chunks/false.js-B2gHlHjM.js +4 -0
- package/focus-app/server/chunks/chunks/false.js-B2gHlHjM.js.map +1 -0
- package/focus-app/server/chunks/chunks/friendly.js-D4fjovnZ.js +246 -0
- package/focus-app/server/chunks/chunks/friendly.js-D4fjovnZ.js.map +1 -0
- package/focus-app/server/chunks/chunks/index.js-Di21TltP.js +1315 -0
- package/focus-app/server/chunks/chunks/index.js-Di21TltP.js.map +1 -0
- package/focus-app/server/chunks/chunks/internal.js-33vbd70h.js +126 -0
- package/focus-app/server/chunks/chunks/internal.js-33vbd70h.js.map +1 -0
- package/focus-app/server/chunks/chunks/root.js-DO1m-gJA.js +2967 -0
- package/focus-app/server/chunks/chunks/root.js-DO1m-gJA.js.map +1 -0
- package/focus-app/server/chunks/chunks/server.js-Bf8x1V_n.js +16 -0
- package/focus-app/server/chunks/chunks/server.js-Bf8x1V_n.js.map +1 -0
- package/focus-app/server/chunks/chunks/utils.js-C_3_iViC.js +2545 -0
- package/focus-app/server/chunks/chunks/utils.js-C_3_iViC.js.map +1 -0
- package/focus-app/server/chunks/chunks/utils2.js-BQzn9ikS.js +38 -0
- package/focus-app/server/chunks/chunks/utils2.js-BQzn9ikS.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/actions/launch/_server.ts.js-DUQcf9xd.js +63 -0
- package/focus-app/server/chunks/entries/endpoints/api/actions/launch/_server.ts.js-DUQcf9xd.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-j0NNcOSZ.js +100 -0
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-j0NNcOSZ.js.map +1 -0
- package/focus-app/server/chunks/entries/fallbacks/error.svelte.js-Dj3sETSX.js +50 -0
- package/focus-app/server/chunks/entries/fallbacks/error.svelte.js-Dj3sETSX.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/_layout.svelte.js-BoLsbuC2.js +1420 -0
- package/focus-app/server/chunks/entries/pages/_layout.svelte.js-BoLsbuC2.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/_page.server.ts.js-ChRBj_xK.js +246 -0
- package/focus-app/server/chunks/entries/pages/_page.server.ts.js-ChRBj_xK.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/_page.svelte.js-QDldMYhk.js +2725 -0
- package/focus-app/server/chunks/entries/pages/_page.svelte.js-QDldMYhk.js.map +1 -0
- package/focus-app/server/chunks/handler-Cp_5hLyY.js +1474 -0
- package/focus-app/server/chunks/handler-Cp_5hLyY.js.map +1 -0
- package/focus-app/server/chunks/index.js-CBh7Wjqp.js +4242 -0
- package/focus-app/server/chunks/index.js-CBh7Wjqp.js.map +1 -0
- package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js +56 -0
- package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js.map +1 -0
- package/focus-app/server/chunks/nodes/0.js-4wlmdsk8.js +9 -0
- package/focus-app/server/chunks/nodes/0.js-4wlmdsk8.js.map +1 -0
- package/focus-app/server/chunks/nodes/1.js-B-LpY-lC.js +9 -0
- package/focus-app/server/chunks/nodes/1.js-B-LpY-lC.js.map +1 -0
- package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js +19 -0
- package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js.map +1 -0
- package/focus-app/shims.js +33 -0
- package/focus-app/shims.js.map +1 -0
- package/package.json +8 -4
- package/skills/h2a/SKILL.md +7 -5
- package/skills/harness/SKILL.md +17 -0
- package/skills/harness/using-harness/SKILL.md +26 -0
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,7 @@ import { execFileSync, spawnSync } from "node:child_process";
|
|
|
40
40
|
import { generateKeyPairSync } from "node:crypto";
|
|
41
41
|
import { copyFileSync, existsSync, mkdirSync, readdirSync, realpathSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
42
42
|
import { homedir, hostname } from "node:os";
|
|
43
|
-
import { dirname, join, resolve as resolvePath } from "node:path";
|
|
43
|
+
import { dirname, isAbsolute, join, resolve as resolvePath } from "node:path";
|
|
44
44
|
import { createRequire } from "node:module";
|
|
45
45
|
import { fileURLToPath } from "node:url";
|
|
46
46
|
// Static import — `@sentropic/track` is a LIGHT library (pure reader/model, no
|
|
@@ -68,7 +68,7 @@ import { H2A_OPENCODE_HOST } from "./hosts/opencode.js";
|
|
|
68
68
|
import { H2A_CLI_MCP_TOOL_NAMES } from "./mcp.js";
|
|
69
69
|
import { renderStopHook, claudeStopHookEntry, claudeDriveReceiveHookEntry, isH2ADriveReceiveHook, isH2ARecordHook, codexPluginManifest, codexMarketplaceManifest, codexPluginTrustCommands, H2A_CODEX_PLUGIN_NAME, H2A_HOST_PLUGIN_HOSTS } from "./hosts/plugin.js";
|
|
70
70
|
import { H2A_STORE_SCHEMA_VERSION, assertHostQualifiedAddress, canonicalAddress, createLocalStore, listPresence, reapAllDeadPresence, reapDeadInstancePresence, readPresence, resolveRecipient, safePathSegment, sanitizeStorePaths, writePresence } from "./runtime/local-files/index.js";
|
|
71
|
-
import { runMcpStdio } from "./runtime/mcp/index.js";
|
|
71
|
+
import { H2A_MCP_READY_FILE_ENV, H2A_MCP_READY_NONCE_ENV, runMcpStdio } from "./runtime/mcp/index.js";
|
|
72
72
|
import { renderK8sSidecar } from "./runtime/deploy/k8s-sidecar.js";
|
|
73
73
|
import { renderK8sTenant } from "./runtime/deploy/k8s-tenant.js";
|
|
74
74
|
import { remoteServerForStore, sendRemoteEnvelope } from "./runtime/remote/index.js";
|
|
@@ -85,10 +85,11 @@ import { conductorFor } from "./runtime/governance/conductor.js";
|
|
|
85
85
|
import { appendConductorClaim } from "./runtime/governance/claims.js";
|
|
86
86
|
import { conductorLaunchCheck } from "./runtime/governance/launch-check.js";
|
|
87
87
|
import { lastSpawnRequestAt, recordSpawnRequest, spawnAllowed } from "./runtime/governance/spawns.js";
|
|
88
|
-
import { createObjectiveLoop, declareObjectiveLoopDone, joinObjectiveLoop, listLoopEvents, listObjectiveLoops, readObjectiveLoop, reportObjectiveLoop, stopObjectiveLoop } from "./runtime/loop/index.js";
|
|
88
|
+
import { createObjectiveLoop, declareObjectiveLoopDone, joinObjectiveLoop, listLoopEvents, listObjectiveLoops, readObjectiveLoop, reportObjectiveLoop, stopObjectiveLoop, validateLoopLaunchSpec } from "./runtime/loop/index.js";
|
|
89
89
|
import { runLoopWatch, runTick } from "./runtime/loop/engine/tick.js";
|
|
90
90
|
import { gatherPendingDecisions } from "./runtime/canevas/gather.js";
|
|
91
91
|
import { runCanevasServe } from "./runtime/canevas/serve.js";
|
|
92
|
+
import { installTrackReportAiConfig, readH2AReportContext, TrackReportAiConfigConflictError } from "./runtime/reporting/index.js";
|
|
92
93
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
93
94
|
// `dist/cli.js` lives in `packages/h2a-cli/dist/`; skills are at
|
|
94
95
|
// `packages/h2a-cli/skills/`. Two levels up from the dist file.
|
|
@@ -225,9 +226,9 @@ export function renderCliHelp() {
|
|
|
225
226
|
" h2a install-skills --host <claude|codex|gemini|agy> [--scope user|project] [--force]",
|
|
226
227
|
" h2a deploy k8s-sidecar [--instance <id>] [--host <h>] [--root <path>] [--image <ref>] [--cli-version <ver>] [--write <file>]",
|
|
227
228
|
" h2a deploy k8s-tenant [--namespace <ns>] [--root <path>] [--replicas <n>] [--storage <size>] [--storage-class <sc>] [--lease-ms <ms>] [--image <ref>] [--cli-version <ver>] [--write <file>]",
|
|
228
|
-
" h2a loop create --name <n> --goal <text> [--repo <path[:role]>] [--track <json>] [--agent <host:role:placement>] [--root <path>]",
|
|
229
|
-
" h2a loop join <loopId> --instance <id> [--agent-id <id>] [--role <role>] [--root <path>]",
|
|
230
|
-
" h2a loop report <loopId> --note <text> [--instance <id>] [--agent-id <id>] [--root <path>]",
|
|
229
|
+
" h2a loop create --name <n> --goal <text> [--repo <path[:role]>] [--track <json>] [--agent <host:role:placement> [--launch-stdin]] [--root <path>]",
|
|
230
|
+
" h2a loop join <loopId> --instance <id> [--agent-id <id>] [--role <role>] [--launch-stdin] [--root <path>]",
|
|
231
|
+
" h2a loop report <loopId> --note <text> [--instance <id>] [--agent-id <id>] [--auto-join] [--root <path>]",
|
|
231
232
|
" h2a loop done <loopId> [--note <text>] [--instance <id>] [--agent-id <id>] [--root <path>]",
|
|
232
233
|
" h2a loop stop <loopId> [--reason <text>] [--root <path>]",
|
|
233
234
|
" h2a loop list [--root <path>]",
|
|
@@ -236,9 +237,19 @@ export function renderCliHelp() {
|
|
|
236
237
|
" h2a loop attach <loopId> --agent <selector> [--root <path>]",
|
|
237
238
|
" h2a loop logs <loopId> [--agent <selector>] [--root <path>]",
|
|
238
239
|
"",
|
|
240
|
+
"Track AI adapters (leaf commands; never call Track report/snapshot):",
|
|
241
|
+
" h2a report-context --workspace-root <absolute-path> [--root <h2a-store>]",
|
|
242
|
+
" h2a report-ai --model <model> --effort <low|medium|high|xhigh> --gateway required (Track context envelope on stdin; one no-tools local-gateway request)",
|
|
243
|
+
" h2a report-ai install-track-config [--force] (atomic user XDG config, mode 0600; preserves overrides by default)",
|
|
244
|
+
"",
|
|
245
|
+
"Focus Web (packaged production app):",
|
|
246
|
+
" h2a focus serve [--repo <path>] [--track-events <path>] [--host <host>] [--port <0-65535>]",
|
|
247
|
+
" h2a focus web [--repo <path>] [--track-events <path>] [--host <host>] [--port <0-65535>] (exact alias)",
|
|
248
|
+
" (defaults to the nearest tracked repo and 127.0.0.1:5178; bare `h2a focus …` remains the Track facade)",
|
|
249
|
+
"",
|
|
239
250
|
"Track (délégué à @sentropic/track — le suivi/record du travail):",
|
|
240
251
|
` h2a ${[...TRACK_FACADE_VERBS].join(" · h2a ")}`,
|
|
241
|
-
" (ex: h2a decision new …, h2a report, h2a item ls — voir `track <verbe> --help`)",
|
|
252
|
+
" (ex: h2a decision new …, h2a report, h2a snapshot, h2a item ls — voir `track <verbe> --help`)",
|
|
242
253
|
"",
|
|
243
254
|
"Harness (délégué à h2a vendored harness — la méthode code-work / PR-workflow):",
|
|
244
255
|
" h2a harness <check|verify|init|audit|brainstorm|test|debug|review|plan|branch|skills> …",
|
|
@@ -1254,6 +1265,21 @@ export async function runMcpServe(flags, io = {
|
|
|
1254
1265
|
warnIfCwdRootFallback(flags, cwd, { stderr: io.stderr, stdout: io.stdout, cwd });
|
|
1255
1266
|
const root = resolveRoot(flags, cwd);
|
|
1256
1267
|
const autoOpen = resolveAutoOpen(flags, cwd);
|
|
1268
|
+
const readinessEnv = io.env ?? process.env;
|
|
1269
|
+
const readyFile = readinessEnv[H2A_MCP_READY_FILE_ENV];
|
|
1270
|
+
const readyNonce = readinessEnv[H2A_MCP_READY_NONCE_ENV];
|
|
1271
|
+
let readiness;
|
|
1272
|
+
if (readyFile !== undefined || readyNonce !== undefined) {
|
|
1273
|
+
if (!readyFile ||
|
|
1274
|
+
!isAbsolute(readyFile) ||
|
|
1275
|
+
readyFile.includes("\0") ||
|
|
1276
|
+
!readyNonce ||
|
|
1277
|
+
!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(readyNonce)) {
|
|
1278
|
+
io.stderr.write("h2a mcp-serve: invalid internal readiness challenge\n");
|
|
1279
|
+
return 1;
|
|
1280
|
+
}
|
|
1281
|
+
readiness = { file: readyFile, nonce: readyNonce };
|
|
1282
|
+
}
|
|
1257
1283
|
// DEC-107/108 (EVO-8 levels 2/3): version handling at boot. **Opt-in** — no
|
|
1258
1284
|
// network on a default boot. `--auto-upgrade` self-installs @latest then
|
|
1259
1285
|
// re-execs in place via process.execve (same PID/stdio, host stays connected;
|
|
@@ -1270,10 +1296,14 @@ export async function runMcpServe(flags, io = {
|
|
|
1270
1296
|
// same-day release isn't masked by the 24h notice cache; the passive
|
|
1271
1297
|
// `--upgrade-check` notice keeps the 24h throttle.
|
|
1272
1298
|
const ttlMs = wantAutoUpgrade ? H2A_AUTO_UPGRADE_CHECK_TTL_MS : H2A_UPGRADE_CHECK_TTL_MS;
|
|
1273
|
-
const result = checkUpgrade(current, {
|
|
1299
|
+
const result = checkUpgrade(current, {
|
|
1300
|
+
cachePath: upgradeCachePath(root),
|
|
1301
|
+
ttlMs,
|
|
1302
|
+
...(io.upgradeRuntime ? { runtime: io.upgradeRuntime } : {})
|
|
1303
|
+
});
|
|
1274
1304
|
if (result.upgradeAvailable) {
|
|
1275
1305
|
if (wantAutoUpgrade) {
|
|
1276
|
-
const ok = performUpgrade();
|
|
1306
|
+
const ok = performUpgrade(io.upgradeRuntime);
|
|
1277
1307
|
if (ok && flags["no-restart"] === undefined && canReexec()) {
|
|
1278
1308
|
io.stderr.write(`h2a mcp-serve: auto-upgraded ${current} → ${result.latest}; restarting into the new version…\n`);
|
|
1279
1309
|
reexecSelf(); // on success the image is replaced (never returns)
|
|
@@ -1326,10 +1356,12 @@ export async function runMcpServe(flags, io = {
|
|
|
1326
1356
|
}
|
|
1327
1357
|
await runMcpStdio({
|
|
1328
1358
|
root,
|
|
1359
|
+
workspaceRoot: process.cwd(),
|
|
1329
1360
|
stdin: io.stdin,
|
|
1330
1361
|
stdout: io.stdout,
|
|
1331
1362
|
stderr: io.stderr,
|
|
1332
1363
|
...(autoOpen ? { autoOpen } : {}),
|
|
1364
|
+
...(readiness ? { readiness } : {}),
|
|
1333
1365
|
...(wake ? { wake } : {}),
|
|
1334
1366
|
...(io.signal ? { signal: io.signal } : {})
|
|
1335
1367
|
});
|
|
@@ -1640,6 +1672,16 @@ function collectRepeatedFlag(argv, flag) {
|
|
|
1640
1672
|
}
|
|
1641
1673
|
return out;
|
|
1642
1674
|
}
|
|
1675
|
+
function parseLoopLaunch(raw) {
|
|
1676
|
+
let value;
|
|
1677
|
+
try {
|
|
1678
|
+
value = JSON.parse(raw);
|
|
1679
|
+
}
|
|
1680
|
+
catch {
|
|
1681
|
+
throw new Error("--launch-stdin must contain valid JSON");
|
|
1682
|
+
}
|
|
1683
|
+
return validateLoopLaunchSpec(value);
|
|
1684
|
+
}
|
|
1643
1685
|
function selectLoopAgent(loop, selector) {
|
|
1644
1686
|
if (!selector)
|
|
1645
1687
|
return undefined;
|
|
@@ -1653,7 +1695,17 @@ function cmdLoop(argv, streams) {
|
|
|
1653
1695
|
if (sub === "create") {
|
|
1654
1696
|
const repos = collectRepeatedFlag(argv, "--repo").map(parseLoopRepo);
|
|
1655
1697
|
const refs = collectRepeatedFlag(argv, "--track").map(parseLoopTrack);
|
|
1656
|
-
|
|
1698
|
+
let agents = collectRepeatedFlag(argv, "--agent").map(parseLoopAgent);
|
|
1699
|
+
if (flags.launch)
|
|
1700
|
+
throw new Error("--launch is unsafe because prompts must not be passed in argv; use --launch-stdin");
|
|
1701
|
+
if (flags["launch-stdin"] === "true") {
|
|
1702
|
+
if (agents.length !== 1)
|
|
1703
|
+
throw new Error("--launch-stdin requires exactly one --agent on loop create");
|
|
1704
|
+
const launch = parseLoopLaunch(stdinText(streams) ?? "");
|
|
1705
|
+
if (agents[0].host !== launch.profile)
|
|
1706
|
+
throw new Error("--agent host must match --launch-stdin profile");
|
|
1707
|
+
agents = [{ ...agents[0], launch }];
|
|
1708
|
+
}
|
|
1657
1709
|
const loop = createObjectiveLoop(root, {
|
|
1658
1710
|
...(flags.id ? { id: flags.id } : {}),
|
|
1659
1711
|
name: flags.name,
|
|
@@ -1675,11 +1727,15 @@ function cmdLoop(argv, streams) {
|
|
|
1675
1727
|
streams.stderr.write("h2a loop join: <loopId> and --instance <id> are required\n");
|
|
1676
1728
|
return 1;
|
|
1677
1729
|
}
|
|
1730
|
+
if (flags.launch)
|
|
1731
|
+
throw new Error("--launch is unsafe because prompts must not be passed in argv; use --launch-stdin");
|
|
1732
|
+
const launch = flags["launch-stdin"] === "true" ? parseLoopLaunch(stdinText(streams) ?? "") : undefined;
|
|
1678
1733
|
const loop = joinObjectiveLoop(root, loopId, {
|
|
1679
1734
|
instance: flags.instance,
|
|
1680
1735
|
...(flags["agent-id"] ? { agentId: flags["agent-id"] } : {}),
|
|
1681
1736
|
...(flags.role ? { role: flags.role } : {}),
|
|
1682
|
-
...(flags.required ? { required: flags.required !== "false" } : {})
|
|
1737
|
+
...(flags.required ? { required: flags.required !== "false" } : {}),
|
|
1738
|
+
...(launch !== undefined ? { launch } : {})
|
|
1683
1739
|
});
|
|
1684
1740
|
streams.stdout.write(`${JSON.stringify(loop, null, 2)}\n`);
|
|
1685
1741
|
return 0;
|
|
@@ -1693,6 +1749,7 @@ function cmdLoop(argv, streams) {
|
|
|
1693
1749
|
const loop = reportObjectiveLoop(root, loopId, {
|
|
1694
1750
|
...(flags.instance ? { instance: flags.instance } : {}),
|
|
1695
1751
|
...(flags["agent-id"] ? { agentId: flags["agent-id"] } : {}),
|
|
1752
|
+
...(flags["auto-join"] === "true" ? { autoJoin: true } : {}),
|
|
1696
1753
|
note: flags.note
|
|
1697
1754
|
});
|
|
1698
1755
|
streams.stdout.write(`${JSON.stringify(loop, null, 2)}\n`);
|
|
@@ -4073,7 +4130,12 @@ function cmdDoctor(flags, streams) {
|
|
|
4073
4130
|
}
|
|
4074
4131
|
}
|
|
4075
4132
|
}
|
|
4076
|
-
// (d) --scan <dir>: find immediate child buses (ONE level deep)
|
|
4133
|
+
// (d) --scan <dir>: find immediate child buses (ONE level deep).
|
|
4134
|
+
// Safety model: a stray bus is ORPHAN only if it has zero live (fresh
|
|
4135
|
+
// heartbeat) presence — checked via the same listPresence() used for the
|
|
4136
|
+
// liveSessions hard check above. A bus with ANY live presence is reported
|
|
4137
|
+
// but NEVER pruned, --prune or not. This is a dry-run-by-default sweep:
|
|
4138
|
+
// the report always lists what --prune WOULD remove; only --prune deletes.
|
|
4077
4139
|
const strayBuses = [];
|
|
4078
4140
|
if (flags.scan) {
|
|
4079
4141
|
try {
|
|
@@ -4090,7 +4152,17 @@ function cmdDoctor(flags, streams) {
|
|
|
4090
4152
|
catch {
|
|
4091
4153
|
instances = 0;
|
|
4092
4154
|
}
|
|
4093
|
-
|
|
4155
|
+
// Liveness gate: any fresh presence heartbeat in this bus makes it
|
|
4156
|
+
// ACTIVE, not orphan — never a deletion candidate.
|
|
4157
|
+
let live = false;
|
|
4158
|
+
try {
|
|
4159
|
+
live = listPresence(candidateBus).length > 0;
|
|
4160
|
+
}
|
|
4161
|
+
catch {
|
|
4162
|
+
// Unreadable presence dir — treat conservatively as NOT orphan.
|
|
4163
|
+
live = true;
|
|
4164
|
+
}
|
|
4165
|
+
strayBuses.push({ path: candidateBus, instances, live, orphan: !live });
|
|
4094
4166
|
}
|
|
4095
4167
|
}
|
|
4096
4168
|
}
|
|
@@ -4098,15 +4170,21 @@ function cmdDoctor(flags, streams) {
|
|
|
4098
4170
|
streams.stderr.write(`h2a doctor: --scan ${flags.scan}: ${error.message}\n`);
|
|
4099
4171
|
}
|
|
4100
4172
|
if (strayBuses.length > 0) {
|
|
4173
|
+
const orphanBuses = strayBuses.filter((b) => b.orphan === true);
|
|
4174
|
+
const liveBuses = strayBuses.filter((b) => b.orphan !== true);
|
|
4101
4175
|
warnings.push({
|
|
4102
4176
|
check: "strayBuses",
|
|
4103
4177
|
count: strayBuses.length,
|
|
4178
|
+
orphanCount: orphanBuses.length,
|
|
4179
|
+
liveCount: liveBuses.length,
|
|
4104
4180
|
buses: strayBuses,
|
|
4105
4181
|
message: `${strayBuses.length} stray repo-local .h2a bus(es) found under ${flags.scan} — ` +
|
|
4106
|
-
`candidate split-brain forks.
|
|
4182
|
+
`candidate split-brain forks. ${orphanBuses.length} orphan (no live presence — ` +
|
|
4183
|
+
`${flags.prune !== undefined ? "removed by" : "would be removed by"} --prune), ` +
|
|
4184
|
+
`${liveBuses.length} live (has active presence — never pruned).`
|
|
4107
4185
|
});
|
|
4108
4186
|
if (flags.prune !== undefined) {
|
|
4109
|
-
for (const bus of
|
|
4187
|
+
for (const bus of orphanBuses) {
|
|
4110
4188
|
const busPath = bus.path;
|
|
4111
4189
|
try {
|
|
4112
4190
|
rmSync(busPath, { recursive: true, force: true });
|
|
@@ -4116,6 +4194,10 @@ function cmdDoctor(flags, streams) {
|
|
|
4116
4194
|
streams.stderr.write(`h2a doctor --prune: cannot remove ${busPath}: ${error.message}\n`);
|
|
4117
4195
|
}
|
|
4118
4196
|
}
|
|
4197
|
+
if (liveBuses.length > 0) {
|
|
4198
|
+
streams.stderr.write(`h2a doctor --prune: skipped ${liveBuses.length} stray bus(es) with live presence (never pruned): ` +
|
|
4199
|
+
`${liveBuses.map((b) => b.path).join(", ")}\n`);
|
|
4200
|
+
}
|
|
4119
4201
|
}
|
|
4120
4202
|
}
|
|
4121
4203
|
}
|
|
@@ -4883,7 +4965,7 @@ export async function cmdKeepalive(flags, streams) {
|
|
|
4883
4965
|
// Verbes spécifiques, sans namespace `track` (dissous comme host/sub).
|
|
4884
4966
|
export const TRACK_FACADE_VERBS = new Set([
|
|
4885
4967
|
"decision", "report", "accept", "blocker", "item", "query",
|
|
4886
|
-
"consolidate", "priority", "branch", "focus", "ingest", "restructure"
|
|
4968
|
+
"consolidate", "priority", "branch", "focus", "ingest", "restructure", "snapshot"
|
|
4887
4969
|
]);
|
|
4888
4970
|
// ④ de-spawn — a strict SUBSET of the facade verbs routed IN-PROCESS via
|
|
4889
4971
|
// `@sentropic/track`'s `runCli`, no child process. Every native verb is proven
|
|
@@ -4896,14 +4978,14 @@ export const TRACK_FACADE_VERBS = new Set([
|
|
|
4896
4978
|
//
|
|
4897
4979
|
// The native set is split READ-ONLY vs WRITE because the throw-fallback rule
|
|
4898
4980
|
// differs (RISK: double-write, see `delegateToTrackNative`):
|
|
4899
|
-
// • READ-ONLY (`query`/`report`) — a native throw wrote nothing, so falling
|
|
4981
|
+
// • READ-ONLY (`query`/`report`/`snapshot`) — a native throw wrote nothing, so falling
|
|
4900
4982
|
// back to the spawn facade is safe.
|
|
4901
4983
|
// • WRITE (the rest) — track's `appendCommand` is ATOMIC under the O_EXCL lock
|
|
4902
4984
|
// (read→validate→append→writeHead→verify): it throws either BEFORE the
|
|
4903
4985
|
// append (validation → nothing written) or AFTER a landed write (the
|
|
4904
4986
|
// verify receipt). A spawn fallback on that throw could DOUBLE-WRITE, so a
|
|
4905
4987
|
// write NEVER falls back on throw — it propagates the error (rc≠0 + stderr).
|
|
4906
|
-
export const TRACK_NATIVE_READONLY_VERBS = new Set(["query", "report"]);
|
|
4988
|
+
export const TRACK_NATIVE_READONLY_VERBS = new Set(["query", "report", "snapshot"]);
|
|
4907
4989
|
// ④ tranche-2 — the SYNC write verbs, de-spawned in-process. Each dispatches
|
|
4908
4990
|
// through runCli's mutating switch as a plain sync `cmd…` returning a `number`.
|
|
4909
4991
|
// `focus` is absent (async); `restructure`/`ingest` are sync file-plan applies.
|
|
@@ -4947,6 +5029,44 @@ export async function runTrackMcpServe(flags, io = {
|
|
|
4947
5029
|
return 1;
|
|
4948
5030
|
}
|
|
4949
5031
|
}
|
|
5032
|
+
function cmdReportContext(flags, streams) {
|
|
5033
|
+
const workspaceRoot = flags["workspace-root"];
|
|
5034
|
+
if (!workspaceRoot || workspaceRoot === "true") {
|
|
5035
|
+
streams.stderr.write("h2a report-context: --workspace-root <absolute-path> is required\n");
|
|
5036
|
+
return 1;
|
|
5037
|
+
}
|
|
5038
|
+
if (!isAbsolute(workspaceRoot)) {
|
|
5039
|
+
streams.stderr.write("h2a report-context: --workspace-root must be an absolute path\n");
|
|
5040
|
+
return 1;
|
|
5041
|
+
}
|
|
5042
|
+
try {
|
|
5043
|
+
const context = readH2AReportContext({
|
|
5044
|
+
storeRoot: resolveRoot(flags, streams.cwd ?? (() => process.cwd())),
|
|
5045
|
+
workspaceRoot
|
|
5046
|
+
});
|
|
5047
|
+
streams.stdout.write(`${JSON.stringify(context)}\n`);
|
|
5048
|
+
return 0;
|
|
5049
|
+
}
|
|
5050
|
+
catch (err) {
|
|
5051
|
+
streams.stderr.write(`h2a report-context: ${err.message}\n`);
|
|
5052
|
+
return 3;
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
function cmdInstallTrackReportAiConfig(flags, streams) {
|
|
5056
|
+
try {
|
|
5057
|
+
const result = installTrackReportAiConfig({ force: flags.force === "true" });
|
|
5058
|
+
streams.stdout.write(`${JSON.stringify({ ok: true, ...result })}\n`);
|
|
5059
|
+
return 0;
|
|
5060
|
+
}
|
|
5061
|
+
catch (err) {
|
|
5062
|
+
if (err instanceof TrackReportAiConfigConflictError) {
|
|
5063
|
+
streams.stderr.write(`h2a report-ai install-track-config: ${err.message}\n`);
|
|
5064
|
+
return 2;
|
|
5065
|
+
}
|
|
5066
|
+
streams.stderr.write(`h2a report-ai install-track-config: ${err.message}\n`);
|
|
5067
|
+
return 3;
|
|
5068
|
+
}
|
|
5069
|
+
}
|
|
4950
5070
|
function resolveTrackBin() {
|
|
4951
5071
|
// Le champ `exports` de @sentropic/track bloque l'accès à ./package.json,
|
|
4952
5072
|
// donc on résout l'entrée puis on remonte jusqu'au package.json du package.
|
|
@@ -5069,6 +5189,14 @@ export function runCli(argv = process.argv.slice(2), streams = {
|
|
|
5069
5189
|
streams.stdout.write(`${JSON.stringify(H2A_CLI_MCP_TOOL_NAMES, null, 2)}\n`);
|
|
5070
5190
|
return 0;
|
|
5071
5191
|
}
|
|
5192
|
+
if (command === "report-context")
|
|
5193
|
+
return cmdReportContext(flags, streams);
|
|
5194
|
+
if (command === "report-ai") {
|
|
5195
|
+
if (argv[1] === "install-track-config")
|
|
5196
|
+
return cmdInstallTrackReportAiConfig(flags, streams);
|
|
5197
|
+
streams.stderr.write("h2a report-ai: async adapter command — run via the h2a binary\n");
|
|
5198
|
+
return 1;
|
|
5199
|
+
}
|
|
5072
5200
|
if (command === "init")
|
|
5073
5201
|
return cmdInit(flags, streams);
|
|
5074
5202
|
if (command === "register")
|