Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 1 addition & 25 deletions packages/coding-agent/src/sdk/bus/telegram-daemon-cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from "node:fs";
import * as path from "node:path";
import { logger, postmortem } from "@gajae-code/utils";
import { logger } from "@gajae-code/utils";
import { YAML } from "bun";
import { applyAtomicYamlPatches, setByPath } from "../../config/atomic-yaml-patch";
import type { Settings } from "../../config/settings";
Expand All @@ -16,7 +16,6 @@ import {
type DaemonState,
FilesystemTopicRegistryCasAuthority,
loadInstallationHostId,
markDaemonOwnerStopped,
readDaemonState,
readOwnerFreshnessSnapshot,
type TelegramDaemonOptions,
Expand Down Expand Up @@ -306,35 +305,12 @@ export async function runDaemonInternal(argv: string[], deps: RunDaemonInternalD
const watchdog = schedule(() => void watchdogTick(), OWNER_WATCHDOG_INTERVAL_MS);
process.once("SIGTERM", onSignal);
process.once("SIGINT", onSignal);
// The daemon releases ownership only after a fully quiesced, fully persisted
// shutdown. Every other ending - a failed final persist, a signal, an
// uncaught error inside a detached async chain - used to leave
// `ownershipPhase: "ready"` on disk for a process that no longer exists, and
// later readers attached to it. Observed in the field: a daemon wrote one
// heartbeat 559 ms after readiness, died on an uncaught topic-registry
// error, and was still advertising itself as ready eight hours later.
//
// `finally` covers a returning or throwing run(); the postmortem hook covers
// the fatal paths that call `process.exit()` without unwinding this frame.
const recordOwnerStopped = (): Promise<boolean> =>
markDaemonOwnerStopped({
settings: settings as Settings,
ownerId,
acquisitionId: ownerId,
pid: deps.processPid ?? process.pid,
now: deps.now,
});
const unregisterPostmortem = postmortem.register("telegram-daemon:owner-state", async () => {
await recordOwnerStopped();
});
try {
await daemon.run();
} finally {
watchdogActive = false;
unschedule(watchdog);
process.off("SIGTERM", onSignal);
process.off("SIGINT", onSignal);
unregisterPostmortem();
await recordOwnerStopped();
}
}
16 changes: 2 additions & 14 deletions packages/coding-agent/src/sdk/bus/telegram-daemon-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,9 @@ export const NOTIFICATION_PROTOCOL_VERSION = 3;
* final-component file symlinks fail-closed under AT_SYMLINK_NOFOLLOW (bounded
* #3761 multi-account activation repair). Generation 51 adds shared durable
* topic authority, archive recovery, and requires Telegram's documented error
* code for idempotent archive settlement. Generation 52 is claimed by the
* pre-readiness daemon-child exit diagnostics slice (#3761). Generation 53
* renders multi-select state for ask-tool asks, not only durable workflow
* gates, and renumbers pre-numbered options exactly once around the selection
* marker. Generation 54 records owner `stoppedAt` on unclean daemon death
* (`markDaemonOwnerStopped` + postmortem/finally wiring) so a dead process
* cannot keep advertising itself as the ready owner (#3965). Generation 55
* contains a shared-topic-authority outage: a failed lease renewal on the
* liveness heartbeat and a failed startup registry load are reported instead
* of escaping to the process-level fatal handler, authority-failure throws
* preserve their underlying cause, and the compensation fence retry is bounded.
* Generation 56 moves exact unlink and process-incarnation authority behind
* lazy native bindings for the startup-cost cut (#3846).
* code for idempotent archive settlement.
*/
export const DAEMON_GENERATION = 56;
export const DAEMON_GENERATION = 52;

/**
* Serving-compatibility boundary for daemon lifecycle requests. Epoch 5
Expand Down
Loading
Loading