toolroll 0.9.36 → 0.9.37
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 +58 -0
- package/dist/assignment-adapters.d.ts +12 -48
- package/dist/assignment-adapters.js +33 -43
- package/dist/build-review.d.ts +1 -1
- package/dist/build-review.js +2 -1
- package/dist/chat-acceptance.d.ts +1 -1
- package/dist/chat-actions.d.ts +18 -12
- package/dist/chat-actions.js +15 -65
- package/dist/chat-ask.js +5 -5
- package/dist/chat-decide.d.ts +14 -1
- package/dist/chat-decide.js +12 -6
- package/dist/chat-delivery-state.d.ts +12 -70
- package/dist/chat-delivery-state.js +17 -135
- package/dist/chat-delivery.js +58 -30
- package/dist/chat-flow.js +8 -6
- package/dist/chat-inbox.js +1 -1
- package/dist/coding-context.d.ts +2 -39
- package/dist/coding-context.js +2 -1
- package/dist/coding-handoff.d.ts +6 -25
- package/dist/coding-handoff.js +11 -5
- package/dist/coding-types.d.ts +2 -26
- package/dist/coding-workspace.d.ts +2 -0
- package/dist/coding-workspace.js +50 -14
- package/dist/contracts/acceptance-terms.d.ts +14 -0
- package/dist/contracts/acceptance-terms.js +16 -0
- package/dist/contracts/chat-actions.d.ts +328 -0
- package/dist/contracts/chat-actions.js +133 -0
- package/dist/contracts/chat-callback-rows.d.ts +59 -0
- package/dist/contracts/chat-callback-rows.js +46 -0
- package/dist/contracts/chat-content.d.ts +276 -0
- package/dist/contracts/chat-content.js +127 -0
- package/dist/contracts/chat-tables.d.ts +6 -0
- package/dist/contracts/chat-tables.js +136 -0
- package/dist/contracts/coding-context.d.ts +97 -0
- package/dist/contracts/coding-context.js +60 -0
- package/dist/contracts/coding-handoff.d.ts +44 -0
- package/dist/contracts/coding-handoff.js +47 -0
- package/dist/contracts/coding-workspace.d.ts +165 -0
- package/dist/contracts/coding-workspace.js +71 -0
- package/dist/contracts/contract.d.ts +7 -2
- package/dist/contracts/contract.js +21 -12
- package/dist/contracts/decision.d.ts +45 -0
- package/dist/contracts/decision.js +45 -0
- package/dist/contracts/discord-callback.d.ts +45 -0
- package/dist/contracts/discord-callback.js +34 -0
- package/dist/contracts/flow-card.d.ts +50 -0
- package/dist/contracts/flow-card.js +46 -0
- package/dist/contracts/flow-send.d.ts +119 -0
- package/dist/contracts/flow-send.js +112 -0
- package/dist/contracts/flow.d.ts +5 -0
- package/dist/contracts/flow.js +5 -0
- package/dist/contracts/gateway-tools.d.ts +374 -0
- package/dist/contracts/gateway-tools.js +94 -0
- package/dist/contracts/lead-context.d.ts +165 -0
- package/dist/contracts/lead-context.js +73 -0
- package/dist/contracts/lead-tools.d.ts +1905 -0
- package/dist/contracts/lead-tools.js +265 -0
- package/dist/contracts/memory-pass.d.ts +158 -0
- package/dist/contracts/memory-pass.js +102 -0
- package/dist/contracts/project-knowledge.d.ts +126 -0
- package/dist/contracts/project-knowledge.js +93 -0
- package/dist/contracts/project-memory.d.ts +117 -0
- package/dist/contracts/project-memory.js +51 -0
- package/dist/contracts/project-skills.d.ts +121 -0
- package/dist/contracts/project-skills.js +76 -0
- package/dist/contracts/review-findings.d.ts +46 -0
- package/dist/contracts/review-findings.js +48 -0
- package/dist/contracts/route.d.ts +484 -0
- package/dist/contracts/route.js +128 -0
- package/dist/contracts/scope.d.ts +105 -0
- package/dist/contracts/scope.js +114 -0
- package/dist/contracts/scout-report.d.ts +234 -0
- package/dist/contracts/scout-report.js +141 -0
- package/dist/contracts/slack-callback.d.ts +43 -0
- package/dist/contracts/slack-callback.js +35 -0
- package/dist/contracts/sort-answer.d.ts +83 -0
- package/dist/contracts/sort-answer.js +77 -0
- package/dist/contracts/stage-output.d.ts +127 -0
- package/dist/contracts/stage-output.js +166 -0
- package/dist/contracts/task-sizing.d.ts +24 -0
- package/dist/contracts/task-sizing.js +28 -0
- package/dist/contracts/teammate-turn.d.ts +43 -0
- package/dist/contracts/teammate-turn.js +51 -0
- package/dist/contracts/teams-callback.d.ts +14 -0
- package/dist/contracts/teams-callback.js +14 -0
- package/dist/contracts/telegram-callback.d.ts +120 -0
- package/dist/contracts/telegram-callback.js +97 -0
- package/dist/decision.d.ts +11 -20
- package/dist/decision.js +86 -167
- package/dist/desktop-update.d.ts +2 -2
- package/dist/discord-chat.js +31 -20
- package/dist/flow-engine.js +14 -17
- package/dist/flow-items.d.ts +4 -13
- package/dist/flow-items.js +1 -15
- package/dist/flow-send.d.ts +6 -37
- package/dist/flow-send.js +18 -14
- package/dist/flow-share.js +7 -1
- package/dist/flow-sort.d.ts +7 -26
- package/dist/flow-sort.js +25 -20
- package/dist/flow-steps.js +3 -2
- package/dist/flows.d.ts +2 -4
- package/dist/flows.js +9 -5
- package/dist/invoke.js +4 -4
- package/dist/lead-context.d.ts +4 -2
- package/dist/lead-context.js +24 -17
- package/dist/mate-tools.d.ts +4 -0
- package/dist/mate-tools.js +108 -275
- package/dist/mcp-connect.d.ts +24 -4
- package/dist/mcp-connect.js +78 -15
- package/dist/mcp.js +84 -216
- package/dist/memory-pass.d.ts +17 -42
- package/dist/memory-pass.js +54 -26
- package/dist/phase-routing.d.ts +19 -72
- package/dist/phase-routing.js +34 -164
- package/dist/project-knowledge.d.ts +16 -35
- package/dist/project-knowledge.js +42 -21
- package/dist/project-memory.d.ts +2 -28
- package/dist/project-memory.js +28 -13
- package/dist/project-skills.d.ts +16 -38
- package/dist/project-skills.js +41 -32
- package/dist/project-tools.d.ts +1 -0
- package/dist/project-tools.js +4 -4
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +4 -16
- package/dist/result-shots.d.ts +1 -1
- package/dist/result-shots.js +2 -1
- package/dist/review-switch.d.ts +3 -8
- package/dist/reviewer.d.ts +8 -12
- package/dist/reviewer.js +11 -35
- package/dist/scope.d.ts +21 -43
- package/dist/scope.js +42 -128
- package/dist/scout-report.d.ts +9 -194
- package/dist/scout-report.js +113 -264
- package/dist/scout.js +15 -11
- package/dist/serve.js +9 -2
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.js +26 -20
- package/dist/slack-state.js +2 -1
- package/dist/store.d.ts +9 -32
- package/dist/store.js +18 -15
- package/dist/structured-output.js +2 -1
- package/dist/subscription-chat.d.ts +4 -0
- package/dist/subscription-chat.js +4 -1
- package/dist/task-review-brief.d.ts +1 -7
- package/dist/task-review-brief.js +6 -6
- package/dist/task-sizing.d.ts +3 -27
- package/dist/task-sizing.js +11 -26
- package/dist/task-text.d.ts +0 -5
- package/dist/task-text.js +1 -3
- package/dist/teammate-question.js +7 -5
- package/dist/teammate-work.js +9 -5
- package/dist/teammates.d.ts +13 -64
- package/dist/teammates.js +32 -33
- package/dist/teams-chat.js +20 -11
- package/dist/telegram-flow.js +4 -3
- package/dist/telegram-mate.d.ts +4 -14
- package/dist/telegram-mate.js +8 -7
- package/dist/telegram-team.d.ts +2 -19
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +52 -42
- package/dist/text-limits.d.ts +142 -1
- package/dist/text-limits.js +144 -1
- package/dist/tools-ui.d.ts +2 -1
- package/dist/tools-ui.js +7 -4
- package/package.json +1 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project knowledge (project-knowledge.ts): one schema for the saved knowledge (instructions and references, every
|
|
3
|
+
* revision in `knowledge_change` and the current one in `project_knowledge`), and for the selection a run is given and
|
|
4
|
+
* keeps (`knowledge_snapshot`). The rules JSON Schema cannot state — UTF-8 byte limits, control characters, secrets,
|
|
5
|
+
* the selection's total size — run in plain code when knowledge is written. A saved payload's digest is checked
|
|
6
|
+
* against its stored bytes before it is parsed, and it is upgraded only in memory: stored bytes are never rewritten.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { limited, readVersioned, versioned } from "./contract.js";
|
|
10
|
+
import { decisionLineSchema } from "./project-memory.js";
|
|
11
|
+
/** How many references a project keeps, and how many a run is given. Text limits live in TEXT_LIMITS. */
|
|
12
|
+
export const KNOWLEDGE_COUNTS = { references: 12, selected: 3, decisions: 8 };
|
|
13
|
+
const written = limited;
|
|
14
|
+
const saved = () => z.string();
|
|
15
|
+
const referenceShape = (text) => ({
|
|
16
|
+
id: z.string(),
|
|
17
|
+
title: text("reference title", "knowledgeTitleBytes"),
|
|
18
|
+
content: text("reference text", "knowledgeReferenceBytes"),
|
|
19
|
+
/** A committed .md or .txt file the text was read from, at `sourceRevision` with blob `sourceSha`; null for a note. */
|
|
20
|
+
path: text("reference path", "knowledgePathBytes").nullable(),
|
|
21
|
+
sourceSha: z.string().nullable(),
|
|
22
|
+
sourceRevision: z.string().nullable(),
|
|
23
|
+
});
|
|
24
|
+
const knowledgeShape = (text) => ({
|
|
25
|
+
instructions: text("instructions", "knowledgeInstructionsBytes"),
|
|
26
|
+
references: z.array(z.strictObject(referenceShape(text))).max(KNOWLEDGE_COUNTS.references),
|
|
27
|
+
});
|
|
28
|
+
export const KNOWLEDGE_VERSION = 1;
|
|
29
|
+
/** Knowledge as it is written. */
|
|
30
|
+
export const knowledgeSchema = versioned(KNOWLEDGE_VERSION, knowledgeShape(written));
|
|
31
|
+
/** Knowledge as it is read back. */
|
|
32
|
+
export const savedKnowledgeSchema = versioned(KNOWLEDGE_VERSION, knowledgeShape(saved));
|
|
33
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34
|
+
function pick(body, fields) {
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const field of fields)
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(body, field))
|
|
38
|
+
out[field] = body[field];
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
const REFERENCE_FIELDS = Object.keys(referenceShape(saved));
|
|
42
|
+
/**
|
|
43
|
+
* Knowledge saved before it carried `version` (through 0.9.36: `{instructions, references}`), as version 1. Its
|
|
44
|
+
* readers took the fields they knew, so this keeps exactly those; values are never rewritten.
|
|
45
|
+
*/
|
|
46
|
+
export function upgradeKnowledgeV0(body) {
|
|
47
|
+
const references = body["references"];
|
|
48
|
+
return {
|
|
49
|
+
version: KNOWLEDGE_VERSION,
|
|
50
|
+
...pick(body, ["instructions"]),
|
|
51
|
+
...(references === undefined ? {} : { references: Array.isArray(references) ? references.map(one => (isRecord(one) ? pick(one, REFERENCE_FIELDS) : one)) : references }),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export const KNOWLEDGE_UPGRADES = { 0: upgradeKnowledgeV0 };
|
|
55
|
+
/** Read saved knowledge: version 1 as itself, an unversioned one upgraded, a newer one refused plainly. */
|
|
56
|
+
export function readKnowledge(input) {
|
|
57
|
+
const read = readVersioned(savedKnowledgeSchema, input, KNOWLEDGE_UPGRADES);
|
|
58
|
+
if (!read.ok)
|
|
59
|
+
return read;
|
|
60
|
+
const { version: _version, ...knowledge } = read.value;
|
|
61
|
+
return { ok: true, value: knowledge };
|
|
62
|
+
}
|
|
63
|
+
/** What a person drafts on the Knowledge page or the CLI; each action reads the fields it needs. */
|
|
64
|
+
export const knowledgeDraftSchema = z.strictObject({
|
|
65
|
+
instructions: z.string().optional(),
|
|
66
|
+
title: z.string().optional(),
|
|
67
|
+
content: z.string().optional(),
|
|
68
|
+
path: z.string().optional(),
|
|
69
|
+
id: z.string().optional(),
|
|
70
|
+
});
|
|
71
|
+
/** A source a run was not given, and why. */
|
|
72
|
+
export const knowledgeOmissionSchema = z.strictObject({ title: z.string(), reason: z.string() });
|
|
73
|
+
const selectionShape = (text) => ({
|
|
74
|
+
revision: z.int().min(0),
|
|
75
|
+
instructions: text("instructions", "knowledgeInstructionsBytes"),
|
|
76
|
+
references: z.array(z.strictObject(referenceShape(text))).max(KNOWLEDGE_COUNTS.references),
|
|
77
|
+
omitted: z.array(knowledgeOmissionSchema),
|
|
78
|
+
/** The run whose selection a reviewer inherited; null for a selection of its own. */
|
|
79
|
+
inheritedFrom: z.int().nullable(),
|
|
80
|
+
/** Settled decisions, one line each; absent when there are none. */
|
|
81
|
+
decisions: z.array(decisionLineSchema).max(KNOWLEDGE_COUNTS.decisions).optional(),
|
|
82
|
+
/** Source excerpts from the crew's checkout (repository-context.ts owns their shape); absent when not captured. */
|
|
83
|
+
repository: z.looseObject({}).optional(),
|
|
84
|
+
});
|
|
85
|
+
export const KNOWLEDGE_SELECTION_VERSION = 1;
|
|
86
|
+
/** The selection a run is given, as it is frozen. The keys are in the order a selection has always been written. */
|
|
87
|
+
export const knowledgeSelectionSchema = versioned(KNOWLEDGE_SELECTION_VERSION, selectionShape(written));
|
|
88
|
+
/** A frozen selection as it is read back. */
|
|
89
|
+
export const savedKnowledgeSelectionSchema = versioned(KNOWLEDGE_SELECTION_VERSION, selectionShape(saved));
|
|
90
|
+
/** Read a frozen selection: version 1 (every selection ever frozen) as itself, a newer one refused plainly. */
|
|
91
|
+
export function readKnowledgeSelection(input) {
|
|
92
|
+
return readVersioned(savedKnowledgeSelectionSchema, input);
|
|
93
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project memory's decisions (project-memory.ts): one schema for a decision as its row reads, the record its history
|
|
3
|
+
* keeps, the change a person or the lead drafts, and the one line a brief carries. The rules JSON Schema cannot state —
|
|
4
|
+
* UTF-8 byte limits, blank text, control characters and secrets — run in plain code (`clean`) when a decision is
|
|
5
|
+
* written; a row is read as it was written, and its digest is checked against the row before anything trusts it.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export declare const DECISION_STATUSES: readonly ["active", "superseded", "retired"];
|
|
9
|
+
export declare const DECISION_SOURCES: readonly ["conversation", "task", "result", "manual", "backward-pass"];
|
|
10
|
+
/** A decision as it is recorded, in the order its digest lists the fields. */
|
|
11
|
+
export declare const decisionRecordSchema: z.ZodObject<{
|
|
12
|
+
repo: z.ZodString;
|
|
13
|
+
revision: z.ZodInt;
|
|
14
|
+
claim: z.ZodString;
|
|
15
|
+
why: z.ZodString;
|
|
16
|
+
status: z.ZodEnum<{
|
|
17
|
+
active: "active";
|
|
18
|
+
retired: "retired";
|
|
19
|
+
superseded: "superseded";
|
|
20
|
+
}>;
|
|
21
|
+
supersedes: z.ZodNullable<z.ZodInt>;
|
|
22
|
+
decidedBy: z.ZodString;
|
|
23
|
+
decidedAt: z.ZodString;
|
|
24
|
+
sourceKind: z.ZodEnum<{
|
|
25
|
+
"backward-pass": "backward-pass";
|
|
26
|
+
conversation: "conversation";
|
|
27
|
+
manual: "manual";
|
|
28
|
+
result: "result";
|
|
29
|
+
task: "task";
|
|
30
|
+
}>;
|
|
31
|
+
sourceRef: z.ZodNullable<z.ZodString>;
|
|
32
|
+
recordedBy: z.ZodString;
|
|
33
|
+
}, z.core.$strict>;
|
|
34
|
+
/** A decision as its row reads. */
|
|
35
|
+
export declare const decisionSchema: z.ZodObject<{
|
|
36
|
+
repo: z.ZodString;
|
|
37
|
+
revision: z.ZodInt;
|
|
38
|
+
claim: z.ZodString;
|
|
39
|
+
why: z.ZodString;
|
|
40
|
+
status: z.ZodEnum<{
|
|
41
|
+
active: "active";
|
|
42
|
+
retired: "retired";
|
|
43
|
+
superseded: "superseded";
|
|
44
|
+
}>;
|
|
45
|
+
supersedes: z.ZodNullable<z.ZodInt>;
|
|
46
|
+
decidedBy: z.ZodString;
|
|
47
|
+
decidedAt: z.ZodString;
|
|
48
|
+
sourceKind: z.ZodEnum<{
|
|
49
|
+
"backward-pass": "backward-pass";
|
|
50
|
+
conversation: "conversation";
|
|
51
|
+
manual: "manual";
|
|
52
|
+
result: "result";
|
|
53
|
+
task: "task";
|
|
54
|
+
}>;
|
|
55
|
+
sourceRef: z.ZodNullable<z.ZodString>;
|
|
56
|
+
recordedBy: z.ZodString;
|
|
57
|
+
id: z.ZodInt;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
export type Decision = z.infer<typeof decisionSchema>;
|
|
60
|
+
export type DecisionRecord = z.infer<typeof decisionRecordSchema>;
|
|
61
|
+
/** What a person or the lead asks to record; only the choice and its reason are required. */
|
|
62
|
+
export declare const decisionDraftSchema: z.ZodObject<{
|
|
63
|
+
claim: z.ZodString;
|
|
64
|
+
why: z.ZodString;
|
|
65
|
+
decidedBy: z.ZodOptional<z.ZodString>;
|
|
66
|
+
decidedAt: z.ZodOptional<z.ZodString>;
|
|
67
|
+
sourceKind: z.ZodOptional<z.ZodEnum<{
|
|
68
|
+
"backward-pass": "backward-pass";
|
|
69
|
+
conversation: "conversation";
|
|
70
|
+
manual: "manual";
|
|
71
|
+
result: "result";
|
|
72
|
+
task: "task";
|
|
73
|
+
}>>;
|
|
74
|
+
sourceRef: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
75
|
+
supersedes: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
|
|
76
|
+
}, z.core.$strict>;
|
|
77
|
+
export type DecisionDraft = z.infer<typeof decisionDraftSchema>;
|
|
78
|
+
/** One decision in a brief: its id, the choice and when; the why loads on demand by id. */
|
|
79
|
+
export declare const decisionLineSchema: z.ZodObject<{
|
|
80
|
+
id: z.ZodInt;
|
|
81
|
+
claim: z.ZodString;
|
|
82
|
+
decidedAt: z.ZodString;
|
|
83
|
+
}, z.core.$strict>;
|
|
84
|
+
export type DecisionLine = z.infer<typeof decisionLineSchema>;
|
|
85
|
+
export declare const DECISION_CHANGE_VERSION = 1;
|
|
86
|
+
/**
|
|
87
|
+
* One entry of a decision's history (`decision_change.payload`): the record when it was made, or the reason its status
|
|
88
|
+
* changed. Entries written before this carried `version` are the same shapes without it; nothing reads them back.
|
|
89
|
+
*/
|
|
90
|
+
export declare const decisionChangeSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
91
|
+
version: z.ZodLiteral<1>;
|
|
92
|
+
repo: z.ZodString;
|
|
93
|
+
revision: z.ZodInt;
|
|
94
|
+
claim: z.ZodString;
|
|
95
|
+
why: z.ZodString;
|
|
96
|
+
status: z.ZodEnum<{
|
|
97
|
+
active: "active";
|
|
98
|
+
retired: "retired";
|
|
99
|
+
superseded: "superseded";
|
|
100
|
+
}>;
|
|
101
|
+
supersedes: z.ZodNullable<z.ZodInt>;
|
|
102
|
+
decidedBy: z.ZodString;
|
|
103
|
+
decidedAt: z.ZodString;
|
|
104
|
+
sourceKind: z.ZodEnum<{
|
|
105
|
+
"backward-pass": "backward-pass";
|
|
106
|
+
conversation: "conversation";
|
|
107
|
+
manual: "manual";
|
|
108
|
+
result: "result";
|
|
109
|
+
task: "task";
|
|
110
|
+
}>;
|
|
111
|
+
sourceRef: z.ZodNullable<z.ZodString>;
|
|
112
|
+
recordedBy: z.ZodString;
|
|
113
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
114
|
+
version: z.ZodLiteral<1>;
|
|
115
|
+
reason: z.ZodString;
|
|
116
|
+
}, z.core.$strict>]>;
|
|
117
|
+
export type DecisionChange = z.infer<typeof decisionChangeSchema>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project memory's decisions (project-memory.ts): one schema for a decision as its row reads, the record its history
|
|
3
|
+
* keeps, the change a person or the lead drafts, and the one line a brief carries. The rules JSON Schema cannot state —
|
|
4
|
+
* UTF-8 byte limits, blank text, control characters and secrets — run in plain code (`clean`) when a decision is
|
|
5
|
+
* written; a row is read as it was written, and its digest is checked against the row before anything trusts it.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { limited, versioned } from "./contract.js";
|
|
9
|
+
export const DECISION_STATUSES = ["active", "superseded", "retired"];
|
|
10
|
+
export const DECISION_SOURCES = ["conversation", "task", "result", "manual", "backward-pass"];
|
|
11
|
+
const written = limited;
|
|
12
|
+
const saved = () => z.string();
|
|
13
|
+
const recordShape = (text) => ({
|
|
14
|
+
repo: z.string(),
|
|
15
|
+
revision: z.int().min(1),
|
|
16
|
+
claim: text("decision", "decisionClaimBytes"),
|
|
17
|
+
why: text("reason", "decisionWhyBytes"),
|
|
18
|
+
status: z.enum(DECISION_STATUSES),
|
|
19
|
+
supersedes: z.int().nullable(),
|
|
20
|
+
// An omitted draft author defaults to the account name, which has never had the explicit author's byte limit.
|
|
21
|
+
decidedBy: z.string(),
|
|
22
|
+
decidedAt: z.string(),
|
|
23
|
+
sourceKind: z.enum(DECISION_SOURCES),
|
|
24
|
+
sourceRef: text("source", "decisionSourceBytes").nullable(),
|
|
25
|
+
recordedBy: z.string(),
|
|
26
|
+
});
|
|
27
|
+
/** A decision as it is recorded, in the order its digest lists the fields. */
|
|
28
|
+
export const decisionRecordSchema = z.strictObject(recordShape(written));
|
|
29
|
+
/** A decision as its row reads. */
|
|
30
|
+
export const decisionSchema = z.strictObject({ id: z.int(), ...recordShape(saved) });
|
|
31
|
+
/** What a person or the lead asks to record; only the choice and its reason are required. */
|
|
32
|
+
export const decisionDraftSchema = z.strictObject({
|
|
33
|
+
claim: z.string(),
|
|
34
|
+
why: z.string(),
|
|
35
|
+
decidedBy: z.string().optional(),
|
|
36
|
+
decidedAt: z.string().optional(),
|
|
37
|
+
sourceKind: z.enum(DECISION_SOURCES).optional(),
|
|
38
|
+
sourceRef: z.string().nullable().optional(),
|
|
39
|
+
supersedes: z.int().nullable().optional(),
|
|
40
|
+
});
|
|
41
|
+
/** One decision in a brief: its id, the choice and when; the why loads on demand by id. */
|
|
42
|
+
export const decisionLineSchema = z.strictObject({ id: z.int(), claim: z.string(), decidedAt: z.string() });
|
|
43
|
+
export const DECISION_CHANGE_VERSION = 1;
|
|
44
|
+
/**
|
|
45
|
+
* One entry of a decision's history (`decision_change.payload`): the record when it was made, or the reason its status
|
|
46
|
+
* changed. Entries written before this carried `version` are the same shapes without it; nothing reads them back.
|
|
47
|
+
*/
|
|
48
|
+
export const decisionChangeSchema = z.union([
|
|
49
|
+
versioned(DECISION_CHANGE_VERSION, recordShape(written)),
|
|
50
|
+
versioned(DECISION_CHANGE_VERSION, { reason: limited("reason", "decisionRetireBytes") }),
|
|
51
|
+
]);
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project skills (project-skills.ts): one schema for a skill package (`skill_package`), a project's selection of
|
|
3
|
+
* versions (`project_skill_change`), and the versions a run is pinned to (`skill_snapshot`, and the snapshot a reviewer
|
|
4
|
+
* reads). The rules JSON Schema cannot state — UTF-8 byte limits, base64, path safety, YAML metadata, secrets, the
|
|
5
|
+
* selection's total size — run in plain code (`validateSkill`, `changeSkills`) when a skill is imported or chosen.
|
|
6
|
+
*
|
|
7
|
+
* Two payloads carry no envelope, on purpose. A package is content-addressed: its digest is its version, so the same
|
|
8
|
+
* folder imported before and after this contract is the same version. A selection maps skill names to versions, and
|
|
9
|
+
* `version` is itself a valid skill name, so a key there would collide with one; an older runtime also reads every
|
|
10
|
+
* value in it as a choice. Both are read exactly as they have always been written.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { type ContractResult } from "./contract.js";
|
|
14
|
+
/** How many files a package holds, how many versions a project enables and a person's library keeps. Text limits live
|
|
15
|
+
* in TEXT_LIMITS. */
|
|
16
|
+
export declare const SKILL_COUNTS: {
|
|
17
|
+
readonly files: 64;
|
|
18
|
+
readonly enabled: 8;
|
|
19
|
+
readonly library: 100;
|
|
20
|
+
};
|
|
21
|
+
/** Every skill limit by its long-standing name: the counts above and the byte limits from TEXT_LIMITS. */
|
|
22
|
+
export declare const SKILL_LIMITS: {
|
|
23
|
+
readonly files: 64;
|
|
24
|
+
readonly packageBytes: number;
|
|
25
|
+
readonly fileBytes: number;
|
|
26
|
+
readonly bodyBytes: number;
|
|
27
|
+
readonly enabled: 8;
|
|
28
|
+
readonly selectionBytes: number;
|
|
29
|
+
};
|
|
30
|
+
/** A skill name: lowercase words joined by hyphens. */
|
|
31
|
+
export declare const SKILL_NAME: RegExp;
|
|
32
|
+
export declare const skillFileSchema: z.ZodObject<{
|
|
33
|
+
path: z.ZodString;
|
|
34
|
+
base64: z.ZodString;
|
|
35
|
+
}, z.core.$strict>;
|
|
36
|
+
/** A package as it is imported. */
|
|
37
|
+
export declare const skillPackageSchema: z.ZodObject<{
|
|
38
|
+
name: z.ZodString;
|
|
39
|
+
description: z.ZodString;
|
|
40
|
+
source: z.ZodString;
|
|
41
|
+
requirements: z.ZodString;
|
|
42
|
+
warnings: z.ZodArray<z.ZodString>;
|
|
43
|
+
files: z.ZodArray<z.ZodObject<{
|
|
44
|
+
path: z.ZodString;
|
|
45
|
+
base64: z.ZodString;
|
|
46
|
+
}, z.core.$strict>>;
|
|
47
|
+
}, z.core.$strict>;
|
|
48
|
+
/** A package as it is read back. */
|
|
49
|
+
export declare const savedSkillPackageSchema: z.ZodObject<{
|
|
50
|
+
name: z.ZodString;
|
|
51
|
+
description: z.ZodString;
|
|
52
|
+
source: z.ZodString;
|
|
53
|
+
requirements: z.ZodString;
|
|
54
|
+
warnings: z.ZodArray<z.ZodString>;
|
|
55
|
+
files: z.ZodArray<z.ZodObject<{
|
|
56
|
+
path: z.ZodString;
|
|
57
|
+
base64: z.ZodString;
|
|
58
|
+
}, z.core.$strict>>;
|
|
59
|
+
}, z.core.$strict>;
|
|
60
|
+
/** A package with its version (the digest of its bytes). */
|
|
61
|
+
export declare const savedSkillSchema: z.ZodObject<{
|
|
62
|
+
name: z.ZodString;
|
|
63
|
+
description: z.ZodString;
|
|
64
|
+
source: z.ZodString;
|
|
65
|
+
requirements: z.ZodString;
|
|
66
|
+
warnings: z.ZodArray<z.ZodString>;
|
|
67
|
+
files: z.ZodArray<z.ZodObject<{
|
|
68
|
+
path: z.ZodString;
|
|
69
|
+
base64: z.ZodString;
|
|
70
|
+
}, z.core.$strict>>;
|
|
71
|
+
sha: z.ZodString;
|
|
72
|
+
}, z.core.$strict>;
|
|
73
|
+
export type SkillFile = z.infer<typeof skillFileSchema>;
|
|
74
|
+
export type SkillPackage = z.infer<typeof skillPackageSchema>;
|
|
75
|
+
export type SavedSkill = z.infer<typeof savedSkillSchema>;
|
|
76
|
+
/** One skill's chosen version, and whether it is on. */
|
|
77
|
+
export declare const skillChoiceSchema: z.ZodObject<{
|
|
78
|
+
sha: z.ZodString;
|
|
79
|
+
enabled: z.ZodBoolean;
|
|
80
|
+
}, z.core.$strict>;
|
|
81
|
+
/** A project's selection: each skill name and its chosen version. */
|
|
82
|
+
export declare const skillSelectionSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
83
|
+
sha: z.ZodString;
|
|
84
|
+
enabled: z.ZodBoolean;
|
|
85
|
+
}, z.core.$strict>>;
|
|
86
|
+
export type SkillChoice = z.infer<typeof skillChoiceSchema>;
|
|
87
|
+
export type SkillSelection = z.infer<typeof skillSelectionSchema>;
|
|
88
|
+
export declare const SKILLS_SNAPSHOT_VERSION = 1;
|
|
89
|
+
/** The versions a run is pinned to, as frozen: the packages by digest. */
|
|
90
|
+
export declare const savedSkillsSnapshotSchema: z.ZodObject<{
|
|
91
|
+
version: z.ZodLiteral<1>;
|
|
92
|
+
revision: z.ZodInt;
|
|
93
|
+
identity: z.ZodString;
|
|
94
|
+
inheritedFrom: z.ZodNullable<z.ZodInt>;
|
|
95
|
+
test: z.ZodBoolean;
|
|
96
|
+
packageShas: z.ZodArray<z.ZodString>;
|
|
97
|
+
}, z.core.$strict>;
|
|
98
|
+
/** The same snapshot with each package read, as a run and its reviewer get it. */
|
|
99
|
+
export declare const skillsSnapshotSchema: z.ZodObject<{
|
|
100
|
+
version: z.ZodLiteral<1>;
|
|
101
|
+
revision: z.ZodInt;
|
|
102
|
+
identity: z.ZodString;
|
|
103
|
+
inheritedFrom: z.ZodNullable<z.ZodInt>;
|
|
104
|
+
test: z.ZodBoolean;
|
|
105
|
+
packages: z.ZodArray<z.ZodObject<{
|
|
106
|
+
name: z.ZodString;
|
|
107
|
+
description: z.ZodString;
|
|
108
|
+
source: z.ZodString;
|
|
109
|
+
requirements: z.ZodString;
|
|
110
|
+
warnings: z.ZodArray<z.ZodString>;
|
|
111
|
+
files: z.ZodArray<z.ZodObject<{
|
|
112
|
+
path: z.ZodString;
|
|
113
|
+
base64: z.ZodString;
|
|
114
|
+
}, z.core.$strict>>;
|
|
115
|
+
sha: z.ZodString;
|
|
116
|
+
}, z.core.$strict>>;
|
|
117
|
+
}, z.core.$strict>;
|
|
118
|
+
export type SavedSkillsSnapshot = z.infer<typeof savedSkillsSnapshotSchema>;
|
|
119
|
+
export type SkillsSnapshot = z.infer<typeof skillsSnapshotSchema>;
|
|
120
|
+
/** Read a frozen snapshot: version 1 (every snapshot ever frozen) as itself, a newer one refused plainly. */
|
|
121
|
+
export declare function readSkillsSnapshotPayload(input: unknown): ContractResult<SavedSkillsSnapshot>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project skills (project-skills.ts): one schema for a skill package (`skill_package`), a project's selection of
|
|
3
|
+
* versions (`project_skill_change`), and the versions a run is pinned to (`skill_snapshot`, and the snapshot a reviewer
|
|
4
|
+
* reads). The rules JSON Schema cannot state — UTF-8 byte limits, base64, path safety, YAML metadata, secrets, the
|
|
5
|
+
* selection's total size — run in plain code (`validateSkill`, `changeSkills`) when a skill is imported or chosen.
|
|
6
|
+
*
|
|
7
|
+
* Two payloads carry no envelope, on purpose. A package is content-addressed: its digest is its version, so the same
|
|
8
|
+
* folder imported before and after this contract is the same version. A selection maps skill names to versions, and
|
|
9
|
+
* `version` is itself a valid skill name, so a key there would collide with one; an older runtime also reads every
|
|
10
|
+
* value in it as a choice. Both are read exactly as they have always been written.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { TEXT_LIMITS } from "../text-limits.js";
|
|
14
|
+
import { limited, readVersioned, versioned } from "./contract.js";
|
|
15
|
+
/** How many files a package holds, how many versions a project enables and a person's library keeps. Text limits live
|
|
16
|
+
* in TEXT_LIMITS. */
|
|
17
|
+
export const SKILL_COUNTS = { files: 64, enabled: 8, library: 100 };
|
|
18
|
+
/** Every skill limit by its long-standing name: the counts above and the byte limits from TEXT_LIMITS. */
|
|
19
|
+
export const SKILL_LIMITS = {
|
|
20
|
+
files: SKILL_COUNTS.files,
|
|
21
|
+
packageBytes: TEXT_LIMITS.skillPackageBytes,
|
|
22
|
+
fileBytes: TEXT_LIMITS.skillFileBytes,
|
|
23
|
+
bodyBytes: TEXT_LIMITS.skillBodyBytes,
|
|
24
|
+
enabled: SKILL_COUNTS.enabled,
|
|
25
|
+
selectionBytes: TEXT_LIMITS.skillSelectionBytes,
|
|
26
|
+
};
|
|
27
|
+
const written = limited;
|
|
28
|
+
const saved = () => z.string();
|
|
29
|
+
/** A skill name: lowercase words joined by hyphens. */
|
|
30
|
+
export const SKILL_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
31
|
+
const fileShape = (text) => ({
|
|
32
|
+
/** Relative to the skill folder; no hidden parts, `.` or `..`. */
|
|
33
|
+
path: text("file path", "skillPath"),
|
|
34
|
+
/** The file's bytes, base64 (each at most TEXT_LIMITS.skillFileBytes once decoded). */
|
|
35
|
+
base64: z.string(),
|
|
36
|
+
});
|
|
37
|
+
const packageShape = (text) => ({
|
|
38
|
+
name: text("skill name", "skillNameBytes").regex(SKILL_NAME),
|
|
39
|
+
description: text("description", "skillDescriptionBytes"),
|
|
40
|
+
/** Where it was imported from: an uploaded folder or a GitHub folder pinned to a commit. */
|
|
41
|
+
source: text("source", "skillSourceBytes"),
|
|
42
|
+
/** SKILL.md's `compatibility`, or empty. */
|
|
43
|
+
requirements: text("requirements", "skillRequirementsBytes"),
|
|
44
|
+
warnings: z.array(z.string()),
|
|
45
|
+
files: z.array(z.strictObject(fileShape(text))).min(1).max(SKILL_COUNTS.files),
|
|
46
|
+
});
|
|
47
|
+
export const skillFileSchema = z.strictObject(fileShape(written));
|
|
48
|
+
/** A package as it is imported. */
|
|
49
|
+
export const skillPackageSchema = z.strictObject(packageShape(written));
|
|
50
|
+
/** A package as it is read back. */
|
|
51
|
+
export const savedSkillPackageSchema = z.strictObject(packageShape(saved));
|
|
52
|
+
/** A package with its version (the digest of its bytes). */
|
|
53
|
+
export const savedSkillSchema = z.strictObject({ ...packageShape(saved), sha: z.string() });
|
|
54
|
+
/** One skill's chosen version, and whether it is on. */
|
|
55
|
+
export const skillChoiceSchema = z.strictObject({ sha: z.string(), enabled: z.boolean() });
|
|
56
|
+
/** A project's selection: each skill name and its chosen version. */
|
|
57
|
+
export const skillSelectionSchema = z.record(z.string(), skillChoiceSchema);
|
|
58
|
+
const snapshotFacts = {
|
|
59
|
+
/** The selection revision the versions came from; 0 for none. */
|
|
60
|
+
revision: z.int().min(0),
|
|
61
|
+
/** The project identity they were chosen under, or `unconfigured`. */
|
|
62
|
+
identity: z.string(),
|
|
63
|
+
/** The run a reviewer or later attempt inherited them from. */
|
|
64
|
+
inheritedFrom: z.int().nullable(),
|
|
65
|
+
/** A skill test: the one package is the version under test. */
|
|
66
|
+
test: z.boolean(),
|
|
67
|
+
};
|
|
68
|
+
export const SKILLS_SNAPSHOT_VERSION = 1;
|
|
69
|
+
/** The versions a run is pinned to, as frozen: the packages by digest. */
|
|
70
|
+
export const savedSkillsSnapshotSchema = versioned(SKILLS_SNAPSHOT_VERSION, { ...snapshotFacts, packageShas: z.array(z.string()) });
|
|
71
|
+
/** The same snapshot with each package read, as a run and its reviewer get it. */
|
|
72
|
+
export const skillsSnapshotSchema = versioned(SKILLS_SNAPSHOT_VERSION, { ...snapshotFacts, packages: z.array(savedSkillSchema) });
|
|
73
|
+
/** Read a frozen snapshot: version 1 (every snapshot ever frozen) as itself, a newer one refused plainly. */
|
|
74
|
+
export function readSkillsSnapshotPayload(input) {
|
|
75
|
+
return readVersioned(savedSkillsSnapshotSchema, input);
|
|
76
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The automatic build review's findings (build-review.ts): one schema for the reply a reviewer gives, the `findings`
|
|
3
|
+
* a Claude reviewer's `--json-schema` describes (provider.ts, inside the review channel it shares with evidence
|
|
4
|
+
* reviews), and what `build_review.findings_json` keeps. `parseBuildFindings` (reviewer.ts) reads a reply through it;
|
|
5
|
+
* a saved row is the same payload, written by `settle` after that read.
|
|
6
|
+
*
|
|
7
|
+
* As before, controls and runs of whitespace collapse to one space before text limits are checked. Unknown keys
|
|
8
|
+
* are ignored in both the review envelope and each finding.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { type ContractResult } from "./contract.js";
|
|
12
|
+
export declare const FINDING_SEVERITIES: readonly ["HIGH", "MEDIUM", "LOW"];
|
|
13
|
+
export type FindingSeverity = (typeof FINDING_SEVERITIES)[number];
|
|
14
|
+
/** How many findings one review may raise. */
|
|
15
|
+
export declare const FINDINGS_MAX = 40;
|
|
16
|
+
/** One finding: how bad, where (a path and the closest line), and how it fails, in one sentence. */
|
|
17
|
+
export declare const buildFindingSchema: z.ZodObject<{
|
|
18
|
+
severity: z.ZodEnum<{
|
|
19
|
+
HIGH: "HIGH";
|
|
20
|
+
LOW: "LOW";
|
|
21
|
+
MEDIUM: "MEDIUM";
|
|
22
|
+
}>;
|
|
23
|
+
file: z.ZodString;
|
|
24
|
+
line: z.ZodNumber;
|
|
25
|
+
scenario: z.ZodString;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type BuildFinding = z.infer<typeof buildFindingSchema>;
|
|
28
|
+
export declare const FINDINGS_VERSION = 1;
|
|
29
|
+
export declare const buildFindingsSchema: z.ZodObject<{
|
|
30
|
+
version: z.ZodLiteral<1>;
|
|
31
|
+
findings: z.ZodArray<z.ZodObject<{
|
|
32
|
+
severity: z.ZodEnum<{
|
|
33
|
+
HIGH: "HIGH";
|
|
34
|
+
LOW: "LOW";
|
|
35
|
+
MEDIUM: "MEDIUM";
|
|
36
|
+
}>;
|
|
37
|
+
file: z.ZodString;
|
|
38
|
+
line: z.ZodNumber;
|
|
39
|
+
scenario: z.ZodString;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export type BuildFindings = z.infer<typeof buildFindingsSchema>;
|
|
43
|
+
/** The `findings` a reviewer's structured reply may carry (provider.ts's review channel), from the same schema. */
|
|
44
|
+
export declare const FINDINGS_MODEL_SCHEMA: Readonly<Record<string, unknown>>;
|
|
45
|
+
/** Read a findings payload: version 1 as itself, a newer one refused plainly, anything else by path. */
|
|
46
|
+
export declare function readBuildFindings(input: unknown): ContractResult<BuildFindings>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The automatic build review's findings (build-review.ts): one schema for the reply a reviewer gives, the `findings`
|
|
3
|
+
* a Claude reviewer's `--json-schema` describes (provider.ts, inside the review channel it shares with evidence
|
|
4
|
+
* reviews), and what `build_review.findings_json` keeps. `parseBuildFindings` (reviewer.ts) reads a reply through it;
|
|
5
|
+
* a saved row is the same payload, written by `settle` after that read.
|
|
6
|
+
*
|
|
7
|
+
* As before, controls and runs of whitespace collapse to one space before text limits are checked. Unknown keys
|
|
8
|
+
* are ignored in both the review envelope and each finding.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { TEXT_LIMITS } from "../text-limits.js";
|
|
12
|
+
import { limited, readVersioned, toModelSchema, versioned } from "./contract.js";
|
|
13
|
+
export const FINDING_SEVERITIES = ["HIGH", "MEDIUM", "LOW"];
|
|
14
|
+
/** How many findings one review may raise. */
|
|
15
|
+
export const FINDINGS_MAX = 40;
|
|
16
|
+
/** One finding: how bad, where (a path and the closest line), and how it fails, in one sentence. */
|
|
17
|
+
export const buildFindingSchema = z.object({
|
|
18
|
+
severity: z.enum(FINDING_SEVERITIES),
|
|
19
|
+
file: limited("file", "reviewPath").min(1).describe(`file: at most ${TEXT_LIMITS.reviewPath} characters, on one line.`),
|
|
20
|
+
line: z.number().min(1).multipleOf(1),
|
|
21
|
+
scenario: limited("scenario", "reviewNote").min(1).describe(`scenario: at most ${TEXT_LIMITS.reviewNote} characters, on one line.`),
|
|
22
|
+
});
|
|
23
|
+
export const FINDINGS_VERSION = 1;
|
|
24
|
+
export const buildFindingsSchema = versioned(FINDINGS_VERSION, {
|
|
25
|
+
findings: z.array(buildFindingSchema).max(FINDINGS_MAX),
|
|
26
|
+
}).strip();
|
|
27
|
+
/** The `findings` a reviewer's structured reply may carry (provider.ts's review channel), from the same schema. */
|
|
28
|
+
export const FINDINGS_MODEL_SCHEMA = toModelSchema(buildFindingsSchema.shape.findings);
|
|
29
|
+
/** Read a findings payload: version 1 as itself, a newer one refused plainly, anything else by path. */
|
|
30
|
+
export function readBuildFindings(input) {
|
|
31
|
+
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
32
|
+
const body = input;
|
|
33
|
+
if (Array.isArray(body["findings"])) {
|
|
34
|
+
input = { ...body, findings: body["findings"].map(entry => {
|
|
35
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
36
|
+
return entry;
|
|
37
|
+
const finding = { ...entry };
|
|
38
|
+
for (const key of ["file", "scenario"]) {
|
|
39
|
+
const text = finding[key];
|
|
40
|
+
if (typeof text === "string")
|
|
41
|
+
finding[key] = text.replace(/[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]+/g, " ").replace(/\s+/g, " ").trim();
|
|
42
|
+
}
|
|
43
|
+
return finding;
|
|
44
|
+
}) };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return readVersioned(buildFindingsSchema, input);
|
|
48
|
+
}
|