agent-yes 1.224.1 → 1.225.0

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 (32) hide show
  1. package/dist/SUPPORTED_CLIS-ldWdY2jy.js +11 -0
  2. package/dist/{SUPPORTED_CLIS-DThRslpE.js → SUPPORTED_CLIS-nDMA0vtp.js} +2 -2
  3. package/dist/{agentShare-CX0Yx0xV.js → agentShare-BLl0-SpO.js} +2 -2
  4. package/dist/{callback-CvMtnvHj.js → callback-CCZfvMHZ.js} +3 -3
  5. package/dist/{callback-BS1sVPyI.js → callback-CuWuj9gy.js} +2 -2
  6. package/dist/cli.js +4 -4
  7. package/dist/index.js +5 -5
  8. package/dist/{notifyDaemon-Bn0fdB-q.js → notifyDaemon-DF7_EjVu.js} +2 -2
  9. package/dist/{rustBinary-Dt7076RL.js → rustBinary-DsKB37nM.js} +2 -2
  10. package/dist/{schedule-CibcxLts.js → schedule-KFStEXIX.js} +5 -5
  11. package/dist/{serve-BeChfwBV.js → serve-BBrh1z4b.js} +14 -14
  12. package/dist/{setup-MPt6wg7U.js → setup-DvP49xV5.js} +2 -2
  13. package/dist/{subcommands-DXRmodQq.js → subcommands-DMoKYWpB.js} +1 -1
  14. package/dist/{subcommands-DHC1a4y2.js → subcommands-T3C9EhOr.js} +9 -9
  15. package/dist/{todoBlock-C5wUhsSH.js → todoAutomation-fxtfT_44.js} +149 -3
  16. package/dist/{todoCli-BdJaiX1x.js → todoCli-dk8WNgcS.js} +42 -6
  17. package/dist/{todoDigest-DaEklQg1.js → todoDigest-DSTG9ksk.js} +11 -2
  18. package/dist/todoDigest-gKP1XibO.js +3 -0
  19. package/dist/{ts-QB4DPAk_.js → ts-BPtf-Tpg.js} +2 -2
  20. package/dist/{versionChecker-C_CrMn4v.js → versionChecker-defO9ozI.js} +2 -2
  21. package/dist/{ws-BYkQq5aZ.js → ws-DLkxWjt9.js} +2 -2
  22. package/package.json +1 -1
  23. package/ts/index.ts +4 -0
  24. package/ts/todoAutomation.spec.ts +189 -0
  25. package/ts/todoAutomation.ts +138 -0
  26. package/ts/todoCli.spec.ts +82 -1
  27. package/ts/todoCli.ts +74 -1
  28. package/ts/todoLifecycle.ts +10 -0
  29. package/ts/todoStore.spec.ts +61 -1
  30. package/ts/todoStore.ts +62 -0
  31. package/dist/SUPPORTED_CLIS-CRNfIM9q.js +0 -11
  32. package/dist/todoDigest-CAi1HHla.js +0 -3
@@ -0,0 +1,11 @@
1
+ import "./ts-BPtf-Tpg.js";
2
+ import "./logger-CDIsZ-Pp.js";
3
+ import "./versionChecker-defO9ozI.js";
4
+ import "./JsonlStore-Bm5Nj6v_.js";
5
+ import "./globalPidIndex-CoNr7tS8.js";
6
+ import "./pidStore-DCqpU_bI.js";
7
+ import "./messageLog-Bb_Ie3Ck.js";
8
+ import "./todoAutomation-fxtfT_44.js";
9
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-nDMA0vtp.js";
10
+
11
+ export { SUPPORTED_CLIS };
@@ -1,8 +1,8 @@
1
- import { t as CLIS_CONFIG } from "./ts-QB4DPAk_.js";
1
+ import { t as CLIS_CONFIG } from "./ts-BPtf-Tpg.js";
2
2
 
3
3
  //#region ts/SUPPORTED_CLIS.ts
4
4
  const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
5
5
 
6
6
  //#endregion
7
7
  export { SUPPORTED_CLIS as t };
8
- //# sourceMappingURL=SUPPORTED_CLIS-DThRslpE.js.map
8
+ //# sourceMappingURL=SUPPORTED_CLIS-nDMA0vtp.js.map
@@ -2,7 +2,7 @@ import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./messageLog-Bb_Ie3Ck.js";
4
4
  import "./configShared-nnIwDYY-.js";
5
- import { M as resolveOne } from "./subcommands-DHC1a4y2.js";
5
+ import { M as resolveOne } from "./subcommands-T3C9EhOr.js";
6
6
  import "./e2e-D5jaSHyY.js";
7
7
  import "./webrtcLink-DknpJQ0y.js";
8
8
  import "./remotes-D-jPl9Fj.js";
@@ -229,4 +229,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
229
229
 
230
230
  //#endregion
231
231
  export { createScopedShare, listShares, revokeAllShares, revokeShare };
232
- //# sourceMappingURL=agentShare-CX0Yx0xV.js.map
232
+ //# sourceMappingURL=agentShare-BLl0-SpO.js.map
@@ -1,5 +1,5 @@
1
1
  import { t as agentYesHome } from "./agentYesHome-CtHb5b71.js";
2
- import { M as resolveOne } from "./subcommands-DHC1a4y2.js";
2
+ import { M as resolveOne } from "./subcommands-T3C9EhOr.js";
3
3
  import { a as mintCapability, o as parseExpires } from "./callbackCore-CgnOT1Cp.js";
4
4
  import { randomBytes } from "node:crypto";
5
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
@@ -72,7 +72,7 @@ async function resolveBase(flag) {
72
72
  if (flag) return flag;
73
73
  if (process.env.AGENT_YES_CALLBACK_BASE) return process.env.AGENT_YES_CALLBACK_BASE;
74
74
  try {
75
- const { resolveLocalServeUrl } = await import("./serve-BeChfwBV.js");
75
+ const { resolveLocalServeUrl } = await import("./serve-BBrh1z4b.js");
76
76
  const url = await resolveLocalServeUrl();
77
77
  if (url) return url;
78
78
  } catch {}
@@ -187,4 +187,4 @@ async function cmdCallback(rest) {
187
187
 
188
188
  //#endregion
189
189
  export { loadOrCreateCallbackSecret as i, isCallbackRevoked as n, loadCallbackSecretReadOnly as r, cmdCallback as t };
190
- //# sourceMappingURL=callback-CvMtnvHj.js.map
190
+ //# sourceMappingURL=callback-CCZfvMHZ.js.map
@@ -2,11 +2,11 @@ import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./messageLog-Bb_Ie3Ck.js";
4
4
  import "./configShared-nnIwDYY-.js";
5
- import "./subcommands-DHC1a4y2.js";
5
+ import "./subcommands-T3C9EhOr.js";
6
6
  import "./e2e-D5jaSHyY.js";
7
7
  import "./webrtcLink-DknpJQ0y.js";
8
8
  import "./remotes-D-jPl9Fj.js";
9
9
  import "./callbackCore-CgnOT1Cp.js";
10
- import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-CvMtnvHj.js";
10
+ import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-CCZfvMHZ.js";
11
11
 
12
12
  export { cmdCallback };
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import { t as invokedCliName } from "./invokedCli-uqM2YYA7.js";
3
3
  import { n as logger } from "./logger-CDIsZ-Pp.js";
4
- import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-C_CrMn4v.js";
5
- import { n as getRustBinary } from "./rustBinary-Dt7076RL.js";
4
+ import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-defO9ozI.js";
5
+ import { n as getRustBinary } from "./rustBinary-DsKB37nM.js";
6
6
  import { argv } from "process";
7
7
  import { spawn } from "child_process";
8
8
  import ms from "ms";
@@ -285,7 +285,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
285
285
  const rawArg = process.argv[2];
286
286
  const managerCommands = !invokedCliName(process.argv);
287
287
  const isHelpFlag = rawArg === "-h" || rawArg === "--help";
288
- const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-DXRmodQq.js");
288
+ const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-DMoKYWpB.js");
289
289
  if (isHelpFlag && process.argv.length === 3) {
290
290
  await cmdHelp(managerCommands);
291
291
  process.exit(0);
@@ -327,7 +327,7 @@ if (config.useRust) {
327
327
  }
328
328
  }
329
329
  if (rustBinary) {
330
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-CRNfIM9q.js");
330
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-ldWdY2jy.js");
331
331
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
332
332
  if (config.verbose) {
333
333
  console.log(`[rust] Using binary: ${rustBinary}`);
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { i as AgentContext, n as agentYes, o as removeControlCharacters, r as config, t as CLIS_CONFIG } from "./ts-QB4DPAk_.js";
1
+ import { i as AgentContext, n as agentYes, o as removeControlCharacters, r as config, t as CLIS_CONFIG } from "./ts-BPtf-Tpg.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-C_CrMn4v.js";
3
+ import "./versionChecker-defO9ozI.js";
4
4
  import "./JsonlStore-Bm5Nj6v_.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
6
  import "./pidStore-DCqpU_bI.js";
7
7
  import "./messageLog-Bb_Ie3Ck.js";
8
- import { a as unblockedTasks, c as canTransition, d as nextStates, f as requiredGate, i as renderTree, l as initialState, n as openBlockers, p as statesOf, r as renderDigest, s as LIFECYCLES, u as isKnownKind } from "./todoDigest-DaEklQg1.js";
9
- import { a as openStore, i as TodoStore, n as monitorHint, r as CycleError, t as describeBlock } from "./todoBlock-C5wUhsSH.js";
8
+ import { a as unblockedTasks, c as ORPHANED_STATE, d as isKnownKind, f as nextStates, i as renderTree, l as canTransition, m as statesOf, n as openBlockers, o as DONE_STATE, p as requiredGate, r as renderDigest, s as LIFECYCLES, u as initialState } from "./todoDigest-DSTG9ksk.js";
9
+ import { a as TodoStore, i as CycleError, n as describeBlock, o as openStore, r as monitorHint, t as reconcileTodos } from "./todoAutomation-fxtfT_44.js";
10
10
 
11
- export { AgentContext, CLIS_CONFIG, CycleError, LIFECYCLES, TodoStore, canTransition, config, agentYes as default, describeBlock, initialState, isKnownKind, monitorHint, nextStates, openBlockers, openStore, removeControlCharacters, renderDigest, renderTree, requiredGate, statesOf, unblockedTasks };
11
+ export { AgentContext, CLIS_CONFIG, CycleError, DONE_STATE, LIFECYCLES, ORPHANED_STATE, TodoStore, canTransition, config, agentYes as default, describeBlock, initialState, isKnownKind, monitorHint, nextStates, openBlockers, openStore, reconcileTodos, removeControlCharacters, renderDigest, renderTree, requiredGate, statesOf, unblockedTasks };
@@ -2,7 +2,7 @@ import { n as logger } from "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./messageLog-Bb_Ie3Ck.js";
4
4
  import "./configShared-nnIwDYY-.js";
5
- import { $ as daemonLockOwnerPath, G as gcInboxes, J as listInboxParents, K as hostId, Q as daemonLockDir, S as listRecords, W as appendEvent, X as readInbox, Y as liveWatchers, Z as shouldStealLock, _ as isPidAlive, c as deriveLiveState, et as notifyDir, k as renderLogTailLines } from "./subcommands-DHC1a4y2.js";
5
+ import { $ as daemonLockOwnerPath, G as gcInboxes, J as listInboxParents, K as hostId, Q as daemonLockDir, S as listRecords, W as appendEvent, X as readInbox, Y as liveWatchers, Z as shouldStealLock, _ as isPidAlive, c as deriveLiveState, et as notifyDir, k as renderLogTailLines } from "./subcommands-T3C9EhOr.js";
6
6
  import "./e2e-D5jaSHyY.js";
7
7
  import "./webrtcLink-DknpJQ0y.js";
8
8
  import "./remotes-D-jPl9Fj.js";
@@ -589,4 +589,4 @@ async function ensureDaemon() {
589
589
 
590
590
  //#endregion
591
591
  export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
592
- //# sourceMappingURL=notifyDaemon-Bn0fdB-q.js.map
592
+ //# sourceMappingURL=notifyDaemon-DF7_EjVu.js.map
@@ -1,4 +1,4 @@
1
- import { r as getInstalledPackage } from "./versionChecker-C_CrMn4v.js";
1
+ import { r as getInstalledPackage } from "./versionChecker-defO9ozI.js";
2
2
  import { execFileSync } from "child_process";
3
3
  import { existsSync, mkdirSync, unlinkSync } from "fs";
4
4
  import { chmod, copyFile } from "fs/promises";
@@ -225,4 +225,4 @@ async function getRustBinary(options = {}) {
225
225
 
226
226
  //#endregion
227
227
  export { getRustBinary as n, findSpawnHiddenLauncher as t };
228
- //# sourceMappingURL=rustBinary-Dt7076RL.js.map
228
+ //# sourceMappingURL=rustBinary-DsKB37nM.js.map
@@ -1,12 +1,12 @@
1
- import "./ts-QB4DPAk_.js";
1
+ import "./ts-BPtf-Tpg.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-C_CrMn4v.js";
3
+ import "./versionChecker-defO9ozI.js";
4
4
  import "./JsonlStore-Bm5Nj6v_.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
6
  import "./pidStore-DCqpU_bI.js";
7
7
  import "./messageLog-Bb_Ie3Ck.js";
8
- import "./todoBlock-C5wUhsSH.js";
9
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DThRslpE.js";
8
+ import "./todoAutomation-fxtfT_44.js";
9
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-nDMA0vtp.js";
10
10
  import { d as resolveSpawnCwd } from "./workspaceConfig-dHHBQh0F.js";
11
11
  import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-DoBOoeUW.js";
12
12
  import { createHash } from "node:crypto";
@@ -153,4 +153,4 @@ async function cmdSchedule(rest) {
153
153
 
154
154
  //#endregion
155
155
  export { cmdSchedule };
156
- //# sourceMappingURL=schedule-CibcxLts.js.map
156
+ //# sourceMappingURL=schedule-KFStEXIX.js.map
@@ -1,22 +1,22 @@
1
- import { a as CLAUDE_SESSION_PIN_ENV } from "./ts-QB4DPAk_.js";
1
+ import { a as CLAUDE_SESSION_PIN_ENV } from "./ts-BPtf-Tpg.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import { r as getInstalledPackage } from "./versionChecker-C_CrMn4v.js";
4
- import { t as findSpawnHiddenLauncher } from "./rustBinary-Dt7076RL.js";
3
+ import { r as getInstalledPackage } from "./versionChecker-defO9ozI.js";
4
+ import { t as findSpawnHiddenLauncher } from "./rustBinary-DsKB37nM.js";
5
5
  import { t as agentYesHome$1 } from "./agentYesHome-CtHb5b71.js";
6
6
  import "./JsonlStore-Bm5Nj6v_.js";
7
7
  import { a as updateGlobalPidStatus } from "./globalPidIndex-CoNr7tS8.js";
8
8
  import "./pidStore-DCqpU_bI.js";
9
9
  import { r as recordInbox } from "./messageLog-Bb_Ie3Ck.js";
10
10
  import { t as pgidForWrapper } from "./reaper-BNKvujYy.js";
11
- import "./todoBlock-C5wUhsSH.js";
11
+ import "./todoAutomation-fxtfT_44.js";
12
12
  import "./configShared-nnIwDYY-.js";
13
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DThRslpE.js";
14
- import { A as renderRawLog, D as recentMessageEdges, E as readPtysize, L as snapshotStatus, M as resolveOne, O as recentReadEdges, S as listRecords, T as readNotes, U as writeToIpc, b as isUserTyping, f as extractNeedsInput, j as renderRawLogLines, k as renderLogTailLines, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, q as isTransientLockMkdirError, tt as TYPING_BADGE, u as extractBadges } from "./subcommands-DHC1a4y2.js";
13
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-nDMA0vtp.js";
14
+ import { A as renderRawLog, D as recentMessageEdges, E as readPtysize, L as snapshotStatus, M as resolveOne, O as recentReadEdges, S as listRecords, T as readNotes, U as writeToIpc, b as isUserTyping, f as extractNeedsInput, j as renderRawLogLines, k as renderLogTailLines, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, q as isTransientLockMkdirError, tt as TYPING_BADGE, u as extractBadges } from "./subcommands-T3C9EhOr.js";
15
15
  import "./e2e-D5jaSHyY.js";
16
16
  import "./webrtcLink-DknpJQ0y.js";
17
17
  import "./remotes-D-jPl9Fj.js";
18
18
  import { i as frameVisitorMessage, s as verifyCapability, t as MAX_CALLBACK_MSG_BYTES } from "./callbackCore-CgnOT1Cp.js";
19
- import { n as isCallbackRevoked, r as loadCallbackSecretReadOnly } from "./callback-CvMtnvHj.js";
19
+ import { n as isCallbackRevoked, r as loadCallbackSecretReadOnly } from "./callback-CCZfvMHZ.js";
20
20
  import { a as getSpawnHook, c as hasProvisionHook, d as resolveSpawnCwd, i as getProvisionRoot, l as hasSpawnHook, r as getProvisionHook, u as isProvisionAllowed } from "./workspaceConfig-dHHBQh0F.js";
21
21
  import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-DoBOoeUW.js";
22
22
  import { r as spawnRejectionReason } from "./spawnGate-Vmd1d9OQ.js";
@@ -1992,7 +1992,7 @@ Options:
1992
1992
  }
1993
1993
  });
1994
1994
  if (req.method === "GET" && p === "/api/ws") {
1995
- const ws = await import("./ws-BYkQq5aZ.js");
1995
+ const ws = await import("./ws-DLkxWjt9.js");
1996
1996
  try {
1997
1997
  await ws.loadProvision();
1998
1998
  } catch (e) {
@@ -2012,7 +2012,7 @@ Options:
2012
2012
  if (req.method === "GET" && p === "/api/ws/status") {
2013
2013
  const dirRaw = url.searchParams.get("path");
2014
2014
  if (!dirRaw) return new Response("missing ?path=<workspace dir>", { status: 400 });
2015
- const ws = await import("./ws-BYkQq5aZ.js");
2015
+ const ws = await import("./ws-DLkxWjt9.js");
2016
2016
  let prov;
2017
2017
  try {
2018
2018
  prov = await ws.loadProvision();
@@ -2601,7 +2601,7 @@ Options:
2601
2601
  const perm = body.perm ?? "r";
2602
2602
  if (perm !== "r" && perm !== "rw") return new Response(`invalid perm ${perm} (want r or rw)`, { status: 400 });
2603
2603
  try {
2604
- const { createScopedShare } = await import("./agentShare-CX0Yx0xV.js");
2604
+ const { createScopedShare } = await import("./agentShare-BLl0-SpO.js");
2605
2605
  const share = await createScopedShare({
2606
2606
  agent: body.agent,
2607
2607
  perm,
@@ -2616,12 +2616,12 @@ Options:
2616
2616
  }
2617
2617
  }
2618
2618
  if (req.method === "GET" && p === "/api/shares") {
2619
- const { listShares } = await import("./agentShare-CX0Yx0xV.js");
2619
+ const { listShares } = await import("./agentShare-BLl0-SpO.js");
2620
2620
  return Response.json(listShares());
2621
2621
  }
2622
2622
  const revokeM = /^\/api\/share\/([^/]+)$/.exec(p);
2623
2623
  if (req.method === "DELETE" && revokeM) {
2624
- const { revokeShare } = await import("./agentShare-CX0Yx0xV.js");
2624
+ const { revokeShare } = await import("./agentShare-BLl0-SpO.js");
2625
2625
  const ok = revokeShare(decodeURIComponent(revokeM[1]));
2626
2626
  return new Response(ok ? "revoked" : "no such share", { status: ok ? 200 : 404 });
2627
2627
  }
@@ -2923,7 +2923,7 @@ Options:
2923
2923
  const shutdown = (resolve) => {
2924
2924
  if (heartbeat) clearInterval(heartbeat);
2925
2925
  closeShare?.();
2926
- import("./agentShare-CX0Yx0xV.js").then((m) => m.revokeAllShares()).catch(() => {});
2926
+ import("./agentShare-BLl0-SpO.js").then((m) => m.revokeAllShares()).catch(() => {});
2927
2927
  server?.stop();
2928
2928
  Promise.resolve(releaseHostLock?.()).catch(() => {}).then(resolve);
2929
2929
  };
@@ -2936,4 +2936,4 @@ Options:
2936
2936
 
2937
2937
  //#endregion
2938
2938
  export { cmdServe, resolveLocalServeUrl };
2939
- //# sourceMappingURL=serve-BeChfwBV.js.map
2939
+ //# sourceMappingURL=serve-BBrh1z4b.js.map
@@ -32,7 +32,7 @@ async function cmdSetup(rest) {
32
32
  if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
33
33
  if (noShare) return 0;
34
34
  process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
35
- const { cmdServe } = await import("./serve-BeChfwBV.js");
35
+ const { cmdServe } = await import("./serve-BBrh1z4b.js");
36
36
  return cmdServe([
37
37
  "install",
38
38
  "--share",
@@ -42,4 +42,4 @@ async function cmdSetup(rest) {
42
42
 
43
43
  //#endregion
44
44
  export { cmdSetup };
45
- //# sourceMappingURL=setup-MPt6wg7U.js.map
45
+ //# sourceMappingURL=setup-DvP49xV5.js.map
@@ -2,7 +2,7 @@ import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./messageLog-Bb_Ie3Ck.js";
4
4
  import "./configShared-nnIwDYY-.js";
5
- import { A as renderRawLog, B as submitAndConfirm, C as matchKeyword, D as recentMessageEdges, E as readPtysize, F as restartHintLines, H as writeKeysPaced, I as runSubcommand, L as snapshotStatus, M as resolveOne, N as resolveReadWindow, O as recentReadEdges, P as resolveResumeArgs, R as stdinActivityPath, S as listRecords, T as readNotes, U as writeToIpc, V as waitForLogQuiet, _ as isPidAlive, a as cmdHelp, b as isUserTyping, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as renderRawLogLines, k as renderLogTailLines, l as deriveLiveStatus, m as finalizedLines, n as READ_PAGE_DEFAULT, o as controlCodeFromName, p as extractTaskCounts, r as TYPING_WINDOW_MS, s as cursorAbs, t as GRACEFUL_EXIT_COMMANDS, u as extractBadges, v as isSlashCommand, w as menuSelectKeys, x as lastStdinAt, y as isSubcommand, z as stopTipForCli } from "./subcommands-DHC1a4y2.js";
5
+ import { A as renderRawLog, B as submitAndConfirm, C as matchKeyword, D as recentMessageEdges, E as readPtysize, F as restartHintLines, H as writeKeysPaced, I as runSubcommand, L as snapshotStatus, M as resolveOne, N as resolveReadWindow, O as recentReadEdges, P as resolveResumeArgs, R as stdinActivityPath, S as listRecords, T as readNotes, U as writeToIpc, V as waitForLogQuiet, _ as isPidAlive, a as cmdHelp, b as isUserTyping, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as renderRawLogLines, k as renderLogTailLines, l as deriveLiveStatus, m as finalizedLines, n as READ_PAGE_DEFAULT, o as controlCodeFromName, p as extractTaskCounts, r as TYPING_WINDOW_MS, s as cursorAbs, t as GRACEFUL_EXIT_COMMANDS, u as extractBadges, v as isSlashCommand, w as menuSelectKeys, x as lastStdinAt, y as isSubcommand, z as stopTipForCli } from "./subcommands-T3C9EhOr.js";
6
6
  import "./e2e-D5jaSHyY.js";
7
7
  import "./webrtcLink-DknpJQ0y.js";
8
8
  import "./remotes-D-jPl9Fj.js";
@@ -1239,23 +1239,23 @@ async function runSubcommand(argv) {
1239
1239
  case "restart": return await cmdRestart(rest);
1240
1240
  case "note": return await cmdNote(rest);
1241
1241
  case "todo": {
1242
- const { runTodoSubcommand } = await import("./todoCli-BdJaiX1x.js");
1242
+ const { runTodoSubcommand } = await import("./todoCli-dk8WNgcS.js");
1243
1243
  return runTodoSubcommand(rest);
1244
1244
  }
1245
1245
  case "serve": {
1246
- const { cmdServe } = await import("./serve-BeChfwBV.js");
1246
+ const { cmdServe } = await import("./serve-BBrh1z4b.js");
1247
1247
  return cmdServe(rest);
1248
1248
  }
1249
1249
  case "setup": {
1250
- const { cmdSetup } = await import("./setup-MPt6wg7U.js");
1250
+ const { cmdSetup } = await import("./setup-DvP49xV5.js");
1251
1251
  return cmdSetup(rest);
1252
1252
  }
1253
1253
  case "ws": {
1254
- const { cmdWs } = await import("./ws-BYkQq5aZ.js");
1254
+ const { cmdWs } = await import("./ws-DLkxWjt9.js");
1255
1255
  return cmdWs(rest);
1256
1256
  }
1257
1257
  case "schedule": {
1258
- const { cmdSchedule } = await import("./schedule-CibcxLts.js");
1258
+ const { cmdSchedule } = await import("./schedule-KFStEXIX.js");
1259
1259
  return cmdSchedule(rest);
1260
1260
  }
1261
1261
  case "remote": {
@@ -1267,7 +1267,7 @@ async function runSubcommand(argv) {
1267
1267
  return cmdExpose(rest);
1268
1268
  }
1269
1269
  case "callback": {
1270
- const { cmdCallback } = await import("./callback-BS1sVPyI.js");
1270
+ const { cmdCallback } = await import("./callback-CuWuj9gy.js");
1271
1271
  return cmdCallback(rest);
1272
1272
  }
1273
1273
  case "reap":
@@ -4279,7 +4279,7 @@ async function cmdNotify(rest) {
4279
4279
  }
4280
4280
  const ensure = async () => {
4281
4281
  if (!argv["ensure-daemon"]) return;
4282
- const { ensureDaemon } = await import("./notifyDaemon-Bn0fdB-q.js");
4282
+ const { ensureDaemon } = await import("./notifyDaemon-DF7_EjVu.js");
4283
4283
  await ensureDaemon().catch(() => null);
4284
4284
  };
4285
4285
  await heartbeatWatcher(parent, selfStartedAt);
@@ -4353,7 +4353,7 @@ async function cmdNotifyCursor(args) {
4353
4353
  }
4354
4354
  async function cmdNotifyd(rest) {
4355
4355
  const sub = rest[0] ?? "status";
4356
- const daemon = await import("./notifyDaemon-Bn0fdB-q.js");
4356
+ const daemon = await import("./notifyDaemon-DF7_EjVu.js");
4357
4357
  switch (sub) {
4358
4358
  case "run": return daemon.runDaemon();
4359
4359
  case "once": return daemon.runDaemon({ once: true });
@@ -4380,4 +4380,4 @@ async function cmdNotifyd(rest) {
4380
4380
 
4381
4381
  //#endregion
4382
4382
  export { daemonLockOwnerPath as $, renderRawLog as A, submitAndConfirm as B, matchKeyword as C, recentMessageEdges as D, readPtysize as E, restartHintLines as F, gcInboxes as G, writeKeysPaced as H, runSubcommand as I, listInboxParents as J, hostId as K, snapshotStatus as L, resolveOne as M, resolveReadWindow as N, recentReadEdges as O, resolveResumeArgs as P, daemonLockDir as Q, stdinActivityPath as R, listRecords as S, readNotes as T, writeToIpc as U, waitForLogQuiet as V, appendEvent as W, readInbox as X, liveWatchers as Y, shouldStealLock as Z, isPidAlive as _, cmdHelp as a, isUserTyping as b, deriveLiveState as c, extractMenu as d, notifyDir as et, extractNeedsInput as f, isExitRequest as g, isAgentStuck as h, backoffWhileTyping as i, renderRawLogLines as j, renderLogTailLines as k, deriveLiveStatus as l, finalizedLines as m, READ_PAGE_DEFAULT as n, controlCodeFromName as o, extractTaskCounts as p, isTransientLockMkdirError as q, TYPING_WINDOW_MS as r, cursorAbs as s, GRACEFUL_EXIT_COMMANDS as t, TYPING_BADGE as tt, extractBadges as u, isSlashCommand as v, menuSelectKeys as w, lastStdinAt as x, isSubcommand as y, stopTipForCli as z };
4383
- //# sourceMappingURL=subcommands-DHC1a4y2.js.map
4383
+ //# sourceMappingURL=subcommands-T3C9EhOr.js.map
@@ -1,5 +1,5 @@
1
1
  import { t as JsonlStore } from "./JsonlStore-Bm5Nj6v_.js";
2
- import { c as canTransition, f as requiredGate, l as initialState, o as DONE_STATE, s as LIFECYCLES } from "./todoDigest-DaEklQg1.js";
2
+ import { a as unblockedTasks, c as ORPHANED_STATE, l as canTransition, o as DONE_STATE, p as requiredGate, s as LIFECYCLES, u as initialState } from "./todoDigest-DSTG9ksk.js";
3
3
  import path from "path";
4
4
  import { lock } from "proper-lockfile";
5
5
 
@@ -134,6 +134,10 @@ var TodoStore = class TodoStore {
134
134
  isRegisteredGate(name) {
135
135
  return this.gates.has(name);
136
136
  }
137
+ /** All currently-registered gate names — used by `todoAutomation.ts` to find tasks eligible for an automatic `verify()` without exposing the internal gate map. */
138
+ registeredGateNames() {
139
+ return [...this.gates.keys()];
140
+ }
137
141
  all() {
138
142
  return this.jsonl.getAll();
139
143
  }
@@ -338,6 +342,46 @@ var TodoStore = class TodoStore {
338
342
  setBlock(id, block) {
339
343
  return this.rawUpdate(id, () => ({ block }));
340
344
  }
345
+ /**
346
+ * Clears a `waiting-on-agent` block ONLY if the FRESH record's block is
347
+ * still that exact type and `agentId` — used by automation
348
+ * (`todoAutomation.ts`'s `reconcile`), which decides from a snapshot that
349
+ * can be stale by the time this runs. Clearing unconditionally by `id`
350
+ * alone could erase a genuinely different, newer block (e.g. a manual
351
+ * `blocked-by-human` set after the decision was made) that happened to
352
+ * land in between (codex-review Important). Throws instead of silently
353
+ * no-op-ing so the caller can report the skip rather than claim success.
354
+ */
355
+ clearWaitingOnAgentBlock(id, expectedAgentId) {
356
+ return this.rawUpdate(id, (fresh) => {
357
+ if (fresh.block?.type !== "waiting-on-agent" || fresh.block.agentId !== expectedAgentId) throw new Error(`task ${id}: block changed since this was decided (expected waiting-on-agent for "${expectedAgentId}") — not clearing`);
358
+ return { block: null };
359
+ });
360
+ }
361
+ /**
362
+ * Side-channel transition to `orphaned` (see `ORPHANED_STATE`'s doc comment
363
+ * in `todoLifecycle.ts`) — deliberately NOT gated through `canTransition`,
364
+ * since no kind's graph declares an edge into it: this is automation
365
+ * (`todoAutomation.ts`) observing that the task's owner process is gone,
366
+ * not a statement about the work reaching some declared state. Refuses to
367
+ * orphan a task that is already `done` or already `orphaned` (finished
368
+ * work, or already-recorded, should never be re-flagged), OR whose FRESH
369
+ * owner no longer matches `expectedOwner` — the decision was made from a
370
+ * snapshot, and another process may have reassigned the task to a still-
371
+ * live owner in the meantime; orphaning it anyway would be acting on stale
372
+ * information (codex-review Important).
373
+ */
374
+ markOrphaned(id, expectedOwner, reassignCandidates) {
375
+ return this.rawUpdate(id, (fresh) => {
376
+ if (fresh.state === DONE_STATE || fresh.state === ORPHANED_STATE) throw new Error(`task ${id}: cannot mark orphaned — already "${fresh.state}"`);
377
+ if (fresh.owner !== expectedOwner) throw new Error(`task ${id}: owner changed since this was decided (expected "${expectedOwner}", now "${fresh.owner ?? "(none)"}") — not orphaning`);
378
+ return {
379
+ orphanedFrom: fresh.state,
380
+ reassignCandidates,
381
+ state: ORPHANED_STATE
382
+ };
383
+ });
384
+ }
341
385
  async addDep(id, blockerId) {
342
386
  if (blockerId === id) throw new Error(`task ${id} cannot depend on itself`);
343
387
  if (!this.get(blockerId)) throw new Error(`no such task: ${blockerId}`);
@@ -406,5 +450,107 @@ function describeBlock(block) {
406
450
  }
407
451
 
408
452
  //#endregion
409
- export { openStore as a, TodoStore as i, monitorHint as n, CycleError as r, describeBlock as t };
410
- //# sourceMappingURL=todoBlock-C5wUhsSH.js.map
453
+ //#region ts/todoAutomation.ts
454
+ /**
455
+ * Reactive layer for the `ay todo` engine (Milestone 2): makes the engine
456
+ * self-driving for agent-facing signals `agent-yes` already tracks, instead
457
+ * of requiring every state change to be typed by hand.
458
+ *
459
+ * `reconcileTodos` is pure — decision logic only, no I/O — exactly the same
460
+ * "decide" / "do" split `symval-dev-cli`'s existing `watchdog.ts`
461
+ * (`decideActions`) already uses successfully: the hard-to-get-right parts
462
+ * (edge cases) live in a function that takes plain data in and returns plain
463
+ * data out, so they are trivially unit-testable without a real store, real
464
+ * processes, or real time. Applying the returned actions to a real
465
+ * `TodoStore` (I/O) is a separate, thin step (see `todoCli.ts`'s `reconcile`
466
+ * verb) deliberately kept out of this file — including revalidating each
467
+ * action against a FRESH record immediately before writing, since the
468
+ * snapshot this function decided from can be stale by the time the caller
469
+ * applies it (codex-review Important, see the action shapes below).
470
+ */
471
+ /**
472
+ * `TodoRecord.owner` is opaque — a human name/handle OR a tracked agent's
473
+ * stable id, this module cannot tell which just by looking at the string.
474
+ * The only safe signal is whether the identifier appears in the live-agent
475
+ * registry AT ALL: a KNOWN agent id whose latest record says `exited` is
476
+ * confirmed dead and orphan-eligible; an identifier with NO record at all is
477
+ * assumed to be a human owner (who was never going to appear there) and is
478
+ * never orphaned on that basis alone. Getting this backwards would orphan
479
+ * every human-owned task on every tick, since a human obviously never shows
480
+ * up in the agent process table.
481
+ */
482
+ function deadOwnerAgent(ownerId, agents) {
483
+ const rec = agents.find((a) => a.agent_id === ownerId);
484
+ return rec !== void 0 && rec.status === "exited";
485
+ }
486
+ /** Up to `limit` OTHER agent ids currently idle — candidates to hand an orphaned task to. */
487
+ function idleCandidates(excludeAgentId, agents, limit = 3) {
488
+ return agents.filter((a) => !!a.agent_id).filter((a) => a.agent_id !== excludeAgentId && a.status === "idle").map((a) => a.agent_id).slice(0, limit);
489
+ }
490
+ /**
491
+ * Decide what should happen given the current tasks and the current live-agent
492
+ * snapshot. Four rules, each traceable to a specific requirement (see
493
+ * `docs/2026-07-23-todo-lifecycle-execplan.md`'s Milestone 2 section):
494
+ *
495
+ * - owner's agent process is gone and the task isn't finished → `orphan`.
496
+ * - a `waiting-on-agent` block whose agent went idle or exited successfully
497
+ * (exit code 0) → `clear-waiting-on-agent`.
498
+ * - a task currently in `unblockedTasks()` with an owner → `notify-unblocked`,
499
+ * reported on EVERY call (no dedup/state file): there is no real delivery
500
+ * channel wired yet (see `todoCli.ts`'s `reconcile` verb doc comment), so
501
+ * persisting "already notified" would silently retire the one signal an
502
+ * owner would ever get with nobody having actually received it
503
+ * (codex-review Important) — the same no-dedup convention `renderDigest`'s
504
+ * own "unblocked" section already uses.
505
+ * - a task in a state whose outgoing edge's gate is registered → `auto-verify`
506
+ * (the actual gate CALL is real I/O and happens in the caller via `store.verify()`;
507
+ * this only decides which tasks are eligible to try).
508
+ *
509
+ * An orphaned task is skipped for the OTHER rules this same tick (its owner is
510
+ * gone, so it cannot also be "waiting on" that same dead agent in a meaningful
511
+ * way, and it is no longer eligible for auto-verify either).
512
+ */
513
+ function reconcileTodos(tasks, agents, registeredGates) {
514
+ const actions = [];
515
+ const orphanedThisTick = /* @__PURE__ */ new Set();
516
+ for (const t of tasks) {
517
+ if (t.state === DONE_STATE || t.state === ORPHANED_STATE) continue;
518
+ if (t.owner && deadOwnerAgent(t.owner, agents)) {
519
+ actions.push({
520
+ type: "orphan",
521
+ taskId: t._id,
522
+ from: t.state,
523
+ expectedOwner: t.owner,
524
+ candidates: idleCandidates(t.owner, agents)
525
+ });
526
+ orphanedThisTick.add(t._id);
527
+ continue;
528
+ }
529
+ if (t.block?.type === "waiting-on-agent") {
530
+ const agentId = t.block.agentId;
531
+ const agent = agents.find((a) => a.agent_id === agentId);
532
+ if (agent && (agent.status === "idle" || agent.status === "exited" && agent.exit_code === 0)) actions.push({
533
+ type: "clear-waiting-on-agent",
534
+ taskId: t._id,
535
+ expectedAgentId: agentId
536
+ });
537
+ }
538
+ if (LIFECYCLES[t.kind].transitions.some((edge) => edge.from === t.state && edge.gate && registeredGates.has(edge.gate))) actions.push({
539
+ type: "auto-verify",
540
+ taskId: t._id
541
+ });
542
+ }
543
+ for (const t of unblockedTasks(tasks)) {
544
+ if (orphanedThisTick.has(t._id) || !t.owner) continue;
545
+ actions.push({
546
+ type: "notify-unblocked",
547
+ taskId: t._id,
548
+ owner: t.owner
549
+ });
550
+ }
551
+ return actions;
552
+ }
553
+
554
+ //#endregion
555
+ export { TodoStore as a, CycleError as i, describeBlock as n, openStore as o, monitorHint as r, reconcileTodos as t };
556
+ //# sourceMappingURL=todoAutomation-fxtfT_44.js.map
@@ -1,7 +1,8 @@
1
1
  import "./logger-CDIsZ-Pp.js";
2
2
  import "./JsonlStore-Bm5Nj6v_.js";
3
- import { i as renderTree, r as renderDigest, s as LIFECYCLES, u as isKnownKind } from "./todoDigest-DaEklQg1.js";
4
- import { a as openStore, r as CycleError, t as describeBlock } from "./todoBlock-C5wUhsSH.js";
3
+ import { i as readGlobalPids } from "./globalPidIndex-CoNr7tS8.js";
4
+ import { d as isKnownKind, i as renderTree, r as renderDigest, s as LIFECYCLES } from "./todoDigest-DSTG9ksk.js";
5
+ import { i as CycleError, n as describeBlock, o as openStore, t as reconcileTodos } from "./todoAutomation-fxtfT_44.js";
5
6
  import yargs from "yargs";
6
7
 
7
8
  //#region ts/todoCli.ts
@@ -274,7 +275,7 @@ async function runTodoSubcommand(rest0) {
274
275
  const rootId = a._[0] !== void 0 ? String(a._[0]) : void 0;
275
276
  const tasks = store.all();
276
277
  if (opts.format === "json") {
277
- const { buildTreeJSON } = await import("./todoDigest-CAi1HHla.js");
278
+ const { buildTreeJSON } = await import("./todoDigest-gKP1XibO.js");
278
279
  emit(opts, buildTreeJSON(tasks, rootId), "");
279
280
  } else process.stdout.write(renderTree(tasks, rootId) + "\n");
280
281
  return 0;
@@ -283,7 +284,7 @@ async function runTodoSubcommand(rest0) {
283
284
  const opts = commonOptsOf(await commonOptions(yargs(args)).help(false).exitProcess(false).parseAsync());
284
285
  const tasks = (await openStore(opts.root)).all();
285
286
  if (opts.format === "json") {
286
- const { unblockedTasks } = await import("./todoDigest-CAi1HHla.js");
287
+ const { unblockedTasks } = await import("./todoDigest-gKP1XibO.js");
287
288
  emit(opts, {
288
289
  tasks,
289
290
  unblocked: unblockedTasks(tasks).map((t) => t._id)
@@ -291,10 +292,45 @@ async function runTodoSubcommand(rest0) {
291
292
  } else process.stdout.write(renderDigest(tasks) + "\n");
292
293
  return 0;
293
294
  }
294
- default: fail(`unknown "ay todo" verb: "${verb ?? ""}" (expected: new/ls/get/transition/approve/verify/block/unblock/dep/tree/digest)`);
295
+ case "reconcile": {
296
+ const opts = commonOptsOf(await commonOptions(yargs(args)).help(false).exitProcess(false).parseAsync());
297
+ const store = await openStore(opts.root);
298
+ const agents = await readGlobalPids({ liveOnly: false });
299
+ const registeredGates = new Set(store.registeredGateNames());
300
+ const actions = reconcileTodos(store.all(), agents, registeredGates);
301
+ const applied = [];
302
+ for (const action of actions) try {
303
+ switch (action.type) {
304
+ case "orphan":
305
+ await store.markOrphaned(action.taskId, action.expectedOwner, action.candidates);
306
+ applied.push(`orphaned ${action.taskId} (was ${action.from}) — reassign candidates: ${action.candidates.join(", ") || "(none idle)"}`);
307
+ break;
308
+ case "clear-waiting-on-agent":
309
+ await store.clearWaitingOnAgentBlock(action.taskId, action.expectedAgentId);
310
+ applied.push(`cleared waiting-on-agent block on ${action.taskId} (agent ${action.expectedAgentId})`);
311
+ break;
312
+ case "auto-verify": {
313
+ const result = await store.verify(action.taskId);
314
+ applied.push(`auto-verified ${action.taskId} -> ${result.state}`);
315
+ break;
316
+ }
317
+ case "notify-unblocked":
318
+ applied.push(`${action.taskId} is now unblocked (owner: ${action.owner})`);
319
+ break;
320
+ }
321
+ } catch (err) {
322
+ applied.push(`skipped ${action.type} on ${action.taskId}: ${err instanceof Error ? err.message : String(err)}`);
323
+ }
324
+ emit(opts, {
325
+ actions,
326
+ applied
327
+ }, applied.length ? applied.join("\n") : "(nothing to reconcile)");
328
+ return 0;
329
+ }
330
+ default: fail(`unknown "ay todo" verb: "${verb ?? ""}" (expected: new/ls/get/transition/approve/verify/block/unblock/dep/tree/digest/reconcile)`);
295
331
  }
296
332
  }
297
333
 
298
334
  //#endregion
299
335
  export { runTodoSubcommand };
300
- //# sourceMappingURL=todoCli-BdJaiX1x.js.map
336
+ //# sourceMappingURL=todoCli-dk8WNgcS.js.map
@@ -6,6 +6,15 @@
6
6
  * doing state) moves a task out of a finished-adjacent state.
7
7
  */
8
8
  const DONE_STATE = "done";
9
+ /**
10
+ * Not a normal graph edge on any kind's `transitions` list — a task can be
11
+ * moved here from ANY state, by automation only (see `todoAutomation.ts`),
12
+ * when its owning agent process has vanished. Kept out of the declarative
13
+ * graphs deliberately: it is a side-channel signal about the WORKER, not a
14
+ * statement about the work itself, so it should never appear as a normal
15
+ * `canTransition`-reachable edge a human/CLI could aim for directly.
16
+ */
17
+ const ORPHANED_STATE = "orphaned";
9
18
  const LIFECYCLES = {
10
19
  code: {
11
20
  states: [
@@ -271,5 +280,5 @@ function renderDigest(tasks) {
271
280
  }
272
281
 
273
282
  //#endregion
274
- export { unblockedTasks as a, canTransition as c, nextStates as d, requiredGate as f, renderTree as i, initialState as l, openBlockers as n, DONE_STATE as o, statesOf as p, renderDigest as r, LIFECYCLES as s, buildTreeJSON as t, isKnownKind as u };
275
- //# sourceMappingURL=todoDigest-DaEklQg1.js.map
283
+ export { unblockedTasks as a, ORPHANED_STATE as c, isKnownKind as d, nextStates as f, renderTree as i, canTransition as l, statesOf as m, openBlockers as n, DONE_STATE as o, requiredGate as p, renderDigest as r, LIFECYCLES as s, buildTreeJSON as t, initialState as u };
284
+ //# sourceMappingURL=todoDigest-DSTG9ksk.js.map
@@ -0,0 +1,3 @@
1
+ import { a as unblockedTasks, i as renderTree, n as openBlockers, r as renderDigest, t as buildTreeJSON } from "./todoDigest-DSTG9ksk.js";
2
+
3
+ export { buildTreeJSON, unblockedTasks };