@rubytech/create-realagent-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.
- package/dist/__tests__/email-sampler-unit.test.js +22 -0
- package/dist/index.js +3 -0
- package/dist/port-resolution.js +9 -1
- package/package.json +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.d.ts +46 -2
- package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.js +84 -32
- package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
- package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +0 -0
- package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +48 -2
- package/payload/platform/lib/routine-templates/src/roster.ts +133 -35
- package/payload/platform/lib/telegram-store-read/dist/index.d.ts +59 -0
- package/payload/platform/lib/telegram-store-read/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/telegram-store-read/dist/index.js +219 -0
- package/payload/platform/lib/telegram-store-read/dist/index.js.map +1 -0
- package/payload/platform/lib/telegram-store-read/src/__tests__/fold.test.ts +124 -0
- package/payload/platform/lib/telegram-store-read/src/index.ts +262 -0
- package/payload/platform/lib/telegram-store-read/tsconfig.json +9 -0
- package/payload/platform/lib/telegram-store-read/vitest.config.ts +9 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -6
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +11 -0
- package/payload/platform/plugins/connector/PLUGIN.md +9 -1
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.d.ts +2 -0
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.d.ts.map +1 -0
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.js +67 -0
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.js.map +1 -0
- package/payload/platform/plugins/connector/mcp/dist/index.js +36 -5
- package/payload/platform/plugins/connector/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts +35 -0
- package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts.map +1 -1
- package/payload/platform/plugins/connector/mcp/dist/lib/store.js +33 -0
- package/payload/platform/plugins/connector/mcp/dist/lib/store.js.map +1 -1
- package/payload/platform/plugins/connector/mcp/package.json +4 -2
- package/payload/platform/plugins/connector/mcp/vitest.config.ts +8 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/docs/references/outlook-guide.md +21 -2
- package/payload/platform/plugins/docs/references/telegram-guide.md +15 -1
- package/payload/platform/plugins/email/PLUGIN.md +14 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.js +233 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js +30 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/main.js +68 -3
- package/payload/platform/plugins/email/mcp/dist/sampler/main.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.d.ts +3 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.js +146 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.d.ts +150 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.js +199 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts +5 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js +10 -5
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js +11 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +8 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js +324 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js +102 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js +125 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js +109 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts +25 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js +94 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts +41 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js +122 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts +73 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js +162 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js.map +1 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +8 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js +90 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +26 -4
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts +78 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js +76 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +8 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +15 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +12 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +34 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +40 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +435 -5
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +21 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +294 -6
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +553 -11
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/public/operator.html +1 -1
- package/payload/server/server.js +69 -5
|
@@ -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}`);
|
package/dist/port-resolution.js
CHANGED
|
@@ -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
|
@@ -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 =
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;;;
|
|
1
|
+
{"version":3,"file":"roster.js","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
|
@@ -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
|
-
|
|
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
|
+
});
|