agent-tempo 1.7.0 → 2.0.0-beta.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.
- package/CLAUDE.md +10 -13
- package/README.md +21 -15
- package/dashboard/dist/assets/index-BbR7zIdK.js.map +1 -1
- package/dashboard/package.json +1 -1
- package/dist/activities/hard-terminate.d.ts +2 -2
- package/dist/activities/hard-terminate.js +3 -9
- package/dist/activities/maestro.d.ts +8 -13
- package/dist/activities/maestro.js +0 -10
- package/dist/activities/outbox.js +4 -2
- package/dist/adapters/base.js +3 -0
- package/dist/cli/commands.d.ts +8 -0
- package/dist/cli/commands.js +79 -11
- package/dist/cli/daemon-command.js +19 -33
- package/dist/cli/help-text.js +7 -7
- package/dist/cli/home-command.d.ts +26 -0
- package/dist/cli/home-command.js +156 -0
- package/dist/cli/removed-verbs.d.ts +0 -4
- package/dist/cli/removed-verbs.js +23 -12
- package/dist/cli/sa-preflight.d.ts +0 -14
- package/dist/cli/sa-preflight.js +1 -17
- package/dist/cli/startup.d.ts +1 -10
- package/dist/cli/startup.js +0 -40
- package/dist/cli.js +34 -80
- package/dist/client/core.js +13 -15
- package/dist/client/index.d.ts +2 -1
- package/dist/client/interface.d.ts +5 -14
- package/dist/client/with-spawn.d.ts +9 -4
- package/dist/client/with-spawn.js +7 -10
- package/dist/config.d.ts +0 -13
- package/dist/constants.d.ts +22 -0
- package/dist/constants.js +23 -1
- package/dist/daemon.js +52 -0
- package/dist/http/auth.d.ts +3 -21
- package/dist/http/auth.js +10 -31
- package/dist/http/event-types.d.ts +5 -4
- package/dist/http/orphans.d.ts +3 -3
- package/dist/http/orphans.js +3 -3
- package/dist/http/server.d.ts +0 -5
- package/dist/http/server.js +69 -29
- package/dist/http/writes.d.ts +1 -1
- package/dist/http/writes.js +25 -2
- package/dist/palette/index.d.ts +6 -7
- package/dist/palette/index.js +6 -7
- package/dist/pi/mission-control/actions.d.ts +67 -1
- package/dist/pi/mission-control/actions.js +61 -0
- package/dist/pi/mission-control/extension.d.ts +77 -0
- package/dist/pi/mission-control/extension.js +171 -0
- package/dist/pi/workflow-client.d.ts +14 -16
- package/dist/pi/workflow-client.js +18 -44
- package/dist/types.d.ts +15 -6
- package/dist/upgrade/boot-guard.d.ts +95 -0
- package/dist/upgrade/boot-guard.js +88 -0
- package/dist/upgrade/from-upgrade.d.ts +95 -0
- package/dist/upgrade/from-upgrade.js +330 -0
- package/dist/upgrade/phase-engine.js +4 -1
- package/dist/utils/duration.d.ts +3 -6
- package/dist/utils/duration.js +3 -6
- package/dist/utils/format-hosts.d.ts +1 -1
- package/dist/utils/format-hosts.js +0 -2
- package/dist/utils/grpc-shutdown-guard.js +0 -4
- package/dist/utils/hosts.d.ts +4 -10
- package/dist/utils/hosts.js +12 -28
- package/dist/utils/search-attributes.d.ts +27 -18
- package/dist/utils/search-attributes.js +39 -18
- package/dist/utils/visibility-deadline.d.ts +16 -0
- package/dist/utils/visibility-deadline.js +16 -0
- package/dist/workflows/maestro-signals.d.ts +0 -13
- package/dist/workflows/maestro-signals.js +6 -14
- package/dist/workflows/maestro.js +27 -32
- package/dist/workflows/scheduler.js +7 -1
- package/dist/workflows/session.js +44 -110
- package/dist/workflows/signals.d.ts +9 -1
- package/dist/workflows/signals.js +8 -6
- package/package.json +1 -6
- package/workflow-bundle.js +239 -182
- package/dist/cli/legacy-migration.d.ts +0 -35
- package/dist/cli/legacy-migration.js +0 -341
- package/dist/client/ensure-conductor-spawned.d.ts +0 -35
- package/dist/client/ensure-conductor-spawned.js +0 -48
- package/dist/tui/App.d.ts +0 -85
- package/dist/tui/App.js +0 -1791
- package/dist/tui/bootstrap-types.d.ts +0 -46
- package/dist/tui/bootstrap-types.js +0 -7
- package/dist/tui/commands.d.ts +0 -71
- package/dist/tui/commands.js +0 -1375
- package/dist/tui/components/ChatView.d.ts +0 -35
- package/dist/tui/components/ChatView.js +0 -54
- package/dist/tui/components/CommandPalette.d.ts +0 -21
- package/dist/tui/components/CommandPalette.js +0 -67
- package/dist/tui/components/ConversationStream.d.ts +0 -114
- package/dist/tui/components/ConversationStream.js +0 -307
- package/dist/tui/components/CreateEnsembleWizard.d.ts +0 -19
- package/dist/tui/components/CreateEnsembleWizard.js +0 -223
- package/dist/tui/components/DestroyConfirmModal.d.ts +0 -17
- package/dist/tui/components/DestroyConfirmModal.js +0 -62
- package/dist/tui/components/ErrorView.d.ts +0 -31
- package/dist/tui/components/ErrorView.js +0 -129
- package/dist/tui/components/HomeView.d.ts +0 -54
- package/dist/tui/components/HomeView.js +0 -306
- package/dist/tui/components/LoadLineupModal.d.ts +0 -18
- package/dist/tui/components/LoadLineupModal.js +0 -79
- package/dist/tui/components/MainView.d.ts +0 -21
- package/dist/tui/components/MainView.js +0 -107
- package/dist/tui/components/NewEnsembleModal.d.ts +0 -9
- package/dist/tui/components/NewEnsembleModal.js +0 -73
- package/dist/tui/components/Picker.d.ts +0 -23
- package/dist/tui/components/Picker.js +0 -70
- package/dist/tui/components/PlayerDetailView.d.ts +0 -26
- package/dist/tui/components/PlayerDetailView.js +0 -118
- package/dist/tui/components/PromptArea.d.ts +0 -50
- package/dist/tui/components/PromptArea.js +0 -303
- package/dist/tui/components/RecruitWizard.d.ts +0 -17
- package/dist/tui/components/RecruitWizard.js +0 -221
- package/dist/tui/components/RestoreConfirmModal.d.ts +0 -18
- package/dist/tui/components/RestoreConfirmModal.js +0 -71
- package/dist/tui/components/ScheduleWizard.d.ts +0 -19
- package/dist/tui/components/ScheduleWizard.js +0 -259
- package/dist/tui/components/Splash.d.ts +0 -23
- package/dist/tui/components/Splash.js +0 -221
- package/dist/tui/components/StatusBar.d.ts +0 -48
- package/dist/tui/components/StatusBar.js +0 -128
- package/dist/tui/components/StatusOverlay.d.ts +0 -15
- package/dist/tui/components/StatusOverlay.js +0 -76
- package/dist/tui/components/TitleBar.d.ts +0 -10
- package/dist/tui/components/TitleBar.js +0 -21
- package/dist/tui/index.d.ts +0 -15
- package/dist/tui/index.js +0 -162
- package/dist/tui/ink-context.d.ts +0 -18
- package/dist/tui/ink-context.js +0 -59
- package/dist/tui/ink-loader.d.ts +0 -26
- package/dist/tui/ink-loader.js +0 -42
- package/dist/tui/removed-commands.d.ts +0 -9
- package/dist/tui/removed-commands.js +0 -22
- package/dist/tui/sse-handler.d.ts +0 -52
- package/dist/tui/sse-handler.js +0 -157
- package/dist/tui/store.d.ts +0 -598
- package/dist/tui/store.js +0 -753
- package/dist/tui/utils/format.d.ts +0 -56
- package/dist/tui/utils/format.js +0 -155
- package/dist/tui/utils/fullscreen.d.ts +0 -23
- package/dist/tui/utils/fullscreen.js +0 -71
- package/dist/tui/utils/history.d.ts +0 -10
- package/dist/tui/utils/history.js +0 -85
- package/dist/tui/utils/platform.d.ts +0 -45
- package/dist/tui/utils/platform.js +0 -258
- package/dist/tui/utils/theme.d.ts +0 -21
- package/dist/tui/utils/theme.js +0 -24
|
@@ -15,20 +15,6 @@ export declare const REQUIRED_SEARCH_ATTRIBUTES: ReadonlyArray<{
|
|
|
15
15
|
name: string;
|
|
16
16
|
type: 'Keyword' | 'Bool';
|
|
17
17
|
}>;
|
|
18
|
-
/**
|
|
19
|
-
* T0.5 (#747) — legacy attributes that pre-v1.8 deployments registered and
|
|
20
|
-
* pre-v1.8 workflow runs still carry. NEVER auto-unregistered (dropping a
|
|
21
|
-
* search attribute is a privileged, operator-only action — see
|
|
22
|
-
* `docs/ops/sa-diet-migration.md`); fresh namespaces simply don't register
|
|
23
|
-
* them. Kept here so tooling can name them in diagnostics and so the
|
|
24
|
-
* dual-read fallback window (memo preferred, SA fallback in
|
|
25
|
-
* `utils/search-attributes.ts`) is documented next to the list it falls
|
|
26
|
-
* back to. Dual-read fallback may be removed at the next major.
|
|
27
|
-
*/
|
|
28
|
-
export declare const LEGACY_SEARCH_ATTRIBUTES: ReadonlyArray<{
|
|
29
|
-
name: string;
|
|
30
|
-
type: 'Keyword' | 'Bool';
|
|
31
|
-
}>;
|
|
32
18
|
export interface SearchAttributePreflightOpts {
|
|
33
19
|
temporalAddress: string;
|
|
34
20
|
temporalNamespace: string;
|
package/dist/cli/sa-preflight.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.REQUIRED_SEARCH_ATTRIBUTES = void 0;
|
|
37
37
|
exports.defaultProbeRegisteredAttributes = defaultProbeRegisteredAttributes;
|
|
38
38
|
exports.isTemporalCloud = isTemporalCloud;
|
|
39
39
|
exports.sdkProbeRegisteredAttributes = sdkProbeRegisteredAttributes;
|
|
@@ -97,22 +97,6 @@ exports.REQUIRED_SEARCH_ATTRIBUTES = Object.freeze([
|
|
|
97
97
|
{ name: 'AgentTempoAttachedHost', type: 'Keyword' },
|
|
98
98
|
{ name: 'AgentTempoAttachmentState', type: 'Keyword' },
|
|
99
99
|
]);
|
|
100
|
-
/**
|
|
101
|
-
* T0.5 (#747) — legacy attributes that pre-v1.8 deployments registered and
|
|
102
|
-
* pre-v1.8 workflow runs still carry. NEVER auto-unregistered (dropping a
|
|
103
|
-
* search attribute is a privileged, operator-only action — see
|
|
104
|
-
* `docs/ops/sa-diet-migration.md`); fresh namespaces simply don't register
|
|
105
|
-
* them. Kept here so tooling can name them in diagnostics and so the
|
|
106
|
-
* dual-read fallback window (memo preferred, SA fallback in
|
|
107
|
-
* `utils/search-attributes.ts`) is documented next to the list it falls
|
|
108
|
-
* back to. Dual-read fallback may be removed at the next major.
|
|
109
|
-
*/
|
|
110
|
-
exports.LEGACY_SEARCH_ATTRIBUTES = Object.freeze([
|
|
111
|
-
{ name: 'AgentTempoGitRoot', type: 'Keyword' },
|
|
112
|
-
{ name: 'AgentTempoPlayerType', type: 'Keyword' },
|
|
113
|
-
{ name: 'AgentTempoIsConductor', type: 'Bool' },
|
|
114
|
-
{ name: 'AgentTempoAttachmentId', type: 'Keyword' },
|
|
115
|
-
]);
|
|
116
100
|
/**
|
|
117
101
|
* Default probe — shells out to `temporal operator search-attribute list`.
|
|
118
102
|
* Returns an empty set on any error so callers fall through to the
|
package/dist/cli/startup.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Config } from '../config';
|
|
2
2
|
import type { EnsembleSummary } from '../client/interface';
|
|
3
|
-
export type StepName = '
|
|
3
|
+
export type StepName = 'preflight' | 'mcpConfig' | 'temporalReach' | 'searchAttrs' | 'daemonBoot' | 'badgeCollection';
|
|
4
4
|
/** Structured per-step result. `ok` = ran successfully; `skipped` = cache hit;
|
|
5
5
|
* `action-taken` = needed repair (e.g. started daemon, registered MCP);
|
|
6
6
|
* `failed` = non-fatal failure recorded for the TUI to surface. */
|
|
@@ -55,15 +55,6 @@ export interface BootstrapArgs {
|
|
|
55
55
|
* simulates a successful start; `'failed'` + `detail` simulates failure.
|
|
56
56
|
*/
|
|
57
57
|
daemonBoot?: (config: Config) => Promise<StepOutcome>;
|
|
58
|
-
/**
|
|
59
|
-
* PR-2 of the v1.0 rebrand — one-shot copy of `~/.agent-tempo/` →
|
|
60
|
-
* `~/.agent-tempo/`. Runs once on first boot of the new binary; idempotent
|
|
61
|
-
* thereafter. Tests should override to avoid touching real $HOME.
|
|
62
|
-
*
|
|
63
|
-
* Failure here MUST NOT block the boot path — record `'failed'` with a
|
|
64
|
-
* detail string and let the rest of bootstrap proceed.
|
|
65
|
-
*/
|
|
66
|
-
legacyHomeMigration?: () => Promise<StepOutcome>;
|
|
67
58
|
/**
|
|
68
59
|
* Inject the Temporal reachability probe (steps 3 + 6). Tests override
|
|
69
60
|
* to avoid real network I/O — default performs `createTemporalConnection`
|
package/dist/cli/startup.js
CHANGED
|
@@ -73,7 +73,6 @@ const orphans_1 = require("../reconcile/orphans");
|
|
|
73
73
|
const client_2 = require("../client");
|
|
74
74
|
const os_1 = require("os");
|
|
75
75
|
const git_info_1 = require("../git-info");
|
|
76
|
-
const legacy_migration_1 = require("./legacy-migration");
|
|
77
76
|
// ─────────────────────────────────────────────────────────────────────────
|
|
78
77
|
// Cache (schema v1)
|
|
79
78
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -241,38 +240,6 @@ function daemonLogErrorTail(logPath) {
|
|
|
241
240
|
// ─────────────────────────────────────────────────────────────────────────
|
|
242
241
|
// Individual steps
|
|
243
242
|
// ─────────────────────────────────────────────────────────────────────────
|
|
244
|
-
/**
|
|
245
|
-
* Default step-0 implementation — invokes the one-shot legacy home migration
|
|
246
|
-
* (`~/.agent-tempo/` → `~/.agent-tempo/`). Idempotent: re-runs are
|
|
247
|
-
* `'skipped'` once the marker is in place. Failure is recorded but never
|
|
248
|
-
* blocks bootstrap (PR-2 brief).
|
|
249
|
-
*/
|
|
250
|
-
async function defaultLegacyHomeMigrationStep() {
|
|
251
|
-
const t0 = perf_hooks_1.performance.now();
|
|
252
|
-
try {
|
|
253
|
-
const result = await (0, legacy_migration_1.migrateLegacyHome)();
|
|
254
|
-
const durationMs = perf_hooks_1.performance.now() - t0;
|
|
255
|
-
const detail = (0, legacy_migration_1.formatMigrationResult)(result);
|
|
256
|
-
switch (result.status) {
|
|
257
|
-
case 'no-legacy':
|
|
258
|
-
case 'already-migrated':
|
|
259
|
-
return { status: 'skipped', durationMs, detail };
|
|
260
|
-
case 'migrated':
|
|
261
|
-
return { status: 'action-taken', durationMs, detail };
|
|
262
|
-
case 'skipped':
|
|
263
|
-
return { status: 'skipped', durationMs, detail };
|
|
264
|
-
case 'failed':
|
|
265
|
-
return { status: 'failed', durationMs, detail };
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
catch (err) {
|
|
269
|
-
return {
|
|
270
|
-
status: 'failed',
|
|
271
|
-
durationMs: perf_hooks_1.performance.now() - t0,
|
|
272
|
-
detail: `legacy-migration crashed: ${err.message}`,
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
243
|
async function stepPreflight(cache, now) {
|
|
277
244
|
if (isCacheFresh(cache.steps.preflight, TTL_24H, now)) {
|
|
278
245
|
return { status: 'skipped', durationMs: 0 };
|
|
@@ -622,12 +589,6 @@ async function bootstrap(args) {
|
|
|
622
589
|
const fetchLatest = args.fetchLatestVersion ?? defaultFetchLatestVersion;
|
|
623
590
|
const cache = readCache(cacheDir, binaryVersion);
|
|
624
591
|
const reachableProbe = args.isTemporalReachable ?? ((c) => isTemporalReachable(c, 3000));
|
|
625
|
-
// Step 0: legacy home migration (`~/.agent-tempo/` → `~/.agent-tempo/`)
|
|
626
|
-
// — PR-2 of the v1.0 rebrand. Runs before preflight so subsequent steps
|
|
627
|
-
// (cache read, MCP config write, daemon boot) all see the new home.
|
|
628
|
-
// MUST NOT block bootstrap — failure becomes a `'failed'` step with
|
|
629
|
-
// `detail`, and we keep going.
|
|
630
|
-
const legacyHomeMigration = await (args.legacyHomeMigration ?? defaultLegacyHomeMigrationStep)();
|
|
631
592
|
// Steps 1–5: fail-fast on step 1 so we don't try to register MCP on an
|
|
632
593
|
// incompatible Node. Each step mutates the cache in-place.
|
|
633
594
|
const preflight = await stepPreflight(cache, now);
|
|
@@ -668,7 +629,6 @@ async function bootstrap(args) {
|
|
|
668
629
|
return {
|
|
669
630
|
durationMs: perf_hooks_1.performance.now() - start,
|
|
670
631
|
steps: {
|
|
671
|
-
legacyHomeMigration,
|
|
672
632
|
preflight,
|
|
673
633
|
mcpConfig,
|
|
674
634
|
temporalReach,
|
package/dist/cli.js
CHANGED
|
@@ -60,7 +60,6 @@ const out = __importStar(require("./cli/output"));
|
|
|
60
60
|
const dev_banner_1 = require("./cli/dev-banner");
|
|
61
61
|
const types_1 = require("./types");
|
|
62
62
|
const config_1 = require("./config");
|
|
63
|
-
const legacy_migration_1 = require("./cli/legacy-migration");
|
|
64
63
|
const global_wrapper_1 = require("./cli/global-wrapper");
|
|
65
64
|
const resolve_ensemble_1 = require("./cli/resolve-ensemble");
|
|
66
65
|
const grpc_shutdown_guard_1 = require("./utils/grpc-shutdown-guard");
|
|
@@ -68,7 +67,9 @@ const grpc_shutdown_guard_1 = require("./utils/grpc-shutdown-guard");
|
|
|
68
67
|
const PACKAGE_ROOT = (0, path_1.resolve)(__dirname, '..');
|
|
69
68
|
function parseArgs(argv) {
|
|
70
69
|
const result = {
|
|
71
|
-
|
|
70
|
+
// #789 — the TUI is deleted; a bare `agent-tempo` now resolves to the
|
|
71
|
+
// `home` command (bootstrap + status + hints), NOT a terminal UI launch.
|
|
72
|
+
command: 'home',
|
|
72
73
|
positional: [],
|
|
73
74
|
dir: process.cwd(),
|
|
74
75
|
skipPreflight: false,
|
|
@@ -145,6 +146,11 @@ function parseArgs(argv) {
|
|
|
145
146
|
else if (arg === '--no-hold') {
|
|
146
147
|
result.noHold = true;
|
|
147
148
|
}
|
|
149
|
+
else if (arg === '--from-upgrade') {
|
|
150
|
+
// `up --from-upgrade` (#786) — recreate protocol-2 workflows from the
|
|
151
|
+
// upgrade snapshot left by `upgrade-to-2`.
|
|
152
|
+
result.fromUpgrade = true;
|
|
153
|
+
}
|
|
148
154
|
else if (arg === '--destroy') {
|
|
149
155
|
result.destroy = true;
|
|
150
156
|
}
|
|
@@ -168,12 +174,10 @@ function parseArgs(argv) {
|
|
|
168
174
|
result.host = argv[++i];
|
|
169
175
|
}
|
|
170
176
|
else if (arg === '--force') {
|
|
171
|
-
// Consumed by `daemon start --force` (bypass stale-PID guard)
|
|
172
|
-
// `migrate-from-claude-tempo --force` (bypass conflict + volatile-state guards).
|
|
177
|
+
// Consumed by `daemon start --force` (bypass stale-PID guard).
|
|
173
178
|
result.force = true;
|
|
174
179
|
}
|
|
175
180
|
else if (arg === '--dry-run') {
|
|
176
|
-
// `migrate-from-claude-tempo --dry-run` — print the plan, write nothing.
|
|
177
181
|
// `upgrade-to-2 --dry-run` — print snapshot + destroy list, change nothing.
|
|
178
182
|
result.dryRun = true;
|
|
179
183
|
}
|
|
@@ -302,39 +306,6 @@ function cliOverrides(args) {
|
|
|
302
306
|
temporalTlsKeyPath: args.temporalTlsKeyPath,
|
|
303
307
|
};
|
|
304
308
|
}
|
|
305
|
-
/**
|
|
306
|
-
* Format + print a {@link LegacyMigrationResult} from
|
|
307
|
-
* `migrate-from-claude-tempo`. Extracted to module scope (an if/else cascade
|
|
308
|
-
* rather than a nested switch) so the body doesn't trip the CLI surface-drift
|
|
309
|
-
* detector, which scans top-level `case '...':` labels in this file.
|
|
310
|
-
*/
|
|
311
|
-
function reportMigrationResult(result) {
|
|
312
|
-
const msg = (0, legacy_migration_1.formatMigrationResult)(result);
|
|
313
|
-
if (result.status === 'no-legacy' || result.status === 'already-migrated') {
|
|
314
|
-
out.success(msg);
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
if (result.status === 'migrated') {
|
|
318
|
-
out.success(msg);
|
|
319
|
-
if (result.copiedFiles?.length) {
|
|
320
|
-
for (const f of result.copiedFiles)
|
|
321
|
-
out.log(` ${out.dim('+')} ${f}`);
|
|
322
|
-
}
|
|
323
|
-
if (result.errors?.length) {
|
|
324
|
-
for (const e of result.errors)
|
|
325
|
-
out.warn(e);
|
|
326
|
-
}
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
if (result.status === 'skipped') {
|
|
330
|
-
out.warn(msg);
|
|
331
|
-
process.exitCode = 1;
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
// 'failed'
|
|
335
|
-
out.error(msg);
|
|
336
|
-
process.exitCode = 1;
|
|
337
|
-
}
|
|
338
309
|
async function main() {
|
|
339
310
|
// Neutralize the Temporal/grpc-js "Channel has been shut down" retry-after-
|
|
340
311
|
// close race before any Temporal-touching command runs. See
|
|
@@ -519,6 +490,7 @@ async function main() {
|
|
|
519
490
|
noHold: args.noHold,
|
|
520
491
|
agent: resolvedAgent(),
|
|
521
492
|
...(args.scenario ? { scenario: args.scenario } : {}),
|
|
493
|
+
...(args.fromUpgrade ? { fromUpgrade: true } : {}),
|
|
522
494
|
...overrides,
|
|
523
495
|
});
|
|
524
496
|
break;
|
|
@@ -687,20 +659,6 @@ async function main() {
|
|
|
687
659
|
out.log(out.dim(' A bare `pi` stays a plain coding session (neither extension activates).'));
|
|
688
660
|
break;
|
|
689
661
|
}
|
|
690
|
-
case 'migrate-from-claude-tempo': {
|
|
691
|
-
// PR-2 of the v1.0 rebrand — one-shot copy of `~/.agent-tempo/` →
|
|
692
|
-
// `~/.agent-tempo/`. Crash-proof (no Temporal deps). The `--dev`
|
|
693
|
-
// top-level flag selects the dev profile (`~/.agent-tempo-dev/` →
|
|
694
|
-
// `~/.agent-tempo-dev/`) via {@link isDevMode}.
|
|
695
|
-
const { migrateLegacyHome } = await Promise.resolve().then(() => __importStar(require('./cli/legacy-migration')));
|
|
696
|
-
const result = await migrateLegacyHome({
|
|
697
|
-
dryRun: !!args.dryRun,
|
|
698
|
-
force: !!args.force,
|
|
699
|
-
profile: (0, config_1.isDevMode)() ? 'dev' : 'prod',
|
|
700
|
-
});
|
|
701
|
-
reportMigrationResult(result);
|
|
702
|
-
break;
|
|
703
|
-
}
|
|
704
662
|
case 'preflight': {
|
|
705
663
|
// Preflight legitimately requires Temporal (that's what it tests), so
|
|
706
664
|
// it's NOT in the crash-proof module set. Dynamic-imported here so its
|
|
@@ -721,35 +679,31 @@ async function main() {
|
|
|
721
679
|
out.success('All checks passed');
|
|
722
680
|
break;
|
|
723
681
|
}
|
|
724
|
-
case '
|
|
682
|
+
case 'home': {
|
|
683
|
+
// E.8 / D2 (#789) — bare `agent-tempo`: the #289 six-step auto-provisioning
|
|
684
|
+
// bootstrap (MCP registration, Temporal reachability, daemon boot,
|
|
685
|
+
// badges + ensembles prefetch), then a status snapshot + next-step hints.
|
|
686
|
+
// One-shot; the live operator surfaces are mission-control
|
|
687
|
+
// (`command-center`, when the Pi seat is installed) and the web dashboard.
|
|
688
|
+
// `--skip-preflight` renders the degraded no-result home. The rich,
|
|
689
|
+
// unit-tested render lives in the crash-proof `home-command` module.
|
|
725
690
|
const config = (0, config_1.getConfig)(overrides);
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
// Bootstrap is best-effort — per-step failures degrade into
|
|
743
|
-
// `StepOutcome.status: 'failed'` and a usable result. A thrown
|
|
744
|
-
// error means something outside the step boundaries broke
|
|
745
|
-
// (e.g. cache-dir creation). Log + continue with an undefined
|
|
746
|
-
// bootstrap payload so the TUI still launches.
|
|
747
|
-
out.warn(`Bootstrap hit an unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
// Dynamic import — TUI module uses ESM ink
|
|
751
|
-
const { run: runTui } = await Promise.resolve().then(() => __importStar(require('./tui/index')));
|
|
752
|
-
await runTui({ config, ensemble: tuiEnsemble, ...(bootstrapResult ? { bootstrap: bootstrapResult } : {}) });
|
|
691
|
+
const { runHome } = await Promise.resolve().then(() => __importStar(require('./cli/home-command')));
|
|
692
|
+
const { probePi, checkPiNodeFloor } = await Promise.resolve().then(() => __importStar(require('./pi/probe')));
|
|
693
|
+
const pkgVersion = require('../package.json').version;
|
|
694
|
+
await runHome({
|
|
695
|
+
bootstrap: args.skipPreflight
|
|
696
|
+
? null
|
|
697
|
+
: async () => {
|
|
698
|
+
const { bootstrap } = await Promise.resolve().then(() => __importStar(require('./cli/startup')));
|
|
699
|
+
return bootstrap({ config });
|
|
700
|
+
},
|
|
701
|
+
// The command-center seat needs BOTH the Pi package and the Node floor
|
|
702
|
+
// (the same pair command-center-command itself enforces) — suggesting
|
|
703
|
+
// it on an old Node would dead-end the user.
|
|
704
|
+
piAvailable: probePi().available && checkPiNodeFloor().ok,
|
|
705
|
+
version: pkgVersion,
|
|
706
|
+
});
|
|
753
707
|
break;
|
|
754
708
|
}
|
|
755
709
|
// `version`, `help`, `upgrade`, `config`, `daemon`, and removed-verb
|
package/dist/client/core.js
CHANGED
|
@@ -42,9 +42,9 @@ exports.createTempoClientCore = createTempoClientCore;
|
|
|
42
42
|
* future SSE event source, and any external SDK consumer that wants a
|
|
43
43
|
* headless surface (no `child_process` dependency).
|
|
44
44
|
*
|
|
45
|
-
* The
|
|
46
|
-
*
|
|
47
|
-
*
|
|
45
|
+
* The spawn method (`createEnsemble`) and the `runTempoCli` helper live in
|
|
46
|
+
* `./with-spawn.ts`, which composes this factory and adds the TTY-bound surface.
|
|
47
|
+
* (`spawnConductor` was removed in #789 with the Ink TUI.)
|
|
48
48
|
*
|
|
49
49
|
* See `docs/adr/0007-tempoclient-core-withspawn-split.md` and
|
|
50
50
|
* `docs/design/tempoclient-core-spawn-split.md`.
|
|
@@ -207,10 +207,10 @@ function createTempoClientCore(client, opts = {}) {
|
|
|
207
207
|
continue;
|
|
208
208
|
const entry = ensembleMap.get(name) || { count: 0, hasConductor: false };
|
|
209
209
|
entry.count++;
|
|
210
|
-
// Preferred: memo `AgentTempoIsConductor` (
|
|
211
|
-
// legacy-SA fallback
|
|
212
|
-
//
|
|
213
|
-
//
|
|
210
|
+
// Preferred: memo `AgentTempoIsConductor` (memo-only after the #788
|
|
211
|
+
// legacy-SA prune). Final fallback: workflow ID convention — covers
|
|
212
|
+
// the brief window after a conductor spawn before visibility
|
|
213
|
+
// propagates.
|
|
214
214
|
const isConductorFromSA = (0, search_attributes_1.getIsConductor)(wf) === true;
|
|
215
215
|
const isConductorFromId = wf.workflowId?.endsWith('-conductor') ?? false;
|
|
216
216
|
if (isConductorFromSA || isConductorFromId) {
|
|
@@ -257,10 +257,9 @@ function createTempoClientCore(client, opts = {}) {
|
|
|
257
257
|
// agent — counting it produced confusing "(2 players)" rows on
|
|
258
258
|
// a fresh ensemble with one real player. Mirrors the
|
|
259
259
|
// `filterRealPlayers` rule used in StatusBar (cf6becd). Detect
|
|
260
|
-
// via the `AgentTempoPlayerType` memo (
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
// propagates.
|
|
260
|
+
// via the `AgentTempoPlayerType` memo (memo-only after the #788
|
|
261
|
+
// legacy-SA prune), with a workflow-id-suffix fallback for the
|
|
262
|
+
// brief post-start window before visibility propagates.
|
|
264
263
|
const playerType = (0, search_attributes_1.getPlayerType)(wf);
|
|
265
264
|
const isMaestroSession = playerType === 'maestro'
|
|
266
265
|
|| (wf.workflowId?.endsWith('-maestro') ?? false);
|
|
@@ -379,10 +378,9 @@ function createTempoClientCore(client, opts = {}) {
|
|
|
379
378
|
for await (const wf of listWorkflows({ query })) {
|
|
380
379
|
const sa = wf.searchAttributes || {};
|
|
381
380
|
const playerId = Array.isArray(sa.AgentTempoPlayerId) ? String(sa.AgentTempoPlayerId[0]) : wf.workflowId;
|
|
382
|
-
// Preferred: memo (
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
// visibility propagates.
|
|
381
|
+
// Preferred: memo (memo-only after the #788 legacy-SA prune). Final
|
|
382
|
+
// fallback: workflow ID convention — covers the brief window after a
|
|
383
|
+
// conductor spawn before visibility propagates.
|
|
386
384
|
const isConductorFromSA = (0, search_attributes_1.getIsConductor)(wf) === true;
|
|
387
385
|
const isConductorFromId = wf.workflowId?.endsWith('-conductor') ?? false;
|
|
388
386
|
players.push({
|
package/dist/client/index.d.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* - {@link createTempoClientCore} — pure Temporal RPC, headless-safe
|
|
8
8
|
* (daemon, MCP server, SSE event source, future SDK consumers).
|
|
9
9
|
* - {@link createTempoClientWithSpawn} — the TTY-bound superset adding
|
|
10
|
-
* `createEnsemble`
|
|
10
|
+
* `createEnsemble` (the CLI `up` path + the command-center board's
|
|
11
|
+
* `/ensemble-up`). `spawnConductor` was removed in #789 with the Ink TUI.
|
|
11
12
|
*
|
|
12
13
|
* `createTempoClient` is preserved as a permanent alias for
|
|
13
14
|
* `createTempoClientWithSpawn` so every existing call site keeps the same
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TempoClient — public interface and related types.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* external integrations)
|
|
4
|
+
* Originally extracted from the former `src/tui/client.ts` so that headless
|
|
5
|
+
* consumers (CLI, tests, external integrations) could depend on the interface
|
|
6
|
+
* without pulling in Ink/React. (The Ink TUI was deleted in #789; the interface
|
|
7
|
+
* remains the shared contract for the CLI, daemon, command-center board, and
|
|
8
|
+
* external integrations.)
|
|
6
9
|
*/
|
|
7
10
|
import type { AgentType, MaestroPlayerInfo, MaestroRelayMessage, HistoryEntry, Message, SentMessage, SessionMetadata, ScheduleEntry, QualityGate, StageEntry, WorktreeEntry, EnsembleChatResult, AttachmentInfo, HostInfo, AnswerEntry, CoatCheckEntry } from '../types';
|
|
8
11
|
import type { CoatCheckPutInput, CoatCheckPutResult, CoatCheckGetInput } from '../workflows/maestro-signals';
|
|
@@ -515,18 +518,6 @@ export interface TempoClientWithSpawn extends TempoClientCore {
|
|
|
515
518
|
* daemon, or other headless processes.
|
|
516
519
|
*/
|
|
517
520
|
createEnsemble(opts: CreateEnsembleOpts): Promise<void>;
|
|
518
|
-
/**
|
|
519
|
-
* Spawn a conductor terminal for an existing ensemble — the restore-
|
|
520
|
-
* after-shutdown path. Shells out to `agent-tempo up <name>` which is
|
|
521
|
-
* idempotent at the workflow layer. Semantically distinct from
|
|
522
|
-
* {@link TempoClientWithSpawn.createEnsemble}: this fires on an ensemble
|
|
523
|
-
* that already exists; a "create" contradiction would mislead future
|
|
524
|
-
* readers. **Requires a TTY context.**
|
|
525
|
-
*/
|
|
526
|
-
spawnConductor(opts: {
|
|
527
|
-
ensemble: string;
|
|
528
|
-
workDir?: string;
|
|
529
|
-
}): Promise<void>;
|
|
530
521
|
}
|
|
531
522
|
/**
|
|
532
523
|
* Backwards-compatible alias preserved indefinitely (per ADR 0007's
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
* no TTY and a stray spawn would launch a terminal nothing can render.
|
|
8
8
|
*
|
|
9
9
|
* The boundary is enforced by the type system: headless callers depend on
|
|
10
|
-
* `TempoClientCore`;
|
|
11
|
-
*
|
|
10
|
+
* `TempoClientCore`; the spawn surface is opt-in.
|
|
11
|
+
*
|
|
12
|
+
* NOTE (#789): `spawnConductor` was removed with the Ink TUI (its only caller
|
|
13
|
+
* was the TUI's `ensure-conductor-spawned` helper). WithSpawn's only distinct
|
|
14
|
+
* method is now `createEnsemble` — still live (CLI `up`, command-center board).
|
|
15
|
+
* The Core-vs-WithSpawn split STAYS (WithSpawn is the universal client alias).
|
|
12
16
|
*
|
|
13
17
|
* See `docs/adr/0007-tempoclient-core-withspawn-split.md`.
|
|
14
18
|
*/
|
|
@@ -18,8 +22,9 @@ import type { TempoClientWithSpawn } from './interface';
|
|
|
18
22
|
export type { CreateTempoClientOpts } from './core';
|
|
19
23
|
/**
|
|
20
24
|
* Build a `TempoClientWithSpawn` over a configured Temporal `Client`.
|
|
21
|
-
* Composes {@link createTempoClientCore} and adds the
|
|
22
|
-
* spawn
|
|
25
|
+
* Composes {@link createTempoClientCore} and adds the TTY-bound
|
|
26
|
+
* `createEnsemble` spawn method. Use this for spawn-capable consumers (the CLI
|
|
27
|
+
* `up` path, the command-center board's `/ensemble-up`); pure-headless callers
|
|
23
28
|
* should use {@link createTempoClientCore} directly.
|
|
24
29
|
*
|
|
25
30
|
* `opts` (e.g. `subscribeDeps`) is forwarded to the Core factory.
|
|
@@ -59,8 +59,9 @@ async function runTempoCli(args, workDir) {
|
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Build a `TempoClientWithSpawn` over a configured Temporal `Client`.
|
|
62
|
-
* Composes {@link createTempoClientCore} and adds the
|
|
63
|
-
* spawn
|
|
62
|
+
* Composes {@link createTempoClientCore} and adds the TTY-bound
|
|
63
|
+
* `createEnsemble` spawn method. Use this for spawn-capable consumers (the CLI
|
|
64
|
+
* `up` path, the command-center board's `/ensemble-up`); pure-headless callers
|
|
64
65
|
* should use {@link createTempoClientCore} directly.
|
|
65
66
|
*
|
|
66
67
|
* `opts` (e.g. `subscribeDeps`) is forwarded to the Core factory.
|
|
@@ -75,13 +76,9 @@ function createTempoClientWithSpawn(client, opts = {}) {
|
|
|
75
76
|
: ['up', opts.ensemble];
|
|
76
77
|
await runTempoCli(args, opts.workDir);
|
|
77
78
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// `createEnsemble` so call sites read as "make sure the conductor
|
|
83
|
-
// terminal is running", not "create a new ensemble".
|
|
84
|
-
await runTempoCli(['up', opts.ensemble], opts.workDir);
|
|
85
|
-
},
|
|
79
|
+
// #789: `spawnConductor` removed with the Ink TUI — its only caller was the
|
|
80
|
+
// TUI's `ensure-conductor-spawned` helper (also deleted). WithSpawn's only
|
|
81
|
+
// distinct method is now `createEnsemble` (still used by the command-center
|
|
82
|
+
// board's `/ensemble-up` + the CLI `up` path).
|
|
86
83
|
};
|
|
87
84
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -257,19 +257,6 @@ export interface PersistedConfig {
|
|
|
257
257
|
temporalTlsKeyPath?: string;
|
|
258
258
|
defaultAgent?: AgentType;
|
|
259
259
|
claudeBin?: string;
|
|
260
|
-
/**
|
|
261
|
-
* Bearer token for the daemon's HTTP/SSE event source (#94, #95,
|
|
262
|
-
* SSE-PROTOCOL.md §3.1). Auto-generated on first daemon boot when
|
|
263
|
-
* bearer mode is required (`AGENT_TEMPO_HTTP_BIND` non-loopback OR
|
|
264
|
-
* a request with a non-loopback `Origin`) and no token is set:
|
|
265
|
-
* `crypto.randomBytes(32).toString('base64url')`, 0600 on POSIX.
|
|
266
|
-
* Rotation = delete this field; next daemon boot regenerates.
|
|
267
|
-
*
|
|
268
|
-
* 3e: this LEGACY single token is migrated to the READ tier (T1) — a daemon
|
|
269
|
-
* with only `httpToken` set keeps read access and emits a one-time startup
|
|
270
|
-
* warning to set an admin token for writes/gate/inner. Prefer `readToken`.
|
|
271
|
-
*/
|
|
272
|
-
httpToken?: string;
|
|
273
260
|
/**
|
|
274
261
|
* 3e RBAC — the READ-tier (T1) bearer token. Env `AGENT_TEMPO_HTTP_READ_TOKEN`
|
|
275
262
|
* takes precedence over this; auto-generated here on first bearer-mode boot if
|
package/dist/constants.d.ts
CHANGED
|
@@ -16,6 +16,28 @@
|
|
|
16
16
|
* for the kill regex to match.
|
|
17
17
|
*/
|
|
18
18
|
export declare const ENSEMBLE_SENTINEL_FLAG = "--remote-control-session-name-prefix";
|
|
19
|
+
/**
|
|
20
|
+
* 2.0 wire-protocol version (#786 — the cutover keystone). Single source of truth
|
|
21
|
+
* for the protocol stamp, the boot guard, and the `claimAttachment` adapter
|
|
22
|
+
* handshake.
|
|
23
|
+
*
|
|
24
|
+
* - **Stamp:** every 2.0-created workflow records `protocol: PROTOCOL_VERSION` on
|
|
25
|
+
* its START input (so it's in history from run 1 and survives `continueAsNew`
|
|
26
|
+
* via the input spread) and upserts the memo key {@link
|
|
27
|
+
* MEMO_KEYS.protocol | `AgentTempoProtocol`} = PROTOCOL_VERSION.
|
|
28
|
+
* - **Boot guard:** a 2.0 daemon refuses to register workers if visibility shows
|
|
29
|
+
* any Running agent-tempo workflow lacking the stamp — a 2.0 worker can never
|
|
30
|
+
* deterministically replay a 1.x-recorded history, so we fail LOUD at boot
|
|
31
|
+
* (printing `agent-tempo upgrade-to-2`) instead of non-determinism-faulting
|
|
32
|
+
* deep in a workflow task later.
|
|
33
|
+
* - **claimAttachment:** the adapter sends `protocolVersion`; a 2.0 workflow
|
|
34
|
+
* rejects any value `!== PROTOCOL_VERSION` (incl. a v1 adapter that omits it).
|
|
35
|
+
*
|
|
36
|
+
* This module is runtime-free, so the constant is safe to import from BOTH the
|
|
37
|
+
* sandboxed workflow bundle (the stamp + claim validator) AND the daemon guard /
|
|
38
|
+
* CLI (the check). Bumping it is a hard cutover — see `docs/design/v2-scoping.md`.
|
|
39
|
+
*/
|
|
40
|
+
export declare const PROTOCOL_VERSION: 2;
|
|
19
41
|
/**
|
|
20
42
|
* Escape the two regex metacharacters that can appear in validated player/ensemble
|
|
21
43
|
* names (which are constrained to `[A-Za-z0-9._-]+`). Safe to interpolate the
|
package/dist/constants.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* code without dragging Node-only modules into the sandboxed bundle.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.ENSEMBLE_SENTINEL_FLAG = void 0;
|
|
9
|
+
exports.PROTOCOL_VERSION = exports.ENSEMBLE_SENTINEL_FLAG = void 0;
|
|
10
10
|
exports.escapeNameForRegex = escapeNameForRegex;
|
|
11
11
|
exports.ensembleReadyBanner = ensembleReadyBanner;
|
|
12
12
|
exports.ensembleReadyDirective = ensembleReadyDirective;
|
|
@@ -22,6 +22,28 @@ exports.ensembleReadyDirective = ensembleReadyDirective;
|
|
|
22
22
|
* for the kill regex to match.
|
|
23
23
|
*/
|
|
24
24
|
exports.ENSEMBLE_SENTINEL_FLAG = '--remote-control-session-name-prefix';
|
|
25
|
+
/**
|
|
26
|
+
* 2.0 wire-protocol version (#786 — the cutover keystone). Single source of truth
|
|
27
|
+
* for the protocol stamp, the boot guard, and the `claimAttachment` adapter
|
|
28
|
+
* handshake.
|
|
29
|
+
*
|
|
30
|
+
* - **Stamp:** every 2.0-created workflow records `protocol: PROTOCOL_VERSION` on
|
|
31
|
+
* its START input (so it's in history from run 1 and survives `continueAsNew`
|
|
32
|
+
* via the input spread) and upserts the memo key {@link
|
|
33
|
+
* MEMO_KEYS.protocol | `AgentTempoProtocol`} = PROTOCOL_VERSION.
|
|
34
|
+
* - **Boot guard:** a 2.0 daemon refuses to register workers if visibility shows
|
|
35
|
+
* any Running agent-tempo workflow lacking the stamp — a 2.0 worker can never
|
|
36
|
+
* deterministically replay a 1.x-recorded history, so we fail LOUD at boot
|
|
37
|
+
* (printing `agent-tempo upgrade-to-2`) instead of non-determinism-faulting
|
|
38
|
+
* deep in a workflow task later.
|
|
39
|
+
* - **claimAttachment:** the adapter sends `protocolVersion`; a 2.0 workflow
|
|
40
|
+
* rejects any value `!== PROTOCOL_VERSION` (incl. a v1 adapter that omits it).
|
|
41
|
+
*
|
|
42
|
+
* This module is runtime-free, so the constant is safe to import from BOTH the
|
|
43
|
+
* sandboxed workflow bundle (the stamp + claim validator) AND the daemon guard /
|
|
44
|
+
* CLI (the check). Bumping it is a hard cutover — see `docs/design/v2-scoping.md`.
|
|
45
|
+
*/
|
|
46
|
+
exports.PROTOCOL_VERSION = 2;
|
|
25
47
|
/**
|
|
26
48
|
* Escape the two regex metacharacters that can appear in validated player/ensemble
|
|
27
49
|
* names (which are constrained to `[A-Za-z0-9._-]+`). Safe to interpolate the
|
package/dist/daemon.js
CHANGED
|
@@ -952,6 +952,58 @@ async function main() {
|
|
|
952
952
|
log('search-attribute preflight probe failed (non-fatal — createWorkers will surface the real error):', result.probeError);
|
|
953
953
|
}
|
|
954
954
|
}
|
|
955
|
+
// #786 — 2.0 cutover BOOT GUARD. Runs AFTER the search-attribute preflight
|
|
956
|
+
// and BEFORE createWorkers(): a 2.0 worker cannot deterministically replay a
|
|
957
|
+
// 1.x-recorded history, so refuse to register workers if visibility still
|
|
958
|
+
// shows ANY Running agent-tempo workflow lacking the protocol-2 stamp (a
|
|
959
|
+
// pre-cutover 1.x run). FAIL-CLOSED — a timed-out/errored scan, or a failure
|
|
960
|
+
// to even run the scan, refuses too (we couldn't PROVE the cutover is clean;
|
|
961
|
+
// see the #845 partial-scan lesson). Namespace-scoped via the client below.
|
|
962
|
+
// See src/upgrade/boot-guard.ts.
|
|
963
|
+
{
|
|
964
|
+
const { checkProtocolGuard } = await Promise.resolve().then(() => __importStar(require('./upgrade/boot-guard')));
|
|
965
|
+
let result;
|
|
966
|
+
let guardConn = null;
|
|
967
|
+
try {
|
|
968
|
+
guardConn = await (0, connection_1.createTemporalConnection)(config);
|
|
969
|
+
const guardClient = new client_1.Client({
|
|
970
|
+
connection: guardConn,
|
|
971
|
+
namespace: config.temporalNamespace,
|
|
972
|
+
interceptors: (0, action_counters_1.actionCountingInterceptors)(),
|
|
973
|
+
});
|
|
974
|
+
result = await checkProtocolGuard(guardClient, { log });
|
|
975
|
+
}
|
|
976
|
+
catch (err) {
|
|
977
|
+
// FAIL-CLOSED — couldn't even run the scan (e.g. connection failure).
|
|
978
|
+
// Without a completed scan we can't prove a clean cutover, so refuse
|
|
979
|
+
// rather than risk a 2.0 worker replaying a 1.x history.
|
|
980
|
+
result = {
|
|
981
|
+
ok: false,
|
|
982
|
+
reason: 'scan-incomplete',
|
|
983
|
+
message: `agent-tempo 2.0 boot guard could not run the protocol scan ` +
|
|
984
|
+
`(${err instanceof Error ? err.message : String(err)}). Refusing to boot ` +
|
|
985
|
+
`(fail-closed). Verify Temporal at ${config.temporalAddress} ` +
|
|
986
|
+
`(namespace ${config.temporalNamespace}) is reachable, then retry.`,
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
finally {
|
|
990
|
+
if (guardConn)
|
|
991
|
+
await guardConn.close().catch(() => { });
|
|
992
|
+
}
|
|
993
|
+
if (!result.ok) {
|
|
994
|
+
process.stderr.write('ERROR: ' + result.message + '\n');
|
|
995
|
+
log(`Daemon refused to boot — ${result.reason} (#786 protocol guard)`);
|
|
996
|
+
try {
|
|
997
|
+
fs.unlinkSync(daemon_1.DAEMON_PID_PATH);
|
|
998
|
+
}
|
|
999
|
+
catch { /* ignore */ }
|
|
1000
|
+
try {
|
|
1001
|
+
fs.unlinkSync(daemon_1.DAEMON_HEARTBEAT_PATH);
|
|
1002
|
+
}
|
|
1003
|
+
catch { /* ignore */ }
|
|
1004
|
+
process.exit(1);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
955
1007
|
// Use mutable refs so signal handlers can be registered before workers
|
|
956
1008
|
// are created — closes the narrow window where a SIGTERM during
|
|
957
1009
|
// createWorkers() would be missed.
|