@monoes/monomindcli 2.13.0 → 2.14.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 (136) hide show
  1. package/dist/src/commands/doctor-mcp-probe.d.ts +48 -0
  2. package/dist/src/commands/doctor-mcp-probe.d.ts.map +1 -0
  3. package/dist/src/commands/doctor-mcp-probe.js +205 -0
  4. package/dist/src/commands/doctor-mcp-probe.js.map +1 -0
  5. package/dist/src/commands/doctor-project-checks.d.ts +12 -1
  6. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  7. package/dist/src/commands/doctor-project-checks.js +55 -4
  8. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  9. package/dist/src/commands/doctor.d.ts.map +1 -1
  10. package/dist/src/commands/doctor.js +10 -1
  11. package/dist/src/commands/doctor.js.map +1 -1
  12. package/dist/src/commands/init.d.ts.map +1 -1
  13. package/dist/src/commands/init.js +17 -0
  14. package/dist/src/commands/init.js.map +1 -1
  15. package/dist/src/commands/mcp.d.ts.map +1 -1
  16. package/dist/src/commands/mcp.js +4 -3
  17. package/dist/src/commands/mcp.js.map +1 -1
  18. package/dist/src/commands/org-observe.d.ts.map +1 -1
  19. package/dist/src/commands/org-observe.js +14 -0
  20. package/dist/src/commands/org-observe.js.map +1 -1
  21. package/dist/src/commands/org.d.ts.map +1 -1
  22. package/dist/src/commands/org.js +12 -2
  23. package/dist/src/commands/org.js.map +1 -1
  24. package/dist/src/init/claudemd-generator.d.ts.map +1 -1
  25. package/dist/src/init/claudemd-generator.js +2 -1
  26. package/dist/src/init/claudemd-generator.js.map +1 -1
  27. package/dist/src/init/mcp-generator.d.ts.map +1 -1
  28. package/dist/src/init/mcp-generator.js +3 -3
  29. package/dist/src/init/mcp-generator.js.map +1 -1
  30. package/dist/src/init/types.d.ts +6 -0
  31. package/dist/src/init/types.d.ts.map +1 -1
  32. package/dist/src/init/types.js.map +1 -1
  33. package/dist/src/init/write-runtime-config.d.ts.map +1 -1
  34. package/dist/src/init/write-runtime-config.js +12 -2
  35. package/dist/src/init/write-runtime-config.js.map +1 -1
  36. package/dist/src/orgrt/agent-runner.d.ts +38 -0
  37. package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
  38. package/dist/src/orgrt/agent-runner.js +47 -0
  39. package/dist/src/orgrt/agent-runner.js.map +1 -1
  40. package/dist/src/orgrt/checkpoint.d.ts +12 -1
  41. package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
  42. package/dist/src/orgrt/checkpoint.js +15 -6
  43. package/dist/src/orgrt/checkpoint.js.map +1 -1
  44. package/dist/src/orgrt/completion-gate.d.ts +74 -0
  45. package/dist/src/orgrt/completion-gate.d.ts.map +1 -1
  46. package/dist/src/orgrt/completion-gate.js +45 -0
  47. package/dist/src/orgrt/completion-gate.js.map +1 -1
  48. package/dist/src/orgrt/cost-tier.d.ts +144 -0
  49. package/dist/src/orgrt/cost-tier.d.ts.map +1 -0
  50. package/dist/src/orgrt/cost-tier.js +183 -0
  51. package/dist/src/orgrt/cost-tier.js.map +1 -0
  52. package/dist/src/orgrt/cross-org.d.ts.map +1 -1
  53. package/dist/src/orgrt/cross-org.js +14 -0
  54. package/dist/src/orgrt/cross-org.js.map +1 -1
  55. package/dist/src/orgrt/daemon.d.ts +12 -1
  56. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  57. package/dist/src/orgrt/daemon.js +216 -49
  58. package/dist/src/orgrt/daemon.js.map +1 -1
  59. package/dist/src/orgrt/decisions.d.ts +14 -2
  60. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  61. package/dist/src/orgrt/decisions.js +216 -10
  62. package/dist/src/orgrt/decisions.js.map +1 -1
  63. package/dist/src/orgrt/file-roots.d.ts +7 -0
  64. package/dist/src/orgrt/file-roots.d.ts.map +1 -1
  65. package/dist/src/orgrt/file-roots.js +38 -1
  66. package/dist/src/orgrt/file-roots.js.map +1 -1
  67. package/dist/src/orgrt/forwarder.d.ts.map +1 -1
  68. package/dist/src/orgrt/forwarder.js +16 -2
  69. package/dist/src/orgrt/forwarder.js.map +1 -1
  70. package/dist/src/orgrt/idle-deadline.d.ts +74 -1
  71. package/dist/src/orgrt/idle-deadline.d.ts.map +1 -1
  72. package/dist/src/orgrt/idle-deadline.js +52 -2
  73. package/dist/src/orgrt/idle-deadline.js.map +1 -1
  74. package/dist/src/orgrt/loadouts.d.ts +38 -0
  75. package/dist/src/orgrt/loadouts.d.ts.map +1 -0
  76. package/dist/src/orgrt/loadouts.js +129 -0
  77. package/dist/src/orgrt/loadouts.js.map +1 -0
  78. package/dist/src/orgrt/mailbox.d.ts +17 -1
  79. package/dist/src/orgrt/mailbox.d.ts.map +1 -1
  80. package/dist/src/orgrt/mailbox.js +50 -3
  81. package/dist/src/orgrt/mailbox.js.map +1 -1
  82. package/dist/src/orgrt/policy.d.ts +42 -2
  83. package/dist/src/orgrt/policy.d.ts.map +1 -1
  84. package/dist/src/orgrt/policy.js +53 -8
  85. package/dist/src/orgrt/policy.js.map +1 -1
  86. package/dist/src/orgrt/prompt-vars.d.ts +11 -0
  87. package/dist/src/orgrt/prompt-vars.d.ts.map +1 -0
  88. package/dist/src/orgrt/prompt-vars.js +49 -0
  89. package/dist/src/orgrt/prompt-vars.js.map +1 -0
  90. package/dist/src/orgrt/questions.d.ts +22 -1
  91. package/dist/src/orgrt/questions.d.ts.map +1 -1
  92. package/dist/src/orgrt/questions.js +24 -3
  93. package/dist/src/orgrt/questions.js.map +1 -1
  94. package/dist/src/orgrt/review-packet.d.ts +29 -0
  95. package/dist/src/orgrt/review-packet.d.ts.map +1 -0
  96. package/dist/src/orgrt/review-packet.js +67 -0
  97. package/dist/src/orgrt/review-packet.js.map +1 -0
  98. package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
  99. package/dist/src/orgrt/role-sandbox.js +16 -3
  100. package/dist/src/orgrt/role-sandbox.js.map +1 -1
  101. package/dist/src/orgrt/session-ledger.d.ts +61 -0
  102. package/dist/src/orgrt/session-ledger.d.ts.map +1 -0
  103. package/dist/src/orgrt/session-ledger.js +113 -0
  104. package/dist/src/orgrt/session-ledger.js.map +1 -0
  105. package/dist/src/orgrt/session.d.ts +45 -5
  106. package/dist/src/orgrt/session.d.ts.map +1 -1
  107. package/dist/src/orgrt/session.js +384 -27
  108. package/dist/src/orgrt/session.js.map +1 -1
  109. package/dist/src/orgrt/task-dag.d.ts +34 -1
  110. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  111. package/dist/src/orgrt/task-dag.js +58 -7
  112. package/dist/src/orgrt/task-dag.js.map +1 -1
  113. package/dist/src/orgrt/tool-spill.d.ts +94 -0
  114. package/dist/src/orgrt/tool-spill.d.ts.map +1 -0
  115. package/dist/src/orgrt/tool-spill.js +180 -0
  116. package/dist/src/orgrt/tool-spill.js.map +1 -0
  117. package/dist/src/orgrt/types.d.ts +138 -0
  118. package/dist/src/orgrt/types.d.ts.map +1 -1
  119. package/dist/src/orgrt/types.js +148 -0
  120. package/dist/src/orgrt/types.js.map +1 -1
  121. package/dist/src/platform-adapters/renderers/mcp.d.ts +20 -2
  122. package/dist/src/platform-adapters/renderers/mcp.d.ts.map +1 -1
  123. package/dist/src/platform-adapters/renderers/mcp.js +25 -5
  124. package/dist/src/platform-adapters/renderers/mcp.js.map +1 -1
  125. package/dist/src/protocol-capabilities.d.ts +2 -1
  126. package/dist/src/protocol-capabilities.d.ts.map +1 -1
  127. package/dist/src/protocol-capabilities.js +2 -1
  128. package/dist/src/protocol-capabilities.js.map +1 -1
  129. package/dist/src/ui/dashboard.html +450 -164
  130. package/dist/src/ui/org-hil.mjs +276 -0
  131. package/dist/src/ui/org-runtime.mjs +350 -0
  132. package/dist/src/ui/orgs.html +15 -4
  133. package/dist/src/ui/routes-org.mjs +290 -541
  134. package/dist/src/ui/server.mjs +25 -5
  135. package/dist/tsconfig.tsbuildinfo +1 -1
  136. package/package.json +6 -5
@@ -2,12 +2,81 @@ export declare const IDLE_WATCHDOG_FILE = "idle-watchdog.json";
2
2
  /** Why there is no deadline right now. Every value except `disabled` is a
3
3
  * legitimate wait the watchdog will not nudge or stop through. */
4
4
  export type IdleHold = 'disabled' | 'restarting' | 'pending-gate' | 'pending-question' | 'pending-approval' | 'endpoint-reply-due' | 'task-blocked';
5
+ /** Every hold reason except `disabled` describes a *wait*: the run is alive
6
+ * and legitimately not progressing yet. `disabled` is the operator having
7
+ * switched the watchdog off (`run_config.idle_minutes: 0`), which is not a
8
+ * wait and not a stall. */
9
+ export type WaitHold = Exclude<IdleHold, 'disabled'>;
10
+ /** ADR-O001 D4 — "every hold carries a deadline". The shape makes a hold
11
+ * with no expiry unrepresentable: a wait hold MUST name the instant it stops
12
+ * suppressing the idle clock. A `hold` used to be a bare reason string and a
13
+ * `null` deadline, which disabled the idle stop for as long as the reason
14
+ * held — measured live at 8.3 hours on `{"hold":"pending-question"}`, with
15
+ * the first turn after the gap costing $17.33 because the prompt cache had
16
+ * long since expired. */
17
+ export type IdleHoldState = {
18
+ reason: 'disabled';
19
+ until: null;
20
+ } | {
21
+ reason: WaitHold;
22
+ until: string;
23
+ };
24
+ /** How long any single wait may suppress the idle watchdog before the run
25
+ * goes back on the normal nudge-then-stop path. Deliberately generous — a
26
+ * human answering a question, approving a tool call or resolving a gate has
27
+ * an hour — and deliberately finite, because the alternative measured 8.3
28
+ * hours. An expired hold does not stop the run by itself: it hands the run
29
+ * back to the idle clock, which nudges the boss first. */
30
+ export declare const HOLD_TTL_MS: number;
31
+ /** One watchdog tick's view of the current hold. `since` anchors the deadline
32
+ * to when the reason FIRST appeared — recomputing it per tick is exactly how
33
+ * a hold lives forever. `alarmed` keeps the expiry audit event to one per
34
+ * spell (same "once, not every tick" rule as `resolvedIdleNudgeCount`). */
35
+ export interface HoldTrack {
36
+ reason: WaitHold;
37
+ since: number;
38
+ alarmed: boolean;
39
+ }
40
+ /** Advance the hold tracker one watchdog tick.
41
+ * - `hold` is the hold still in force, or null once it has expired (or when
42
+ * nothing is holding) — null means the caller runs its normal idle checks.
43
+ * - `expired` names the reason on the single tick the deadline passes, so
44
+ * the caller can say so loudly once instead of every 30 seconds.
45
+ *
46
+ * A wait that knows its own end (a task blocked until a stated real-world
47
+ * time) passes that instant as `until` and keeps it; everything else — the
48
+ * waits on a human or a remote peer, which are the ones that can wait
49
+ * forever — gets `ttlMs` from when the reason first appeared. A changed
50
+ * reason is a new wait and gets a fresh deadline. */
51
+ export declare function advanceHold(prev: HoldTrack | null, wait: WaitHold | {
52
+ reason: WaitHold;
53
+ until: number;
54
+ } | null, now: number, ttlMs?: number): {
55
+ track: HoldTrack | null;
56
+ hold: IdleHoldState | null;
57
+ expired: WaitHold | null;
58
+ };
59
+ /** ADR-O001 D4 — the no-progress detector, Gas Town's "30 minutes hooked
60
+ * without progress" alarm. The idle clock is org-wide and says nothing at
61
+ * all while a hold is in force, so a role that is nominally working while
62
+ * producing no bus activity has to be surfaced on its own. A role that has
63
+ * ended or crashed is silent for a good reason and is not reported. */
64
+ export declare const NO_PROGRESS_MS: number;
65
+ export declare function noProgressRoles(roles: ReadonlyArray<{
66
+ id: string;
67
+ working: boolean;
68
+ lastActivity: number;
69
+ alarmed: boolean;
70
+ }>, now: number, thresholdMs?: number): Array<{
71
+ id: string;
72
+ silentMs: number;
73
+ }>;
5
74
  export interface IdleWatchdogRecord {
6
75
  run: string;
7
76
  idle_minutes: number;
8
77
  /** ISO time the watchdog stops the run if nothing happens before then. */
9
78
  idle_stop_at: string | null;
10
- hold: IdleHold | null;
79
+ hold: IdleHoldState | null;
11
80
  }
12
81
  /** When the watchdog stops the run, assuming no further activity. The stop
13
82
  * lands on the first check at or after this time (checks run every
@@ -32,5 +101,9 @@ export declare function readIdleStatus(root: string, name: string, run: string |
32
101
  idle_stop_at: string | null;
33
102
  idle_stop_in_seconds: number | null;
34
103
  idle_hold: IdleHold | 'unknown' | null;
104
+ /** ISO time the hold expires and the idle clock resumes (ADR-O001 D4).
105
+ * `null` for `disabled`, and for a record written by a pre-D4 daemon whose
106
+ * holds had no deadline at all. */
107
+ idle_hold_until?: string | null;
35
108
  };
36
109
  //# sourceMappingURL=idle-deadline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"idle-deadline.d.ts","sourceRoot":"","sources":["../../../src/orgrt/idle-deadline.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAEvD;mEACmE;AACnE,MAAM,MAAM,QAAQ,GAChB,UAAU,GACV,YAAY,GACZ,cAAc,GACd,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,CAAC;AAEnB,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CACvB;AAED;;;;;4EAK4E;AAC5E,wBAAgB,eAAe,CAAC,CAAC,EAAE;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,MAAM,CAIT;AAMD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,IAAI,CAEzF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEhE;AAED;;kDAEkD;AAClD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,SAAa,GACf;IACD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC;CACxC,CAkBA"}
1
+ {"version":3,"file":"idle-deadline.d.ts","sourceRoot":"","sources":["../../../src/orgrt/idle-deadline.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,45 @@ import { join } from 'node:path';
13
13
  import { writeJsonFileAtomic } from '../utils/json-file.js';
14
14
  import { ORG_DIR } from './types.js';
15
15
  export const IDLE_WATCHDOG_FILE = 'idle-watchdog.json';
16
+ /** How long any single wait may suppress the idle watchdog before the run
17
+ * goes back on the normal nudge-then-stop path. Deliberately generous — a
18
+ * human answering a question, approving a tool call or resolving a gate has
19
+ * an hour — and deliberately finite, because the alternative measured 8.3
20
+ * hours. An expired hold does not stop the run by itself: it hands the run
21
+ * back to the idle clock, which nudges the boss first. */
22
+ export const HOLD_TTL_MS = 60 * 60_000;
23
+ /** Advance the hold tracker one watchdog tick.
24
+ * - `hold` is the hold still in force, or null once it has expired (or when
25
+ * nothing is holding) — null means the caller runs its normal idle checks.
26
+ * - `expired` names the reason on the single tick the deadline passes, so
27
+ * the caller can say so loudly once instead of every 30 seconds.
28
+ *
29
+ * A wait that knows its own end (a task blocked until a stated real-world
30
+ * time) passes that instant as `until` and keeps it; everything else — the
31
+ * waits on a human or a remote peer, which are the ones that can wait
32
+ * forever — gets `ttlMs` from when the reason first appeared. A changed
33
+ * reason is a new wait and gets a fresh deadline. */
34
+ export function advanceHold(prev, wait, now, ttlMs = HOLD_TTL_MS) {
35
+ if (!wait)
36
+ return { track: null, hold: null, expired: null };
37
+ const reason = typeof wait === 'string' ? wait : wait.reason;
38
+ const track = prev && prev.reason === reason ? prev : { reason, since: now, alarmed: false };
39
+ const until = typeof wait === 'string' ? track.since + ttlMs : wait.until;
40
+ if (now < until)
41
+ return { track, hold: { reason, until: new Date(until).toISOString() }, expired: null };
42
+ return { track: { ...track, alarmed: true }, hold: null, expired: track.alarmed ? null : reason };
43
+ }
44
+ /** ADR-O001 D4 — the no-progress detector, Gas Town's "30 minutes hooked
45
+ * without progress" alarm. The idle clock is org-wide and says nothing at
46
+ * all while a hold is in force, so a role that is nominally working while
47
+ * producing no bus activity has to be surfaced on its own. A role that has
48
+ * ended or crashed is silent for a good reason and is not reported. */
49
+ export const NO_PROGRESS_MS = 30 * 60_000;
50
+ export function noProgressRoles(roles, now, thresholdMs = NO_PROGRESS_MS) {
51
+ return roles
52
+ .filter((r) => r.working && !r.alarmed && now - r.lastActivity >= thresholdMs)
53
+ .map((r) => ({ id: r.id, silentMs: now - r.lastActivity }));
54
+ }
16
55
  /** When the watchdog stops the run, assuming no further activity. The stop
17
56
  * lands on the first check at or after this time (checks run every
18
57
  * min(idle/2, 30s)), so treat it as the earliest stop, not an exact one.
@@ -52,12 +91,23 @@ export function readIdleStatus(root, name, run, now = Date.now()) {
52
91
  }
53
92
  if (rec.run !== run)
54
93
  return unknown;
55
- if (!rec.idle_stop_at)
56
- return { idle_stop_at: null, idle_stop_in_seconds: null, idle_hold: rec.hold };
94
+ if (!rec.idle_stop_at) {
95
+ // A pre-D4 daemon wrote the reason as a bare string with no deadline.
96
+ const hold = rec.hold;
97
+ return typeof hold === 'string'
98
+ ? { idle_stop_at: null, idle_stop_in_seconds: null, idle_hold: hold, idle_hold_until: null }
99
+ : {
100
+ idle_stop_at: null,
101
+ idle_stop_in_seconds: null,
102
+ idle_hold: hold?.reason ?? null,
103
+ idle_hold_until: hold?.until ?? null,
104
+ };
105
+ }
57
106
  return {
58
107
  idle_stop_at: rec.idle_stop_at,
59
108
  idle_stop_in_seconds: Math.max(0, Math.round((Date.parse(rec.idle_stop_at) - now) / 1000)),
60
109
  idle_hold: null,
110
+ idle_hold_until: null,
61
111
  };
62
112
  }
63
113
  //# sourceMappingURL=idle-deadline.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"idle-deadline.js","sourceRoot":"","sources":["../../../src/orgrt/idle-deadline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,CAAC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAqBvD;;;;;4EAK4E;AAC5E,MAAM,UAAU,eAAe,CAAC,CAO/B;IACC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,aAAa;QAAE,OAAO,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAClF,OAAO,CAAC,CAAC,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;AACvC,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,IAAY;IAC5C,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY,EAAE,GAAuB;IACjF,mBAAmB,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY;IACxD,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;kDAEkD;AAClD,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,IAAY,EACZ,GAAuB,EACvB,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAMhB,MAAM,OAAO,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,SAAS,EAAE,SAAkB,EAAE,CAAC;IAClG,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAC3C,IAAI,GAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAuB,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG;QAAE,OAAO,OAAO,CAAC;IACpC,IAAI,CAAC,GAAG,CAAC,YAAY;QACnB,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IACjF,OAAO;QACL,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,oBAAoB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1F,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"idle-deadline.js","sourceRoot":"","sources":["../../../src/orgrt/idle-deadline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { OrgTask, TaskDag } from './task-dag.js';
2
+ import type { OrgDef } from './types.js';
3
+ export declare const MAX_LOADOUTS = 15;
4
+ export declare const TARGET_MIN_LOADOUTS = 5;
5
+ /** What the boss sees to select by (org_task's description). */
6
+ export interface LoadoutSummary {
7
+ name: string;
8
+ description?: string;
9
+ }
10
+ /** A loadout ready to go into a session's system prompt. Plain data, resolved
11
+ * once when the session is built, so nothing can change it mid-session. */
12
+ export interface ResolvedLoadout {
13
+ name: string;
14
+ guidance: string;
15
+ }
16
+ /** Errors fail `org validate` and `org run`; warnings are printed only. */
17
+ export declare function validateLoadouts(def: Pick<OrgDef, 'loadouts'>, root: string): {
18
+ errors: string[];
19
+ warnings: string[];
20
+ };
21
+ /** The catalog as the boss's tools present it, or undefined when the org has
22
+ * none — the signal that keeps every tool byte-identical for such orgs. */
23
+ export declare function loadoutCatalog(def: Pick<OrgDef, 'loadouts'> | undefined): LoadoutSummary[] | undefined;
24
+ /** Build the system-prompt text for a loadout: header, prompt, skills in the
25
+ * declared order, then the instructions file. Deterministic for a given
26
+ * config, which is what makes two sessions of the same kind byte-identical. */
27
+ export declare function resolveLoadout(def: Pick<OrgDef, 'loadouts'>, name: string, root: string): ResolvedLoadout;
28
+ /** Why a selection is refused, or null when it is fine (or absent). */
29
+ export declare function checkLoadoutSelection(def: Pick<OrgDef, 'loadouts'>, loadout: string | undefined): string | null;
30
+ /** The loadout a NEW session for `roleId` is built with: that of the role's
31
+ * first ready task in DAG order. Deterministic, and it is exactly the task
32
+ * the lazy spawn is happening for when dispatch spawns the role. */
33
+ export declare function sessionLoadoutFor(dag: TaskDag | undefined, roleId: string): string | undefined;
34
+ /** The task reference that opens every dispatch/re-dispatch message. The
35
+ * loadout rides in the MESSAGE (layer 2), never the prompt, and only when one
36
+ * was selected — so an org without a catalog sends exactly what it did. */
37
+ export declare function taskTag(task: Pick<OrgTask, 'id' | 'loadout'>): string;
38
+ //# sourceMappingURL=loadouts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadouts.d.ts","sourceRoot":"","sources":["../../../src/orgrt/loadouts.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAGrC,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;4EAC4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAQD,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAC7B,IAAI,EAAE,MAAM,GACX;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAsC1C;AAED;4EAC4E;AAC5E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS,GACxC,cAAc,EAAE,GAAG,SAAS,CAM9B;AAED;;gFAEgF;AAChF,wBAAgB,cAAc,CAC5B,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,eAAe,CAejB;AAED,uEAAuE;AACvE,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,GAAG,IAAI,CAOf;AAED;;qEAEqE;AACrE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9F;AAED;;4EAE4E;AAC5E,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAErE"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * ADR-O001 D7 — specialisation via a small catalog of stable loadouts.
3
+ *
4
+ * `buildRolePrompt` runs once per session, so a role's system prompt is a
5
+ * stable cache prefix: one cache write, then 0.1x forever. Specialisation is
6
+ * therefore cheap and VARIETY is expensive — every distinct system prompt is
7
+ * its own cache namespace. A loadout is a named, stable bundle of role-prompt
8
+ * text + skills; the boss selects one by name when it creates a task and never
9
+ * composes prompt text. Everything per-task (which diff, which criteria, what
10
+ * failed last time) goes in the task MESSAGE instead.
11
+ *
12
+ * Catalog size: more than MAX_LOADOUTS is an error at `org validate` and at
13
+ * daemon start. Fewer than TARGET_MIN_LOADOUTS is ALLOWED with a warning — a
14
+ * small org with two kinds of work is not wrong, it just is not the shape the
15
+ * ADR tuned for. An empty `loadouts: {}` is an error (omit the field instead),
16
+ * because it would still switch on the tool argument with nothing to select.
17
+ *
18
+ * Today each role holds ONE long SDK session for its life (see session.ts), so
19
+ * a loadout can only take effect when a role's session is BUILT: the daemon
20
+ * picks it from the role's first ready task (`sessionLoadoutFor`), freezes it
21
+ * on the incarnation (`AgentRuntime.loadout`) and in the checkpoint, and never
22
+ * rewrites it. A later task that asked for a different loadout is delivered to
23
+ * the live session anyway and recorded as a `loadout-mismatch` event — honest,
24
+ * not silently applied. When D3 makes sessions task-keyed, the session for
25
+ * (role, taskKey) is built with `resolveLoadout(def, task.loadout, root)` via
26
+ * the same `SessionOpts.loadout` field, and the mismatch path disappears.
27
+ */
28
+ import { existsSync, readFileSync } from 'node:fs';
29
+ import { isAbsolute, join } from 'node:path';
30
+ import { loadBuiltinRoleSkill } from './role-skills.js';
31
+ export const MAX_LOADOUTS = 15;
32
+ export const TARGET_MIN_LOADOUTS = 5;
33
+ const NAME_RE = /^[a-z0-9][a-z0-9_-]{0,47}$/i;
34
+ function filePath(file, root) {
35
+ return isAbsolute(file) ? file : join(root, file);
36
+ }
37
+ /** Errors fail `org validate` and `org run`; warnings are printed only. */
38
+ export function validateLoadouts(def, root) {
39
+ const errors = [];
40
+ const warnings = [];
41
+ const cat = def.loadouts;
42
+ if (!cat)
43
+ return { errors, warnings };
44
+ const names = Object.keys(cat);
45
+ if (names.length === 0) {
46
+ errors.push('loadouts: the catalog is empty — omit the field instead');
47
+ return { errors, warnings };
48
+ }
49
+ if (names.length > MAX_LOADOUTS) {
50
+ errors.push(`loadouts: ${names.length} loadouts declared, at most ${MAX_LOADOUTS} allowed — each distinct system prompt is its own cache namespace (ADR-O001 D7); merge similar kinds of work`);
51
+ }
52
+ else if (names.length < TARGET_MIN_LOADOUTS) {
53
+ warnings.push(`loadouts: ${names.length} loadouts declared, below the ${TARGET_MIN_LOADOUTS}–${MAX_LOADOUTS} target (allowed)`);
54
+ }
55
+ for (const name of names) {
56
+ const l = cat[name];
57
+ if (!NAME_RE.test(name)) {
58
+ errors.push(`loadout "${name}": name must be letters, digits, "-" or "_" (max 48)`);
59
+ }
60
+ if (!l.prompt?.trim() && !l.skills?.length && !l.instructions_file) {
61
+ errors.push(`loadout "${name}": has no prompt, skills or instructions_file`);
62
+ }
63
+ for (const s of l.skills ?? []) {
64
+ // Name check first: a skill is a file lookup, so "../x" must never reach it.
65
+ if (!NAME_RE.test(s) || !loadBuiltinRoleSkill(s)) {
66
+ errors.push(`loadout "${name}": unknown skill "${s}"`);
67
+ }
68
+ }
69
+ if (l.instructions_file && !existsSync(filePath(l.instructions_file, root))) {
70
+ errors.push(`loadout "${name}": instructions_file not found: ${l.instructions_file}`);
71
+ }
72
+ }
73
+ return { errors, warnings };
74
+ }
75
+ /** The catalog as the boss's tools present it, or undefined when the org has
76
+ * none — the signal that keeps every tool byte-identical for such orgs. */
77
+ export function loadoutCatalog(def) {
78
+ const cat = def?.loadouts;
79
+ if (!cat || Object.keys(cat).length === 0)
80
+ return undefined;
81
+ return Object.entries(cat).map(([name, l]) => l.description ? { name, description: l.description } : { name });
82
+ }
83
+ /** Build the system-prompt text for a loadout: header, prompt, skills in the
84
+ * declared order, then the instructions file. Deterministic for a given
85
+ * config, which is what makes two sessions of the same kind byte-identical. */
86
+ export function resolveLoadout(def, name, root) {
87
+ // hasOwn, not a bare lookup: "constructor" must not resolve via the prototype.
88
+ const l = def.loadouts && Object.hasOwn(def.loadouts, name) ? def.loadouts[name] : undefined;
89
+ if (!l)
90
+ throw new Error(`unknown loadout "${name}"`);
91
+ const parts = [`## Loadout: ${name}`];
92
+ if (l.prompt?.trim())
93
+ parts.push(l.prompt.trim());
94
+ for (const s of l.skills ?? []) {
95
+ const text = NAME_RE.test(s) ? loadBuiltinRoleSkill(s) : null;
96
+ if (text)
97
+ parts.push(text);
98
+ }
99
+ if (l.instructions_file) {
100
+ const text = readFileSync(filePath(l.instructions_file, root), 'utf-8').trim();
101
+ if (text)
102
+ parts.push(text);
103
+ }
104
+ return { name, guidance: parts.join('\n\n') };
105
+ }
106
+ /** Why a selection is refused, or null when it is fine (or absent). */
107
+ export function checkLoadoutSelection(def, loadout) {
108
+ if (loadout === undefined)
109
+ return null;
110
+ if (!def.loadouts)
111
+ return `this org has no loadout catalog — omit "loadout"`;
112
+ if (!Object.hasOwn(def.loadouts, loadout)) {
113
+ return `unknown loadout "${loadout}" — one of: ${Object.keys(def.loadouts).join(', ')}`;
114
+ }
115
+ return null;
116
+ }
117
+ /** The loadout a NEW session for `roleId` is built with: that of the role's
118
+ * first ready task in DAG order. Deterministic, and it is exactly the task
119
+ * the lazy spawn is happening for when dispatch spawns the role. */
120
+ export function sessionLoadoutFor(dag, roleId) {
121
+ return dag?.ready().find((t) => t.assignee === roleId)?.loadout;
122
+ }
123
+ /** The task reference that opens every dispatch/re-dispatch message. The
124
+ * loadout rides in the MESSAGE (layer 2), never the prompt, and only when one
125
+ * was selected — so an org without a catalog sends exactly what it did. */
126
+ export function taskTag(task) {
127
+ return task.loadout ? `[task:${task.id}] [loadout:${task.loadout}]` : `[task:${task.id}]`;
128
+ }
129
+ //# sourceMappingURL=loadouts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadouts.js","sourceRoot":"","sources":["../../../src/orgrt/loadouts.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,13 @@ export interface OrgUserMessage {
9
9
  session_id: string;
10
10
  }
11
11
  export declare function isRecoverableCloseReason(reason: string | undefined): boolean;
12
+ /** ADR-O001 D3 — optional stream boundaries. Omitted = the pre-D3 stream. */
13
+ export interface StreamOptions {
14
+ /** End the stream before yielding a message this rejects (not the first). */
15
+ stopBefore?: (next: string) => boolean;
16
+ /** End the stream after this long with an empty queue. */
17
+ idleExitMs?: number;
18
+ }
12
19
  /**
13
20
  * Async message queue feeding one persistent SDK session.
14
21
  * push() from the daemon (deliveries from other agents / the user);
@@ -43,6 +50,7 @@ export declare class Mailbox {
43
50
  * next one or parking on wake. Sticky for the life of this Mailbox
44
51
  * instance — a draining mailbox is being retired, not reused. */
45
52
  private draining;
53
+ private lastStreamEndValue?;
46
54
  /** Number of real (non-continuation) messages consumed so far across all sessions. */
47
55
  get consumedRealCount(): number;
48
56
  push(text: string): void;
@@ -82,7 +90,15 @@ export declare class Mailbox {
82
90
  * the generator; redelivering would duplicate work and can livelock the
83
91
  * restart loop).
84
92
  */
85
- stream(sessionId?: string): AsyncGenerator<OrgUserMessage>;
93
+ stream(sessionId?: string, opts?: StreamOptions): AsyncGenerator<OrgUserMessage>;
94
+ /** Why the most recent stream() returned early, if it did: 'boundary'
95
+ * (stopBefore rejected the next message) or 'idle' (idleExitMs elapsed). */
96
+ get lastStreamEnd(): 'boundary' | 'idle' | undefined;
97
+ /** The next queued message, without consuming it. */
98
+ peek(): string | undefined;
99
+ /** Resolves true once a message is queued, false if the mailbox closes or
100
+ * drains first. Used to keep a role's process down while it has no mail. */
101
+ waitForMessage(): Promise<boolean>;
86
102
  /** Called by the crash-retry path right after a session dies abnormally. If
87
103
  * a message was mid-flight — shifted for the crashed generator's yield but
88
104
  * never confirmed processed, because the generator was abandoned at that
@@ -1 +1 @@
1
- {"version":3,"file":"mailbox.d.ts","sourceRoot":"","sources":["../../../src/orgrt/mailbox.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,kBAAkB,EAAE,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAcD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE5E;AAED;;;;GAIG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAO;IACxC;;6EAEyE;IACzE,MAAM,CAAC,QAAQ,CAAC,eAAe,4BAA4B;IAC3D,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,MAAM,CAAS;IACvB;;gFAE4E;IAC5E,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,qFAAqF;IACrF,OAAO,CAAC,UAAU,CAAK;IACvB;uFACmF;IACnF,OAAO,CAAC,YAAY,CAAK;IACzB;;;;uDAImD;IACnD,OAAO,CAAC,QAAQ,CAAuB;IACvC;;;sEAGkE;IAClE,OAAO,CAAC,QAAQ,CAAS;IAEzB,sFAAsF;IACtF,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQvB;IAED,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAc3B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;yEACqE;IACrE,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED;;;;;;;;;;OAUG;IACH,MAAM,IAAI,IAAI,CAEb;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;;;gFAO4E;IAC5E,UAAU,IAAI,MAAM,EAAE,CAOrB;IAED;;;;;;;;OAQG;IACI,MAAM,CAAC,SAAS,SAAK,GAAG,cAAc,CAAC,cAAc,CAAC,CAkC5D;IAED;;;;;;;2DAOuD;IACvD,eAAe,IAAI,IAAI,CAStB;IAED,gEAAgE;IAChE,SAAS,IAAI;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAO5F;IAED,4DAA4D;IAC5D,WAAW,CAAC,KAAK,EAAE;QACjB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,IAAI,CAUP;CACF"}
1
+ {"version":3,"file":"mailbox.d.ts","sourceRoot":"","sources":["../../../src/orgrt/mailbox.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,kBAAkB,EAAE,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAcD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE5E;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAO;IACxC;;6EAEyE;IACzE,MAAM,CAAC,QAAQ,CAAC,eAAe,4BAA4B;IAC3D,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,MAAM,CAAS;IACvB;;gFAE4E;IAC5E,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,qFAAqF;IACrF,OAAO,CAAC,UAAU,CAAK;IACvB;uFACmF;IACnF,OAAO,CAAC,YAAY,CAAK;IACzB;;;;uDAImD;IACnD,OAAO,CAAC,QAAQ,CAAuB;IACvC;;;sEAGkE;IAClE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,kBAAkB,CAAC,CAAsB;IAEjD,sFAAsF;IACtF,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQvB;IAED,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAc3B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;yEACqE;IACrE,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED;;;;;;;;;;OAUG;IACH,MAAM,IAAI,IAAI,CAEb;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;;;gFAO4E;IAC5E,UAAU,IAAI,MAAM,EAAE,CAOrB;IAED;;;;;;;;OAQG;IACI,MAAM,CAAC,SAAS,SAAK,EAAE,IAAI,GAAE,aAAkB,GAAG,cAAc,CAAC,cAAc,CAAC,CAwDtF;IAED;iFAC6E;IAC7E,IAAI,aAAa,IAAI,UAAU,GAAG,MAAM,GAAG,SAAS,CAEnD;IAED,qDAAqD;IACrD,IAAI,IAAI,MAAM,GAAG,SAAS,CAEzB;IAED;iFAC6E;IACvE,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CASvC;IAED;;;;;;;2DAOuD;IACvD,eAAe,IAAI,IAAI,CAStB;IAED,gEAAgE;IAChE,SAAS,IAAI;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAO5F;IAED,4DAA4D;IAC5D,WAAW,CAAC,KAAK,EAAE;QACjB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,IAAI,CAUP;CACF"}
@@ -47,6 +47,7 @@ export class Mailbox {
47
47
  * next one or parking on wake. Sticky for the life of this Mailbox
48
48
  * instance — a draining mailbox is being retired, not reused. */
49
49
  draining = false;
50
+ lastStreamEndValue;
50
51
  /** Number of real (non-continuation) messages consumed so far across all sessions. */
51
52
  get consumedRealCount() {
52
53
  return this.consumedReal;
@@ -127,8 +128,10 @@ export class Mailbox {
127
128
  * the generator; redelivering would duplicate work and can livelock the
128
129
  * restart loop).
129
130
  */
130
- async *stream(sessionId = '') {
131
+ async *stream(sessionId = '', opts = {}) {
131
132
  const gen = ++this.generation;
133
+ this.lastStreamEndValue = undefined;
134
+ let yielded = false;
132
135
  // Drop (never resolve) any stale waker — see detach().
133
136
  this.wake = null;
134
137
  // A fresh generator starts with nothing in flight — any prior value
@@ -141,7 +144,16 @@ export class Mailbox {
141
144
  return; // superseded — leave the queue for the live generator
142
145
  if (this.draining)
143
146
  return;
147
+ // D3: a message belonging to another model session ends this stream
148
+ // (so its query() ends and the process exits) and stays queued for
149
+ // the session that owns it. Never applied to the first message —
150
+ // the caller chose this session FOR that message.
151
+ if (yielded && opts.stopBefore?.(this.queue[0])) {
152
+ this.lastStreamEndValue = 'boundary';
153
+ return;
154
+ }
144
155
  const content = this.queue.shift();
156
+ yielded = true;
145
157
  if (!content.startsWith(Mailbox.CONTINUE_PREFIX))
146
158
  this.consumedReal++;
147
159
  this.inFlight = content;
@@ -162,11 +174,46 @@ export class Mailbox {
162
174
  }
163
175
  if (this.closed || gen !== this.generation || this.draining)
164
176
  return;
165
- await new Promise((r) => {
166
- this.wake = r;
177
+ const woke = await new Promise((r) => {
178
+ this.wake = () => r(true);
179
+ if (opts.idleExitMs !== undefined) {
180
+ const t = setTimeout(() => r(false), opts.idleExitMs);
181
+ t.unref?.();
182
+ }
167
183
  });
168
184
  if (gen !== this.generation)
169
185
  return;
186
+ if (!woke) {
187
+ // D3: idle long enough — end the stream so the role's process can
188
+ // exit; the next push waits in the queue for a resumed session.
189
+ this.wake = null;
190
+ this.lastStreamEndValue = 'idle';
191
+ return;
192
+ }
193
+ }
194
+ }
195
+ /** Why the most recent stream() returned early, if it did: 'boundary'
196
+ * (stopBefore rejected the next message) or 'idle' (idleExitMs elapsed). */
197
+ get lastStreamEnd() {
198
+ return this.lastStreamEndValue;
199
+ }
200
+ /** The next queued message, without consuming it. */
201
+ peek() {
202
+ return this.queue[0];
203
+ }
204
+ /** Resolves true once a message is queued, false if the mailbox closes or
205
+ * drains first. Used to keep a role's process down while it has no mail. */
206
+ async waitForMessage() {
207
+ while (true) {
208
+ if (this.draining)
209
+ return false;
210
+ if (this.queue.length > 0)
211
+ return true;
212
+ if (this.closed)
213
+ return false;
214
+ await new Promise((r) => {
215
+ this.wake = r;
216
+ });
170
217
  }
171
218
  }
172
219
  /** Called by the crash-retry path right after a session dies abnormally. If
@@ -1 +1 @@
1
- {"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../../../src/orgrt/mailbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../../../src/orgrt/mailbox.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,17 @@ export type Decision = {
7
7
  behavior: 'deny';
8
8
  message: string;
9
9
  };
10
+ /** ADR-O001 D1: the four token quantities an Anthropic response bills for.
11
+ * They are SIBLINGS, not subsets — `input` is the uncached remainder only,
12
+ * while `cacheRead` (~0.1x input) and `cacheCreation` (~1.25x input) are
13
+ * billed on top of it. Summing only `input + output`, as this engine used
14
+ * to, reports ~0.3% of real consumption on a well-cached run. */
15
+ export interface TokenUsage {
16
+ input: number;
17
+ output: number;
18
+ cacheRead: number;
19
+ cacheCreation: number;
20
+ }
10
21
  export declare function redactSecrets(text: string): string;
11
22
  /** #289: the bounded, redacted slice of a tool's result body that goes on the
12
23
  * bus. Redacts BEFORE truncating, so a cut-off credential can't leak the way
@@ -45,7 +56,8 @@ export declare class PolicyEngine {
45
56
  * lists (file-roots.ts's `fileToolDenied()`) still apply inside every
46
57
  * root, cwd included — see the deny pass below. */
47
58
  private roots;
48
- private used;
59
+ /** ADR-O001 D1: the four billable quantities, tracked separately. */
60
+ private tokens;
49
61
  /** ORG-7: accumulated USD cost for this role, mirrors `used` (tokens). */
50
62
  private usedUsd;
51
63
  private toolContext;
@@ -62,10 +74,38 @@ export declare class PolicyEngine {
62
74
  * daemon derived at spawn (maxTokens/maxUsd) are kept unless the new policy
63
75
  * sets them itself. */
64
76
  updatePolicy(next: RolePolicy): void;
77
+ /** Legacy scalar accumulator. A caller with no breakdown to give (a
78
+ * pre-ADR-O001 checkpoint, a runner that reports one number) lands on the
79
+ * uncached `input` bucket — the basis such a number has always been on —
80
+ * so it counts toward both `usage` and `budgetedUsage` and nothing that
81
+ * used to bind stops binding. */
65
82
  addUsage(tokens: number): void;
83
+ /** ADR-O001 D1: add one turn's real usage, per quantity. */
84
+ addTokenUsage(u: Partial<TokenUsage>): void;
85
+ /** The honest meter: every billable token this role has consumed, cache
86
+ * reads and cache writes included. Reporting, checkpoints and dashboards
87
+ * read this. */
66
88
  get usage(): number;
67
- /** Set usage counter directly for checkpoint/resume - Pattern 3 */
89
+ /** The four quantities, for per-role persistence (checkpoint.ts). */
90
+ get tokenUsage(): TokenUsage;
91
+ /** ADR-O001 D1: what `maxTokens` (role.budget_tokens / run_config.budget_tokens)
92
+ * is compared against.
93
+ *
94
+ * It deliberately is NOT `usage`. Counting cache tokens multiplies the
95
+ * observed volume by ~100x on a well-cached run, so an existing
96
+ * `budget_tokens` — including the schema's 1M default, which every org
97
+ * gets whether or not it asked for one — would exhaust within a couple of
98
+ * turns and close every mailbox. The meter therefore becomes honest while
99
+ * the budget keeps the basis it was written against, unless a config opts
100
+ * in via `run_config.budget_tokens_basis: 'billable'`. USD budgets
101
+ * (`budget_usd`) are unaffected and are the control ADR-O001 recommends. */
102
+ get budgetedUsage(): number;
103
+ /** Set usage counter directly for checkpoint/resume - Pattern 3.
104
+ * Scalar form: a pre-ADR-O001 checkpoint has no breakdown to restore, so
105
+ * the value lands on the legacy (uncached) basis it was recorded on. */
68
106
  setUsage(tokens: number): void;
107
+ /** Restore a persisted breakdown (checkpoint.ts's `tokenUsage`). */
108
+ setTokenUsage(u: TokenUsage): void;
69
109
  get overBudget(): boolean;
70
110
  /** ORG-7: accumulate real USD cost (from 'usage' bus events' data.cost_usd). */
71
111
  addUsageUsd(costUsd: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/orgrt/policy.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,YAAY,CAAC;AAE3E,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC5D;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAgD1C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;mFAGmF;AACnF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CASA;AAID;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA6BjD;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC;kFAC8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAClC,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CAC7D;AAID,qBAAa,YAAY;IAMrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACd,MAAM,EAAE,UAAU;IACzB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,GAAG;IACX;;;;wDAIoD;IACpD,OAAO,CAAC,KAAK;IAdf,OAAO,CAAC,IAAI,CAAK;IACjB,0EAA0E;IAC1E,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,WAAW,CAAyB;IAC5C,YACW,IAAI,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM;IACnB;;;;wDAIoD;IAC5C,KAAK,GAAE,MAAM,EAAO,EAC1B;IAEJ,4DAA4D;IAC5D,cAAc,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAE3C;IAED;;4BAEwB;IACxB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAMnC;IAED,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE7B;IACD,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE7B;IACD,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,gFAAgF;IAChF,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjC;IACD,IAAI,QAAQ,IAAI,MAAM,CAErB;IACD,gFAAgF;IAChF,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjC;IACD;;wEAEoE;IACpE,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED;;;yEAGqE;IAC/D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqM7F;CACF;AAED;;2EAE2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOvE;AAwCD;0CAC0C;AAC1C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE1F"}
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/orgrt/policy.ts"],"names":[],"mappings":"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"}