@rubytech/create-maxy-code 0.1.603 → 0.1.605

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 (153) hide show
  1. package/dist/__tests__/email-sampler-unit.test.js +22 -0
  2. package/dist/index.js +3 -0
  3. package/dist/port-resolution.js +9 -1
  4. package/package.json +1 -1
  5. package/payload/platform/lib/routine-templates/dist/roster.d.ts +46 -2
  6. package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
  7. package/payload/platform/lib/routine-templates/dist/roster.js +84 -32
  8. package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
  9. package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +0 -0
  10. package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +48 -2
  11. package/payload/platform/lib/routine-templates/src/roster.ts +133 -35
  12. package/payload/platform/lib/telegram-store-read/dist/index.d.ts +59 -0
  13. package/payload/platform/lib/telegram-store-read/dist/index.d.ts.map +1 -0
  14. package/payload/platform/lib/telegram-store-read/dist/index.js +219 -0
  15. package/payload/platform/lib/telegram-store-read/dist/index.js.map +1 -0
  16. package/payload/platform/lib/telegram-store-read/src/__tests__/fold.test.ts +124 -0
  17. package/payload/platform/lib/telegram-store-read/src/index.ts +262 -0
  18. package/payload/platform/lib/telegram-store-read/tsconfig.json +9 -0
  19. package/payload/platform/lib/telegram-store-read/vitest.config.ts +9 -0
  20. package/payload/platform/package.json +2 -2
  21. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -6
  22. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +11 -0
  23. package/payload/platform/plugins/connector/PLUGIN.md +9 -1
  24. package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.d.ts +2 -0
  25. package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.d.ts.map +1 -0
  26. package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.js +67 -0
  27. package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.js.map +1 -0
  28. package/payload/platform/plugins/connector/mcp/dist/index.js +36 -5
  29. package/payload/platform/plugins/connector/mcp/dist/index.js.map +1 -1
  30. package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts +35 -0
  31. package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts.map +1 -1
  32. package/payload/platform/plugins/connector/mcp/dist/lib/store.js +33 -0
  33. package/payload/platform/plugins/connector/mcp/dist/lib/store.js.map +1 -1
  34. package/payload/platform/plugins/connector/mcp/package.json +4 -2
  35. package/payload/platform/plugins/connector/mcp/vitest.config.ts +8 -0
  36. package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
  37. package/payload/platform/plugins/docs/references/outlook-guide.md +21 -2
  38. package/payload/platform/plugins/docs/references/telegram-guide.md +15 -1
  39. package/payload/platform/plugins/email/PLUGIN.md +14 -1
  40. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.d.ts +2 -0
  41. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.d.ts.map +1 -0
  42. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.js +233 -0
  43. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.js.map +1 -0
  44. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js +30 -0
  45. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js.map +1 -1
  46. package/payload/platform/plugins/email/mcp/dist/sampler/main.js +68 -3
  47. package/payload/platform/plugins/email/mcp/dist/sampler/main.js.map +1 -1
  48. package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.d.ts +3 -0
  49. package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.d.ts.map +1 -0
  50. package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.js +146 -0
  51. package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.js.map +1 -0
  52. package/payload/platform/plugins/email/mcp/dist/sampler/retention.d.ts +150 -0
  53. package/payload/platform/plugins/email/mcp/dist/sampler/retention.d.ts.map +1 -0
  54. package/payload/platform/plugins/email/mcp/dist/sampler/retention.js +199 -0
  55. package/payload/platform/plugins/email/mcp/dist/sampler/retention.js.map +1 -0
  56. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts +5 -0
  57. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts.map +1 -1
  58. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js +10 -5
  59. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js.map +1 -1
  60. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js +11 -0
  61. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js.map +1 -1
  62. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  63. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +8 -0
  64. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  65. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts +2 -0
  66. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts.map +1 -0
  67. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js +324 -0
  68. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js.map +1 -0
  69. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts +2 -0
  70. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts.map +1 -0
  71. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js +102 -0
  72. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js.map +1 -0
  73. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts +2 -0
  74. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts.map +1 -0
  75. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js +125 -0
  76. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js.map +1 -0
  77. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts +2 -0
  78. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts.map +1 -0
  79. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js +109 -0
  80. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js.map +1 -0
  81. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts +25 -0
  82. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts.map +1 -0
  83. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js +94 -0
  84. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js.map +1 -0
  85. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts +41 -0
  86. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts.map +1 -0
  87. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js +122 -0
  88. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js.map +1 -0
  89. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts +73 -0
  90. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts.map +1 -0
  91. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js +162 -0
  92. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js.map +1 -0
  93. package/payload/platform/plugins/scheduling/PLUGIN.md +8 -1
  94. package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
  95. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  96. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts +2 -0
  97. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts.map +1 -0
  98. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js +90 -0
  99. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js.map +1 -0
  100. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +26 -4
  101. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
  102. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts +78 -0
  103. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts.map +1 -0
  104. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js +76 -0
  105. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js.map +1 -0
  106. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +8 -0
  107. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
  108. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +9 -1
  109. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
  110. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +15 -0
  111. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -1
  112. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +12 -1
  113. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  114. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +34 -1
  115. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  116. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +9 -1
  117. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  118. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +40 -0
  119. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -1
  120. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +435 -5
  121. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
  122. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
  123. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +21 -1
  124. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
  125. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +294 -6
  126. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
  127. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +553 -11
  128. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
  129. package/payload/platform/plugins/telegram/PLUGIN.md +1 -1
  130. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.d.ts +2 -0
  131. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.d.ts.map +1 -0
  132. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.js +157 -0
  133. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.js.map +1 -0
  134. package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin.test.js +2 -2
  135. package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin.test.js.map +1 -1
  136. package/payload/platform/plugins/telegram/mcp/dist/index.js +32 -34
  137. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  138. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js +1 -1
  139. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js.map +1 -1
  140. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.d.ts +27 -0
  141. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.d.ts.map +1 -0
  142. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.js +152 -0
  143. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.js.map +1 -0
  144. package/payload/platform/plugins/telegram/skills/build/SKILL.md +1 -1
  145. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -1
  146. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  147. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  148. package/payload/server/public/operator.html +1 -1
  149. package/payload/server/server.js +69 -5
  150. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts +0 -16
  151. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts.map +0 -1
  152. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js +0 -68
  153. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js.map +0 -1
@@ -29,3 +29,25 @@ test("carries the plugin runtime env and the brand .env", () => {
29
29
  assert.match(unit, /^Environment=EMAIL_SAMPLER_INTERVAL_SEC=60$/m);
30
30
  assert.match(unit, /^EnvironmentFile=-\/home\/x\/\.maxy\/\.env$/m);
31
31
  });
32
+ // Task 2683 — the Outlook arm shares this unit's process, so it needs the same
33
+ // Azure app credentials the session-manager unit carries. Without them
34
+ // callGraph cannot refresh an access token, so every Outlook mailbox would
35
+ // sample correctly until its current token expired and then error permanently.
36
+ test("a brand with an outlook client id stamps both outlook env lines", () => {
37
+ const withOutlook = buildEmailSamplerUnitFile({
38
+ productName: "Maxy",
39
+ installDir: "/home/x/maxy-code",
40
+ persistDir: "/home/x/.maxy",
41
+ accountId: "acc-1",
42
+ logPath: "/home/x/.maxy/logs/email-sampler.log",
43
+ outlookClientId: "azure-app-id",
44
+ });
45
+ assert.match(withOutlook, /^Environment=OUTLOOK_CLIENT_ID=azure-app-id$/m);
46
+ assert.match(withOutlook, /^Environment=OUTLOOK_TENANT_ID=common$/m);
47
+ // Both land above EnvironmentFile so the brand .env can still override.
48
+ assert.ok(withOutlook.indexOf("OUTLOOK_TENANT_ID") < withOutlook.indexOf("EnvironmentFile="), "outlook env must precede EnvironmentFile");
49
+ });
50
+ test("a brand with no outlook client id stamps neither outlook env line", () => {
51
+ assert.doesNotMatch(unit, /OUTLOOK_CLIENT_ID/);
52
+ assert.doesNotMatch(unit, /OUTLOOK_TENANT_ID/);
53
+ });
package/dist/index.js CHANGED
@@ -4582,6 +4582,9 @@ WantedBy=default.target
4582
4582
  persistDir,
4583
4583
  accountId: installAccountId,
4584
4584
  logPath: emailSamplerLogPath,
4585
+ // Task 2683 — the sampler's Outlook arm runs in this process and needs the
4586
+ // brand's Azure app to refresh a token.
4587
+ outlookClientId: BRAND.outlookClientId,
4585
4588
  });
4586
4589
  writeFileSync(join(serviceDir, emailSamplerUnitName), emailSamplerUnit);
4587
4590
  logFile(` email-sampler installed: ${emailSamplerUnitName} LOG_PATH=${emailSamplerLogPath}`);
@@ -172,6 +172,14 @@ WantedBy=default.target
172
172
  `;
173
173
  }
174
174
  export function buildEmailSamplerUnitFile(o) {
175
+ // Task 2683 — the Outlook arm runs inside this unit's process, so it needs the
176
+ // same Azure app credentials the session-manager unit carries. Both lines land
177
+ // together so OUTLOOK_TENANT_ID never trails a bare client id. Without them
178
+ // callGraph cannot refresh an access token, so every Outlook mailbox would
179
+ // sample correctly until its current token expired and then error for ever.
180
+ const outlookEnv = o.outlookClientId
181
+ ? `\nEnvironment=OUTLOOK_CLIENT_ID=${o.outlookClientId}\nEnvironment=OUTLOOK_TENANT_ID=common`
182
+ : "";
175
183
  return `[Unit]
176
184
  Description=${o.productName} Email Sampler
177
185
  After=network.target
@@ -186,7 +194,7 @@ Environment=NODE_ENV=production
186
194
  Environment=ACCOUNT_ID=${o.accountId}
187
195
  Environment=PLATFORM_ROOT=${o.installDir}/platform
188
196
  Environment=EMAIL_SAMPLER_LOG_PATH=${o.logPath}
189
- Environment=EMAIL_SAMPLER_INTERVAL_SEC=${o.intervalSec ?? 60}
197
+ Environment=EMAIL_SAMPLER_INTERVAL_SEC=${o.intervalSec ?? 60}${outlookEnv}
190
198
  EnvironmentFile=-${o.persistDir}/.env
191
199
  StandardOutput=append:${o.persistDir}/logs/server.log
192
200
  StandardError=append:${o.persistDir}/logs/server.log
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.603",
3
+ "version": "0.1.605",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -34,7 +34,7 @@
34
34
  * routine's prompt only when the stored `routineTemplateVersion` is BELOW this
35
35
  * and no operator has edited the row, so an unbumped edit ships to new installs
36
36
  * and never reaches existing ones — bump it in the same commit as the edit. */
37
- export declare const ROUTINE_TEMPLATE_VERSION = 6;
37
+ export declare const ROUTINE_TEMPLATE_VERSION = 10;
38
38
  /**
39
39
  * Task 2379 — the check shapes a shipped template may name.
40
40
  *
@@ -76,7 +76,51 @@ export interface RoutineGraphCheck {
76
76
  readonly type: "graph";
77
77
  readonly scope: "appointments";
78
78
  }
79
- export type RoutineGateCheck = RoutineMailCheck | RoutineD1Check | RoutineWhatsappCheck | RoutineCalendarCheck | RoutineTelegramCheck | RoutineGraphCheck;
79
+ /** Task 2684 nodes of one label this routine has not yet flagged processed.
80
+ *
81
+ * The other graph check compares one stored timestamp, which can skip a node
82
+ * written between the probe and the promote. This one holds no position at all:
83
+ * "outstanding for this routine" is an exact set, so a node the probe missed is
84
+ * simply still unflagged next fire.
85
+ *
86
+ * `label` is a closed pair rather than a free string because a Cypher label
87
+ * cannot be a parameter. `Section` and `ConversationArchive` are different
88
+ * grains: sections are written per ingest, so new content always arrives
89
+ * unflagged, while an archive is MERGEd per thread, so a reply into a thread
90
+ * this routine already flagged leaves that node flagged. */
91
+ export interface RoutineGraphUnflaggedCheck {
92
+ readonly type: "graph-unflagged";
93
+ readonly label: "ConversationArchive" | "Section";
94
+ }
95
+ /** Task 2689 — the memory sweep's own state: its two review queues, and whether
96
+ * it has stopped running. No fields, because an account has exactly one sweep
97
+ * and one of each queue. What is compared is a digest, so the routine wakes
98
+ * when a queue moves or the sweep goes silent, never merely because the sweep
99
+ * ran again — it runs hourly and this routine is weekly. */
100
+ /** Task 2688 — records changed in a connector this account registered, since
101
+ * the routine last woke.
102
+ *
103
+ * `scope` is a KIND of connector, never a name: the account describes the
104
+ * queue once, on the connector's own registry record, and the template names
105
+ * only which kind it watches. That is what lets a shipped template gate on a
106
+ * third-party system at all, since it can carry no per-account value (Task
107
+ * 2389). A connector that is not registered, or whose credential is refused,
108
+ * answers quiet, so the routine no-ops rather than erroring every fire. */
109
+ export interface RoutineConnectorCheck {
110
+ readonly type: "connector";
111
+ readonly scope: "operational" | "accounting";
112
+ }
113
+ export interface RoutineSweepCheck {
114
+ readonly type: "sweep";
115
+ }
116
+ /** Task 2689 — growth under the account's own directory since the last accepted
117
+ * wake. `minGrowthBytes` is a size rather than per-account data, so a shipped
118
+ * template may name it and still be correct on every install. */
119
+ export interface RoutineFilesystemCheck {
120
+ readonly type: "filesystem";
121
+ readonly minGrowthBytes?: number;
122
+ }
123
+ export type RoutineGateCheck = RoutineMailCheck | RoutineD1Check | RoutineWhatsappCheck | RoutineCalendarCheck | RoutineTelegramCheck | RoutineGraphCheck | RoutineGraphUnflaggedCheck | RoutineConnectorCheck | RoutineSweepCheck | RoutineFilesystemCheck;
80
124
  /** The plugin and the tool are constants for every roster gate, so a template
81
125
  * carries neither. `hasWork` is true when ANY check is true. */
82
126
  export interface RoutineGate {
@@ -1 +1 @@
1
- {"version":3,"file":"roster.d.ts","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH;;;gFAGgF;AAChF,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AACD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;CACtC;AACD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AACD;iDACiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AACD;2EAC2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC;AACD,MAAM,MAAM,gBAAgB,GACxB,gBAAgB,GAChB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,oBAAoB,GACpB,iBAAiB,CAAC;AAEtB;iEACiE;AACjE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC9C;AAWD;;;;;;;;;;;4DAW4D;AAC5D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAUnE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAE1D;AAED,MAAM,WAAW,eAAe;IAC9B;;mEAE+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;6EAGyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;wEACoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;2CAIuC;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B;;;+DAG2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;2BAO2B;AAC3B,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAI/D;AA8KD;;;;;;;;iFAQiF;AACjF,eAAO,MAAM,cAAc,EAAE,SAAS,eAAe,EAiIpD,CAAC;AAEF;;6DAE6D;AAC7D,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAAqC,CAAC"}
1
+ {"version":3,"file":"roster.d.ts","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"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"}
@@ -40,7 +40,7 @@ exports.isClassified = isClassified;
40
40
  * routine's prompt only when the stored `routineTemplateVersion` is BELOW this
41
41
  * and no operator has edited the row, so an unbumped edit ships to new installs
42
42
  * and never reaches existing ones — bump it in the same commit as the edit. */
43
- exports.ROUTINE_TEMPLATE_VERSION = 6;
43
+ exports.ROUTINE_TEMPLATE_VERSION = 10;
44
44
  // Task 2663 — `GATE_COMMIT_TOKEN` is deleted. It stood in for a
45
45
  // `scheduling-gate` call the routine's own turn made to advance its watermark,
46
46
  // and the whole reason it had to be a token was that a template cannot write the
@@ -64,12 +64,33 @@ exports.ROUTINE_TEMPLATE_VERSION = 6;
64
64
  function isWatermarkedCheck(check) {
65
65
  if (check.type === "whatsapp")
66
66
  return check.scope === "inbound";
67
+ // Task 2684 — `graph-unflagged` is NOT watermarked, and it is the first check
68
+ // that is neither watermarked nor stateless. Its state is a flag on each node,
69
+ // written by the dispatcher on an accepted wake, so it needs no stored
70
+ // position and a routine gated only on it needs no commit line. It is listed
71
+ // by omission from the set below, and a test pins that: a later edit that
72
+ // added it here would make `gateNeedsCommit` demand a commit for a check that
73
+ // has no mark to advance.
74
+ //
67
75
  // Task 2681 — `graph` compares an ISO `updatedAt` against a stored one, so a
68
76
  // commitless graph gate reports work on every fire exactly as a mail one does.
77
+ //
78
+ // Task 2688 — `connector` holds one position PER registered connector, and
79
+ // compares each against the instant that connector's queue was last read, so
80
+ // it is watermarked for the same reason.
81
+ //
82
+ // Task 2689 — `sweep` compares a digest and `filesystem` compares a byte
83
+ // count, both against a stored value, so both belong here for the same
84
+ // reason. Their positions are promoted by the dispatcher on an accepted wake,
85
+ // which is what makes "since the last report" literal rather than "since the
86
+ // last fire".
69
87
  return (check.type === "mail" ||
70
88
  check.type === "calendar" ||
71
89
  check.type === "telegram" ||
72
- check.type === "graph");
90
+ check.type === "graph" ||
91
+ check.type === "connector" ||
92
+ check.type === "sweep" ||
93
+ check.type === "filesystem");
73
94
  }
74
95
  function gateNeedsCommit(gate) {
75
96
  return gate.checks.some(isWatermarkedCheck);
@@ -134,17 +155,6 @@ Tomorrow: list tomorrow's appointments with outlook-calendar-list or google-cale
134
155
  Say what is unfinished and what tomorrow looks like, in that order, in plain sentences. Do not congratulate, do not summarise the day back, do not pad the message to look thorough.
135
156
 
136
157
  If nothing is waiting, nothing is overdue and tomorrow is empty, end the turn without replying.`;
137
- const APPOINTMENT_REMINDER = `Remind the people attending an appointment that is coming up, so nobody is reminded twice and nobody is missed.
138
-
139
- Call capabilities-here first. If neither a mail plugin nor a messaging channel is enabled, end the turn without replying.
140
-
141
- Find appointments starting within the next reminder window with schedule-list, and read each one's attendees. Resolve each attendee to a person and a contact route with contact-lookup. An attendee you cannot resolve to a route is not a failure to work around: leave them, and say so at the end.
142
-
143
- Send each attendee one reminder on the route they are already reachable on: email-send for a mailbox, whatsapp-reply or the Telegram message tool for a messaging thread that already exists. Carry the time, the place and what the appointment is about. Do not open a new conversation with someone who has never messaged the business.
144
-
145
- Send at most one reminder per attendee per appointment. Before sending, check the appointment's notes for a reminder already recorded, and record the one you send there.
146
-
147
- Reply with one line naming who was reminded and who could not be reached. If no appointment falls in the window, end the turn without replying.`;
148
158
  const COMMITMENT_CHASE = `Find the promises the business has made and not kept, and the promises made to it that nobody has kept.
149
159
 
150
160
  Call capabilities-here first and use only the surfaces it reports.
@@ -261,7 +271,20 @@ exports.ROUTINE_ROSTER = [
261
271
  description: "Sends one morning message covering what needs a decision, what is time-bound and what changed overnight; stays silent when there is nothing worth saying.",
262
272
  recurrence: "30 7 * * 1-5",
263
273
  prompt: START_OF_DAY,
264
- gateless: "A morning briefing is judgement every fire, so a gate would either always pass or suppress the briefing.",
274
+ // Task 2686 the briefing's two gateable arms. `Section` rather than
275
+ // `ConversationArchive` on every email-driven row here: sections are written
276
+ // per ingest, so a reply into a thread this routine already flagged arrives
277
+ // as a fresh unflagged node, while the archive is MERGEd per thread and
278
+ // would stay flagged — muting the routine on the traffic it exists to read.
279
+ // The check names a label and not a source, so any ingested content wakes
280
+ // these rows, which over-wakes and never mutes. The briefing's third arm,
281
+ // open and overdue work, has no check type: Task 2714.
282
+ gate: {
283
+ checks: [
284
+ { type: "graph-unflagged", label: "Section" },
285
+ { type: "graph", scope: "appointments" },
286
+ ],
287
+ },
265
288
  },
266
289
  {
267
290
  key: "inbound-check",
@@ -269,7 +292,10 @@ exports.ROUTINE_ROSTER = [
269
292
  description: "Triages mail that arrived since the last check and writes replies for you to approve; it never sends anything itself.",
270
293
  recurrence: "*/30 9-17 * * 1-5",
271
294
  prompt: INBOUND_CHECK,
272
- gateless: "Conditional on new mail, but the mail check matches an exact mailbox address and no shipped template can name one (Task 2389).",
295
+ // Task 2686 the mail check still cannot name a mailbox, but the sampler
296
+ // puts every inbound message in the graph, so the unflagged-section check
297
+ // reaches the same mail without per-account data.
298
+ gate: { checks: [{ type: "graph-unflagged", label: "Section" }] },
273
299
  },
274
300
  {
275
301
  key: "telegram-inbound-check",
@@ -282,18 +308,18 @@ exports.ROUTINE_ROSTER = [
282
308
  {
283
309
  key: "end-of-day",
284
310
  name: "End of day wrap-up",
285
- description: "Closes the day with your unsent drafts, overdue work and tomorrow's diary; says nothing when all three are empty.",
311
+ description: "Closes the day with your unsent drafts, overdue work and tomorrow's diary, once new mail or a diary change has woken it.",
286
312
  recurrence: "0 18 * * 1-5",
287
313
  prompt: END_OF_DAY,
288
- gateless: "A wrap-up is judgement every fire, so no cheap check stands in for reading the three surfaces it reports.",
289
- },
290
- {
291
- key: "appointment-reminder",
292
- name: "Appointment reminders",
293
- description: "Reminds each attendee once before a booked appointment, on a route they already use; it never opens a conversation with a stranger.",
294
- recurrence: "0 * * * *",
295
- prompt: APPOINTMENT_REMINDER,
296
- gateless: "Conditional on an appointment falling in the window, but no check type reads appointments held in the graph (Task 2389).",
314
+ // Task 2686 — the wrap-up wakes on new mail or a diary change. Its other two
315
+ // surfaces, unsent drafts and overdue work, have no check type, so a day
316
+ // whose only outstanding item is one of those is silent until Task 2714.
317
+ gate: {
318
+ checks: [
319
+ { type: "graph-unflagged", label: "Section" },
320
+ { type: "graph", scope: "appointments" },
321
+ ],
322
+ },
297
323
  },
298
324
  {
299
325
  key: "commitment-chase",
@@ -301,7 +327,11 @@ exports.ROUTINE_ROSTER = [
301
327
  description: "Surfaces promises the business made and did not keep, and promises made to it that nobody kept; it reports them rather than chasing them.",
302
328
  recurrence: "0 10 * * 2",
303
329
  prompt: COMMITMENT_CHASE,
304
- gateless: "Whether a promise has been dropped is the judgement itself, so no check can answer it more cheaply.",
330
+ // Task 2686 a dropped promise is a judgement, but the correspondence it
331
+ // judges is not: this wakes when inbound mail it has not read is in the
332
+ // graph. Its outbound arm reads sent mail, which the sampler does not ingest
333
+ // and no shipped template can name a mailbox for: Task 2715.
334
+ gate: { checks: [{ type: "graph-unflagged", label: "Section" }] },
305
335
  },
306
336
  {
307
337
  key: "calendar-reconcile",
@@ -319,7 +349,9 @@ exports.ROUTINE_ROSTER = [
319
349
  description: "Reconciles the people you correspond with against the people on record, creating and updating contacts; it never merges two records that might be two people.",
320
350
  recurrence: "45 6 * * 1-5",
321
351
  prompt: CONTACT_RECONCILE,
322
- gateless: "Conditional on new correspondence, but no check type reads correspondence (Task 2389).",
352
+ // Task 2686 correspondence is readable now: the sampler writes it and the
353
+ // unflagged-section check counts what this routine has not reconciled.
354
+ gate: { checks: [{ type: "graph-unflagged", label: "Section" }] },
323
355
  },
324
356
  {
325
357
  key: "crm-reconcile",
@@ -327,7 +359,9 @@ exports.ROUTINE_ROSTER = [
327
359
  description: "Brings across what changed in whichever operational system this business runs; it reads only and never writes back to that system.",
328
360
  recurrence: "0 3 * * *",
329
361
  prompt: CRM_RECONCILE,
330
- gateless: "Conditional on connector movement, but no check type reads a connector queue (Task 2389).",
362
+ // Task 2688 wakes when a connector the account registered as its
363
+ // operational system holds records changed since the last accepted wake.
364
+ gate: { checks: [{ type: "connector", scope: "operational" }] },
331
365
  },
332
366
  {
333
367
  key: "finance-reconcile",
@@ -335,7 +369,10 @@ exports.ROUTINE_ROSTER = [
335
369
  description: "Reconciles the accounting system against the internal ledger and reports what does not agree; it never adjusts an entry to make the two sides match.",
336
370
  recurrence: "0 4 * * 1",
337
371
  prompt: FINANCE_RECONCILE,
338
- gateless: "Conditional on accounting movement, but no check type reads an accounting ledger (Task 2389).",
372
+ // Task 2688 wakes on movement in the connector the account registered as
373
+ // its accounting system. A connector that is absent or whose credential is
374
+ // refused answers quiet, so this no-ops rather than erroring every fire.
375
+ gate: { checks: [{ type: "connector", scope: "accounting" }] },
339
376
  },
340
377
  {
341
378
  key: "weekly-digest",
@@ -343,7 +380,15 @@ exports.ROUTINE_ROSTER = [
343
380
  description: "Writes the week in three paragraphs at most: what changed, what is stuck, and what next week turns on.",
344
381
  recurrence: "0 16 * * 5",
345
382
  prompt: WEEKLY_DIGEST,
346
- gateless: "A digest is judgement every fire, and a gate would suppress the report it exists to send.",
383
+ // Task 2686 a week with no correspondence and no diary movement has
384
+ // nothing to report movement on, so the digest is silent rather than
385
+ // writing three paragraphs about a week in which nothing happened.
386
+ gate: {
387
+ checks: [
388
+ { type: "graph-unflagged", label: "Section" },
389
+ { type: "graph", scope: "appointments" },
390
+ ],
391
+ },
347
392
  },
348
393
  {
349
394
  key: "channel-link-check",
@@ -359,7 +404,11 @@ exports.ROUTINE_ROSTER = [
359
404
  description: "Reports what the hourly graph sweep last did and what is waiting for review; it reads only and never runs the sweep itself.",
360
405
  recurrence: "0 9 * * 1",
361
406
  prompt: GRAPH_HEALTH,
362
- gateless: "Reports the sweep's state every fire by design, so there is nothing conditional to check.",
407
+ // Task 2689 — the sweep's state IS the delta. The digest carries the two
408
+ // review-queue counts and whether the sweep has stopped writing reports,
409
+ // never the newest report's identity: the sweep runs hourly, so a digest
410
+ // that moved on every run would make this weekly routine wake every fire.
411
+ gate: { checks: [{ type: "sweep" }] },
363
412
  },
364
413
  {
365
414
  key: "filesystem-health",
@@ -367,7 +416,10 @@ exports.ROUTINE_ROSTER = [
367
416
  description: "Reports what has grown under the account directory and which paths are worth attention; it deletes nothing.",
368
417
  recurrence: "0 9 * * 1",
369
418
  prompt: FILESYSTEM_HEALTH,
370
- gateless: "Reports what has grown every fire by design, so there is nothing conditional to check.",
419
+ // Task 2689 64 MiB of growth under the account directory since the last
420
+ // report. What has ACCUMULATED is the question, so an account that is large
421
+ // and stable has nothing new to say and the routine stays silent.
422
+ gate: { checks: [{ type: "filesystem", minGrowthBytes: 67108864 }] },
371
423
  },
372
424
  ];
373
425
  /** Every roster key, in roster order. The scheduling heartbeat's `op=roster`
@@ -1 +1 @@
1
- {"version":3,"file":"roster.js","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"roster.js","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,7 @@ import {
25
25
  type RoutineMergeAction,
26
26
  type SeedSessionLike,
27
27
  } from "../index.js";
28
- import { isClassified } from "../roster.js";
28
+ import { isClassified, type RoutineGateCheck } from "../roster.js";
29
29
 
30
30
  interface FakeCall {
31
31
  query: string;
@@ -415,7 +415,28 @@ describe("gate seeding", () => {
415
415
  expect(byKey.get("channel-link-check")).toBe('[{"type":"whatsapp","scope":"status"}]');
416
416
  expect(byKey.get("calendar-reconcile")).toBe('[{"type":"calendar","connector":"account"},{"type":"graph","scope":"appointments"}]');
417
417
  expect(byKey.get("telegram-inbound-check")).toBe('[{"type":"telegram","scope":"inbound"}]');
418
- expect(byKey.get("weekly-digest")).toBeNull();
418
+ // Task 2686 — weekly-digest is gated now, so the null example moved to a row
419
+ // that is still gateless, and the digest's own two checks are asserted here.
420
+ expect(byKey.get("weekly-digest")).toBe(
421
+ '[{"type":"graph-unflagged","label":"Section"},{"type":"graph","scope":"appointments"}]',
422
+ );
423
+ expect(byKey.get("inbound-check")).toBe('[{"type":"graph-unflagged","label":"Section"}]');
424
+ // Task 2689 — the gateless example is DERIVED rather than named. 2686 gated
425
+ // six rows and moved this assertion onto `graph-health`; 2689 gated
426
+ // `graph-health` and `filesystem-health`, so it moved again. Every row still
427
+ // carrying a reason is a target of 2687 or 2688, so naming one would break
428
+ // on their landing too. When 2691 removes the field, the `!` here throws and
429
+ // points at the assertion that has to go with it.
430
+ // Task 2688 — there is no gateless row left to sample. 2686 gated six rows
431
+ // and moved this assertion onto `graph-health`; 2689 gated `graph-health`
432
+ // and `filesystem-health`, so it moved again; 2687 withdrew
433
+ // `appointment-reminder` and 2688 gated the last two, which leaves the
434
+ // shipped roster carrying no `gateless` reason at all. The seed's null arm
435
+ // is now unreachable from this roster and dies with the field in Task 2691,
436
+ // so what is asserted here is the fact that replaced it: every shipped row
437
+ // seeds serialised checks, and none seeds null.
438
+ expect(ROUTINE_ROSTER.filter((r) => r.gate == null)).toEqual([]);
439
+ expect([...byKey.values()].filter((v) => v === null)).toEqual([]);
419
440
  });
420
441
 
421
442
  it("serialises the checks in exactly one place", () => {
@@ -437,3 +458,28 @@ describe("telegram-inbound-check template (Task 2675)", () => {
437
458
  expect(gateNeedsCommit(tg.gate!)).toBe(true);
438
459
  });
439
460
  });
461
+
462
+ // Task 2684 — the unflagged-node check carries no stored position, so it must
463
+ // never join the watermarked set. If it did, `gateNeedsCommit` would demand a
464
+ // commit for a check with no mark to advance, and `schedule-audit`'s stalled-
465
+ // mark check would measure a routine against a file it never writes.
466
+ describe("graph-unflagged check classification (Task 2684)", () => {
467
+ const CHECK: RoutineGateCheck = { type: "graph-unflagged", label: "Section" };
468
+
469
+ it("is not watermarked — its state is the flag on each node", () => {
470
+ expect(isWatermarkedCheck(CHECK)).toBe(false);
471
+ });
472
+
473
+ it("needs no commit when it is a gate's only check", () => {
474
+ expect(gateNeedsCommit({ checks: [CHECK] })).toBe(false);
475
+ });
476
+
477
+ it("does not suppress a watermarked sibling's commit", () => {
478
+ expect(gateNeedsCommit({ checks: [CHECK, { type: "telegram", scope: "inbound" }] })).toBe(true);
479
+ });
480
+
481
+ it("accepts both grains the email sampler writes", () => {
482
+ const archives: RoutineGateCheck = { type: "graph-unflagged", label: "ConversationArchive" };
483
+ expect(isWatermarkedCheck(archives)).toBe(false);
484
+ });
485
+ });