toolroll 0.9.41 → 0.9.43
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 +37 -0
- package/dist/chat-actions.js +1 -1
- package/dist/chat-approval.d.ts +45 -0
- package/dist/chat-approval.js +81 -0
- package/dist/chat-channel.js +5 -0
- package/dist/chat-decide.d.ts +18 -6
- package/dist/chat-decide.js +54 -20
- package/dist/chat-flow.js +2 -2
- package/dist/cli.js +4 -2
- package/dist/coding-types.d.ts +2 -24
- package/dist/coding-workspace.js +12 -11
- package/dist/contracts/cli.d.ts +736 -0
- package/dist/contracts/cli.js +223 -0
- package/dist/contracts/coding-activity.d.ts +64 -0
- package/dist/contracts/coding-activity.js +58 -0
- package/dist/contracts/console-api.d.ts +484 -0
- package/dist/contracts/console-api.js +274 -0
- package/dist/contracts/diff-stat.d.ts +58 -0
- package/dist/contracts/diff-stat.js +59 -0
- package/dist/contracts/integration-metadata.d.ts +99 -0
- package/dist/contracts/integration-metadata.js +101 -0
- package/dist/contracts/lead-tools.d.ts +11 -0
- package/dist/contracts/lead-tools.js +2 -0
- package/dist/contracts/model-catalog.d.ts +21 -0
- package/dist/contracts/model-catalog.js +14 -0
- package/dist/contracts/native-census.d.ts +42 -0
- package/dist/contracts/native-census.js +36 -0
- package/dist/contracts/observation-request.d.ts +37 -0
- package/dist/contracts/observation-request.js +25 -0
- package/dist/contracts/provider.d.ts +30 -0
- package/dist/contracts/provider.js +15 -0
- package/dist/contracts/recipes.d.ts +166 -0
- package/dist/contracts/recipes.js +52 -0
- package/dist/contracts/retention.d.ts +42 -0
- package/dist/contracts/retention.js +24 -0
- package/dist/contracts/storage.d.ts +23 -0
- package/dist/contracts/storage.js +10 -0
- package/dist/contracts/store-json.d.ts +315 -0
- package/dist/contracts/store-json.js +196 -0
- package/dist/contracts/trigger-payloads.d.ts +369 -0
- package/dist/contracts/trigger-payloads.js +144 -0
- package/dist/contracts/update-journal.d.ts +254 -0
- package/dist/contracts/update-journal.js +155 -0
- package/dist/contracts/verification-view.d.ts +93 -0
- package/dist/contracts/verification-view.js +43 -0
- package/dist/control-setup.d.ts +1 -1
- package/dist/desktop-update.d.ts +7 -40
- package/dist/desktop-update.js +36 -8
- package/dist/evidence.d.ts +3 -19
- package/dist/flow-engine.d.ts +2 -0
- package/dist/flow-engine.js +10 -2
- package/dist/flow-triggers.js +61 -60
- package/dist/flows-cli.d.ts +28 -0
- package/dist/flows-cli.js +43 -1
- package/dist/guides.js +2 -0
- package/dist/mate-contract.js +1 -1
- package/dist/mate-tools.js +43 -1
- package/dist/mcp-connect.js +37 -22
- package/dist/model-catalog.js +8 -6
- package/dist/observations.d.ts +2 -6
- package/dist/observations.js +13 -9
- package/dist/operate.js +55 -4
- package/dist/process-recovery-eligibility.d.ts +1 -1
- package/dist/process-recovery-native.d.ts +2 -13
- package/dist/process-recovery-native.js +8 -5
- package/dist/project-tools.d.ts +6 -24
- package/dist/project-tools.js +22 -18
- package/dist/provider.d.ts +3 -8
- package/dist/provider.js +15 -11
- package/dist/recipes.d.ts +3 -28
- package/dist/recipes.js +79 -52
- package/dist/retention.d.ts +4 -5
- package/dist/retention.js +5 -4
- package/dist/scope.d.ts +4 -2
- package/dist/serve.js +193 -30
- package/dist/storage.d.ts +2 -1
- package/dist/storage.js +12 -9
- package/dist/store.d.ts +11 -16
- package/dist/store.js +122 -160
- package/dist/surface.d.ts +6 -54
- package/dist/surface.js +10 -2
- package/dist/teammate-work.js +1 -1
- package/dist/telegram-flow.d.ts +41 -1
- package/dist/telegram-flow.js +96 -12
- package/dist/telegram.js +27 -3
- package/dist/toolroll-update.d.ts +8 -99
- package/dist/toolroll-update.js +28 -18
- package/dist/verification-evidence.js +27 -12
- package/package.json +1 -1
package/dist/store.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { chatSchema, chatTables } from "./contracts/chat-tables.js";
|
|
2
|
+
import { parseStoreColumn, readStoreColumn, readStoreStringifiedList, readStoreTextList } from "./contracts/store-json.js";
|
|
2
3
|
import { assessmentFromSavedEvidence, verificationEvidence } from "./verification-evidence.js";
|
|
3
4
|
import { LEARNING_SCHEMA, queueLearning } from "./project-learning.js";
|
|
4
5
|
import { SKILLS_SCHEMA } from "./project-skills.js";
|
|
@@ -353,6 +354,40 @@ CREATE TABLE IF NOT EXISTS telegram_flow_choice (
|
|
|
353
354
|
);
|
|
354
355
|
CREATE INDEX IF NOT EXISTS telegram_flow_choice_visit ON telegram_flow_choice (card, entry);
|
|
355
356
|
`;
|
|
357
|
+
/** An owner's lasting choice to approve plans and merges from their paired chat (chat-approval.ts), for all their
|
|
358
|
+
* projects (scope '*') or one (its path), with the limits they agreed to. Off unless a row says on; a project's own row
|
|
359
|
+
* outranks the all-projects one. `generation` is the account's at the change: a reset password ends it. */
|
|
360
|
+
export const CHAT_APPROVAL_SCHEMA = `
|
|
361
|
+
CREATE TABLE IF NOT EXISTS chat_approval_setting (
|
|
362
|
+
approver TEXT NOT NULL,
|
|
363
|
+
scope TEXT NOT NULL,
|
|
364
|
+
enabled INTEGER NOT NULL CHECK (enabled IN (0,1)),
|
|
365
|
+
full_access INTEGER NOT NULL DEFAULT 0 CHECK (full_access IN (0,1)),
|
|
366
|
+
attempt_cap_microusd INTEGER CHECK (attempt_cap_microusd IS NULL OR attempt_cap_microusd >= 0),
|
|
367
|
+
generation INTEGER NOT NULL,
|
|
368
|
+
digest TEXT NOT NULL,
|
|
369
|
+
updated_by TEXT NOT NULL,
|
|
370
|
+
updated_at TEXT NOT NULL,
|
|
371
|
+
PRIMARY KEY (approver, scope)
|
|
372
|
+
);
|
|
373
|
+
`;
|
|
374
|
+
/** The second tap on a flow decision in Telegram (telegram-flow.ts): Approve arms Yes and Cancel, bound to the binding,
|
|
375
|
+
* chat, message and exact visit of the card; Yes decides it once. */
|
|
376
|
+
export const TELEGRAM_FLOW_CONFIRM_SCHEMA = `
|
|
377
|
+
CREATE TABLE IF NOT EXISTS telegram_flow_confirm (
|
|
378
|
+
token TEXT PRIMARY KEY,
|
|
379
|
+
binding INTEGER NOT NULL,
|
|
380
|
+
chat_id TEXT NOT NULL,
|
|
381
|
+
message_id TEXT NOT NULL,
|
|
382
|
+
card INTEGER NOT NULL,
|
|
383
|
+
entry INTEGER NOT NULL,
|
|
384
|
+
phase TEXT NOT NULL CHECK (phase IN ('yes','cancel')),
|
|
385
|
+
created_at TEXT NOT NULL,
|
|
386
|
+
expires_at TEXT NOT NULL,
|
|
387
|
+
consumed_at TEXT
|
|
388
|
+
);
|
|
389
|
+
CREATE INDEX IF NOT EXISTS telegram_flow_confirm_visit ON telegram_flow_confirm (card, entry);
|
|
390
|
+
`;
|
|
356
391
|
export const CHAT_DECIDE_SCHEMA = `
|
|
357
392
|
CREATE TABLE IF NOT EXISTS chat_decide_action (
|
|
358
393
|
token TEXT PRIMARY KEY,
|
|
@@ -504,10 +539,10 @@ const isCheckExitCode = (value) => value === null || (Number.isSafeInteger(value
|
|
|
504
539
|
/** Read a stored suite list; a malformed optional summary reads as no suite detail. */
|
|
505
540
|
export function checkSuitesOf(value) {
|
|
506
541
|
try {
|
|
507
|
-
const
|
|
508
|
-
if (!
|
|
542
|
+
const read = readStoreColumn("run_check.suites_json", value ?? "[]");
|
|
543
|
+
if (!read.ok)
|
|
509
544
|
return [];
|
|
510
|
-
return
|
|
545
|
+
return read.value.filter((one) => {
|
|
511
546
|
if (one === null || typeof one !== "object")
|
|
512
547
|
return false;
|
|
513
548
|
const row = one;
|
|
@@ -620,37 +655,22 @@ function readTeammateMemory(row) {
|
|
|
620
655
|
createdBy: String(row["created_by"]), createdAt: String(row["created_at"]), updatedBy: String(row["updated_by"]), updatedAt: String(row["updated_at"]), usedAt: row["used_at"] === null ? null : String(row["used_at"]) };
|
|
621
656
|
}
|
|
622
657
|
function readTeammateSuggestion(row) {
|
|
623
|
-
const parsed = (key, fallback) => {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
catch {
|
|
627
|
-
return fallback;
|
|
628
|
-
} };
|
|
629
|
-
return { id: Number(row["id"]), teammate: Number(row["teammate"]), tool: String(row["tool"]), action: String(row["action"]), rule: parsed("rule_json", { use: "ask" }), was: parsed("was_json", { use: "ask" }),
|
|
630
|
-
evidence: parsed("evidence_json", []), said: String(row["said"]), state: String(row["state"]),
|
|
658
|
+
const parsed = (column, key, fallback) => { const read = readStoreColumn(column, row[key]); return read.ok ? read.value : fallback; };
|
|
659
|
+
return { id: Number(row["id"]), teammate: Number(row["teammate"]), tool: String(row["tool"]), action: String(row["action"]), rule: parsed("teammate_suggestion.rule_json", "rule_json", { use: "ask" }), was: parsed("teammate_suggestion.was_json", "was_json", { use: "ask" }),
|
|
660
|
+
evidence: parsed("teammate_suggestion.evidence_json", "evidence_json", []), said: String(row["said"]), state: String(row["state"]),
|
|
631
661
|
decidedBy: row["decided_by"] === null ? null : String(row["decided_by"]), decidedAt: row["decided_at"] === null ? null : String(row["decided_at"]), createdAt: String(row["created_at"]) };
|
|
632
662
|
}
|
|
633
663
|
function readTeammateCall(row) {
|
|
634
664
|
const text = (key) => row[key] === null || row[key] === undefined ? null : String(row[key]);
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
input = JSON.parse(String(row["input_json"]));
|
|
638
|
-
}
|
|
639
|
-
catch {
|
|
640
|
-
input = {};
|
|
641
|
-
}
|
|
665
|
+
const read = readStoreColumn("teammate_call.input_json", row["input_json"]);
|
|
666
|
+
const input = read.ok ? read.value : {};
|
|
642
667
|
return { id: Number(row["id"]), teammate: Number(row["teammate"]), card: Number(row["card"]), entry: Number(row["entry"]), tool: String(row["tool"]), action: String(row["action"]), input,
|
|
643
668
|
rule: String(row["rule"]), why: String(row["why"]), state: String(row["state"]), result: text("result"), decidedBy: text("decided_by"), decidedAt: text("decided_at"),
|
|
644
669
|
createdAt: String(row["created_at"]), doneAt: text("done_at"), undoOf: row["undo_of"] === null || row["undo_of"] === undefined ? null : Number(row["undo_of"]), undoneBy: text("undone_by"), undoneAt: text("undone_at") };
|
|
645
670
|
}
|
|
646
671
|
function readTeammateGrant(row) {
|
|
647
|
-
const parsed = (key, fallback) => {
|
|
648
|
-
|
|
649
|
-
}
|
|
650
|
-
catch {
|
|
651
|
-
return fallback;
|
|
652
|
-
} };
|
|
653
|
-
return { teammate: Number(row["teammate"]), tool: String(row["tool"]), actions: parsed("actions_json", []), rules: parsed("rules_json", {}),
|
|
672
|
+
const parsed = (column, key, fallback) => { const read = readStoreColumn(column, row[key]); return read.ok ? read.value : fallback; };
|
|
673
|
+
return { teammate: Number(row["teammate"]), tool: String(row["tool"]), actions: parsed("teammate_tool.actions_json", "actions_json", []), rules: parsed("teammate_tool.rules_json", "rules_json", {}),
|
|
654
674
|
listedAt: row["listed_at"] === null ? null : String(row["listed_at"]), updatedBy: String(row["updated_by"]), updatedAt: String(row["updated_at"]) };
|
|
655
675
|
}
|
|
656
676
|
function readTeammateRow(row) {
|
|
@@ -663,7 +683,7 @@ function readTeammateRow(row) {
|
|
|
663
683
|
function readTeammateQuestion(row) {
|
|
664
684
|
const text = (key) => row[key] === null || row[key] === undefined ? null : String(row[key]);
|
|
665
685
|
return { id: Number(row["id"]), teammate: Number(row["teammate"]), card: Number(row["card"]), entry: Number(row["entry"]), question: String(row["question"]),
|
|
666
|
-
options:
|
|
686
|
+
options: parseStoreColumn("teammate_question.options_json", row["options_json"]), askedOf: String(row["asked_of"]), state: String(row["state"]),
|
|
667
687
|
choice: text("choice"), answer: text("answer"), answeredBy: text("answered_by"), answeredVia: text("answered_via"), answeredAt: text("answered_at"), createdAt: String(row["created_at"]),
|
|
668
688
|
toolCall: row["tool_call"] === null || row["tool_call"] === undefined ? null : Number(row["tool_call"]),
|
|
669
689
|
suggestion: row["suggestion"] === null || row["suggestion"] === undefined ? null : Number(row["suggestion"]) };
|
|
@@ -697,10 +717,11 @@ function readFlowCardRow(row) {
|
|
|
697
717
|
function readFlowCardSource(value) {
|
|
698
718
|
if (typeof value !== "string")
|
|
699
719
|
return null;
|
|
720
|
+
const read = readStoreColumn("flow_card.source_json", value);
|
|
721
|
+
if (!read.ok)
|
|
722
|
+
return null;
|
|
700
723
|
try {
|
|
701
|
-
const parsed =
|
|
702
|
-
if (typeof parsed["label"] !== "string")
|
|
703
|
-
return null;
|
|
724
|
+
const parsed = read.value;
|
|
704
725
|
const mail = parsed["mail"] !== null && typeof parsed["mail"] === "object" ? parsed["mail"] : null;
|
|
705
726
|
const chat = parsed["chat"] !== null && typeof parsed["chat"] === "object" ? parsed["chat"] : null;
|
|
706
727
|
return { kind: String(parsed["kind"] ?? ""), label: parsed["label"], url: typeof parsed["url"] === "string" ? parsed["url"] : null,
|
|
@@ -3977,6 +3998,9 @@ function initializeStore(db, file) {
|
|
|
3977
3998
|
db.exec(MATE_ASK_SCHEMA);
|
|
3978
3999
|
// Decisions in the chat app (no version bump: additive only): result, plan and merge buttons, and Request changes.
|
|
3979
4000
|
db.exec(CHAT_DECIDE_SCHEMA);
|
|
4001
|
+
// An owner's lasting chat-approval setting (no version bump: additive only; absent means off).
|
|
4002
|
+
db.exec(CHAT_APPROVAL_SCHEMA);
|
|
4003
|
+
db.exec(TELEGRAM_FLOW_CONFIRM_SCHEMA);
|
|
3980
4004
|
// A flow's "Send to me" and "Person chooses" zones (no version bump: additive only).
|
|
3981
4005
|
db.exec(FLOW_SEND_SCHEMA);
|
|
3982
4006
|
db.exec(SPEND_SCHEMA);
|
|
@@ -6684,12 +6708,10 @@ function migrateToV24(db) {
|
|
|
6684
6708
|
}
|
|
6685
6709
|
else {
|
|
6686
6710
|
let touches = [];
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
touches = [];
|
|
6692
|
-
}
|
|
6711
|
+
const read = readStoreColumn("task_scope.touches", row.touches);
|
|
6712
|
+
// Unlike the display reader, v24 passed every valid JSON value to digestOf, including non-arrays.
|
|
6713
|
+
if (read.ok)
|
|
6714
|
+
touches = read.value;
|
|
6693
6715
|
const recomputed = digestOf({ goal: row.goal, outOfScope: row.outOfScope, touches, budgetMicrousd: row.budget }, resolved.profile);
|
|
6694
6716
|
stampUnapproved.run(snapshot, recomputed, provenance, row.taskId);
|
|
6695
6717
|
}
|
|
@@ -8812,7 +8834,7 @@ export class Store {
|
|
|
8812
8834
|
// (setup review): the approval is what was stale, and it is new.
|
|
8813
8835
|
const ref = this.db.prepare("SELECT id FROM task_ref WHERE backend = ? AND external_id = ?").get(BUILT_IN, taskId);
|
|
8814
8836
|
if (ref !== undefined) {
|
|
8815
|
-
if (basis === undefined)
|
|
8837
|
+
if (basis === undefined || basis.kind === "chat")
|
|
8816
8838
|
this.noteTaskAct(Number(ref["id"]), "approved", now);
|
|
8817
8839
|
this.db.prepare("DELETE FROM hold WHERE owner_kind = 'backoff' AND owner_id = ?").run(`stale:${Number(ref["id"])}`);
|
|
8818
8840
|
this.db
|
|
@@ -8828,7 +8850,9 @@ export class Store {
|
|
|
8828
8850
|
subject: "Scope approved",
|
|
8829
8851
|
body: basis === undefined
|
|
8830
8852
|
? `Approved by ${currentActor()?.lead === true ? "the lead" : lifecycleWords(by, 40)}. A connected worker can take it next.`
|
|
8831
|
-
:
|
|
8853
|
+
: basis.kind === "chat"
|
|
8854
|
+
? `Approved by ${lifecycleWords(by, 40)} in chat. A connected worker can take it next.`
|
|
8855
|
+
: "Approved automatically under the operating mode. A connected worker can take it next.",
|
|
8832
8856
|
link: chatControlHref("task", taskId),
|
|
8833
8857
|
}, now);
|
|
8834
8858
|
}
|
|
@@ -9086,7 +9110,7 @@ export class Store {
|
|
|
9086
9110
|
return { ok: true };
|
|
9087
9111
|
let terms;
|
|
9088
9112
|
try {
|
|
9089
|
-
terms =
|
|
9113
|
+
terms = parseStoreColumn("operating_mode.terms_json", mode.termsJson);
|
|
9090
9114
|
}
|
|
9091
9115
|
catch {
|
|
9092
9116
|
return { ok: true };
|
|
@@ -9243,15 +9267,7 @@ export class Store {
|
|
|
9243
9267
|
const row = this.db.prepare("SELECT * FROM approval_policy WHERE repo = ?").get(repo);
|
|
9244
9268
|
if (row === undefined)
|
|
9245
9269
|
return { ...NO_RULES, updatedBy: null, updatedAt: null };
|
|
9246
|
-
|
|
9247
|
-
try {
|
|
9248
|
-
const parsed = JSON.parse(String(row["protected_paths"]));
|
|
9249
|
-
if (Array.isArray(parsed))
|
|
9250
|
-
paths = parsed.filter((one) => typeof one === "string");
|
|
9251
|
-
}
|
|
9252
|
-
catch {
|
|
9253
|
-
paths = [];
|
|
9254
|
-
}
|
|
9270
|
+
const paths = readStoreTextList("approval_policy.protected_paths", row["protected_paths"]);
|
|
9255
9271
|
return { notRequester: Number(row["not_requester"]) === 1, protectProject: Number(row["protect_project"]) === 1, protectedPaths: paths, updatedBy: String(row["updated_by"]), updatedAt: String(row["updated_at"]) };
|
|
9256
9272
|
}
|
|
9257
9273
|
/** Change a project's rules; the ledger keeps before → after. */
|
|
@@ -9302,15 +9318,7 @@ export class Store {
|
|
|
9302
9318
|
return { verdict: "seal", protectedWork: false };
|
|
9303
9319
|
const repo = String(ref["repo"]);
|
|
9304
9320
|
const rules = this.approvalRules(repo);
|
|
9305
|
-
|
|
9306
|
-
try {
|
|
9307
|
-
const parsed = JSON.parse(String(scope?.["touches"] ?? "[]"));
|
|
9308
|
-
if (Array.isArray(parsed))
|
|
9309
|
-
touches = parsed.map(String);
|
|
9310
|
-
}
|
|
9311
|
-
catch {
|
|
9312
|
-
touches = [];
|
|
9313
|
-
}
|
|
9321
|
+
const touches = readStoreStringifiedList("task_scope.touches", scope?.["touches"] ?? "[]");
|
|
9314
9322
|
const protectedWork = isProtectedWork(rules, touches);
|
|
9315
9323
|
if (!rules.notRequester && !protectedWork)
|
|
9316
9324
|
return { verdict: "seal", protectedWork: false };
|
|
@@ -12048,7 +12056,7 @@ export class Store {
|
|
|
12048
12056
|
let reviewAuto = false;
|
|
12049
12057
|
if (mode !== null && mode.digest === String(row["mode_digest"] ?? "")) {
|
|
12050
12058
|
try {
|
|
12051
|
-
reviewAuto =
|
|
12059
|
+
reviewAuto = parseStoreColumn("operating_mode.terms_json", mode.termsJson).reviewAuto === true;
|
|
12052
12060
|
}
|
|
12053
12061
|
catch {
|
|
12054
12062
|
reviewAuto = false;
|
|
@@ -13458,13 +13466,10 @@ export class Store {
|
|
|
13458
13466
|
const row = this.db.prepare("SELECT entries_json FROM fallback_config WHERE scope = ? AND phase = 'build'").get(scope);
|
|
13459
13467
|
if (row === undefined)
|
|
13460
13468
|
return { ok: true, entries: [] };
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
parsed = JSON.parse(String(row["entries_json"]));
|
|
13464
|
-
}
|
|
13465
|
-
catch {
|
|
13469
|
+
const read = readStoreColumn("fallback_config.entries_json", row["entries_json"]);
|
|
13470
|
+
if (!read.ok && read.malformed)
|
|
13466
13471
|
return { ok: false, problem: `the fallback configuration for ${scope} is not valid JSON — set it again with \`config set fallback\`, or clear it` };
|
|
13467
|
-
|
|
13472
|
+
const parsed = read.ok ? read.value : null;
|
|
13468
13473
|
if (!Array.isArray(parsed))
|
|
13469
13474
|
return { ok: false, problem: `the fallback configuration for ${scope} is not a list of entries — set it again with \`config set fallback\`, or clear it` };
|
|
13470
13475
|
// A PRESENT row carries one to three entries (atomic authority
|
|
@@ -13834,7 +13839,7 @@ export class Store {
|
|
|
13834
13839
|
.filter(row => {
|
|
13835
13840
|
if (assignedRunner !== null)
|
|
13836
13841
|
return String(row["runner"]) === assignedRunner;
|
|
13837
|
-
const repos =
|
|
13842
|
+
const repos = readStoreTextList("runner.repos", row["repos"]);
|
|
13838
13843
|
return repo === null || repos.includes(repo);
|
|
13839
13844
|
})
|
|
13840
13845
|
.sort((a, b) => Number(alive(b)) - Number(alive(a)));
|
|
@@ -14004,7 +14009,7 @@ export class Store {
|
|
|
14004
14009
|
if (open !== null) {
|
|
14005
14010
|
let pinned = null;
|
|
14006
14011
|
try {
|
|
14007
|
-
const terms =
|
|
14012
|
+
const terms = parseStoreColumn("attended_authorization.terms_json", open.termsJson);
|
|
14008
14013
|
pinned = profileFromJson(typeof terms.profileJson === "string" ? terms.profileJson : null);
|
|
14009
14014
|
}
|
|
14010
14015
|
catch {
|
|
@@ -14695,7 +14700,10 @@ export class Store {
|
|
|
14695
14700
|
.all(...admittedRepos);
|
|
14696
14701
|
const optionsOf = (raw) => {
|
|
14697
14702
|
try {
|
|
14698
|
-
const
|
|
14703
|
+
const read = readStoreColumn("decision.options", raw);
|
|
14704
|
+
if (!read.ok)
|
|
14705
|
+
return [];
|
|
14706
|
+
const parsed = read.value;
|
|
14699
14707
|
return Array.isArray(parsed)
|
|
14700
14708
|
? parsed.slice(0, 6).map(one => ({ id: String(one?.id ?? ""), label: String(one?.label ?? ""), reversible: one?.reversible === true }))
|
|
14701
14709
|
: [];
|
|
@@ -15856,7 +15864,7 @@ export class Store {
|
|
|
15856
15864
|
refuse(`the attended authorization ${live.id} was minted for ${live.runner} at generation ${live.runnerGeneration}, not ${named.generation}`);
|
|
15857
15865
|
let pinned = null;
|
|
15858
15866
|
try {
|
|
15859
|
-
const terms =
|
|
15867
|
+
const terms = parseStoreColumn("attended_authorization.terms_json", live.termsJson);
|
|
15860
15868
|
pinned = profileFromJson(typeof terms.profileJson === "string" ? terms.profileJson : null);
|
|
15861
15869
|
}
|
|
15862
15870
|
catch {
|
|
@@ -17421,7 +17429,7 @@ export class Store {
|
|
|
17421
17429
|
let quickMint = false;
|
|
17422
17430
|
if (mode !== null && mode.digest === input.basis.digest && mode.signedBy === input.approver) {
|
|
17423
17431
|
try {
|
|
17424
|
-
quickMint =
|
|
17432
|
+
quickMint = parseStoreColumn("operating_mode.terms_json", mode.termsJson).quickMint === true;
|
|
17425
17433
|
}
|
|
17426
17434
|
catch {
|
|
17427
17435
|
quickMint = false;
|
|
@@ -18544,6 +18552,7 @@ export class Store {
|
|
|
18544
18552
|
const stamp = now.toISOString();
|
|
18545
18553
|
this.db.prepare("UPDATE telegram_flow_action SET consumed_at = ? WHERE card = ? AND entry = ? AND consumed_at IS NULL").run(stamp, card, entry);
|
|
18546
18554
|
this.db.prepare("UPDATE telegram_flow_prompt SET consumed_at = ? WHERE card = ? AND entry = ? AND consumed_at IS NULL").run(stamp, card, entry);
|
|
18555
|
+
this.db.prepare("UPDATE telegram_flow_confirm SET consumed_at = ? WHERE card = ? AND entry = ? AND consumed_at IS NULL").run(stamp, card, entry);
|
|
18547
18556
|
}
|
|
18548
18557
|
recordTelegramFlowPrompt(prompt, now, hours = 24) {
|
|
18549
18558
|
this.db.prepare("INSERT OR REPLACE INTO telegram_flow_prompt (chat_id, message_id, binding, card, entry, mode, created_at, expires_at, consumed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)")
|
|
@@ -18808,7 +18817,7 @@ export class Store {
|
|
|
18808
18817
|
if (mode !== null) {
|
|
18809
18818
|
let publication;
|
|
18810
18819
|
try {
|
|
18811
|
-
publication =
|
|
18820
|
+
publication = parseStoreColumn("operating_mode.terms_json", mode.termsJson).publication;
|
|
18812
18821
|
}
|
|
18813
18822
|
catch {
|
|
18814
18823
|
publication = undefined;
|
|
@@ -18938,7 +18947,7 @@ export class Store {
|
|
|
18938
18947
|
if (basis === "mode") {
|
|
18939
18948
|
let publication;
|
|
18940
18949
|
try {
|
|
18941
|
-
publication = mode === null ? undefined :
|
|
18950
|
+
publication = mode === null ? undefined : parseStoreColumn("operating_mode.terms_json", mode.termsJson).publication;
|
|
18942
18951
|
}
|
|
18943
18952
|
catch {
|
|
18944
18953
|
publication = undefined;
|
|
@@ -18950,7 +18959,7 @@ export class Store {
|
|
|
18950
18959
|
else if (basis === "grant" && mode !== null) {
|
|
18951
18960
|
let publication;
|
|
18952
18961
|
try {
|
|
18953
|
-
publication =
|
|
18962
|
+
publication = parseStoreColumn("operating_mode.terms_json", mode.termsJson).publication;
|
|
18954
18963
|
}
|
|
18955
18964
|
catch {
|
|
18956
18965
|
publication = undefined;
|
|
@@ -19486,7 +19495,7 @@ export class Store {
|
|
|
19486
19495
|
teammateEvents(teammate, limit, since = null) {
|
|
19487
19496
|
return this.db.prepare(`SELECT * FROM teammate_event WHERE teammate = ? ${since === null ? "" : "AND at >= ?"} ORDER BY id DESC LIMIT ?`).all(...(since === null ? [teammate, limit] : [teammate, since, limit])).map(row => ({
|
|
19488
19497
|
id: Number(row["id"]), teammate: Number(row["teammate"]), card: row["card"] === null ? null : Number(row["card"]), entry: row["entry"] === null ? null : Number(row["entry"]),
|
|
19489
|
-
kind: String(row["kind"]), said: String(row["said"]), detail: row["detail_json"] === null ? null :
|
|
19498
|
+
kind: String(row["kind"]), said: String(row["said"]), detail: row["detail_json"] === null ? null : parseStoreColumn("teammate_event.detail_json", row["detail_json"]),
|
|
19490
19499
|
by: row["by"] === null ? null : String(row["by"]), at: String(row["at"])
|
|
19491
19500
|
}));
|
|
19492
19501
|
}
|
|
@@ -19837,15 +19846,7 @@ export class Store {
|
|
|
19837
19846
|
/** A card's discussion, oldest first. */
|
|
19838
19847
|
flowComments(card) {
|
|
19839
19848
|
return this.db.prepare("SELECT * FROM flow_comment WHERE card = ? ORDER BY id").all(card).map(row => {
|
|
19840
|
-
|
|
19841
|
-
try {
|
|
19842
|
-
const parsed = JSON.parse(String(row["mentions_json"]));
|
|
19843
|
-
if (Array.isArray(parsed))
|
|
19844
|
-
mentions = parsed.filter((one) => typeof one === "string");
|
|
19845
|
-
}
|
|
19846
|
-
catch {
|
|
19847
|
-
mentions = [];
|
|
19848
|
-
}
|
|
19849
|
+
const mentions = readStoreTextList("flow_comment.mentions_json", row["mentions_json"]);
|
|
19849
19850
|
return { id: Number(row["id"]), card: Number(row["card"]), kind: String(row["kind"]), author: String(row["author"]), body: String(row["body"]), mentions, at: String(row["at"]) };
|
|
19850
19851
|
});
|
|
19851
19852
|
}
|
|
@@ -19947,13 +19948,8 @@ export class Store {
|
|
|
19947
19948
|
const row = this.db.prepare("SELECT tools_json FROM tool_seal WHERE task = ? AND approved_digest = ?").get(taskId, approvedDigest);
|
|
19948
19949
|
if (row === undefined)
|
|
19949
19950
|
return null;
|
|
19950
|
-
|
|
19951
|
-
|
|
19952
|
-
return Array.isArray(parsed) ? parsed.filter((one) => typeof one?.name === "string" && typeof one?.digest === "string") : [];
|
|
19953
|
-
}
|
|
19954
|
-
catch {
|
|
19955
|
-
return [];
|
|
19956
|
-
}
|
|
19951
|
+
const read = readStoreColumn("tool_seal.tools_json", row["tools_json"]);
|
|
19952
|
+
return read.ok ? read.value.filter((one) => typeof one?.name === "string" && typeof one?.digest === "string") : [];
|
|
19957
19953
|
}
|
|
19958
19954
|
/** What one attempt launched with (first launch of the run wins its record; a resumed turn updates it). */
|
|
19959
19955
|
recordRunTools(run, toolsJson, now) {
|
|
@@ -19969,19 +19965,15 @@ export class Store {
|
|
|
19969
19965
|
const row = this.db.prepare("SELECT json_extract(tools_json, '$.fence') AS fence FROM run_tool WHERE run = ?").get(run);
|
|
19970
19966
|
if (row === undefined || row["fence"] === null)
|
|
19971
19967
|
return null;
|
|
19972
|
-
|
|
19973
|
-
|
|
19974
|
-
}
|
|
19975
|
-
catch {
|
|
19976
|
-
return null;
|
|
19977
|
-
}
|
|
19968
|
+
const read = readStoreColumn("run_tool.tools_json.fence", row["fence"]);
|
|
19969
|
+
return read.ok ? read.value : null;
|
|
19978
19970
|
}
|
|
19979
19971
|
runTools(run) {
|
|
19980
19972
|
const row = this.db.prepare("SELECT tools_json FROM run_tool WHERE run = ?").get(run);
|
|
19981
19973
|
if (row === undefined)
|
|
19982
19974
|
return null;
|
|
19983
19975
|
try {
|
|
19984
|
-
const parsed =
|
|
19976
|
+
const parsed = parseStoreColumn("run_tool.tools_json", row["tools_json"]);
|
|
19985
19977
|
return { tools: Array.isArray(parsed.tools) ? parsed.tools : [], skipped: Array.isArray(parsed.skipped) ? parsed.skipped : [] };
|
|
19986
19978
|
}
|
|
19987
19979
|
catch {
|
|
@@ -20075,7 +20067,7 @@ export class Store {
|
|
|
20075
20067
|
const row = this.db.prepare("SELECT a.* FROM mate_ask a JOIN mate_turn t ON t.id = a.turn WHERE a.turn = ? AND t.state = 'answered'").get(turn);
|
|
20076
20068
|
if (row === undefined)
|
|
20077
20069
|
return null;
|
|
20078
|
-
const options =
|
|
20070
|
+
const options = parseStoreColumn("mate_ask.options_json", row["options_json"]);
|
|
20079
20071
|
return { turn: Number(row["turn"]), thread: Number(row["thread"]), question: String(row["question"]), options: Array.isArray(options) ? options.map(String) : [], createdAt: String(row["created_at"]) };
|
|
20080
20072
|
}
|
|
20081
20073
|
/** What a tap on the question finds: open; answered (its owner has written in its thread since the reply that asked
|
|
@@ -22721,13 +22713,7 @@ export class Store {
|
|
|
22721
22713
|
const row = this.db.prepare("SELECT about_json FROM lead_config WHERE account = ?").get(account);
|
|
22722
22714
|
if (row === undefined)
|
|
22723
22715
|
return [];
|
|
22724
|
-
|
|
22725
|
-
const lines = JSON.parse(String(row["about_json"]));
|
|
22726
|
-
return Array.isArray(lines) ? lines.filter((one) => typeof one === "string") : [];
|
|
22727
|
-
}
|
|
22728
|
-
catch {
|
|
22729
|
-
return [];
|
|
22730
|
-
}
|
|
22716
|
+
return readStoreTextList("lead_config.about_json", row["about_json"]);
|
|
22731
22717
|
}
|
|
22732
22718
|
/** Save what this person's lead knows about them (checked by the caller: lead-about.ts). A person who never named
|
|
22733
22719
|
* their lead gets an empty name and persona, so they keep following the defaults. */
|
|
@@ -23284,7 +23270,7 @@ export class Store {
|
|
|
23284
23270
|
mateRequestReceipt(session, request) {
|
|
23285
23271
|
const row = this.db.prepare("SELECT result FROM mutation WHERE idempotency_key = ? AND operation = 'mate-send'")
|
|
23286
23272
|
.get(`mate-send:${session}:${request}`);
|
|
23287
|
-
return row === undefined ? null :
|
|
23273
|
+
return row === undefined ? null : parseStoreColumn("mutation.result", row["result"]);
|
|
23288
23274
|
}
|
|
23289
23275
|
/**
|
|
23290
23276
|
* Run `body` once per key, ever.
|
|
@@ -23315,7 +23301,7 @@ export class Store {
|
|
|
23315
23301
|
.prepare("SELECT result FROM mutation WHERE idempotency_key = ?")
|
|
23316
23302
|
.get(idempotencyKey);
|
|
23317
23303
|
if (seen !== undefined)
|
|
23318
|
-
return
|
|
23304
|
+
return parseStoreColumn("mutation.result", seen["result"]);
|
|
23319
23305
|
const result = body();
|
|
23320
23306
|
if (!worthRecording(result))
|
|
23321
23307
|
return result;
|
|
@@ -23596,7 +23582,7 @@ function readDecision(row) {
|
|
|
23596
23582
|
state: String(row["state"]),
|
|
23597
23583
|
recap: String(row["recap"]),
|
|
23598
23584
|
question: String(row["question"]),
|
|
23599
|
-
options:
|
|
23585
|
+
options: parseStoreColumn("decision.options", row["options"]),
|
|
23600
23586
|
recommendation: String(row["recommendation"]),
|
|
23601
23587
|
assignee: row["assignee"] === null ? null : String(row["assignee"]),
|
|
23602
23588
|
deadline: row["deadline"] === null ? null : String(row["deadline"]),
|
|
@@ -23638,7 +23624,7 @@ function readPlanRevision(row) {
|
|
|
23638
23624
|
kind: String(row["kind"]),
|
|
23639
23625
|
authorityKind: String(row["authority_kind"]),
|
|
23640
23626
|
authorityDigest: String(row["authority_digest"]),
|
|
23641
|
-
changedFields: row["changed_fields"] === null || row["changed_fields"] === undefined ? [] :
|
|
23627
|
+
changedFields: row["changed_fields"] === null || row["changed_fields"] === undefined ? [] : parseStoreColumn("plan_revision.changed_fields", row["changed_fields"]),
|
|
23642
23628
|
status: String(row["status"]),
|
|
23643
23629
|
createdAt: String(row["created_at"]),
|
|
23644
23630
|
resolvedAt: row["resolved_at"] === null || row["resolved_at"] === undefined ? null : String(row["resolved_at"]),
|
|
@@ -23665,7 +23651,7 @@ function readRunCheckpoint(row) {
|
|
|
23665
23651
|
run: Number(row["run"]),
|
|
23666
23652
|
taskRef: Number(row["task_ref"]),
|
|
23667
23653
|
planRevision: Number(row["plan_revision"]),
|
|
23668
|
-
snapshot:
|
|
23654
|
+
snapshot: parseStoreColumn("run_checkpoint.snapshot_json", row["snapshot_json"]),
|
|
23669
23655
|
createdAt: String(row["created_at"]),
|
|
23670
23656
|
};
|
|
23671
23657
|
}
|
|
@@ -23738,7 +23724,7 @@ function readTelegramConversationPart(row) {
|
|
|
23738
23724
|
text: String(row["text"]),
|
|
23739
23725
|
replyTo: text("reply_to"),
|
|
23740
23726
|
proposal: row["proposal"] === null || row["proposal"] === undefined ? null : Number(row["proposal"]),
|
|
23741
|
-
keyboard: row["keyboard_json"] === null || row["keyboard_json"] === undefined ? null :
|
|
23727
|
+
keyboard: row["keyboard_json"] === null || row["keyboard_json"] === undefined ? null : parseStoreColumn("telegram_conversation_part.keyboard_json", row["keyboard_json"]),
|
|
23742
23728
|
state: String(row["state"]),
|
|
23743
23729
|
messageId: text("message_id"),
|
|
23744
23730
|
taskId: text("task_id"),
|
|
@@ -23804,7 +23790,7 @@ function readPublicationGrant(row) {
|
|
|
23804
23790
|
remote: String(row["remote"]),
|
|
23805
23791
|
headPrefix: String(row["head_prefix"]),
|
|
23806
23792
|
base: String(row["base"]),
|
|
23807
|
-
capabilities:
|
|
23793
|
+
capabilities: parseStoreColumn("publication_grant.capabilities", row["capabilities"]),
|
|
23808
23794
|
selector: String(row["selector"]),
|
|
23809
23795
|
draft: Number(row["draft"]) === 1,
|
|
23810
23796
|
grantedBy: String(row["granted_by"]),
|
|
@@ -23879,8 +23865,8 @@ function readTaskRef(row) {
|
|
|
23879
23865
|
? null
|
|
23880
23866
|
: String(row["coordinator_cid"]),
|
|
23881
23867
|
assignedRunner: row["assigned_runner"] === null || row["assigned_runner"] === undefined ? null : String(row["assigned_runner"]),
|
|
23882
|
-
zones:
|
|
23883
|
-
capabilityRequirements:
|
|
23868
|
+
zones: readStoreTextList("task_ref.zones", row["zones"]),
|
|
23869
|
+
capabilityRequirements: readStoreTextList("task_ref.capability_requirements", row["capability_requirements"]),
|
|
23884
23870
|
parkRate: Number(row["park_rate"]),
|
|
23885
23871
|
plan: row["plan"] === null || row["plan"] === undefined
|
|
23886
23872
|
? null
|
|
@@ -23968,9 +23954,9 @@ function readRoutine(row) {
|
|
|
23968
23954
|
repo: String(row["repo"]),
|
|
23969
23955
|
goal: String(row["goal"]),
|
|
23970
23956
|
outOfScope: row["out_of_scope"] === null ? null : String(row["out_of_scope"]),
|
|
23971
|
-
touches:
|
|
23972
|
-
acceptance: readAcceptance(row["acceptance_json"]),
|
|
23973
|
-
requirements:
|
|
23957
|
+
touches: readStoreTextList("routine.touches", row["touches"]),
|
|
23958
|
+
acceptance: readAcceptance("routine.acceptance_json", row["acceptance_json"]),
|
|
23959
|
+
requirements: readStoreTextList("routine.requirements", row["requirements"]),
|
|
23974
23960
|
schedule: String(row["schedule"]),
|
|
23975
23961
|
singleFlight: Number(row["single_flight"]) === 1,
|
|
23976
23962
|
costCeilingUsd: row["cost_ceiling_usd"] === null ? null : Number(row["cost_ceiling_usd"]),
|
|
@@ -24004,7 +23990,7 @@ function readTournamentTerms(row) {
|
|
|
24004
23990
|
active: Number(row["active"]) === 1,
|
|
24005
23991
|
kind: String(row["kind"] ?? "race") === "comparison" ? "comparison" : "race",
|
|
24006
23992
|
raceDigest: String(row["race_digest"]),
|
|
24007
|
-
agents:
|
|
23993
|
+
agents: parseStoreColumn("tournament_terms.agents", row["agents"]),
|
|
24008
23994
|
n: Number(row["n"]),
|
|
24009
23995
|
perAgentBudgetMicrousd: Number(row["per_agent_budget_microusd"]),
|
|
24010
23996
|
overrunReserveMicrousd: Number(row["overrun_reserve_microusd"]),
|
|
@@ -24169,12 +24155,12 @@ function readCoordinatorProposal(row) {
|
|
|
24169
24155
|
name: String(row["name"]),
|
|
24170
24156
|
repo: String(row["repo"]),
|
|
24171
24157
|
kind: String(row["kind"]),
|
|
24172
|
-
payload:
|
|
24158
|
+
payload: parseStoreColumn("coordinator_proposal.payload_json", row["payload_json"]),
|
|
24173
24159
|
state: String(row["state"]),
|
|
24174
24160
|
createdAt: String(row["created_at"]),
|
|
24175
24161
|
resolvedAt: row["resolved_at"] === null ? null : String(row["resolved_at"]),
|
|
24176
24162
|
resolvedBy: row["resolved_by"] === null ? null : String(row["resolved_by"]),
|
|
24177
|
-
outcome: row["outcome_json"] === null ? null :
|
|
24163
|
+
outcome: row["outcome_json"] === null ? null : parseStoreColumn("coordinator_proposal.outcome_json", row["outcome_json"]),
|
|
24178
24164
|
};
|
|
24179
24165
|
}
|
|
24180
24166
|
function readMateProposal(row) {
|
|
@@ -24185,13 +24171,13 @@ function readMateProposal(row) {
|
|
|
24185
24171
|
thread: Number(row["thread"]),
|
|
24186
24172
|
turn: Number(row["turn"]),
|
|
24187
24173
|
kind: String(row["kind"]),
|
|
24188
|
-
payload:
|
|
24174
|
+
payload: parseStoreColumn("mate_proposal.payload_json", row["payload_json"]),
|
|
24189
24175
|
ceilingDigest: String(row["ceiling_digest"]),
|
|
24190
24176
|
state: String(row["state"]),
|
|
24191
24177
|
createdAt: String(row["created_at"]),
|
|
24192
24178
|
resolvedAt: maybe("resolved_at"),
|
|
24193
24179
|
resolvedBy: maybe("resolved_by"),
|
|
24194
|
-
outcome: outcome === null ? null :
|
|
24180
|
+
outcome: outcome === null ? null : parseStoreColumn("mate_proposal.outcome_json", outcome),
|
|
24195
24181
|
};
|
|
24196
24182
|
}
|
|
24197
24183
|
function readMateTurn(row) {
|
|
@@ -24261,9 +24247,10 @@ function readMatrixJson(raw) {
|
|
|
24261
24247
|
if (raw === null || raw === undefined)
|
|
24262
24248
|
return [];
|
|
24263
24249
|
try {
|
|
24264
|
-
const
|
|
24265
|
-
if (!
|
|
24250
|
+
const read = readStoreColumn("proof_verdict.matrix_json", raw);
|
|
24251
|
+
if (!read.ok)
|
|
24266
24252
|
return [];
|
|
24253
|
+
const parsed = read.value;
|
|
24267
24254
|
// `answered` and `review` are additive (post-v39/v40 review findings):
|
|
24268
24255
|
// a row stored before either fix simply has none, never a throw at
|
|
24269
24256
|
// render.
|
|
@@ -24274,15 +24261,7 @@ function readMatrixJson(raw) {
|
|
|
24274
24261
|
}
|
|
24275
24262
|
}
|
|
24276
24263
|
function readProofVerdict(row) {
|
|
24277
|
-
|
|
24278
|
-
try {
|
|
24279
|
-
const parsed = JSON.parse(String(row["reasons_json"]));
|
|
24280
|
-
if (Array.isArray(parsed))
|
|
24281
|
-
reasons = parsed.map(one => String(one));
|
|
24282
|
-
}
|
|
24283
|
-
catch {
|
|
24284
|
-
reasons = [];
|
|
24285
|
-
}
|
|
24264
|
+
const reasons = readStoreStringifiedList("proof_verdict.reasons_json", row["reasons_json"]);
|
|
24286
24265
|
return {
|
|
24287
24266
|
run: Number(row["run"]),
|
|
24288
24267
|
verdict: String(row["verdict"]),
|
|
@@ -24296,10 +24275,10 @@ function readReviewBindingList(raw) {
|
|
|
24296
24275
|
if (typeof raw !== "string")
|
|
24297
24276
|
return [];
|
|
24298
24277
|
try {
|
|
24299
|
-
const
|
|
24300
|
-
if (!
|
|
24278
|
+
const read = readStoreColumn("criterion_review.screenshots_json", raw);
|
|
24279
|
+
if (!read.ok)
|
|
24301
24280
|
return [];
|
|
24302
|
-
return
|
|
24281
|
+
return read.value
|
|
24303
24282
|
.filter((one) => typeof one === "object" && one !== null)
|
|
24304
24283
|
.map(one => ({
|
|
24305
24284
|
artifact: Number(one["artifact"]),
|
|
@@ -24388,15 +24367,7 @@ export function revisionTermsOf(sourceRef, sourceScope, coverage, permissionDefa
|
|
|
24388
24367
|
};
|
|
24389
24368
|
}
|
|
24390
24369
|
function readRepairChain(row) {
|
|
24391
|
-
|
|
24392
|
-
try {
|
|
24393
|
-
const parsed = JSON.parse(String(row["unresolved_json"]));
|
|
24394
|
-
if (Array.isArray(parsed))
|
|
24395
|
-
unresolved = parsed.map(one => String(one));
|
|
24396
|
-
}
|
|
24397
|
-
catch {
|
|
24398
|
-
unresolved = [];
|
|
24399
|
-
}
|
|
24370
|
+
const unresolved = readStoreStringifiedList("repair_chain.unresolved_json", row["unresolved_json"]);
|
|
24400
24371
|
return {
|
|
24401
24372
|
id: Number(row["id"]),
|
|
24402
24373
|
rootTask: String(row["root_task"]),
|
|
@@ -24457,11 +24428,11 @@ export function contestantProfileOf(provider, model, repairModel, permissionMode
|
|
|
24457
24428
|
/** The stored rubric, re-proved through the same strict parser that admits
|
|
24458
24429
|
* one on the way in — never trusted bytes back out. Malformed or absent
|
|
24459
24430
|
* reads back as `[]`, matching every rubric-less scope. */
|
|
24460
|
-
function readAcceptance(value) {
|
|
24431
|
+
function readAcceptance(column, value) {
|
|
24461
24432
|
if (value === null || value === undefined)
|
|
24462
24433
|
return [];
|
|
24463
24434
|
try {
|
|
24464
|
-
return parseAcceptanceCriteria(
|
|
24435
|
+
return parseAcceptanceCriteria(parseStoreColumn(column, value)).criteria;
|
|
24465
24436
|
}
|
|
24466
24437
|
catch {
|
|
24467
24438
|
return [];
|
|
@@ -24522,7 +24493,7 @@ function readScope(row) {
|
|
|
24522
24493
|
taskId: String(row["task_id"]),
|
|
24523
24494
|
goal: String(row["goal"]),
|
|
24524
24495
|
outOfScope: row["out_of_scope"] === null ? null : String(row["out_of_scope"]),
|
|
24525
|
-
touches:
|
|
24496
|
+
touches: readStoreTextList("task_scope.touches", row["touches"]),
|
|
24526
24497
|
proposedAt: String(row["proposed_at"]),
|
|
24527
24498
|
digest: String(row["digest"]),
|
|
24528
24499
|
budgetMicrousd: row["budget_microusd"] === null || row["budget_microusd"] === undefined ? null : Number(row["budget_microusd"]),
|
|
@@ -24546,7 +24517,7 @@ function readScope(row) {
|
|
|
24546
24517
|
proposedChainJson: row["proposed_chain_json"] === null || row["proposed_chain_json"] === undefined ? null : String(row["proposed_chain_json"]),
|
|
24547
24518
|
approvedChainJson: row["approved_chain_json"] === null || row["approved_chain_json"] === undefined ? null : String(row["approved_chain_json"]),
|
|
24548
24519
|
approvalKind: String(row["approval_kind"] ?? "profile") === "chain" ? "chain" : "profile",
|
|
24549
|
-
acceptance: readAcceptance(row["acceptance_json"]),
|
|
24520
|
+
acceptance: readAcceptance("task_scope.acceptance_json", row["acceptance_json"]),
|
|
24550
24521
|
qualityMode: row["quality_mode"] === "strict" ? "strict" : "default",
|
|
24551
24522
|
riskLevel: isRiskLevel(row["risk_level"]) ? row["risk_level"] : "routine",
|
|
24552
24523
|
proposedRouteJson: row["proposed_route_json"] === null || row["proposed_route_json"] === undefined ? null : String(row["proposed_route_json"]),
|
|
@@ -24561,8 +24532,8 @@ function readRunner(row) {
|
|
|
24561
24532
|
name: String(row["name"]),
|
|
24562
24533
|
host: String(row["host"]),
|
|
24563
24534
|
capacity: Number(row["capacity"]),
|
|
24564
|
-
repos:
|
|
24565
|
-
agents:
|
|
24535
|
+
repos: readStoreTextList("runner.repos", row["repos"]),
|
|
24536
|
+
agents: readStoreTextList("runner.agents", row["agents"]),
|
|
24566
24537
|
registeredAt: String(row["registered_at"]),
|
|
24567
24538
|
heartbeatAt: String(row["heartbeat_at"]),
|
|
24568
24539
|
retiredAt: row["retired_at"] === null ? null : String(row["retired_at"]),
|
|
@@ -24655,8 +24626,8 @@ function readGrant(row) {
|
|
|
24655
24626
|
return {
|
|
24656
24627
|
repo: String(row["repo"]),
|
|
24657
24628
|
backend: String(row["backend"]),
|
|
24658
|
-
paths:
|
|
24659
|
-
mutations:
|
|
24629
|
+
paths: readStoreTextList("backend_grant.paths", row["paths"]),
|
|
24630
|
+
mutations: readStoreTextList("backend_grant.mutations", row["mutations"]),
|
|
24660
24631
|
selector: String(row["selector"]) === "all" ? "all" : "ours",
|
|
24661
24632
|
credentialScope: row["credential_scope"] === null ? null : String(row["credential_scope"]),
|
|
24662
24633
|
observedByGit: Number(row["observed_by_git"]) === 1,
|
|
@@ -24672,15 +24643,6 @@ function readGrant(row) {
|
|
|
24672
24643
|
dispatchBlockedDetail: row["dispatch_blocked_detail"] === null || row["dispatch_blocked_detail"] === undefined ? null : String(row["dispatch_blocked_detail"]),
|
|
24673
24644
|
};
|
|
24674
24645
|
}
|
|
24675
|
-
function readJsonArray(value) {
|
|
24676
|
-
try {
|
|
24677
|
-
const parsed = JSON.parse(String(value));
|
|
24678
|
-
return Array.isArray(parsed) ? parsed.filter((one) => typeof one === "string") : [];
|
|
24679
|
-
}
|
|
24680
|
-
catch {
|
|
24681
|
-
return [];
|
|
24682
|
-
}
|
|
24683
|
-
}
|
|
24684
24646
|
export function verifiedAuthor(name) {
|
|
24685
24647
|
return name;
|
|
24686
24648
|
}
|