toolroll 0.9.51 → 0.9.53
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/CHANGELOG.md +20 -0
- package/README.md +55 -80
- package/dist/agentconfig.d.ts +11 -36
- package/dist/agentconfig.js +3 -62
- package/dist/approval-policy.d.ts +1 -1
- package/dist/approval-policy.js +1 -1
- package/dist/backup.d.ts +8 -0
- package/dist/backup.js +10 -1
- package/dist/board.d.ts +3 -19
- package/dist/board.js +4 -42
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +18 -18
- package/dist/browser-workspace.d.ts +3 -1
- package/dist/builder.d.ts +9 -40
- package/dist/builder.js +50 -257
- package/dist/chat-actions.js +3 -14
- package/dist/chat-controls.d.ts +0 -4
- package/dist/chat-controls.js +0 -1
- package/dist/chat-decide.js +1 -3
- package/dist/chat-delivery.d.ts +0 -2
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-quiet.js +2 -2
- package/dist/chat-task-actions.d.ts +1 -1
- package/dist/chat-task-actions.js +0 -2
- package/dist/claim.d.ts +79 -244
- package/dist/claim.js +688 -1023
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +10 -2
- package/dist/contracts/cli.d.ts +0 -13
- package/dist/contracts/cli.js +0 -2
- package/dist/contracts/console-api.d.ts +5 -10
- package/dist/contracts/console-api.js +4 -10
- package/dist/contracts/flow.d.ts +50 -0
- package/dist/contracts/flow.js +26 -1
- package/dist/contracts/lead-tools.d.ts +0 -13
- package/dist/contracts/lead-tools.js +3 -3
- package/dist/contracts/store-json.d.ts +1 -25
- package/dist/contracts/store-json.js +3 -13
- package/dist/converse.d.ts +1 -11
- package/dist/converse.js +6 -38
- package/dist/coordinator.d.ts +0 -1
- package/dist/coordinator.js +3 -5
- package/dist/database-reclaim.d.ts +4 -0
- package/dist/database-reclaim.js +13 -0
- package/dist/demo.d.ts +1 -1
- package/dist/demo.js +17 -27
- package/dist/desktop-update-gate.js +0 -1
- package/dist/desktop-update.d.ts +1 -1
- package/dist/desktop-update.js +1 -3
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/dispose.d.ts +2 -3
- package/dist/dispose.js +17 -92
- package/dist/envelope.js +0 -3
- package/dist/exec.d.ts +0 -64
- package/dist/exec.js +3 -356
- package/dist/exhaustion.d.ts +22 -76
- package/dist/exhaustion.js +14 -140
- package/dist/export.js +4 -4
- package/dist/flow-engine.js +1 -1
- package/dist/flow-schedule.d.ts +154 -0
- package/dist/flow-schedule.js +321 -0
- package/dist/flow-share.js +1 -1
- package/dist/flow-triggers.d.ts +6 -1
- package/dist/flow-triggers.js +65 -10
- package/dist/flows-cli.js +8 -4
- package/dist/flows-ui.js +2 -0
- package/dist/flows.js +1 -1
- package/dist/guides.js +9 -29
- package/dist/invoke.d.ts +1 -24
- package/dist/invoke.js +17 -259
- package/dist/lead-status.js +2 -4
- package/dist/lead-voice.js +1 -1
- package/dist/live-bus.d.ts +3 -3
- package/dist/live-bus.js +3 -3
- package/dist/mate-doors.d.ts +1 -2
- package/dist/mate-doors.js +12 -25
- package/dist/mate-tools.d.ts +2 -2
- package/dist/mate-tools.js +10 -22
- package/dist/modes.d.ts +6 -7
- package/dist/modes.js +7 -13
- package/dist/monitoring.js +32 -8
- package/dist/notification-delivery.d.ts +19 -0
- package/dist/notification-delivery.js +37 -0
- package/dist/operate-remote-arguments.js +2 -6
- package/dist/operate-remote.js +6 -7
- package/dist/operate.d.ts +0 -6
- package/dist/operate.js +283 -2378
- package/dist/phase-routing.d.ts +13 -23
- package/dist/phase-routing.js +13 -35
- package/dist/plan-auto.js +2 -2
- package/dist/planner-source.js +2 -1
- package/dist/policy.d.ts +1 -4
- package/dist/policy.js +0 -8
- package/dist/process-recovery-eligibility.js +2 -3
- package/dist/process-recovery-settlement.js +1 -0
- package/dist/project-delete.js +3 -15
- package/dist/proposal.d.ts +4 -24
- package/dist/proposal.js +3 -88
- package/dist/provider-auth.d.ts +3 -3
- package/dist/provider-auth.js +4 -6
- package/dist/provider.d.ts +11 -25
- package/dist/provider.js +4 -36
- package/dist/push.js +1 -1
- package/dist/recipe-ui.js +6 -6
- package/dist/recipes.d.ts +3 -3
- package/dist/recipes.js +27 -23
- package/dist/retention.js +6 -5
- package/dist/run-closeout.d.ts +1 -1
- package/dist/run-closeout.js +1 -4
- package/dist/scope.d.ts +11 -65
- package/dist/scope.js +17 -82
- package/dist/serve.js +16 -25
- package/dist/server/chat.js +7 -30
- package/dist/server/flows.js +11 -10
- package/dist/server/guards.js +0 -1
- package/dist/server/pages-assets.js +1 -1
- package/dist/server/pages.js +0 -2
- package/dist/server/people-tokens.js +0 -4
- package/dist/server/route-table.d.ts +1 -1
- package/dist/server/route-table.js +2 -17
- package/dist/server/settings.js +4 -9
- package/dist/server/shared.d.ts +29 -212
- package/dist/server/shared.js +73 -780
- package/dist/server/task-views.js +9 -76
- package/dist/server/tasks.d.ts +1 -50
- package/dist/server/tasks.js +36 -946
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.d.ts +0 -2
- package/dist/slack-chat.js +0 -1
- package/dist/store.d.ts +142 -1382
- package/dist/store.js +900 -4083
- package/dist/surface.js +10 -25
- package/dist/task-composer.d.ts +1 -1
- package/dist/task-composer.js +1 -1
- package/dist/task-control.d.ts +3 -10
- package/dist/task-control.js +2 -7
- package/dist/teammate-desk.js +1 -1
- package/dist/teammates-ui.js +1 -1
- package/dist/telegram-mate.d.ts +0 -3
- package/dist/telegram-mate.js +0 -1
- package/dist/templates.d.ts +11 -7
- package/dist/templates.js +12 -9
- package/dist/toolroll-update.d.ts +24 -3
- package/dist/toolroll-update.js +159 -16
- package/dist/webhooks.d.ts +10 -22
- package/dist/webhooks.js +43 -81
- package/dist/work-index.js +3 -7
- package/dist/workspace-revision.d.ts +28 -1
- package/dist/workspace-revision.js +276 -49
- package/dist/workspace-ui.js +1 -1
- package/package.json +1 -3
- package/scripts/recovery-canary.mjs +3 -3
- package/dist/contest.d.ts +0 -318
- package/dist/contest.js +0 -753
- package/dist/held.d.ts +0 -150
- package/dist/held.js +0 -799
- package/dist/liveness.d.ts +0 -30
- package/dist/liveness.js +0 -42
- package/dist/pricing.d.ts +0 -45
- package/dist/pricing.js +0 -77
- package/dist/routine.d.ts +0 -228
- package/dist/routine.js +0 -764
- package/dist/supervisor.mjs +0 -297
package/dist/exhaustion.js
CHANGED
|
@@ -1,152 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* How a finished attempt ended, classified where the evidence still exists
|
|
3
|
+
* (the provider adapter's structural terminal record), never in disposal.
|
|
4
|
+
* The one class that changes what happens next is `auth-expired`: a sign-in
|
|
5
|
+
* or API key that no longer works pauses dispatch for that provider until
|
|
6
|
+
* someone signs in, instead of burning attempts. Everything else is the
|
|
7
|
+
* ordinary failure road.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* no fixture for a (provider, version) can therefore NEVER return an
|
|
12
|
-
* eligible class — so it can never authorize a paid fallback. A
|
|
13
|
-
* successful run cannot establish the exhausted shape; only real
|
|
14
|
-
* exhaustion can, and the plane cannot manufacture it.
|
|
15
|
-
*
|
|
16
|
-
* Precedence (C5), applied by the classifier:
|
|
17
|
-
* - A present STRUCTURAL FAILURE terminal blocks success ingestion even
|
|
18
|
-
* on exit 0 (that is the parser's job; this module reads the record).
|
|
19
|
-
* - Only an ALLOWLISTED, version+auth-specific pattern yields an ELIGIBLE
|
|
20
|
-
* class. Exit code, bare rate-limit prose, timeout, notFound, stderr,
|
|
21
|
-
* and zero tokens NEVER independently establish exhaustion.
|
|
22
|
-
* - Everything unmatched is `unknown` — the ordinary failure road.
|
|
23
|
-
* - A sign-in that no longer works (`auth-expired`) is recognized FIRST,
|
|
24
|
-
* for every provider and version: an expired or revoked login is not a
|
|
25
|
-
* property of a CLI version, and retrying it only burns attempts. It is
|
|
26
|
-
* never fallback-eligible — a lapsed login must not reach a paid key.
|
|
27
|
-
*/
|
|
28
|
-
/** The two classes that may authorize a fallback advance. */
|
|
29
|
-
export const FALLBACK_ELIGIBLE = new Set([
|
|
30
|
-
"usage-exhausted",
|
|
31
|
-
"credits-depleted",
|
|
32
|
-
]);
|
|
33
|
-
export function isFallbackEligible(cls) {
|
|
34
|
-
return FALLBACK_ELIGIBLE.has(cls);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* The registry. EVERY entry ships empty (fail closed). A real fixture,
|
|
38
|
-
* once captured from a genuinely exhausted subscription and reviewed,
|
|
39
|
-
* adds the exact patterns under that provider+version — and ONLY then can
|
|
40
|
-
* that (provider, version) ever return an eligible class.
|
|
41
|
-
*
|
|
42
|
-
* The outer key is the provider; the inner key is the exact CLI version
|
|
43
|
-
* string the gateway proved at spawn (never a range — a version this
|
|
44
|
-
* build has no fixture for is unrecognized, so fail closed).
|
|
45
|
-
*/
|
|
46
|
-
const RECOGNIZERS = {
|
|
47
|
-
claude: {},
|
|
48
|
-
codex: {},
|
|
49
|
-
openrouter: {},
|
|
50
|
-
gemini: {},
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* The recognizer lookup. Reads ONLY the module-level RECOGNIZERS registry —
|
|
54
|
-
* there is NO mutation surface, so no build (production or otherwise) can
|
|
55
|
-
* install a recognizer at runtime; a real fixture arrives as a source edit,
|
|
56
|
-
* reviewed in a text diff (Codex E2/E3 review, finding 1). The suite proves
|
|
57
|
-
* the eligible path by MOCKING this module, never by a shipped seam.
|
|
58
|
-
* Object.hasOwn keeps the lookup TOTAL for adversarial version strings
|
|
59
|
-
* (foundation review, finding 3): "__proto__" / "constructor" / "toString"
|
|
60
|
-
* resolve to "no recognizer", never an inherited property.
|
|
61
|
-
*/
|
|
62
|
-
function recognizersFromRegistry(provider, version) {
|
|
63
|
-
if (!Object.hasOwn(RECOGNIZERS[provider], version))
|
|
64
|
-
return undefined;
|
|
65
|
-
return RECOGNIZERS[provider][version];
|
|
66
|
-
}
|
|
67
|
-
/** Whether THIS build carries a fixture-backed recognizer for a
|
|
68
|
-
* (provider, version). The C8 gate consults this at every authority
|
|
69
|
-
* point — not only at classification — so a downgrade to an unfixtured
|
|
70
|
-
* build severs any in-flight fallback authority. */
|
|
71
|
-
export function hasRecognizer(provider, version) {
|
|
72
|
-
if (version === null)
|
|
73
|
-
return false;
|
|
74
|
-
const perVersion = recognizersFromRegistry(provider, version);
|
|
75
|
-
if (perVersion === undefined)
|
|
76
|
-
return false;
|
|
77
|
-
return perVersion.eligibleUsage.length > 0 || perVersion.eligibleCredits.length > 0;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* The EXACT C8 capability check (Codex E2/E3 review, finding 8): whether
|
|
81
|
-
* this build can recognize the specific eligible class an AUTH MODE would
|
|
82
|
-
* produce — a subscription's `usage-exhausted` needs a nonempty
|
|
83
|
-
* eligibleUsage set; an api-key account's `credits-depleted` needs a
|
|
84
|
-
* nonempty eligibleCredits set. `hasRecognizer` (any-eligible) is too coarse
|
|
85
|
-
* at the authority point: a version fixtured for usage only must NOT
|
|
86
|
-
* authorize a credits-depleted advance.
|
|
87
|
-
*/
|
|
88
|
-
export function recognizesEligible(provider, version, authMode) {
|
|
89
|
-
if (version === null)
|
|
90
|
-
return false;
|
|
91
|
-
const perVersion = recognizersFromRegistry(provider, version);
|
|
92
|
-
if (perVersion === undefined)
|
|
93
|
-
return false;
|
|
94
|
-
return authMode === "subscription" ? perVersion.eligibleUsage.length > 0 : perVersion.eligibleCredits.length > 0;
|
|
95
|
-
}
|
|
96
|
-
/** The eligible class an auth mode can legitimately carry — the C8
|
|
97
|
-
* consistency invariant: `usage-exhausted` iff subscription,
|
|
98
|
-
* `credits-depleted` iff api-key. A stamp that violates this pairing is a
|
|
99
|
-
* bad/overwritten record and must never advance. */
|
|
100
|
-
export function classMatchesAuthMode(cls, authMode) {
|
|
101
|
-
if (cls === "usage-exhausted")
|
|
102
|
-
return authMode === "subscription";
|
|
103
|
-
if (cls === "credits-depleted")
|
|
104
|
-
return authMode === "api-key";
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Classify a finished attempt. Fail closed: no recognizer for this exact
|
|
109
|
-
* (provider, version) => never an eligible class. `authMode` decides which
|
|
110
|
-
* eligible class a match yields — a subscription that hits its cap is
|
|
111
|
-
* `usage-exhausted`; an api-key account out of credits is
|
|
112
|
-
* `credits-depleted`. A structural failure with no eligible/transient
|
|
113
|
-
* match is `not-exhausted`; no structural failure and no match is
|
|
114
|
-
* `unknown`.
|
|
9
|
+
* `usage-exhausted`, `credits-depleted` and `transient-throttle` are only
|
|
10
|
+
* ever read from older runs' records (they were stamped by a removed
|
|
11
|
+
* feature); this build never produces them.
|
|
115
12
|
*/
|
|
13
|
+
/** Classify a finished attempt: a sign-in that no longer works first, for
|
|
14
|
+
* any provider or version; then a structural failure terminal is
|
|
15
|
+
* `not-exhausted`, and anything else `unknown`. */
|
|
116
16
|
export function classifyTerminal(args) {
|
|
117
|
-
const {
|
|
118
|
-
// A sign-in that no longer works, before anything else and for any
|
|
119
|
-
// provider or version: no fixture is needed to know a login is gone.
|
|
17
|
+
const { terminal } = args;
|
|
120
18
|
if (terminal !== null && terminal.failed === true && isAuthFailure(`${terminal.code ?? ""}\n${terminal.text ?? ""}`))
|
|
121
19
|
return "auth-expired";
|
|
122
20
|
if (typeof args.earlyExit === "string" && isAuthFailure(args.earlyExit))
|
|
123
21
|
return "auth-expired";
|
|
124
|
-
if (terminal === null)
|
|
125
|
-
return "unknown";
|
|
126
|
-
// The classifier's contract permits failed:false, but a non-failure
|
|
127
|
-
// terminal is never exhaustion (Codex foundation review, finding 4):
|
|
128
|
-
// only a structural FAILURE terminal is even eligible for matching.
|
|
129
|
-
if (terminal.failed !== true)
|
|
22
|
+
if (terminal === null || terminal.failed !== true)
|
|
130
23
|
return "unknown";
|
|
131
|
-
const perVersion = version === null ? undefined : recognizersFromRegistry(provider, version);
|
|
132
|
-
const haystack = `${terminal.code ?? ""}\n${terminal.text ?? ""}`;
|
|
133
|
-
if (perVersion !== undefined) {
|
|
134
|
-
// Transient throttle is checked FIRST so a throttle can never be read
|
|
135
|
-
// as exhaustion (Claude's "temporarily limiting requests — not your
|
|
136
|
-
// usage limit" family).
|
|
137
|
-
if (perVersion.transient.some(re => re.test(haystack)))
|
|
138
|
-
return "transient-throttle";
|
|
139
|
-
// Then the eligible sets, gated by auth mode.
|
|
140
|
-
if (authMode === "subscription" && perVersion.eligibleUsage.some(re => re.test(haystack))) {
|
|
141
|
-
return "usage-exhausted";
|
|
142
|
-
}
|
|
143
|
-
if (authMode === "api-key" && perVersion.eligibleCredits.some(re => re.test(haystack))) {
|
|
144
|
-
return "credits-depleted";
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// A structural FAILURE terminal that matched nothing is a definite
|
|
148
|
-
// non-exhaustion terminal (a non-failure terminal already returned
|
|
149
|
-
// unknown above).
|
|
150
24
|
return "not-exhausted";
|
|
151
25
|
}
|
|
152
26
|
/**
|
package/dist/export.js
CHANGED
|
@@ -34,7 +34,7 @@ const DERIVED_TABLE = /^(sqlite_|memory_search)/;
|
|
|
34
34
|
/** Columns that hold a secret (or what stands in for one): never exported. */
|
|
35
35
|
const SECRET_COLUMNS = new Set([
|
|
36
36
|
"api_token.secret_hash", "lead_credential.secret_hash", "approver.credential_hash", "coordinator_credential.credential_hash", "runner.credential_hash", "invite.token_hash",
|
|
37
|
-
"flow_trigger.hook_hash", "
|
|
37
|
+
"flow_trigger.hook_hash", "push_subscription.endpoint", "push_subscription.p256dh", "push_subscription.auth",
|
|
38
38
|
"chat_turn.credential_key", "mate_session.credential_key", "mate_turn.credential_key", "bridge_lease.push_url", "workflow_preview.token",
|
|
39
39
|
"quota.credential_fp", "oauth_grant.renew_hash", "oauth_client.source_hash",
|
|
40
40
|
]);
|
|
@@ -54,10 +54,10 @@ export function categoryOf(table) {
|
|
|
54
54
|
const rules = [
|
|
55
55
|
[/^(action_ledger|ledger_seal|ledger_checkpoint|sync_ledger)$/, "ledger"],
|
|
56
56
|
[/^teammate/, "teammates"],
|
|
57
|
-
[/^(flow|
|
|
57
|
+
[/^(flow|workflow_)/, "flows"],
|
|
58
58
|
[/^(chat_|mate_|team_|telegram_|slack_|discord_|teams_|notification|push_|bridge_lease)/, "chats"],
|
|
59
59
|
[/^(approver|api_token|lead_credential|invite|sso_identity|coordinator_|oauth_)/, "people"],
|
|
60
|
-
[/^(run|artifact|claim|worktree$|execution_slot|
|
|
60
|
+
[/^(run|artifact|claim|worktree$|execution_slot|criterion_review|diff_comment|proof_|review_request|repair_chain|incident|publication$|merge_|side_spend|knowledge_snapshot|learning_snapshot|skill_snapshot)/, "runs"],
|
|
61
61
|
[/^(task|hold$|plan_|scope_|tool_seal|decision|external_|skill_test)/, "tasks"],
|
|
62
62
|
[/^(project|approval_policy|capability|verify_command|worktree_setup|backend_grant|intake_grant|publication_grant|operating_mode|knowledge_|learning_|memory_|skill_)/, "projects"],
|
|
63
63
|
[/(_config|_default|_defaults)$|^(budget|model_|provider_|installation_fact|runtime_check|monitoring_status|integration_check|quota|mode_rail|schema_version)/, "settings"],
|
|
@@ -215,7 +215,7 @@ Everything this installation knew on ${now.toISOString().slice(0, 16).replace("T
|
|
|
215
215
|
- \`ledger/\`: the action ledger (\`action_ledger\`), each entry's seal (\`ledger_seal\`) and the checkpoints (\`ledger_checkpoint\`).
|
|
216
216
|
- \`evidence-packs/\`: one JSON file per task: who asked, the exact terms and who approved them, runs and cost, checks, completion and its ledger entries.
|
|
217
217
|
- \`chats/\`: conversations with the lead and teammates, and Telegram, Slack, Discord and Teams messages and notifications.
|
|
218
|
-
- \`flows/\`: flows, their cards, scripts and triggers
|
|
218
|
+
- \`flows/\`: flows, their cards, scripts and triggers (schedules included) and saved recipes.
|
|
219
219
|
- \`teammates/\`: teammates, their versions, memory, tools and turns.
|
|
220
220
|
- \`people/\`: accounts, API token names and invitations (no passwords or tokens).
|
|
221
221
|
- \`settings/\`: models, budgets, spend and permission defaults, provider readings; \`files.json\` holds the settings kept in files.
|
package/dist/flow-engine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The flow engine: moves cards through their flow's zones. Deterministic
|
|
3
|
-
* and model-free — it runs in a worker's pass beside
|
|
3
|
+
* and model-free — it runs in a worker's pass beside builds, files work
|
|
4
4
|
* through the ordinary task door (so every approval and check a task needs
|
|
5
5
|
* still applies), reads task state, posts messages through the outbox, and
|
|
6
6
|
* waits for people. See flows.ts for what each zone does.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schedules (v115: flow-owned; routines became scheduled flows).
|
|
3
|
+
*
|
|
4
|
+
* A schedule trigger fires on one of four readable cadences. Its two failure modes are subtle enough to deserve
|
|
5
|
+
* names: advancing one interval after downtime leaves the next firing in the past — a catch-up burst; advancing to
|
|
6
|
+
* `now + interval` drifts the cadence forever. The rule is ALIGNED advancement: the next occurrence strictly after
|
|
7
|
+
* now, anchored to the occurrence that just fired (for `every`) or to the clock itself (for calendar schedules).
|
|
8
|
+
* Missed slots while nothing was running fire ONCE — the overdue occurrence — and are never backfilled.
|
|
9
|
+
*/
|
|
10
|
+
import type { StandingOrder } from "./contracts/flow.js";
|
|
11
|
+
import { type PhaseRoute } from "./phase-routing.js";
|
|
12
|
+
import { type AcceptanceCriterion, type ExecutionProfile } from "./scope.js";
|
|
13
|
+
import { type Store } from "./store.js";
|
|
14
|
+
export type { StandingOrder };
|
|
15
|
+
export type Schedule = {
|
|
16
|
+
kind: "every";
|
|
17
|
+
minutes: number;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "daily";
|
|
20
|
+
hhmm: string;
|
|
21
|
+
timezone?: string;
|
|
22
|
+
}
|
|
23
|
+
/** v96: Monday to Friday. */
|
|
24
|
+
| {
|
|
25
|
+
kind: "weekdays";
|
|
26
|
+
hhmm: string;
|
|
27
|
+
timezone?: string;
|
|
28
|
+
} | {
|
|
29
|
+
kind: "weekly";
|
|
30
|
+
day: number;
|
|
31
|
+
hhmm: string;
|
|
32
|
+
timezone?: string;
|
|
33
|
+
};
|
|
34
|
+
export declare const WEEKDAYS: readonly ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
35
|
+
export declare function validTimezone(value: string): boolean;
|
|
36
|
+
/** Bounds a person would pick on purpose: 5 minutes to 7 days. */
|
|
37
|
+
export declare const MIN_EVERY_MINUTES = 5;
|
|
38
|
+
export declare const MAX_EVERY_MINUTES: number;
|
|
39
|
+
/**
|
|
40
|
+
* Existing daily schedules remain UTC. Calendar schedules may name an IANA
|
|
41
|
+
* timezone, whose wall-clock time stays fixed across daylight saving changes.
|
|
42
|
+
* No cron expressions in v1 — a schedule the operator cannot read at a
|
|
43
|
+
* glance is a schedule they cannot honestly approve.
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseSchedule(text: string): Schedule | null;
|
|
46
|
+
export declare function scheduleText(schedule: Schedule): string;
|
|
47
|
+
/** The schedule, in words an operator agrees to. */
|
|
48
|
+
export declare function describeSchedule(schedule: Schedule): string;
|
|
49
|
+
/**
|
|
50
|
+
* The first occurrence after approval: the schedule starts counting from the
|
|
51
|
+
* yes, because "approved at 14:07, every 60 minutes" firing instantly would
|
|
52
|
+
* spend before the approver's hand left the keyboard.
|
|
53
|
+
*/
|
|
54
|
+
export declare function firstFireAt(schedule: Schedule, now: Date): string;
|
|
55
|
+
/**
|
|
56
|
+
* Aligned advancement: the smallest cadence occurrence STRICTLY after now.
|
|
57
|
+
* `anchor` is the occurrence that just fired (or was just skipped) — the
|
|
58
|
+
* cadence grid grows from it, so a pass that ran late does not tilt every
|
|
59
|
+
* later firing by its lateness.
|
|
60
|
+
*/
|
|
61
|
+
export declare function nextFireAt(schedule: Schedule, anchorIso: string, now: Date): string;
|
|
62
|
+
/** The rolling window a standing order's cost ceiling counts over: seven days, and every surface says so. */
|
|
63
|
+
export declare const BUDGET_WINDOW_MS: number;
|
|
64
|
+
/** A firing's task id: the order's stem stamped with its slot (`nightly-deps-20261008-0700`). */
|
|
65
|
+
export declare function instanceId(stem: string, slotIso: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* The exact standing order an approver agreed to, as 128 bits — byte for byte what a routine's digest was, so a
|
|
68
|
+
* routine's approval moved onto a scheduled flow (v115) still verifies: the project, the terms, the schedule, the
|
|
69
|
+
* ceiling, and the agents the approval froze. Editing any of them (or moving the flow) strands the approval.
|
|
70
|
+
*/
|
|
71
|
+
export declare function standingDigestOf(repo: string, schedule: string, order: StandingOrder, acceptance: readonly AcceptanceCriterion[], profile: ExecutionProfile, route: PhaseRoute): string;
|
|
72
|
+
export type StandingApproval = {
|
|
73
|
+
live: true;
|
|
74
|
+
by: string | null;
|
|
75
|
+
profile: ExecutionProfile;
|
|
76
|
+
route: PhaseRoute;
|
|
77
|
+
acceptance: AcceptanceCriterion[];
|
|
78
|
+
} | {
|
|
79
|
+
live: false;
|
|
80
|
+
problem: string | null;
|
|
81
|
+
acceptance: AcceptanceCriterion[] | null;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Whether a standing order's carried approval still stands, read whole before anything is written: the frozen agents
|
|
85
|
+
* read back, re-hash with the order's terms, this schedule and project to the digest the approver signed, state no
|
|
86
|
+
* problem, and build and repair on the approved profile's own agents. `problem` is null when there is no approval.
|
|
87
|
+
*/
|
|
88
|
+
export declare function standingApproval(order: StandingOrder, repo: string, schedule: string): StandingApproval;
|
|
89
|
+
export type StandingFiring = {
|
|
90
|
+
made: "filed";
|
|
91
|
+
taskId: string;
|
|
92
|
+
approved: boolean;
|
|
93
|
+
note: string | null;
|
|
94
|
+
} | {
|
|
95
|
+
made: "skipped";
|
|
96
|
+
note: string;
|
|
97
|
+
};
|
|
98
|
+
/** A firing that must not stand: thrown inside the transaction so nothing it wrote survives. */
|
|
99
|
+
export declare class StandingOrderRefused extends Error {
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* File one firing of a standing order (v115, what firing a routine did), inside the caller's transaction. It skips,
|
|
103
|
+
* saying why, while the last task is unfinished or the rolling 7-day ceiling is reached (an unmeasured paid run fails
|
|
104
|
+
* closed). Otherwise it files the order's terms unchanged: approved by the carried approval when that still verifies
|
|
105
|
+
* — on exactly the agents it froze, sealed like any automatic approval under the project's rules — or else as an
|
|
106
|
+
* ordinary proposal that waits for the project's approval rules like any other.
|
|
107
|
+
*/
|
|
108
|
+
export declare function fileStandingOrder(store: Store, input: {
|
|
109
|
+
flowId: number;
|
|
110
|
+
repo: string;
|
|
111
|
+
trigger: number;
|
|
112
|
+
schedule: string;
|
|
113
|
+
order: StandingOrder;
|
|
114
|
+
title: string;
|
|
115
|
+
slot: string;
|
|
116
|
+
}, now: Date): StandingFiring;
|
|
117
|
+
/** A standing order in the words a person reads before turning its schedule on. */
|
|
118
|
+
export declare function describeStandingOrder(order: StandingOrder, repo: string, schedule: string): string[];
|
|
119
|
+
/** The terms a person sets a standing order up with (a template's, a recipe's): what each firing files. */
|
|
120
|
+
export type StandingTerms = {
|
|
121
|
+
goal: string;
|
|
122
|
+
outOfScope: string | null;
|
|
123
|
+
touches: string[];
|
|
124
|
+
requirements: string[];
|
|
125
|
+
acceptance: readonly AcceptanceCriterion[];
|
|
126
|
+
budgetPerRunMicrousd: number | null;
|
|
127
|
+
costCeilingUsd: number | null;
|
|
128
|
+
};
|
|
129
|
+
/** Every problem with a standing order's terms and schedule at once, as `field: problem` lines (none when it can be set up). */
|
|
130
|
+
export declare function standingTermsProblems(terms: StandingTerms, schedule: string): string[];
|
|
131
|
+
export type ScheduledFlowMade = {
|
|
132
|
+
ok: true;
|
|
133
|
+
flow: number;
|
|
134
|
+
trigger: number;
|
|
135
|
+
} | {
|
|
136
|
+
ok: false;
|
|
137
|
+
message: string;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* A scheduled flow a person set up (a template or a recipe; v115, what filing a routine was): a Build step that follows
|
|
141
|
+
* the task each firing files, then Done, and a schedule trigger carrying the terms as its standing order — with no
|
|
142
|
+
* approval, so each firing waits for approval under the project's rules. The schedule starts PAUSED with no time:
|
|
143
|
+
* nothing repeats until a person turns it on, and it starts counting then. Its tasks are filed as `filedBy`'s (default
|
|
144
|
+
* `by`; null files them as automation's). Inside the caller's transaction, if any.
|
|
145
|
+
*/
|
|
146
|
+
export declare function createScheduledFlow(store: Store, input: {
|
|
147
|
+
repo: string;
|
|
148
|
+
name: string;
|
|
149
|
+
stem: string;
|
|
150
|
+
schedule: string;
|
|
151
|
+
terms: StandingTerms;
|
|
152
|
+
by: string;
|
|
153
|
+
filedBy?: string | null;
|
|
154
|
+
}, now: Date): ScheduledFlowMade;
|