kanbo-cli 0.1.0
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/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/better-sqlite3-fU3G4xnX.cjs +2254 -0
- package/dist/better-sqlite3-fU3G4xnX.cjs.map +1 -0
- package/dist/cli.cjs +42949 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/dist-Cd6wg8pp.cjs +942 -0
- package/dist/dist-Cd6wg8pp.cjs.map +1 -0
- package/dist/drizzle-postgres/0000_board.sql +135 -0
- package/dist/drizzle-postgres/0001_history_order.sql +2 -0
- package/dist/drizzle-postgres/0002_issue_pull_requests.sql +16 -0
- package/dist/drizzle-postgres/0003_milestone_start_date.sql +1 -0
- package/dist/drizzle-postgres/0004_status_entry_rules.sql +1 -0
- package/dist/drizzle-postgres/0005_run_external_session_ref.sql +1 -0
- package/dist/drizzle-postgres/README.md +61 -0
- package/dist/drizzle-postgres/meta/0000_snapshot.json +1078 -0
- package/dist/drizzle-postgres/meta/0001_snapshot.json +1090 -0
- package/dist/drizzle-postgres/meta/0002_snapshot.json +1239 -0
- package/dist/drizzle-postgres/meta/0003_snapshot.json +1245 -0
- package/dist/drizzle-postgres/meta/0004_snapshot.json +1251 -0
- package/dist/drizzle-postgres/meta/0005_snapshot.json +1257 -0
- package/dist/drizzle-postgres/meta/_journal.json +48 -0
- package/dist/drizzle-sqlite/0000_board.sql +133 -0
- package/dist/drizzle-sqlite/0001_issue_pull_requests.sql +15 -0
- package/dist/drizzle-sqlite/0002_milestone_start_date.sql +1 -0
- package/dist/drizzle-sqlite/0003_status_entry_rules.sql +1 -0
- package/dist/drizzle-sqlite/0004_run_external_session_ref.sql +1 -0
- package/dist/drizzle-sqlite/README.md +67 -0
- package/dist/drizzle-sqlite/meta/0000_snapshot.json +946 -0
- package/dist/drizzle-sqlite/meta/0001_snapshot.json +1054 -0
- package/dist/drizzle-sqlite/meta/0002_snapshot.json +1061 -0
- package/dist/drizzle-sqlite/meta/0003_snapshot.json +1068 -0
- package/dist/drizzle-sqlite/meta/0004_snapshot.json +1075 -0
- package/dist/drizzle-sqlite/meta/_journal.json +41 -0
- package/dist/lib/board-store-B16YarvX.d.mts +281 -0
- package/dist/lib/board-store-BHHo_ZlR.d.cts +281 -0
- package/dist/lib/index.cjs +340 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/index.d.cts +1608 -0
- package/dist/lib/index.d.mts +1608 -0
- package/dist/lib/index.mjs +284 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/manifest-C0EcwwgO.mjs +7866 -0
- package/dist/lib/manifest-C0EcwwgO.mjs.map +1 -0
- package/dist/lib/manifest-CpZOcB_6.cjs +8272 -0
- package/dist/lib/manifest-CpZOcB_6.cjs.map +1 -0
- package/dist/lib/mcp/index.cjs +184 -0
- package/dist/lib/mcp/index.cjs.map +1 -0
- package/dist/lib/mcp/index.d.cts +346 -0
- package/dist/lib/mcp/index.d.mts +346 -0
- package/dist/lib/mcp/index.mjs +173 -0
- package/dist/lib/mcp/index.mjs.map +1 -0
- package/dist/lib/migrate-BhYi9cXw.mjs +656 -0
- package/dist/lib/migrate-BhYi9cXw.mjs.map +1 -0
- package/dist/lib/migrate-DnMjTCvu.cjs +709 -0
- package/dist/lib/migrate-DnMjTCvu.cjs.map +1 -0
- package/dist/lib/migrations-path-CZxVOgeD.cjs +109 -0
- package/dist/lib/migrations-path-CZxVOgeD.cjs.map +1 -0
- package/dist/lib/migrations-path-Ciwan537.mjs +80 -0
- package/dist/lib/migrations-path-Ciwan537.mjs.map +1 -0
- package/dist/lib/postgres/index.cjs +56 -0
- package/dist/lib/postgres/index.cjs.map +1 -0
- package/dist/lib/postgres/index.d.cts +3403 -0
- package/dist/lib/postgres/index.d.mts +3403 -0
- package/dist/lib/postgres/index.mjs +35 -0
- package/dist/lib/postgres/index.mjs.map +1 -0
- package/dist/lib/roles.sql-B9rt-x4o.cjs +1033 -0
- package/dist/lib/roles.sql-B9rt-x4o.cjs.map +1 -0
- package/dist/lib/roles.sql-CvyCGt38.mjs +920 -0
- package/dist/lib/roles.sql-CvyCGt38.mjs.map +1 -0
- package/dist/lib/schema-epoch-ZyumVL_A.d.cts +16 -0
- package/dist/lib/schema-epoch-ZyumVL_A.d.mts +16 -0
- package/dist/lib/schema-fsHqNAip.d.cts +3612 -0
- package/dist/lib/schema-fsHqNAip.d.mts +3612 -0
- package/dist/lib/sqlite/index.cjs +23 -0
- package/dist/lib/sqlite/index.d.cts +175 -0
- package/dist/lib/sqlite/index.d.mts +175 -0
- package/dist/lib/sqlite/index.mjs +4 -0
- package/dist/lib/sqlite/schema.cjs +266 -0
- package/dist/lib/sqlite/schema.cjs.map +1 -0
- package/dist/lib/sqlite/schema.d.cts +2 -0
- package/dist/lib/sqlite/schema.d.mts +2 -0
- package/dist/lib/sqlite/schema.mjs +256 -0
- package/dist/lib/sqlite/schema.mjs.map +1 -0
- package/dist/lib/tool-names-9cmCn0gP.d.cts +112 -0
- package/dist/lib/tool-names-Dxg1UTUl.d.mts +112 -0
- package/dist/page/board.css +477 -0
- package/dist/page/board.js +2 -0
- package/drizzle-postgres/0000_board.sql +135 -0
- package/drizzle-postgres/0001_history_order.sql +2 -0
- package/drizzle-postgres/0002_issue_pull_requests.sql +16 -0
- package/drizzle-postgres/0003_milestone_start_date.sql +1 -0
- package/drizzle-postgres/0004_status_entry_rules.sql +1 -0
- package/drizzle-postgres/0005_run_external_session_ref.sql +1 -0
- package/drizzle-postgres/README.md +61 -0
- package/drizzle-postgres/meta/0000_snapshot.json +1078 -0
- package/drizzle-postgres/meta/0001_snapshot.json +1090 -0
- package/drizzle-postgres/meta/0002_snapshot.json +1239 -0
- package/drizzle-postgres/meta/0003_snapshot.json +1245 -0
- package/drizzle-postgres/meta/0004_snapshot.json +1251 -0
- package/drizzle-postgres/meta/0005_snapshot.json +1257 -0
- package/drizzle-postgres/meta/_journal.json +48 -0
- package/drizzle-sqlite/0000_board.sql +133 -0
- package/drizzle-sqlite/0001_issue_pull_requests.sql +15 -0
- package/drizzle-sqlite/0002_milestone_start_date.sql +1 -0
- package/drizzle-sqlite/0003_status_entry_rules.sql +1 -0
- package/drizzle-sqlite/0004_run_external_session_ref.sql +1 -0
- package/drizzle-sqlite/README.md +67 -0
- package/drizzle-sqlite/meta/0000_snapshot.json +946 -0
- package/drizzle-sqlite/meta/0001_snapshot.json +1054 -0
- package/drizzle-sqlite/meta/0002_snapshot.json +1061 -0
- package/drizzle-sqlite/meta/0003_snapshot.json +1068 -0
- package/drizzle-sqlite/meta/0004_snapshot.json +1075 -0
- package/drizzle-sqlite/meta/_journal.json +41 -0
- package/package.json +147 -0
|
@@ -0,0 +1,1608 @@
|
|
|
1
|
+
import { a as IssuePullRequest, c as IssueStatus, f as issueFieldChanges, i as IssueMilestone, l as KanbanMeta, n as IssueComment, o as IssueRelation, r as IssueFieldChange, s as IssueRun, t as Issue, v as issues } from "./schema-fsHqNAip.mjs";
|
|
2
|
+
import { a as BoardStore, c as IssueContextRefStore, d as IssuePullRequestStore, f as IssueRelationStore, g as KanbanMetaStore, h as IssueStatusStore, i as BoardRunProjectionScope, l as IssueFieldChangeStore, m as IssueRunStore, n as BoardLinkedPullRequest, o as BoardTransactionMode, p as IssueRowStore, r as BoardRunProjection, s as IssueCommentStore, t as BoardActiveRun, u as IssueMilestoneStore } from "./board-store-B16YarvX.mjs";
|
|
3
|
+
import { a as ENTRY_RULES, c as EntryRuleFacts, d as evaluateEntryRules, f as readChecklist, i as KanboToolName, l as UNMET_ENTRY_RULE_REASONS, m as serializeEntryRules, n as KANBO_TOOL_NAMES, o as ENTRY_RULE_DESCRIPTIONS, p as readEntryRules, r as KanboToolCliEquivalent, s as EntryRule, t as KANBO_TOOL_CLI_EQUIVALENTS, u as UnmetEntryRule } from "./tool-names-Dxg1UTUl.mjs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/cli/output.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Every exit code this tool promises, and what it means — the capabilities
|
|
8
|
+
* manifest's `exitCodes` reads this rather than naming the codes again. `0` and
|
|
9
|
+
* `1` are not declared above: they need no name of their own, success and "I
|
|
10
|
+
* could not do that" being every command line's baseline.
|
|
11
|
+
*/
|
|
12
|
+
declare const CLI_EXIT_CODES: readonly [{
|
|
13
|
+
readonly code: 0;
|
|
14
|
+
readonly meaning: "Success.";
|
|
15
|
+
}, {
|
|
16
|
+
readonly code: 1;
|
|
17
|
+
readonly meaning: "The command did not do what it was asked. See the message.";
|
|
18
|
+
}, {
|
|
19
|
+
readonly code: 2;
|
|
20
|
+
readonly meaning: "Nothing to work on, or nothing told the command what to work on.";
|
|
21
|
+
}, {
|
|
22
|
+
readonly code: 3;
|
|
23
|
+
readonly meaning: "The database is older than the board schema this build speaks.";
|
|
24
|
+
}, {
|
|
25
|
+
readonly code: 4;
|
|
26
|
+
readonly meaning: "The command is a person's to run, and this shell is not a person.";
|
|
27
|
+
}];
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/capabilities/manifest.d.ts
|
|
30
|
+
/**
|
|
31
|
+
* A machine-readable description of this board, for an agent that has never
|
|
32
|
+
* seen it before: an orchestrator deciding how to work a card, a host wiring
|
|
33
|
+
* up its own tools against the board, anything that is not a person reading
|
|
34
|
+
* the README.
|
|
35
|
+
*
|
|
36
|
+
* Every list below is read out of the same constants and registrations the
|
|
37
|
+
* board itself runs on — `KANBO_TOOLS`, `registerKanboCommands`,
|
|
38
|
+
* `BOARD_RULES`, the canonical strings `ops/cards.ts` and `ops/runs.ts` write,
|
|
39
|
+
* the roles `roles.sql.ts` creates — rather than written out a second time.
|
|
40
|
+
* `manifest.test.ts` is what keeps that true: it fails the day one of those
|
|
41
|
+
* sources gains something this file was not told about.
|
|
42
|
+
*
|
|
43
|
+
* `buildCapabilitiesManifest` and `renderCapabilitiesMarkdown` are the one
|
|
44
|
+
* source two servings come from: `kanbo capabilities` prints either shape
|
|
45
|
+
* from a terminal, and `kanbo mcp` serves both as resources
|
|
46
|
+
* (`kanbo://capabilities`, `kanbo://capabilities.md`).
|
|
47
|
+
*/
|
|
48
|
+
/** The manifest's own shape version, bumped when a field is added or removed — not the package's version. */
|
|
49
|
+
declare const CAPABILITIES_MANIFEST_VERSION = "3";
|
|
50
|
+
/** The board's name and the build that is answering, as `kanbo mcp` itself reports them. */
|
|
51
|
+
interface KanboCapabilitiesPackage {
|
|
52
|
+
name: string;
|
|
53
|
+
version: string;
|
|
54
|
+
}
|
|
55
|
+
/** One of the three places a board can live, and what tells them apart. */
|
|
56
|
+
interface KanboCapabilityStorage {
|
|
57
|
+
/** `own-file` is `kanbo init --file`; `host-file` is a host app's own database; `postgres` is external. */
|
|
58
|
+
kind: 'host-file' | 'own-file' | 'postgres';
|
|
59
|
+
label: string;
|
|
60
|
+
description: string;
|
|
61
|
+
/** The board schema generation this build speaks, from `BOARD_SCHEMA_EPOCH` — the same number in all three. */
|
|
62
|
+
schemaEpoch: number;
|
|
63
|
+
}
|
|
64
|
+
/** One of the board's MCP tools, with the JSON Schema an orchestrator validates a call against. */
|
|
65
|
+
interface KanboCapabilityTool {
|
|
66
|
+
name: string;
|
|
67
|
+
title: string;
|
|
68
|
+
description: string;
|
|
69
|
+
/** `tool.inputSchema` converted with zod's own `toJSONSchema` — never hand-written. */
|
|
70
|
+
inputSchema: Record<string, unknown>;
|
|
71
|
+
/** What to type instead, from `KANBO_TOOL_CLI_EQUIVALENTS`: the `kanbo` command. */
|
|
72
|
+
cli: KanboToolCliEquivalent;
|
|
73
|
+
}
|
|
74
|
+
/** One flag a CLI command takes, as commander itself declares it. */
|
|
75
|
+
interface KanboCapabilityCommandOption {
|
|
76
|
+
/** The flag spelling commander prints in `--help`, e.g. `--title <title>`. */
|
|
77
|
+
flags: string;
|
|
78
|
+
description: string;
|
|
79
|
+
/** Set by `.requiredOption(...)`: the command refuses to run without it. */
|
|
80
|
+
mandatory: boolean;
|
|
81
|
+
}
|
|
82
|
+
/** One positional argument a CLI command takes, as commander itself declares it. */
|
|
83
|
+
interface KanboCapabilityCommandArgument {
|
|
84
|
+
name: string;
|
|
85
|
+
description: string;
|
|
86
|
+
required: boolean;
|
|
87
|
+
}
|
|
88
|
+
/** One leaf command of the `kanbo` binary — a command with no subcommands of its own. */
|
|
89
|
+
interface KanboCapabilityCommand {
|
|
90
|
+
/** How a person types it, without the leading `kanbo`: `card create`, `approve`. */
|
|
91
|
+
path: string;
|
|
92
|
+
description: string;
|
|
93
|
+
arguments: KanboCapabilityCommandArgument[];
|
|
94
|
+
options: KanboCapabilityCommandOption[];
|
|
95
|
+
/** `true` for the commands `requireHumanActor` guards: refused in a shell that says it belongs to an agent. */
|
|
96
|
+
humanOnly: boolean;
|
|
97
|
+
/** Every exit code this build promises, from `CLI_EXIT_CODES` — the same table for every command. */
|
|
98
|
+
exitCodes: typeof CLI_EXIT_CODES;
|
|
99
|
+
}
|
|
100
|
+
/** The two database roles an external board is worked through, and what the database itself refuses the agent. */
|
|
101
|
+
interface KanboCapabilitiesRoles {
|
|
102
|
+
person: string;
|
|
103
|
+
agent: string;
|
|
104
|
+
/** What the database says back when the agent role tries the two things that are a person's. */
|
|
105
|
+
refusals: string[];
|
|
106
|
+
}
|
|
107
|
+
/** One rule a column may ask of a card before an agent moves the card in (ruling 6-1). */
|
|
108
|
+
interface KanboCapabilityEntryRule {
|
|
109
|
+
rule: EntryRule;
|
|
110
|
+
description: string;
|
|
111
|
+
}
|
|
112
|
+
/** Everything an orchestrator can read about this board before it has opened one. */
|
|
113
|
+
interface KanboCapabilities {
|
|
114
|
+
version: string;
|
|
115
|
+
package: KanboCapabilitiesPackage;
|
|
116
|
+
storages: KanboCapabilityStorage[];
|
|
117
|
+
tools: KanboCapabilityTool[];
|
|
118
|
+
commands: KanboCapabilityCommand[];
|
|
119
|
+
/** The board-independent rules `kanbo prime` states — no columns here, because a column is per board. */
|
|
120
|
+
rules: string[];
|
|
121
|
+
/** Every rule a column may ask of a card, from `ENTRY_RULES` — which columns ask for which is per board, in `kanbo_columns`. */
|
|
122
|
+
entryRules: KanboCapabilityEntryRule[];
|
|
123
|
+
/** The literal strings the board writes for a run's lifecycle, an approval and a return — prefixes end in the punctuation or space that precedes the part a caller fills in. */
|
|
124
|
+
canonicalStrings: Record<string, string>;
|
|
125
|
+
roles: KanboCapabilitiesRoles;
|
|
126
|
+
limits: string[];
|
|
127
|
+
}
|
|
128
|
+
/** Everything this build of the board can tell an orchestrator about itself. */
|
|
129
|
+
declare function buildCapabilitiesManifest(): KanboCapabilities;
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/capabilities/markdown.d.ts
|
|
132
|
+
/** The manifest, laid out under one heading per field — stable and diffable, never a snapshot to update by hand. */
|
|
133
|
+
declare function renderCapabilitiesMarkdown(manifest: KanboCapabilities): string;
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/cli/binding.d.ts
|
|
136
|
+
/** The binding file itself, relative to the project root. */
|
|
137
|
+
declare const BINDING_FILE_PATH: string;
|
|
138
|
+
declare const BindingSchema: z.ZodObject<{
|
|
139
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
140
|
+
workspaceId: z.ZodString;
|
|
141
|
+
boardId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
142
|
+
dbPath: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
143
|
+
databaseUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
144
|
+
agentDatabaseUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
145
|
+
identifier: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
146
|
+
}, z.core.$strip>;
|
|
147
|
+
/** The project's binding, as it is written and read back. */
|
|
148
|
+
type KanboBinding = z.infer<typeof BindingSchema>;
|
|
149
|
+
/**
|
|
150
|
+
* The binding this project folder has of its own — not a parent's.
|
|
151
|
+
*
|
|
152
|
+
* `kanbo init` merges into it rather than replacing it: a person re-running
|
|
153
|
+
* the command to refresh an instruction block never said anything about the
|
|
154
|
+
* board, and a second `init` that quietly dropped the connection string would
|
|
155
|
+
* leave a project bound to nothing.
|
|
156
|
+
*/
|
|
157
|
+
declare function readProjectBinding(projectDir: string): KanboBinding | null;
|
|
158
|
+
/** The binding in that exact file, or `null` when there is none to read. */
|
|
159
|
+
declare function readBinding(path: string): KanboBinding | null;
|
|
160
|
+
/**
|
|
161
|
+
* Bind the project folder to a board.
|
|
162
|
+
*
|
|
163
|
+
* The binding itself is kept out of git, because the workspace id in it means
|
|
164
|
+
* nothing in anyone else's checkout. The ignore rule names the files kanbo
|
|
165
|
+
* writes rather than `*`, so a person who does want something in `.kanbo`
|
|
166
|
+
* committed can still add it. The user's own `.gitignore` is not touched at
|
|
167
|
+
* all; it is not kanbo's file to edit.
|
|
168
|
+
*
|
|
169
|
+
* It is written `0600`, because it may hold one or two connection strings and
|
|
170
|
+
* keeping a file out of a repository is not keeping it away from the other
|
|
171
|
+
* accounts on the machine. `mode` only applies to a file this call creates, so
|
|
172
|
+
* an existing one — a second `init`, or a file written before this rule — is
|
|
173
|
+
* narrowed explicitly. Windows has no such bits and `chmodSync` does nothing
|
|
174
|
+
* there, which is the right nothing: no permission to narrow, and no failure
|
|
175
|
+
* to handle.
|
|
176
|
+
*/
|
|
177
|
+
declare function writeBinding(projectDir: string, binding: KanboBinding): string;
|
|
178
|
+
/**
|
|
179
|
+
* Make sure `.kanbo/.gitignore` also covers a board file of this project's
|
|
180
|
+
* own — `kanbo init --file` calls this once, right after creating it — and
|
|
181
|
+
* the two files SQLite leaves beside it in WAL mode, `-wal` and `-shm`, which
|
|
182
|
+
* hold committed data of their own and are exactly as much a secret as the
|
|
183
|
+
* database itself.
|
|
184
|
+
*
|
|
185
|
+
* Only when the file is inside `.kanbo`, which is where `--file` puts it by
|
|
186
|
+
* default: the ignore rule only ever grows kanbo's own directory, and a path
|
|
187
|
+
* chosen elsewhere in the project gets no line here, the same way the user's
|
|
188
|
+
* own `.gitignore` is never touched at all.
|
|
189
|
+
*/
|
|
190
|
+
declare function ignoreBoardFile(projectDir: string, absoluteDbPath: string): void;
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/default-board-file-path.d.ts
|
|
193
|
+
/**
|
|
194
|
+
* Where a board file of a project's own goes when nobody names a path —
|
|
195
|
+
* `kanbo init --file` writes it here, and an app that attaches a project's
|
|
196
|
+
* board file can import the same constant rather than spelling it again.
|
|
197
|
+
*/
|
|
198
|
+
declare const DEFAULT_BOARD_FILE_PATH: string;
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/domain/issue-view.d.ts
|
|
201
|
+
/** An issue row with its `labels` column decoded from JSON. */
|
|
202
|
+
type IssueView = Omit<Issue, 'labels'> & {
|
|
203
|
+
labels: string[];
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Who a board change is attributed to. The `issue_field_changes.actor_kind`
|
|
207
|
+
* column owns the union; comment authors carry the same kinds plus the
|
|
208
|
+
* `system.*` markers that `normalizeCommentAuthorKind` folds away.
|
|
209
|
+
*/
|
|
210
|
+
type IssueActorKind = IssueFieldChange['actorKind'];
|
|
211
|
+
declare function toIssueView(issue: Issue): IssueView;
|
|
212
|
+
/**
|
|
213
|
+
* Fold a comment's author kind onto the actor kinds a reader renders: only a
|
|
214
|
+
* person, an agent and a provider target speak for themselves, so every
|
|
215
|
+
* `system.*` marker — whatever it marks — is the board speaking as `system`.
|
|
216
|
+
*/
|
|
217
|
+
declare function normalizeCommentAuthorKind(authorKind: IssueComment['authorKind']): IssueActorKind;
|
|
218
|
+
/** Who a row is filed under, as the row stores it — what a host resolves into a name to show. */
|
|
219
|
+
interface IssueActorReference {
|
|
220
|
+
kind: IssueActorKind;
|
|
221
|
+
id: string | null;
|
|
222
|
+
sourceChatSessionId: string | null;
|
|
223
|
+
}
|
|
224
|
+
/** What a stored row says about who wrote it: the name its writer gave, and the chat session it came from. */
|
|
225
|
+
interface IssueWriterProvenance {
|
|
226
|
+
authorId: IssueComment['authorId'];
|
|
227
|
+
sourceChatSessionId: IssueComment['sourceChatSessionId'];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Was this row written by an outside writer?
|
|
231
|
+
*
|
|
232
|
+
* An outside writer is stored as `system`, the same kind the board writes
|
|
233
|
+
* under, so the kind alone cannot say. What a row carries can: a writer from
|
|
234
|
+
* outside — the `kanbo` command line, an agent someone ran themselves — gives
|
|
235
|
+
* a name and speaks from no chat session, while the board writing on its
|
|
236
|
+
* own behalf gives no name (`BOARD_ACTOR`) and an app's agent runtime filed under
|
|
237
|
+
* `system` always carries the session it was called in. The caller establishes
|
|
238
|
+
* the `system` kind first; this answers the rest of the question, and says in
|
|
239
|
+
* its type that such a writer has a name to show.
|
|
240
|
+
*/
|
|
241
|
+
declare function isOutsideWriter(provenance: IssueWriterProvenance): provenance is IssueWriterProvenance & {
|
|
242
|
+
authorId: string;
|
|
243
|
+
};
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/domain/numbering.d.ts
|
|
246
|
+
/**
|
|
247
|
+
* What numbering needs to know about a workspace: enough to build the key stem,
|
|
248
|
+
* and nothing else. A host app's workspace row satisfies it; so does a workspace
|
|
249
|
+
* a command-line tool resolved from a path, without the board reading anybody's
|
|
250
|
+
* tables to find it.
|
|
251
|
+
*
|
|
252
|
+
* Written out rather than `Pick`ed from a row type, because the board has no row
|
|
253
|
+
* to pick from: a workspace belongs to whoever tracks it, and this package declares only what it
|
|
254
|
+
* needs of one.
|
|
255
|
+
*/
|
|
256
|
+
interface BoardWorkspaceIdentity {
|
|
257
|
+
id: string;
|
|
258
|
+
identifier: string;
|
|
259
|
+
name: string;
|
|
260
|
+
}
|
|
261
|
+
/** The three-letter stem every issue key in the workspace starts with. */
|
|
262
|
+
declare function readIssuePrefix(workspace: BoardWorkspaceIdentity): string;
|
|
263
|
+
declare function formatIssueId(prefix: string, number: number): string;
|
|
264
|
+
/**
|
|
265
|
+
* The key and number the next issue of this workspace gets. The loop skips keys
|
|
266
|
+
* an earlier prefix already took, so a renamed workspace never collides with its
|
|
267
|
+
* own history.
|
|
268
|
+
*/
|
|
269
|
+
declare function nextIssueIdentity(workspace: BoardWorkspaceIdentity, store: BoardStore): Promise<{
|
|
270
|
+
id: string;
|
|
271
|
+
number: number;
|
|
272
|
+
}>;
|
|
273
|
+
declare function nextIssueNumber(workspaceId: string, tx: BoardStore): Promise<number>;
|
|
274
|
+
declare function nextIssueOrder(workspaceId: string, tx: BoardStore): Promise<number>;
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/domain/activity-types.d.ts
|
|
277
|
+
type IssueActivityValueToken = 'changed' | 'current-user' | 'empty' | 'no-due-date' | 'no-labels' | 'no-milestone' | 'no-parent' | 'no-status' | 'priority-high' | 'priority-low' | 'priority-medium' | 'priority-none' | 'priority-urgent' | 'unassigned' | 'unknown-issue' | 'unknown-milestone' | 'unknown-status' | 'unknown-user';
|
|
278
|
+
type IssueActivityValueView = {
|
|
279
|
+
kind: 'date';
|
|
280
|
+
timestamp: number;
|
|
281
|
+
} | {
|
|
282
|
+
kind: 'text';
|
|
283
|
+
text: string;
|
|
284
|
+
} | {
|
|
285
|
+
kind: 'token';
|
|
286
|
+
token: IssueActivityValueToken;
|
|
287
|
+
};
|
|
288
|
+
type IssueActivityField = 'assignee' | 'description' | 'due-date' | 'labels' | 'metadata' | 'milestone' | 'parent' | 'priority' | 'status' | 'status-line' | 'title' | 'workspace';
|
|
289
|
+
type IssueActivityAction = 'added-description' | 'changed-field' | 'cleared-description' | 'renamed-issue' | 'updated-description';
|
|
290
|
+
interface IssueActivityFieldChangeView {
|
|
291
|
+
action: IssueActivityAction;
|
|
292
|
+
field: IssueActivityField | null;
|
|
293
|
+
fromValue: IssueActivityValueView | null;
|
|
294
|
+
toValue: IssueActivityValueView | null;
|
|
295
|
+
}
|
|
296
|
+
interface IssueActivityCommentView {
|
|
297
|
+
content: string;
|
|
298
|
+
systemKind: 'delegated' | 'system' | 'undelegated' | null;
|
|
299
|
+
}
|
|
300
|
+
/** The actor a board shows beside a comment or an activity row. */
|
|
301
|
+
interface IssueCommentAuthorView {
|
|
302
|
+
kind: IssueActorKind;
|
|
303
|
+
id: string | null;
|
|
304
|
+
displayName: string;
|
|
305
|
+
avatarUrl: string | null;
|
|
306
|
+
label: string | null;
|
|
307
|
+
}
|
|
308
|
+
interface IssueActivityItemView {
|
|
309
|
+
id: string;
|
|
310
|
+
issueId: string;
|
|
311
|
+
kind: 'comment' | 'created' | 'field-change';
|
|
312
|
+
actor: IssueCommentAuthorView;
|
|
313
|
+
comment: IssueActivityCommentView | null;
|
|
314
|
+
fieldChange: IssueActivityFieldChangeView | null;
|
|
315
|
+
sourceChatSessionId: string | null;
|
|
316
|
+
createdAt: number;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* The rows an Activity projection resolves ids against, read once per issue so
|
|
320
|
+
* formatting a change never goes back to the store.
|
|
321
|
+
*/
|
|
322
|
+
interface IssueActivityLookup {
|
|
323
|
+
issue: Issue;
|
|
324
|
+
issueById: Map<string, Pick<Issue, 'id' | 'title'>>;
|
|
325
|
+
milestoneById: Map<string, Pick<IssueMilestone, 'id' | 'title'>>;
|
|
326
|
+
statusById: Map<string, Pick<IssueStatus, 'id' | 'name'>>;
|
|
327
|
+
workspaceById: Map<string, Pick<BoardWorkspaceIdentity, 'id' | 'name'>>;
|
|
328
|
+
}
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region src/domain/card-display-title.d.ts
|
|
331
|
+
/**
|
|
332
|
+
* What a card is called wherever a person or an agent reads it by name.
|
|
333
|
+
*
|
|
334
|
+
* A card written as a description alone is titled with its own key (every
|
|
335
|
+
* writer does that). Named by its key, such a card says nothing — so its name
|
|
336
|
+
* is the first line of its description instead. A browser bundle that does not
|
|
337
|
+
* load this package keeps the same rule on its own, tested with the same
|
|
338
|
+
* examples.
|
|
339
|
+
*/
|
|
340
|
+
declare function cardDisplayTitle(card: {
|
|
341
|
+
id: string;
|
|
342
|
+
title: string;
|
|
343
|
+
description?: string | null;
|
|
344
|
+
}): string;
|
|
345
|
+
//#endregion
|
|
346
|
+
//#region src/domain/database-url.d.ts
|
|
347
|
+
/**
|
|
348
|
+
* A board's connection string, as it may be said out loud.
|
|
349
|
+
*
|
|
350
|
+
* Everything a person needs to recognise which board they are talking to is
|
|
351
|
+
* the host and the database name. The password is the one part that must never
|
|
352
|
+
* reach a terminal, a log, a `--json` result or a tool's answer — and it is not
|
|
353
|
+
* the only part: a connection string carries options in its query, and a
|
|
354
|
+
* `?password=…` there is as much a secret as the one in front of the host.
|
|
355
|
+
*
|
|
356
|
+
* It is a fact about the value rather than about the command line, which is why
|
|
357
|
+
* it lives here: the MCP tools hand back messages they did not write either,
|
|
358
|
+
* and they must not be made to carry the board tool's own runtime to say them
|
|
359
|
+
* safely.
|
|
360
|
+
*/
|
|
361
|
+
/**
|
|
362
|
+
* The connection string with everything secret taken out of it.
|
|
363
|
+
*
|
|
364
|
+
* A string this cannot take apart is not examined to find out why — it is
|
|
365
|
+
* replaced entirely, because whatever is wrong with it, the secret is still
|
|
366
|
+
* somewhere inside. A missing scheme counts as that: `user:secret@host/db`
|
|
367
|
+
* parses, as a `user:` URL whose whole password is in the path, and printing it
|
|
368
|
+
* back would say the secret out loud.
|
|
369
|
+
*/
|
|
370
|
+
declare function maskDatabaseUrl(url: string): string;
|
|
371
|
+
/**
|
|
372
|
+
* Every connection string inside a line of text, masked.
|
|
373
|
+
*
|
|
374
|
+
* A message this package did not write — a driver's, a migrator's — may carry
|
|
375
|
+
* the whole connection string in the middle of a sentence, and it reaches the
|
|
376
|
+
* same terminal, or the same agent, as everything else.
|
|
377
|
+
*/
|
|
378
|
+
declare function maskDatabaseUrls(text: string): string;
|
|
379
|
+
//#endregion
|
|
380
|
+
//#region src/domain/errors.d.ts
|
|
381
|
+
/**
|
|
382
|
+
* Every failure the board itself can name. HTTP status codes are not part of
|
|
383
|
+
* this list: what each code is over HTTP is `BOARD_ERROR_RESPONSES`
|
|
384
|
+
* (`../serve/board-error-responses.ts`), the one table `kanbo serve` and any app
|
|
385
|
+
* serving the board over HTTP answer with.
|
|
386
|
+
*
|
|
387
|
+
* Five of them are about where a board lives rather than about what is on it,
|
|
388
|
+
* and they are named here for the same reason as the rest: a host that keeps
|
|
389
|
+
* one board in a file and another in a database still answers its callers in
|
|
390
|
+
* one vocabulary. `board_storage_not_prepared` is a connection string pointing
|
|
391
|
+
* at a database that holds no board this build can speak for,
|
|
392
|
+
* `board_storage_unavailable` is one the host could not reach at all,
|
|
393
|
+
* `board_storage_not_configured` is a workspace that names no board to look at,
|
|
394
|
+
* `board_storage_not_empty` is a board still holding cards when something asked
|
|
395
|
+
* to point the workspace somewhere else, and `board_mixed_workspaces` is a
|
|
396
|
+
* single operation naming cards that turned out to live in two different
|
|
397
|
+
* boards — which no transaction can commit as one.
|
|
398
|
+
*/
|
|
399
|
+
type BoardErrorCode = 'board_approval_requires_user' | 'board_column_rules_requires_user' | 'board_column_rules_unmet' | 'board_copy_conflict' | 'board_entry_rule_invalid' | 'board_execution_mode_locked' | 'board_mixed_workspaces' | 'board_pull_request_invalid' | 'board_pull_request_not_found' | 'board_pull_request_not_yours' | 'board_return_no_previous_column' | 'board_return_requires_user' | 'board_run_already_finished' | 'board_run_not_found' | 'board_run_session_ref_conflict' | 'board_run_session_ref_invalid' | 'board_run_session_ref_requires_user' | 'board_schema_outdated' | 'board_sprint_carry_invalid' | 'board_sprint_close_requires_user' | 'board_sprint_dates_invalid' | 'board_storage_not_configured' | 'board_storage_not_empty' | 'board_storage_not_prepared' | 'board_storage_unavailable' | 'issue_comment_delete_requires_user' | 'issue_comment_not_found' | 'issue_context_ref_invalid_index' | 'issue_milestone_not_found' | 'issue_not_found' | 'issue_parent_not_found' | 'issue_parent_self_reference' | 'issue_relation_not_found' | 'issue_relation_self_reference' | 'issue_status_name_empty' | 'issue_status_not_found' | 'issue_status_reference_conflict' | 'issue_workspace_not_found';
|
|
400
|
+
/** A board rule the caller broke, carrying the offending values in `details`. */
|
|
401
|
+
declare class BoardError extends Error {
|
|
402
|
+
readonly code: BoardErrorCode;
|
|
403
|
+
readonly details?: Record<string, unknown>;
|
|
404
|
+
constructor(code: BoardErrorCode, details?: Record<string, unknown>);
|
|
405
|
+
}
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region src/domain/external-session-ref.d.ts
|
|
408
|
+
/**
|
|
409
|
+
* Where an external agent's own log of a run lives, once it has said (ruling
|
|
410
|
+
* 7-1): which tool wrote it, and the id that tool knows the session by.
|
|
411
|
+
*/
|
|
412
|
+
interface ExternalSessionRef {
|
|
413
|
+
provider: 'claude' | 'codex';
|
|
414
|
+
/**
|
|
415
|
+
* The tool's own id for the session — a Claude Code session id, or a Codex
|
|
416
|
+
* session id (the one in the rollout's `session_meta`, which Codex prints).
|
|
417
|
+
*/
|
|
418
|
+
id: string;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Read an external session reference out of what an agent passed to
|
|
422
|
+
* `kanbo run start --session` or `kanbo run attach-session`: `claude:<id>` —
|
|
423
|
+
* a Claude Code session id — or `codex:<id>` — a Codex session id. Anything
|
|
424
|
+
* else is refused with `board_run_session_ref_invalid` rather than stored
|
|
425
|
+
* unread, because a ref this build cannot parse back is a transcript nobody
|
|
426
|
+
* can ever open.
|
|
427
|
+
*
|
|
428
|
+
* Doubles as the validator: a caller that only needs to know whether a string
|
|
429
|
+
* is well formed calls this and catches the throw, the same as
|
|
430
|
+
* `parsePullRequestRef`.
|
|
431
|
+
*/
|
|
432
|
+
declare function parseExternalSessionRef(input: string): ExternalSessionRef;
|
|
433
|
+
/** The stored and printed form: `claude:<id>` or `codex:<id>`. */
|
|
434
|
+
declare function formatExternalSessionRef(ref: ExternalSessionRef): string;
|
|
435
|
+
//#endregion
|
|
436
|
+
//#region src/domain/field-changes.d.ts
|
|
437
|
+
/**
|
|
438
|
+
* The issue columns whose edits are written to the audit trail.
|
|
439
|
+
*
|
|
440
|
+
* `statusLine` is absent on purpose: `writeStatusLine` records every line it
|
|
441
|
+
* writes itself, and no patch ever carries the column. `waitingFor` is absent
|
|
442
|
+
* too — whose turn it is shows in the card's own line and in the
|
|
443
|
+
* `system.approved` / `system.returned` comments around it, so a row saying the
|
|
444
|
+
* same thing a third time would only crowd the history.
|
|
445
|
+
*/
|
|
446
|
+
declare const TRACKED_FIELDS: readonly ["workspaceId", "title", "description", "priority", "labels", "milestoneId", "parentIssueId", "statusId", "assigneeKind", "assigneeId", "dueDate", "delegateAgentId", "delegateProviderTargetId", "contextRefs", "executionMode", "order"];
|
|
447
|
+
/** Who an issue edit is attributed to, with the chat session it came from. */
|
|
448
|
+
interface IssueMutationActor {
|
|
449
|
+
kind: IssueActorKind;
|
|
450
|
+
id: string | null;
|
|
451
|
+
sourceChatSessionId?: string | null;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* The audit rows one patch produces: a row per tracked field whose stringified
|
|
455
|
+
* value actually changed. Nothing is written here — the caller inserts what
|
|
456
|
+
* comes back, so the diff stays a pure function of the row, the patch, the
|
|
457
|
+
* actor and the clock.
|
|
458
|
+
*/
|
|
459
|
+
declare function diffFieldChanges(before: Issue, updates: Partial<typeof issues.$inferInsert>, actor: IssueMutationActor, now: number): Array<typeof issueFieldChanges.$inferInsert>;
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/domain/issue-activity.d.ts
|
|
462
|
+
declare function activityKindOrder(kind: IssueActivityItemView['kind']): number;
|
|
463
|
+
/**
|
|
464
|
+
* The badge a system comment renders under. Delegation owns two of its own; the
|
|
465
|
+
* rest of the `system.*` markers read as plain system comments until they earn
|
|
466
|
+
* a badge.
|
|
467
|
+
*
|
|
468
|
+
* A plain `system` row is where provenance decides: a writer from outside —
|
|
469
|
+
* the command line, an agent someone ran themselves — is stored as `system` too, and what it wrote is an ordinary comment
|
|
470
|
+
* rather than a line about the board — `isOutsideWriter` is that question.
|
|
471
|
+
*/
|
|
472
|
+
declare function readSystemCommentKind(authorKind: IssueComment['authorKind'], provenance: IssueWriterProvenance): IssueActivityCommentView['systemKind'];
|
|
473
|
+
/**
|
|
474
|
+
* Who a comment is shown under. A `system.*` marker is the board's own line
|
|
475
|
+
* about what happened — a run launched, a person's decision — so the id it
|
|
476
|
+
* carries names whoever caused the line, never its author. Only a plain
|
|
477
|
+
* `system` row can name a writer.
|
|
478
|
+
*/
|
|
479
|
+
declare function commentAuthorReference(comment: IssueComment): IssueActorReference;
|
|
480
|
+
declare function formatActivityIssueReference(value: string | null, lookup: IssueActivityLookup): IssueActivityValueView;
|
|
481
|
+
declare function formatPlainActivityValue(value: string | null): IssueActivityValueView;
|
|
482
|
+
declare function parseActivityStringArray(value: string | null): string[] | null;
|
|
483
|
+
declare function isEmptyActivityValue(value: string | null): value is null | '' | '[]';
|
|
484
|
+
declare function activityText(text: string | null): IssueActivityValueView | null;
|
|
485
|
+
declare function activityToken(token: IssueActivityValueToken): IssueActivityValueView;
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/domain/pull-request-fact-keys.d.ts
|
|
488
|
+
/**
|
|
489
|
+
* The dedupe keys the facts about one pull request are written under on a card.
|
|
490
|
+
*
|
|
491
|
+
* Whatever watches a pull request writes them — opened, merged, closed and a CI
|
|
492
|
+
* verdict per head — and whatever reads a card's pull requests, this package's
|
|
493
|
+
* `ci_green` entry rule included, reads them back (rulings 4-7, 6-2), so the spelling lives here,
|
|
494
|
+
* with the board, rather than being copied into each. Owner and repo are lower-cased
|
|
495
|
+
* because GitHub names are case-insensitive (ruling 4-6): `Acme/Repo#7` and
|
|
496
|
+
* `acme/repo#7` key to the same facts.
|
|
497
|
+
*/
|
|
498
|
+
interface PullRequestFactKeys {
|
|
499
|
+
opened: string;
|
|
500
|
+
merged: string;
|
|
501
|
+
closed: string;
|
|
502
|
+
/** GitHub answered 404/422 for this link on enough consecutive ticks that the watcher dropped it (`pr-watcher.ts`). */
|
|
503
|
+
gone: string;
|
|
504
|
+
/** What every CI verdict key of this pull request starts with; the head sha and `:green` or `:red` follow. */
|
|
505
|
+
ciPrefix: string;
|
|
506
|
+
}
|
|
507
|
+
declare function pullRequestFactKeys({ owner, repo, number }: {
|
|
508
|
+
owner: string;
|
|
509
|
+
repo: string;
|
|
510
|
+
number: number;
|
|
511
|
+
}): PullRequestFactKeys;
|
|
512
|
+
//#endregion
|
|
513
|
+
//#region src/domain/status-name.d.ts
|
|
514
|
+
/**
|
|
515
|
+
* The columns a workspace gets the first time someone opens its board, in board
|
|
516
|
+
* order. A workspace that already holds statuses is never re-seeded.
|
|
517
|
+
*/
|
|
518
|
+
declare const DEFAULT_STATUSES: readonly [{
|
|
519
|
+
readonly name: "Backlog";
|
|
520
|
+
readonly description: "Idea captured, not ready to work on";
|
|
521
|
+
readonly color: "#6b7280";
|
|
522
|
+
readonly category: "backlog";
|
|
523
|
+
}, {
|
|
524
|
+
readonly name: "To Do";
|
|
525
|
+
readonly description: "Spelled out, ready to launch";
|
|
526
|
+
readonly color: "#9ca3af";
|
|
527
|
+
readonly category: "unstarted";
|
|
528
|
+
}, {
|
|
529
|
+
readonly name: "In Progress";
|
|
530
|
+
readonly description: "The orchestrator and its agents are working";
|
|
531
|
+
readonly color: "#f59e0b";
|
|
532
|
+
readonly category: "started";
|
|
533
|
+
}, {
|
|
534
|
+
readonly name: "In Review";
|
|
535
|
+
readonly description: "Work done; being checked or waiting for you";
|
|
536
|
+
readonly color: "#8b5cf6";
|
|
537
|
+
readonly category: "started";
|
|
538
|
+
}, {
|
|
539
|
+
readonly name: "Done";
|
|
540
|
+
readonly description: "Accepted";
|
|
541
|
+
readonly color: "#22c55e";
|
|
542
|
+
readonly category: "completed";
|
|
543
|
+
}, {
|
|
544
|
+
readonly name: "Canceled";
|
|
545
|
+
readonly description: "Canceled";
|
|
546
|
+
readonly color: "#6b7280";
|
|
547
|
+
readonly category: "canceled";
|
|
548
|
+
}];
|
|
549
|
+
/**
|
|
550
|
+
* The slug two status names have in common when they mean the same column:
|
|
551
|
+
* case and the run of spaces or dashes between words are ignored, so `In
|
|
552
|
+
* Progress`, `in-progress` and `IN_PROGRESS` all resolve to one status.
|
|
553
|
+
*/
|
|
554
|
+
declare function normalizeStatusName(value: string): string;
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region src/domain/time.d.ts
|
|
557
|
+
/**
|
|
558
|
+
* Unix seconds — the unit every board timestamp column stores.
|
|
559
|
+
*
|
|
560
|
+
* The package carries its own clock, so it depends on nothing of its host's.
|
|
561
|
+
*/
|
|
562
|
+
declare function currentUnixSeconds(): number;
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/ops/change-seq.d.ts
|
|
565
|
+
/**
|
|
566
|
+
* One board write in progress: the store to work through, and — behind it — the
|
|
567
|
+
* transaction and the change flag the whole write shares.
|
|
568
|
+
*
|
|
569
|
+
* An operation that takes a scope joins the write it belongs to instead of
|
|
570
|
+
* opening one of its own, which is how a card operation that seeds columns, a
|
|
571
|
+
* status line and a comment still counts as a single change.
|
|
572
|
+
*/
|
|
573
|
+
interface BoardWriteScope<TStore extends BoardStore = BoardStore> {
|
|
574
|
+
/** The transactional store, wrapped so every write through it is noticed. */
|
|
575
|
+
readonly tx: TStore;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Run `fn` as one board write: everything it writes commits together, and the
|
|
579
|
+
* board's change counter goes up by exactly one if it wrote anything at all.
|
|
580
|
+
*
|
|
581
|
+
* The counter is what tells a reader — the board UI polling, a CLI, another
|
|
582
|
+
* agent — that the board is not the board it last read. It is bumped from the
|
|
583
|
+
* outermost scope only, after `fn` returns and only when a mutating store method
|
|
584
|
+
* was actually called, so a read-only pass and a transaction that rolls back
|
|
585
|
+
* both leave it untouched. Pass `scope` to join a write that is already open
|
|
586
|
+
* instead of starting a second one.
|
|
587
|
+
*
|
|
588
|
+
* The transaction takes its write lock up front (`immediate`), so two writers
|
|
589
|
+
* racing for the same board file fail fast rather than half-way through. A write
|
|
590
|
+
* that starts while the host already holds a transaction of its own becomes a
|
|
591
|
+
* savepoint inside it — the board counter then commits, or rolls back, with
|
|
592
|
+
* whatever the host is doing.
|
|
593
|
+
*
|
|
594
|
+
* The caller rule of the underlying transaction applies in full: `fn` must be
|
|
595
|
+
* the only database-touching async chain in flight, and inside it only
|
|
596
|
+
* operations that resolve without I/O may be awaited.
|
|
597
|
+
*/
|
|
598
|
+
declare function runBoardWrite<TStore extends BoardStore, TResult>(store: TStore, fn: (scope: BoardWriteScope<TStore>) => Promise<TResult>, scope?: BoardWriteScope<TStore>): Promise<TResult>;
|
|
599
|
+
/**
|
|
600
|
+
* How many times the board has changed. A reader that holds a number and reads
|
|
601
|
+
* the same one back is looking at the board it already has.
|
|
602
|
+
*/
|
|
603
|
+
declare function readChangeSeq(store: BoardStore): Promise<number>;
|
|
604
|
+
//#endregion
|
|
605
|
+
//#region src/ops/types.d.ts
|
|
606
|
+
/**
|
|
607
|
+
* Who is acting on the board.
|
|
608
|
+
*
|
|
609
|
+
* Four kinds reach it: a person, an agent an app launched and knows, a provider
|
|
610
|
+
* target standing in for one, and anything else — a command-line tool, a
|
|
611
|
+
* script, an agent someone ran themselves. `id` is whatever the host calls that
|
|
612
|
+
* actor, or `null` when it has no name to give; `chatSessionId` is the app's
|
|
613
|
+
* chat session the action came from, and means nothing to a board written from
|
|
614
|
+
* outside.
|
|
615
|
+
*/
|
|
616
|
+
interface BoardActor {
|
|
617
|
+
kind: 'user' | 'agent' | 'provider-target' | 'external';
|
|
618
|
+
id: string | null;
|
|
619
|
+
name?: string;
|
|
620
|
+
chatSessionId?: string | null;
|
|
621
|
+
/**
|
|
622
|
+
* A person's own terminal placing a card (ruling 6-6): the write is still
|
|
623
|
+
* filed under `kind`/`id`, but a column's entry rules warn instead of
|
|
624
|
+
* refusing, as they do for a person on the board page. Only the entry-rule check reads
|
|
625
|
+
* it; it is never stored.
|
|
626
|
+
*/
|
|
627
|
+
placesForPerson?: boolean;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* The board writing on its own behalf: the lines and comments the board produces
|
|
631
|
+
* from a run's lifecycle, which no person and no agent typed.
|
|
632
|
+
*
|
|
633
|
+
* This matters beyond provenance. Whether a failed run ends with "no report"
|
|
634
|
+
* depends on the agent having written a status line since it started, so a line
|
|
635
|
+
* the board wrote itself must never be filed under the agent that was running.
|
|
636
|
+
*/
|
|
637
|
+
declare const BOARD_ACTOR: BoardActor;
|
|
638
|
+
/** A comment as the board writes it, before the row exists. */
|
|
639
|
+
interface BoardCommentInput {
|
|
640
|
+
issueId: string;
|
|
641
|
+
content: string;
|
|
642
|
+
authorKind: IssueComment['authorKind'];
|
|
643
|
+
authorId?: string | null;
|
|
644
|
+
sourceChatSessionId?: string | null;
|
|
645
|
+
agentActivityId?: string | null;
|
|
646
|
+
/**
|
|
647
|
+
* The key that makes the comment a fact rather than a message: writing it
|
|
648
|
+
* again with the same key leaves the first one standing.
|
|
649
|
+
*/
|
|
650
|
+
dedupeKey?: string | null;
|
|
651
|
+
}
|
|
652
|
+
//#endregion
|
|
653
|
+
//#region src/ops/cards.d.ts
|
|
654
|
+
/** Which column a caller means, when it may name either. */
|
|
655
|
+
interface ColumnReference {
|
|
656
|
+
statusId?: string | null;
|
|
657
|
+
statusName?: string | null;
|
|
658
|
+
}
|
|
659
|
+
/** A new card. The workspace comes in resolved: the board never reads anybody else's tables to find it. */
|
|
660
|
+
interface CreateCardInput extends ColumnReference {
|
|
661
|
+
workspace: BoardWorkspaceIdentity;
|
|
662
|
+
/** Optional: a card written as a description alone is titled with its own key. */
|
|
663
|
+
title?: string | null;
|
|
664
|
+
description?: string | null;
|
|
665
|
+
priority?: Issue['priority'];
|
|
666
|
+
labels?: string[];
|
|
667
|
+
milestoneId?: string | null;
|
|
668
|
+
parentIssueId?: string | null;
|
|
669
|
+
dueDate?: number | null;
|
|
670
|
+
assigneeKind?: string | null;
|
|
671
|
+
assigneeId?: string | null;
|
|
672
|
+
executionMode?: Issue['executionMode'];
|
|
673
|
+
}
|
|
674
|
+
/** Everything a card's fields can be changed to. */
|
|
675
|
+
interface UpdateCardInput extends ColumnReference {
|
|
676
|
+
workspaceId?: string;
|
|
677
|
+
title?: string;
|
|
678
|
+
description?: string | null;
|
|
679
|
+
priority?: Issue['priority'];
|
|
680
|
+
labels?: string[];
|
|
681
|
+
milestoneId?: string | null;
|
|
682
|
+
parentIssueId?: string | null;
|
|
683
|
+
assigneeKind?: string | null;
|
|
684
|
+
assigneeId?: string | null;
|
|
685
|
+
dueDate?: number | null;
|
|
686
|
+
order?: number;
|
|
687
|
+
executionMode?: Issue['executionMode'];
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* A card as a write that may have put it in a column hands it back. `unmetRules`
|
|
691
|
+
* is there only when a person put the card in a column whose entry rules it does
|
|
692
|
+
* not meet (ruling 6-3) — the write went through, and this is what to warn them
|
|
693
|
+
* about. An agent never sees it: it is refused instead.
|
|
694
|
+
*/
|
|
695
|
+
type BoardCardWrite = Issue & {
|
|
696
|
+
unmetRules?: UnmetEntryRule[];
|
|
697
|
+
};
|
|
698
|
+
/** A comment a person or an agent writes; the author defaults to the actor. */
|
|
699
|
+
interface AddCommentInput extends Omit<BoardCommentInput, 'authorKind' | 'dedupeKey'> {
|
|
700
|
+
authorKind?: BoardCommentInput['authorKind'];
|
|
701
|
+
}
|
|
702
|
+
/** A fact the board records once, however many times it is told. */
|
|
703
|
+
interface CreateCommentOnceInput {
|
|
704
|
+
issueId: string;
|
|
705
|
+
authorKind: BoardCommentInput['authorKind'];
|
|
706
|
+
content: string;
|
|
707
|
+
dedupeKey: string;
|
|
708
|
+
actor: BoardActor;
|
|
709
|
+
}
|
|
710
|
+
//#endregion
|
|
711
|
+
//#region src/ops/card-batch.d.ts
|
|
712
|
+
/** The fields one change can set on many cards at once. */
|
|
713
|
+
interface BulkUpdateCardsInput {
|
|
714
|
+
statusId?: string | null;
|
|
715
|
+
priority?: Issue['priority'];
|
|
716
|
+
labels?: string[];
|
|
717
|
+
milestoneId?: string | null;
|
|
718
|
+
assigneeKind?: string | null;
|
|
719
|
+
assigneeId?: string | null;
|
|
720
|
+
dueDate?: number | null;
|
|
721
|
+
}
|
|
722
|
+
/** What a bulk change did: how many cards it wrote, and — for a person — which of them entered a column short of its rules. */
|
|
723
|
+
interface BulkUpdateCardsResult {
|
|
724
|
+
updated: number;
|
|
725
|
+
unmetRules?: Array<{
|
|
726
|
+
issueId: string;
|
|
727
|
+
unmet: UnmetEntryRule[];
|
|
728
|
+
}>;
|
|
729
|
+
}
|
|
730
|
+
//#endregion
|
|
731
|
+
//#region src/ops/migrate.d.ts
|
|
732
|
+
/** Which workspace's cards move where, and how their columns and milestones are matched up. */
|
|
733
|
+
interface MigrateCardsInput {
|
|
734
|
+
sourceId: string;
|
|
735
|
+
targetId: string;
|
|
736
|
+
/**
|
|
737
|
+
* Both workspaces' columns, in board order. The host reads them from each
|
|
738
|
+
* workspace's own board, which is not always the board the cards are moved on:
|
|
739
|
+
* a preview of a move across two boards reads the target's columns from the
|
|
740
|
+
* target while the cards are still on the source.
|
|
741
|
+
*/
|
|
742
|
+
sourceStatuses: IssueStatus[];
|
|
743
|
+
targetStatuses: IssueStatus[];
|
|
744
|
+
/** A source column name → the target column name it becomes, when the names differ. */
|
|
745
|
+
statusMappings?: Record<string, string>;
|
|
746
|
+
/** A source milestone title → the target milestone title it becomes, when the titles differ. */
|
|
747
|
+
milestoneMappings?: Record<string, string>;
|
|
748
|
+
/** Count what would happen, and write nothing. */
|
|
749
|
+
dryRun?: boolean;
|
|
750
|
+
}
|
|
751
|
+
/** What a move of every card from one workspace to another did — or, for a dry run, would do. */
|
|
752
|
+
interface MigrateCardsResult {
|
|
753
|
+
processed: number;
|
|
754
|
+
updated: number;
|
|
755
|
+
numbersReassigned: number;
|
|
756
|
+
statusesMapped: {
|
|
757
|
+
from: string;
|
|
758
|
+
to: string;
|
|
759
|
+
}[];
|
|
760
|
+
milestonesMapped: {
|
|
761
|
+
from: string;
|
|
762
|
+
to: string | null;
|
|
763
|
+
}[];
|
|
764
|
+
parentIssuesCleared: number;
|
|
765
|
+
}
|
|
766
|
+
//#endregion
|
|
767
|
+
//#region src/ops/relations.d.ts
|
|
768
|
+
/** The card on the other end of an edge, as much of it as a relation row shows. */
|
|
769
|
+
type IssueRelationCounterpart = Pick<Issue, 'id' | 'workspaceId' | 'number' | 'title' | 'statusId' | 'priority'>;
|
|
770
|
+
/** An edge as seen from one of the two cards it touches. */
|
|
771
|
+
type IssueRelationView = IssueRelation & {
|
|
772
|
+
/** Orientation of the edge relative to the issue the relations were listed for. */
|
|
773
|
+
direction: 'outgoing' | 'incoming';
|
|
774
|
+
/** The issue on the other end of the edge, resolved across workspaces. */
|
|
775
|
+
counterpart: IssueRelationCounterpart | null;
|
|
776
|
+
};
|
|
777
|
+
/** A new edge between two cards. */
|
|
778
|
+
interface CreateRelationInput {
|
|
779
|
+
sourceIssueId: string;
|
|
780
|
+
targetIssueId: string;
|
|
781
|
+
type: IssueRelation['type'];
|
|
782
|
+
}
|
|
783
|
+
//#endregion
|
|
784
|
+
//#region src/ops/approval.d.ts
|
|
785
|
+
/** Where a card stands with the person who has to approve it. */
|
|
786
|
+
interface BoardApproval {
|
|
787
|
+
state: 'none' | 'pending' | 'approved' | 'returned';
|
|
788
|
+
/** When the person decided, in unix seconds; `null` while nobody has. */
|
|
789
|
+
decidedAt: number | null;
|
|
790
|
+
/** What the person wrote alongside the decision, if anything. */
|
|
791
|
+
comment: string | null;
|
|
792
|
+
}
|
|
793
|
+
//#endregion
|
|
794
|
+
//#region src/ops/pull-requests.d.ts
|
|
795
|
+
/**
|
|
796
|
+
* A pull request a card names, with where it stands as the card's own facts
|
|
797
|
+
* say (ruling 4-7): `merged` or `closed` once the watcher has written that,
|
|
798
|
+
* `open` once it has written «opened», `unknown` before it has read GitHub at
|
|
799
|
+
* all; `ci` is the newest CI verdict written for it, whatever head it was for.
|
|
800
|
+
*/
|
|
801
|
+
type BoardPullRequestStanding = IssuePullRequest & {
|
|
802
|
+
state: 'open' | 'merged' | 'closed' | 'unknown';
|
|
803
|
+
ci: 'green' | 'red' | null;
|
|
804
|
+
};
|
|
805
|
+
//#endregion
|
|
806
|
+
//#region src/ops/sprints.d.ts
|
|
807
|
+
/**
|
|
808
|
+
* A milestone read as a sprint (ruling 5x-3): the row itself, how many of its
|
|
809
|
+
* cards are still open and how many are done, and whether it is the sprint
|
|
810
|
+
* running right now.
|
|
811
|
+
*
|
|
812
|
+
* `done` counts the cards in a `completed` or `canceled` column — the ones
|
|
813
|
+
* closing the sprint leaves where they are; `open` counts every other card,
|
|
814
|
+
* a card in no column at all included — the ones closing it carries on.
|
|
815
|
+
*/
|
|
816
|
+
interface BoardSprint extends IssueMilestone {
|
|
817
|
+
cards: {
|
|
818
|
+
open: number;
|
|
819
|
+
done: number;
|
|
820
|
+
};
|
|
821
|
+
current: boolean;
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* What a milestone is created with; `startDate` and `dueDate` are unix seconds,
|
|
825
|
+
* kept as the first and the last second of their UTC days.
|
|
826
|
+
*/
|
|
827
|
+
interface CreateMilestoneInput {
|
|
828
|
+
workspaceId: string;
|
|
829
|
+
title: string;
|
|
830
|
+
description?: string | null;
|
|
831
|
+
startDate?: number | null;
|
|
832
|
+
dueDate?: number | null;
|
|
833
|
+
status?: IssueMilestone['status'];
|
|
834
|
+
}
|
|
835
|
+
/** What of a milestone can change. */
|
|
836
|
+
type UpdateMilestoneInput = Partial<Omit<CreateMilestoneInput, 'workspaceId'>>;
|
|
837
|
+
/** What closing a sprint did: how many unfinished cards it moved on, and that the sprint is closed. */
|
|
838
|
+
interface CloseSprintResult {
|
|
839
|
+
carried: number;
|
|
840
|
+
closed: true;
|
|
841
|
+
}
|
|
842
|
+
//#endregion
|
|
843
|
+
//#region src/ops/runs.d.ts
|
|
844
|
+
/** What is known about a run when it starts. */
|
|
845
|
+
interface StartRunInput {
|
|
846
|
+
agentName: string;
|
|
847
|
+
agentId?: string | null;
|
|
848
|
+
host?: string | null;
|
|
849
|
+
/** Defaults to the mode the card carries. */
|
|
850
|
+
executionMode?: Issue['executionMode'];
|
|
851
|
+
/** Defaults to the actor's own kind and id. */
|
|
852
|
+
launchedByKind?: IssueRun['launchedByKind'];
|
|
853
|
+
launchedById?: string | null;
|
|
854
|
+
chatSessionId?: string | null;
|
|
855
|
+
branch?: string | null;
|
|
856
|
+
worktreePath?: string | null;
|
|
857
|
+
/** Where the agent's own log of this run lives, if it said: `claude:<id>` or `codex:<id>` (ruling 7-1). */
|
|
858
|
+
externalSessionRef?: string | null;
|
|
859
|
+
}
|
|
860
|
+
/** What a run turned out to be running in, once the host knows. */
|
|
861
|
+
interface AttachRunExecutionInput {
|
|
862
|
+
chatSessionId?: string | null;
|
|
863
|
+
branch?: string | null;
|
|
864
|
+
worktreePath?: string | null;
|
|
865
|
+
/** Where the agent's own log of this run lives, if it said: `claude:<id>` or `codex:<id>` (ruling 7-1). */
|
|
866
|
+
externalSessionRef?: string | null;
|
|
867
|
+
}
|
|
868
|
+
/** How a run ended, and — for a failure or a stop — what to say about it. */
|
|
869
|
+
interface FinishRunInput {
|
|
870
|
+
state: 'finished' | 'failed' | 'stopped';
|
|
871
|
+
errorText?: string | null;
|
|
872
|
+
/**
|
|
873
|
+
* Why a `stopped` run ended, when the answer is neither a person pressing
|
|
874
|
+
* stop nor the app that launched it tidying up quietly: the comment then reads
|
|
875
|
+
* `Run stopped: <reason>` instead of `Run stopped`.
|
|
876
|
+
*/
|
|
877
|
+
reason?: string;
|
|
878
|
+
/**
|
|
879
|
+
* What the card says it is doing once that stop is recorded, whoever the
|
|
880
|
+
* actor is. A stop with no line of its own leaves the rule as it was: the
|
|
881
|
+
* person who pressed stop is named, and anything else says nothing.
|
|
882
|
+
*/
|
|
883
|
+
statusLine?: string;
|
|
884
|
+
}
|
|
885
|
+
/** A run with the attempt number it is, counting from the card's first launch. */
|
|
886
|
+
type BoardRunView = IssueRun & {
|
|
887
|
+
attempt: number;
|
|
888
|
+
};
|
|
889
|
+
//#endregion
|
|
890
|
+
//#region src/ops/activity.d.ts
|
|
891
|
+
/**
|
|
892
|
+
* What the host knows and the board does not: the names of its workspaces, who
|
|
893
|
+
* an actor is, and what an agent is called. A board holds ids for all three and
|
|
894
|
+
* nothing more, so an Activity feed is the board's rows read through these.
|
|
895
|
+
*/
|
|
896
|
+
interface IssueActivityResolver {
|
|
897
|
+
workspaceById: IssueActivityLookup['workspaceById'];
|
|
898
|
+
/** Who a reader sees beside a row. */
|
|
899
|
+
resolveActor: (actor: IssueActorReference) => Promise<IssueCommentAuthorView>;
|
|
900
|
+
/** The agent's name, or `null` when the host has no such agent. */
|
|
901
|
+
resolveAgentName: (agentId: string) => Promise<string | null>;
|
|
902
|
+
}
|
|
903
|
+
//#endregion
|
|
904
|
+
//#region src/ops/columns.d.ts
|
|
905
|
+
/** What a column is made of, beyond the workspace it belongs to and its position. */
|
|
906
|
+
interface BoardColumnInput {
|
|
907
|
+
workspaceId: string;
|
|
908
|
+
name: string;
|
|
909
|
+
description?: string | null;
|
|
910
|
+
color?: string | null;
|
|
911
|
+
category?: IssueStatus['category'];
|
|
912
|
+
/** What a card must satisfy before an agent may put it here — `ENTRY_RULES`, none by default. */
|
|
913
|
+
entryRules?: readonly string[] | null;
|
|
914
|
+
}
|
|
915
|
+
/** What `updateColumn` may change about a column. */
|
|
916
|
+
interface BoardColumnPatch {
|
|
917
|
+
name?: string;
|
|
918
|
+
description?: string | null;
|
|
919
|
+
color?: string | null;
|
|
920
|
+
/** `ENTRY_RULES`; `null` or an empty list asks for nothing. */
|
|
921
|
+
entryRules?: readonly string[] | null;
|
|
922
|
+
}
|
|
923
|
+
//#endregion
|
|
924
|
+
//#region src/ops/index.d.ts
|
|
925
|
+
/**
|
|
926
|
+
* Everything the board can be asked to do, bound to one store.
|
|
927
|
+
*
|
|
928
|
+
* This is the layer the semantics live in — numbering, columns, the status line,
|
|
929
|
+
* approval, runs — and there is exactly one of it. `kanbo serve`, an app's server, the
|
|
930
|
+
* command-line tool and the MCP server all call these operations rather than
|
|
931
|
+
* writing rows of their own, which is why a card launched from a terminal and a
|
|
932
|
+
* card launched from the app end up telling the same story.
|
|
933
|
+
*
|
|
934
|
+
* Every write takes an actor, and every write may take a `scope`: passing the
|
|
935
|
+
* scope of a write already in progress joins it, so a caller composing several
|
|
936
|
+
* operations gets one transaction and one board version bump.
|
|
937
|
+
*/
|
|
938
|
+
declare function createBoardOps<TStore extends BoardStore>(store: TStore): {
|
|
939
|
+
createCard: (input: CreateCardInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<BoardCardWrite>;
|
|
940
|
+
createSubCard: (parentIssueId: string, input: Omit<CreateCardInput, "parentIssueId">, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<BoardCardWrite>;
|
|
941
|
+
updateCard: (issueId: string, input: UpdateCardInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<BoardCardWrite>;
|
|
942
|
+
moveCard: (issueId: string, nameOrId: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<BoardCardWrite>;
|
|
943
|
+
addComment: (input: AddCommentInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
944
|
+
id: string;
|
|
945
|
+
createdAt: number;
|
|
946
|
+
sourceChatSessionId: string | null;
|
|
947
|
+
issueId: string;
|
|
948
|
+
content: string;
|
|
949
|
+
authorKind: "user" | "agent" | "system" | "provider-target" | "system.delegated" | "system.undelegated" | "system.run" | "system.approved" | "system.returned" | "system.pr";
|
|
950
|
+
authorId: string | null;
|
|
951
|
+
agentActivityId: string | null;
|
|
952
|
+
dedupeKey: string | null;
|
|
953
|
+
}>;
|
|
954
|
+
createCommentOnce: (input: CreateCommentOnceInput, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
955
|
+
id: string;
|
|
956
|
+
createdAt: number;
|
|
957
|
+
sourceChatSessionId: string | null;
|
|
958
|
+
issueId: string;
|
|
959
|
+
content: string;
|
|
960
|
+
authorKind: "user" | "agent" | "system" | "provider-target" | "system.delegated" | "system.undelegated" | "system.run" | "system.approved" | "system.returned" | "system.pr";
|
|
961
|
+
authorId: string | null;
|
|
962
|
+
agentActivityId: string | null;
|
|
963
|
+
dedupeKey: string | null;
|
|
964
|
+
}>;
|
|
965
|
+
listComments: (issueId: string) => Promise<{
|
|
966
|
+
id: string;
|
|
967
|
+
createdAt: number;
|
|
968
|
+
sourceChatSessionId: string | null;
|
|
969
|
+
issueId: string;
|
|
970
|
+
content: string;
|
|
971
|
+
authorKind: "user" | "agent" | "system" | "provider-target" | "system.delegated" | "system.undelegated" | "system.run" | "system.approved" | "system.returned" | "system.pr";
|
|
972
|
+
authorId: string | null;
|
|
973
|
+
agentActivityId: string | null;
|
|
974
|
+
dedupeKey: string | null;
|
|
975
|
+
}[]>;
|
|
976
|
+
deleteComment: (commentId: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<void>;
|
|
977
|
+
deleteCard: (issueId: string, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
978
|
+
runIds: string[];
|
|
979
|
+
}>;
|
|
980
|
+
searchCards: (query: string, limit: number) => Promise<{
|
|
981
|
+
number: number;
|
|
982
|
+
id: string;
|
|
983
|
+
workspaceId: string;
|
|
984
|
+
description: string | null;
|
|
985
|
+
order: number;
|
|
986
|
+
createdAt: number;
|
|
987
|
+
title: string;
|
|
988
|
+
dueDate: number | null;
|
|
989
|
+
updatedAt: number;
|
|
990
|
+
statusId: string | null;
|
|
991
|
+
milestoneId: string | null;
|
|
992
|
+
parentIssueId: string | null;
|
|
993
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
994
|
+
labels: string;
|
|
995
|
+
assigneeKind: string | null;
|
|
996
|
+
assigneeId: string | null;
|
|
997
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
998
|
+
createdById: string;
|
|
999
|
+
sourceChatSessionId: string | null;
|
|
1000
|
+
delegateAgentId: string | null;
|
|
1001
|
+
delegateProviderTargetId: string | null;
|
|
1002
|
+
contextRefs: string;
|
|
1003
|
+
statusLine: string | null;
|
|
1004
|
+
waitingFor: "human" | null;
|
|
1005
|
+
executionMode: "worktree" | "main";
|
|
1006
|
+
}[]>;
|
|
1007
|
+
bulkUpdateCards: (issueIds: string[], input: BulkUpdateCardsInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<BulkUpdateCardsResult>;
|
|
1008
|
+
reorderCards: (workspaceId: string, orderedIds: string[], scope?: BoardWriteScope<TStore>) => Promise<void>;
|
|
1009
|
+
migrateCards: (input: MigrateCardsInput) => Promise<MigrateCardsResult>;
|
|
1010
|
+
addContextRef: (issueId: string, ref: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1011
|
+
number: number;
|
|
1012
|
+
id: string;
|
|
1013
|
+
workspaceId: string;
|
|
1014
|
+
description: string | null;
|
|
1015
|
+
order: number;
|
|
1016
|
+
createdAt: number;
|
|
1017
|
+
title: string;
|
|
1018
|
+
dueDate: number | null;
|
|
1019
|
+
updatedAt: number;
|
|
1020
|
+
statusId: string | null;
|
|
1021
|
+
milestoneId: string | null;
|
|
1022
|
+
parentIssueId: string | null;
|
|
1023
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
1024
|
+
labels: string;
|
|
1025
|
+
assigneeKind: string | null;
|
|
1026
|
+
assigneeId: string | null;
|
|
1027
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1028
|
+
createdById: string;
|
|
1029
|
+
sourceChatSessionId: string | null;
|
|
1030
|
+
delegateAgentId: string | null;
|
|
1031
|
+
delegateProviderTargetId: string | null;
|
|
1032
|
+
contextRefs: string;
|
|
1033
|
+
statusLine: string | null;
|
|
1034
|
+
waitingFor: "human" | null;
|
|
1035
|
+
executionMode: "worktree" | "main";
|
|
1036
|
+
}>;
|
|
1037
|
+
removeContextRef: (issueId: string, index: number, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1038
|
+
number: number;
|
|
1039
|
+
id: string;
|
|
1040
|
+
workspaceId: string;
|
|
1041
|
+
description: string | null;
|
|
1042
|
+
order: number;
|
|
1043
|
+
createdAt: number;
|
|
1044
|
+
title: string;
|
|
1045
|
+
dueDate: number | null;
|
|
1046
|
+
updatedAt: number;
|
|
1047
|
+
statusId: string | null;
|
|
1048
|
+
milestoneId: string | null;
|
|
1049
|
+
parentIssueId: string | null;
|
|
1050
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
1051
|
+
labels: string;
|
|
1052
|
+
assigneeKind: string | null;
|
|
1053
|
+
assigneeId: string | null;
|
|
1054
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1055
|
+
createdById: string;
|
|
1056
|
+
sourceChatSessionId: string | null;
|
|
1057
|
+
delegateAgentId: string | null;
|
|
1058
|
+
delegateProviderTargetId: string | null;
|
|
1059
|
+
contextRefs: string;
|
|
1060
|
+
statusLine: string | null;
|
|
1061
|
+
waitingFor: "human" | null;
|
|
1062
|
+
executionMode: "worktree" | "main";
|
|
1063
|
+
}>;
|
|
1064
|
+
listRelations: (issueId: string) => Promise<IssueRelationView[]>;
|
|
1065
|
+
createRelation: (input: CreateRelationInput, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1066
|
+
id: string;
|
|
1067
|
+
createdAt: number;
|
|
1068
|
+
sourceIssueId: string;
|
|
1069
|
+
targetIssueId: string;
|
|
1070
|
+
type: "blocks" | "duplicates" | "relates_to";
|
|
1071
|
+
}>;
|
|
1072
|
+
deleteRelation: (relationId: string, scope?: BoardWriteScope<TStore>) => Promise<void>;
|
|
1073
|
+
listFieldChanges: (issueId: string) => Promise<{
|
|
1074
|
+
id: string;
|
|
1075
|
+
createdAt: number;
|
|
1076
|
+
sourceChatSessionId: string | null;
|
|
1077
|
+
issueId: string;
|
|
1078
|
+
field: string;
|
|
1079
|
+
fromValue: string | null;
|
|
1080
|
+
toValue: string | null;
|
|
1081
|
+
actorKind: "user" | "agent" | "system" | "provider-target";
|
|
1082
|
+
actorId: string | null;
|
|
1083
|
+
}[]>;
|
|
1084
|
+
listActivity: (issueId: string, resolver: IssueActivityResolver) => Promise<IssueActivityItemView[]>;
|
|
1085
|
+
setStatusLine: (issueId: string, statusLine: string | null, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1086
|
+
number: number;
|
|
1087
|
+
id: string;
|
|
1088
|
+
workspaceId: string;
|
|
1089
|
+
description: string | null;
|
|
1090
|
+
order: number;
|
|
1091
|
+
createdAt: number;
|
|
1092
|
+
title: string;
|
|
1093
|
+
dueDate: number | null;
|
|
1094
|
+
updatedAt: number;
|
|
1095
|
+
statusId: string | null;
|
|
1096
|
+
milestoneId: string | null;
|
|
1097
|
+
parentIssueId: string | null;
|
|
1098
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
1099
|
+
labels: string;
|
|
1100
|
+
assigneeKind: string | null;
|
|
1101
|
+
assigneeId: string | null;
|
|
1102
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1103
|
+
createdById: string;
|
|
1104
|
+
sourceChatSessionId: string | null;
|
|
1105
|
+
delegateAgentId: string | null;
|
|
1106
|
+
delegateProviderTargetId: string | null;
|
|
1107
|
+
contextRefs: string;
|
|
1108
|
+
statusLine: string | null;
|
|
1109
|
+
waitingFor: "human" | null;
|
|
1110
|
+
executionMode: "worktree" | "main";
|
|
1111
|
+
}>;
|
|
1112
|
+
waitApproval: (issueId: string, input: {
|
|
1113
|
+
statusLine?: string | null;
|
|
1114
|
+
}, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1115
|
+
number: number;
|
|
1116
|
+
id: string;
|
|
1117
|
+
workspaceId: string;
|
|
1118
|
+
description: string | null;
|
|
1119
|
+
order: number;
|
|
1120
|
+
createdAt: number;
|
|
1121
|
+
title: string;
|
|
1122
|
+
dueDate: number | null;
|
|
1123
|
+
updatedAt: number;
|
|
1124
|
+
statusId: string | null;
|
|
1125
|
+
milestoneId: string | null;
|
|
1126
|
+
parentIssueId: string | null;
|
|
1127
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
1128
|
+
labels: string;
|
|
1129
|
+
assigneeKind: string | null;
|
|
1130
|
+
assigneeId: string | null;
|
|
1131
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1132
|
+
createdById: string;
|
|
1133
|
+
sourceChatSessionId: string | null;
|
|
1134
|
+
delegateAgentId: string | null;
|
|
1135
|
+
delegateProviderTargetId: string | null;
|
|
1136
|
+
contextRefs: string;
|
|
1137
|
+
statusLine: string | null;
|
|
1138
|
+
waitingFor: "human" | null;
|
|
1139
|
+
executionMode: "worktree" | "main";
|
|
1140
|
+
}>;
|
|
1141
|
+
approve: (issueId: string, input: {
|
|
1142
|
+
comment?: string | null;
|
|
1143
|
+
}, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1144
|
+
number: number;
|
|
1145
|
+
id: string;
|
|
1146
|
+
workspaceId: string;
|
|
1147
|
+
description: string | null;
|
|
1148
|
+
order: number;
|
|
1149
|
+
createdAt: number;
|
|
1150
|
+
title: string;
|
|
1151
|
+
dueDate: number | null;
|
|
1152
|
+
updatedAt: number;
|
|
1153
|
+
statusId: string | null;
|
|
1154
|
+
milestoneId: string | null;
|
|
1155
|
+
parentIssueId: string | null;
|
|
1156
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
1157
|
+
labels: string;
|
|
1158
|
+
assigneeKind: string | null;
|
|
1159
|
+
assigneeId: string | null;
|
|
1160
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1161
|
+
createdById: string;
|
|
1162
|
+
sourceChatSessionId: string | null;
|
|
1163
|
+
delegateAgentId: string | null;
|
|
1164
|
+
delegateProviderTargetId: string | null;
|
|
1165
|
+
contextRefs: string;
|
|
1166
|
+
statusLine: string | null;
|
|
1167
|
+
waitingFor: "human" | null;
|
|
1168
|
+
executionMode: "worktree" | "main";
|
|
1169
|
+
}>;
|
|
1170
|
+
returnCard: (issueId: string, input: {
|
|
1171
|
+
comment: string;
|
|
1172
|
+
toStatusName?: string | null;
|
|
1173
|
+
}, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1174
|
+
card: Issue;
|
|
1175
|
+
stoppedRunIds: string[];
|
|
1176
|
+
}>;
|
|
1177
|
+
readApproval: (issueId: string) => Promise<BoardApproval>;
|
|
1178
|
+
linkPullRequest: (issueId: string, urlOrRef: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1179
|
+
number: number;
|
|
1180
|
+
id: string;
|
|
1181
|
+
createdAt: number;
|
|
1182
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1183
|
+
createdById: string | null;
|
|
1184
|
+
issueId: string;
|
|
1185
|
+
owner: string;
|
|
1186
|
+
repo: string;
|
|
1187
|
+
url: string;
|
|
1188
|
+
}>;
|
|
1189
|
+
unlinkPullRequest: (issueId: string, linkId: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1190
|
+
number: number;
|
|
1191
|
+
id: string;
|
|
1192
|
+
createdAt: number;
|
|
1193
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1194
|
+
createdById: string | null;
|
|
1195
|
+
issueId: string;
|
|
1196
|
+
owner: string;
|
|
1197
|
+
repo: string;
|
|
1198
|
+
url: string;
|
|
1199
|
+
}>;
|
|
1200
|
+
listPullRequests: (issueId: string) => Promise<{
|
|
1201
|
+
number: number;
|
|
1202
|
+
id: string;
|
|
1203
|
+
createdAt: number;
|
|
1204
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1205
|
+
createdById: string | null;
|
|
1206
|
+
issueId: string;
|
|
1207
|
+
owner: string;
|
|
1208
|
+
repo: string;
|
|
1209
|
+
url: string;
|
|
1210
|
+
}[]>;
|
|
1211
|
+
listPullRequestStandings: (issueId: string) => Promise<BoardPullRequestStanding[]>;
|
|
1212
|
+
listMilestones: (workspaceId: string | null) => Promise<{
|
|
1213
|
+
id: string;
|
|
1214
|
+
workspaceId: string;
|
|
1215
|
+
description: string | null;
|
|
1216
|
+
createdAt: number;
|
|
1217
|
+
title: string;
|
|
1218
|
+
startDate: number | null;
|
|
1219
|
+
dueDate: number | null;
|
|
1220
|
+
status: "open" | "closed";
|
|
1221
|
+
updatedAt: number;
|
|
1222
|
+
}[]>;
|
|
1223
|
+
deleteMilestone: (milestoneId: string, scope?: BoardWriteScope<TStore>) => Promise<void>;
|
|
1224
|
+
createMilestone: (input: CreateMilestoneInput, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1225
|
+
id: string;
|
|
1226
|
+
workspaceId: string;
|
|
1227
|
+
description: string | null;
|
|
1228
|
+
createdAt: number;
|
|
1229
|
+
title: string;
|
|
1230
|
+
startDate: number | null;
|
|
1231
|
+
dueDate: number | null;
|
|
1232
|
+
status: "open" | "closed";
|
|
1233
|
+
updatedAt: number;
|
|
1234
|
+
}>;
|
|
1235
|
+
updateMilestone: (milestoneId: string, input: UpdateMilestoneInput, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1236
|
+
id: string;
|
|
1237
|
+
workspaceId: string;
|
|
1238
|
+
description: string | null;
|
|
1239
|
+
createdAt: number;
|
|
1240
|
+
title: string;
|
|
1241
|
+
startDate: number | null;
|
|
1242
|
+
dueDate: number | null;
|
|
1243
|
+
status: "open" | "closed";
|
|
1244
|
+
updatedAt: number;
|
|
1245
|
+
}>;
|
|
1246
|
+
listSprints: (workspaceId: string, now?: number) => Promise<BoardSprint[]>;
|
|
1247
|
+
currentSprint: (workspaceId: string, now?: number) => Promise<BoardSprint | null>;
|
|
1248
|
+
closeSprint: (milestoneId: string, input: {
|
|
1249
|
+
carryTo?: string | null;
|
|
1250
|
+
}, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<CloseSprintResult>;
|
|
1251
|
+
listColumns: (workspaceId: string) => Promise<{
|
|
1252
|
+
id: string;
|
|
1253
|
+
workspaceId: string;
|
|
1254
|
+
name: string;
|
|
1255
|
+
description: string | null;
|
|
1256
|
+
color: string | null;
|
|
1257
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1258
|
+
order: number;
|
|
1259
|
+
entryRules: string | null;
|
|
1260
|
+
createdAt: number;
|
|
1261
|
+
}[]>;
|
|
1262
|
+
findColumn: (workspaceId: string, nameOrId: string) => Promise<{
|
|
1263
|
+
id: string;
|
|
1264
|
+
workspaceId: string;
|
|
1265
|
+
name: string;
|
|
1266
|
+
description: string | null;
|
|
1267
|
+
color: string | null;
|
|
1268
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1269
|
+
order: number;
|
|
1270
|
+
entryRules: string | null;
|
|
1271
|
+
createdAt: number;
|
|
1272
|
+
} | null>;
|
|
1273
|
+
requireColumn: (workspaceId: string, nameOrId: string) => Promise<{
|
|
1274
|
+
id: string;
|
|
1275
|
+
workspaceId: string;
|
|
1276
|
+
name: string;
|
|
1277
|
+
description: string | null;
|
|
1278
|
+
color: string | null;
|
|
1279
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1280
|
+
order: number;
|
|
1281
|
+
entryRules: string | null;
|
|
1282
|
+
createdAt: number;
|
|
1283
|
+
}>;
|
|
1284
|
+
ensureDefaultColumns: (workspaceId: string, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1285
|
+
id: string;
|
|
1286
|
+
workspaceId: string;
|
|
1287
|
+
name: string;
|
|
1288
|
+
description: string | null;
|
|
1289
|
+
color: string | null;
|
|
1290
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1291
|
+
order: number;
|
|
1292
|
+
entryRules: string | null;
|
|
1293
|
+
createdAt: number;
|
|
1294
|
+
}[]>;
|
|
1295
|
+
createColumn: (input: BoardColumnInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1296
|
+
id: string;
|
|
1297
|
+
workspaceId: string;
|
|
1298
|
+
name: string;
|
|
1299
|
+
description: string | null;
|
|
1300
|
+
color: string | null;
|
|
1301
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1302
|
+
order: number;
|
|
1303
|
+
entryRules: string | null;
|
|
1304
|
+
createdAt: number;
|
|
1305
|
+
}>;
|
|
1306
|
+
updateColumn: (statusId: string, patch: BoardColumnPatch, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1307
|
+
id: string;
|
|
1308
|
+
workspaceId: string;
|
|
1309
|
+
name: string;
|
|
1310
|
+
description: string | null;
|
|
1311
|
+
color: string | null;
|
|
1312
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1313
|
+
order: number;
|
|
1314
|
+
entryRules: string | null;
|
|
1315
|
+
createdAt: number;
|
|
1316
|
+
}>;
|
|
1317
|
+
describeColumn: (workspaceId: string, nameOrId: string, description: string | null, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1318
|
+
id: string;
|
|
1319
|
+
workspaceId: string;
|
|
1320
|
+
name: string;
|
|
1321
|
+
description: string | null;
|
|
1322
|
+
color: string | null;
|
|
1323
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1324
|
+
order: number;
|
|
1325
|
+
entryRules: string | null;
|
|
1326
|
+
createdAt: number;
|
|
1327
|
+
}>;
|
|
1328
|
+
setColumnEntryRules: (workspaceId: string, nameOrId: string, entryRules: readonly string[] | null, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1329
|
+
id: string;
|
|
1330
|
+
workspaceId: string;
|
|
1331
|
+
name: string;
|
|
1332
|
+
description: string | null;
|
|
1333
|
+
color: string | null;
|
|
1334
|
+
category: "triage" | "backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
1335
|
+
order: number;
|
|
1336
|
+
entryRules: string | null;
|
|
1337
|
+
createdAt: number;
|
|
1338
|
+
}>;
|
|
1339
|
+
enforceColumnEntryForCards: (issueIds: string[], statusId: string, actor: BoardActor) => Promise<{
|
|
1340
|
+
issueId: string;
|
|
1341
|
+
unmet: UnmetEntryRule[];
|
|
1342
|
+
}[]>;
|
|
1343
|
+
deleteColumn: (statusId: string, scope?: BoardWriteScope<TStore>) => Promise<void>;
|
|
1344
|
+
reorderColumns: (workspaceId: string, orderedIds: string[], scope?: BoardWriteScope<TStore>) => Promise<void>;
|
|
1345
|
+
addStandardColumns: (workspaceId: string, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1346
|
+
statuses: IssueStatus[];
|
|
1347
|
+
added: string[];
|
|
1348
|
+
}>;
|
|
1349
|
+
startRun: (issueId: string, input: StartRunInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1350
|
+
id: string;
|
|
1351
|
+
executionMode: "worktree" | "main";
|
|
1352
|
+
issueId: string;
|
|
1353
|
+
launchedByKind: "user" | "agent" | "external";
|
|
1354
|
+
launchedById: string | null;
|
|
1355
|
+
agentId: string | null;
|
|
1356
|
+
agentName: string;
|
|
1357
|
+
host: string | null;
|
|
1358
|
+
branch: string | null;
|
|
1359
|
+
worktreePath: string | null;
|
|
1360
|
+
state: "running" | "finished" | "failed" | "stopped";
|
|
1361
|
+
chatSessionId: string | null;
|
|
1362
|
+
externalSessionRef: string | null;
|
|
1363
|
+
startedAt: number;
|
|
1364
|
+
endedAt: number | null;
|
|
1365
|
+
}>;
|
|
1366
|
+
attachRunExecution: (runId: string, input: AttachRunExecutionInput, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1367
|
+
id: string;
|
|
1368
|
+
executionMode: "worktree" | "main";
|
|
1369
|
+
issueId: string;
|
|
1370
|
+
launchedByKind: "user" | "agent" | "external";
|
|
1371
|
+
launchedById: string | null;
|
|
1372
|
+
agentId: string | null;
|
|
1373
|
+
agentName: string;
|
|
1374
|
+
host: string | null;
|
|
1375
|
+
branch: string | null;
|
|
1376
|
+
worktreePath: string | null;
|
|
1377
|
+
state: "running" | "finished" | "failed" | "stopped";
|
|
1378
|
+
chatSessionId: string | null;
|
|
1379
|
+
externalSessionRef: string | null;
|
|
1380
|
+
startedAt: number;
|
|
1381
|
+
endedAt: number | null;
|
|
1382
|
+
}>;
|
|
1383
|
+
recordRunSessionRef: (runId: string, ref: string, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1384
|
+
id: string;
|
|
1385
|
+
executionMode: "worktree" | "main";
|
|
1386
|
+
issueId: string;
|
|
1387
|
+
launchedByKind: "user" | "agent" | "external";
|
|
1388
|
+
launchedById: string | null;
|
|
1389
|
+
agentId: string | null;
|
|
1390
|
+
agentName: string;
|
|
1391
|
+
host: string | null;
|
|
1392
|
+
branch: string | null;
|
|
1393
|
+
worktreePath: string | null;
|
|
1394
|
+
state: "running" | "finished" | "failed" | "stopped";
|
|
1395
|
+
chatSessionId: string | null;
|
|
1396
|
+
externalSessionRef: string | null;
|
|
1397
|
+
startedAt: number;
|
|
1398
|
+
endedAt: number | null;
|
|
1399
|
+
}>;
|
|
1400
|
+
clearRunSessionRef: (runId: string, actor: BoardActor, options?: {
|
|
1401
|
+
replaceWith?: string;
|
|
1402
|
+
}, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1403
|
+
id: string;
|
|
1404
|
+
executionMode: "worktree" | "main";
|
|
1405
|
+
issueId: string;
|
|
1406
|
+
launchedByKind: "user" | "agent" | "external";
|
|
1407
|
+
launchedById: string | null;
|
|
1408
|
+
agentId: string | null;
|
|
1409
|
+
agentName: string;
|
|
1410
|
+
host: string | null;
|
|
1411
|
+
branch: string | null;
|
|
1412
|
+
worktreePath: string | null;
|
|
1413
|
+
state: "running" | "finished" | "failed" | "stopped";
|
|
1414
|
+
chatSessionId: string | null;
|
|
1415
|
+
externalSessionRef: string | null;
|
|
1416
|
+
startedAt: number;
|
|
1417
|
+
endedAt: number | null;
|
|
1418
|
+
}>;
|
|
1419
|
+
finishRun: (runId: string, input: FinishRunInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
|
|
1420
|
+
id: string;
|
|
1421
|
+
executionMode: "worktree" | "main";
|
|
1422
|
+
issueId: string;
|
|
1423
|
+
launchedByKind: "user" | "agent" | "external";
|
|
1424
|
+
launchedById: string | null;
|
|
1425
|
+
agentId: string | null;
|
|
1426
|
+
agentName: string;
|
|
1427
|
+
host: string | null;
|
|
1428
|
+
branch: string | null;
|
|
1429
|
+
worktreePath: string | null;
|
|
1430
|
+
state: "running" | "finished" | "failed" | "stopped";
|
|
1431
|
+
chatSessionId: string | null;
|
|
1432
|
+
externalSessionRef: string | null;
|
|
1433
|
+
startedAt: number;
|
|
1434
|
+
endedAt: number | null;
|
|
1435
|
+
}>;
|
|
1436
|
+
stopRunningRuns: (issueId: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<string[]>;
|
|
1437
|
+
listRuns: (issueId: string) => Promise<BoardRunView[]>;
|
|
1438
|
+
findRunByChatSessionId: (chatSessionId: string) => Promise<{
|
|
1439
|
+
id: string;
|
|
1440
|
+
executionMode: "worktree" | "main";
|
|
1441
|
+
issueId: string;
|
|
1442
|
+
launchedByKind: "user" | "agent" | "external";
|
|
1443
|
+
launchedById: string | null;
|
|
1444
|
+
agentId: string | null;
|
|
1445
|
+
agentName: string;
|
|
1446
|
+
host: string | null;
|
|
1447
|
+
branch: string | null;
|
|
1448
|
+
worktreePath: string | null;
|
|
1449
|
+
state: "running" | "finished" | "failed" | "stopped";
|
|
1450
|
+
chatSessionId: string | null;
|
|
1451
|
+
externalSessionRef: string | null;
|
|
1452
|
+
startedAt: number;
|
|
1453
|
+
endedAt: number | null;
|
|
1454
|
+
} | null>;
|
|
1455
|
+
readBoardProjection: (workspaceId: string) => Promise<BoardRunProjection[]>;
|
|
1456
|
+
readBoardProjectionForIssues: (issueIds: string[]) => Promise<BoardRunProjection[]>;
|
|
1457
|
+
readBoardProjectionForIssue: (issueId: string) => Promise<BoardRunProjection>;
|
|
1458
|
+
listReady: (input: {
|
|
1459
|
+
workspaceId: string;
|
|
1460
|
+
limit?: number;
|
|
1461
|
+
}) => Promise<{
|
|
1462
|
+
number: number;
|
|
1463
|
+
id: string;
|
|
1464
|
+
workspaceId: string;
|
|
1465
|
+
description: string | null;
|
|
1466
|
+
order: number;
|
|
1467
|
+
createdAt: number;
|
|
1468
|
+
title: string;
|
|
1469
|
+
dueDate: number | null;
|
|
1470
|
+
updatedAt: number;
|
|
1471
|
+
statusId: string | null;
|
|
1472
|
+
milestoneId: string | null;
|
|
1473
|
+
parentIssueId: string | null;
|
|
1474
|
+
priority: "none" | "low" | "medium" | "high" | "urgent";
|
|
1475
|
+
labels: string;
|
|
1476
|
+
assigneeKind: string | null;
|
|
1477
|
+
assigneeId: string | null;
|
|
1478
|
+
createdByKind: "user" | "agent" | "system" | "provider-target";
|
|
1479
|
+
createdById: string;
|
|
1480
|
+
sourceChatSessionId: string | null;
|
|
1481
|
+
delegateAgentId: string | null;
|
|
1482
|
+
delegateProviderTargetId: string | null;
|
|
1483
|
+
contextRefs: string;
|
|
1484
|
+
statusLine: string | null;
|
|
1485
|
+
waitingFor: "human" | null;
|
|
1486
|
+
executionMode: "worktree" | "main";
|
|
1487
|
+
}[]>;
|
|
1488
|
+
buildPrimeText: (workspaceId: string) => Promise<string>;
|
|
1489
|
+
};
|
|
1490
|
+
/** The board's operations, as a type callers can name. */
|
|
1491
|
+
type BoardOps = ReturnType<typeof createBoardOps<BoardStore>>;
|
|
1492
|
+
//#endregion
|
|
1493
|
+
//#region src/ops/board-copy.d.ts
|
|
1494
|
+
/** How many rows of each kind a copy wrote into the target board. */
|
|
1495
|
+
interface BoardCopyCounts {
|
|
1496
|
+
statuses: number;
|
|
1497
|
+
milestones: number;
|
|
1498
|
+
issues: number;
|
|
1499
|
+
comments: number;
|
|
1500
|
+
runs: number;
|
|
1501
|
+
relations: number;
|
|
1502
|
+
fieldChanges: number;
|
|
1503
|
+
/** Cards that carried refs, not rows: context refs are a column on the card. */
|
|
1504
|
+
contextRefs: number;
|
|
1505
|
+
pullRequests: number;
|
|
1506
|
+
}
|
|
1507
|
+
/** Everything one workspace has on a board, read before anything is written. */
|
|
1508
|
+
interface BoardSlice {
|
|
1509
|
+
statuses: IssueStatus[];
|
|
1510
|
+
milestones: IssueMilestone[];
|
|
1511
|
+
/** In an order where a card's parent always comes before it. */
|
|
1512
|
+
issues: Issue[];
|
|
1513
|
+
comments: IssueComment[];
|
|
1514
|
+
runs: IssueRun[];
|
|
1515
|
+
relations: IssueRelation[];
|
|
1516
|
+
fieldChanges: IssueFieldChange[];
|
|
1517
|
+
pullRequests: IssuePullRequest[];
|
|
1518
|
+
/** What reading it had to leave behind, said to a person. */
|
|
1519
|
+
warnings: string[];
|
|
1520
|
+
}
|
|
1521
|
+
/** Nothing copied — what a move that had nothing to move reports. */
|
|
1522
|
+
declare function emptyCopyCounts(): BoardCopyCounts;
|
|
1523
|
+
/**
|
|
1524
|
+
* Everything the workspace has on this board, read in one pass before a single
|
|
1525
|
+
* row is written anywhere.
|
|
1526
|
+
*
|
|
1527
|
+
* Links are collected by id because an edge is listed by both of the cards it
|
|
1528
|
+
* touches, and one reaching a card outside this workspace is left behind rather
|
|
1529
|
+
* than copied: the target holds this workspace's board and nothing else, so the
|
|
1530
|
+
* far end of that edge is not there to point at.
|
|
1531
|
+
*/
|
|
1532
|
+
declare function readBoardSlice(from: BoardStore, workspaceId: string): Promise<BoardSlice>;
|
|
1533
|
+
/**
|
|
1534
|
+
* Write a slice into the target board, in one transaction, and say what was
|
|
1535
|
+
* written and what a person should know about it — the slice's own warnings
|
|
1536
|
+
* first.
|
|
1537
|
+
*
|
|
1538
|
+
* It is idempotent by id. A row the target already has is left exactly as it
|
|
1539
|
+
* is and counted as already present, so a copy interrupted half-way is finished
|
|
1540
|
+
* by running it again, and a second run of a finished one copies nothing. A
|
|
1541
|
+
* clash that is not the same row — a column name or a card number the target
|
|
1542
|
+
* holds under another id — refuses the whole copy before its first insert
|
|
1543
|
+
* (`board_copy_conflict`, ruling 3-55).
|
|
1544
|
+
*/
|
|
1545
|
+
declare function writeBoardSlice(to: BoardStore, slice: BoardSlice, workspaceId: string): Promise<{
|
|
1546
|
+
copied: BoardCopyCounts;
|
|
1547
|
+
warnings: string[];
|
|
1548
|
+
}>;
|
|
1549
|
+
/**
|
|
1550
|
+
* Empty the slice off the board it was read from, in a transaction of its own.
|
|
1551
|
+
*
|
|
1552
|
+
* Only the cards, the columns and the milestones are named: comments, runs,
|
|
1553
|
+
* links, pull request links and the field-change history hang off a card by a
|
|
1554
|
+
* foreign key that cascades on both engines, so deleting the card takes them
|
|
1555
|
+
* with it.
|
|
1556
|
+
*/
|
|
1557
|
+
declare function deleteBoardSlice(from: BoardStore, slice: BoardSlice): Promise<void>;
|
|
1558
|
+
//#endregion
|
|
1559
|
+
//#region src/serve/board-error-responses.d.ts
|
|
1560
|
+
/** What one board failure is over HTTP: the status, the sentence, and the code a client matches on when it is renamed. */
|
|
1561
|
+
interface BoardErrorResponse {
|
|
1562
|
+
status: number;
|
|
1563
|
+
message: string;
|
|
1564
|
+
code?: string;
|
|
1565
|
+
}
|
|
1566
|
+
/**
|
|
1567
|
+
* What each board failure becomes over HTTP.
|
|
1568
|
+
*
|
|
1569
|
+
* The board names its failures and nothing else (`../domain/errors.ts`); the
|
|
1570
|
+
* status code and the sentence a client reads are decided here, once, for both
|
|
1571
|
+
* edges that serve it over HTTP — `kanbo serve` and any app that serves the
|
|
1572
|
+
* same routes — so a client written against one reads the other's failures the
|
|
1573
|
+
* same way. The
|
|
1574
|
+
* table is exhaustive on purpose — a new code in the package fails to compile
|
|
1575
|
+
* until this module says what it means to a caller — and it follows one rule: something the caller asked for that is not
|
|
1576
|
+
* there is 404, something the caller asked for that cannot be done is 400,
|
|
1577
|
+
* answering for a person — approving a card, sending it back or closing a
|
|
1578
|
+
* sprint — as anyone but one is 403, dropping a pull request link somebody else made is the same 403
|
|
1579
|
+
* for the same reason, and acting on a run that has already ended is 409,
|
|
1580
|
+
* because the answer would have been yes a moment earlier. An agent putting a
|
|
1581
|
+
* card in a column whose entry rules it does not meet yet is 409 for the same
|
|
1582
|
+
* reason turned around: the answer will be yes once the card meets them, and
|
|
1583
|
+
* `details.unmet` says what is missing.
|
|
1584
|
+
*
|
|
1585
|
+
* The five failures about where a board is kept read the same rule. A database
|
|
1586
|
+
* that holds no board this build can speak for is 409 — the setting is there,
|
|
1587
|
+
* the board behind it is not yet, and `board-storage prepare` is what settles
|
|
1588
|
+
* that — and one nobody could reach at all is 503, because nothing about the
|
|
1589
|
+
* request was wrong. A workspace naming no board at all is 404: the caller
|
|
1590
|
+
* asked about a setting that is not there. A board still holding cards when
|
|
1591
|
+
* somebody asks to point the workspace elsewhere is 409, because the answer
|
|
1592
|
+
* would have been yes on an empty board and `board-storage migrate` is what
|
|
1593
|
+
* makes it one. An operation naming cards from two different boards is 400: no
|
|
1594
|
+
* transaction reaches both, so the caller asked for something that cannot be
|
|
1595
|
+
* done. A copy that would land on a card number or a column name the target
|
|
1596
|
+
* already holds under a different id is 409 for the same reason the others
|
|
1597
|
+
* are: the answer would have been yes on a target that did not hold that
|
|
1598
|
+
* board, and `details.conflicts` names every value that clashed.
|
|
1599
|
+
*
|
|
1600
|
+
* A failure may also be renamed here: the package names its codes after the
|
|
1601
|
+
* board, while every error the `/issues` routes answer with is named after the
|
|
1602
|
+
* issue, and a client matching on `issue_*` should not have to learn a second
|
|
1603
|
+
* spelling. The code carries through unchanged when no `code` is given.
|
|
1604
|
+
*/
|
|
1605
|
+
declare const BOARD_ERROR_RESPONSES: Record<BoardErrorCode, BoardErrorResponse>;
|
|
1606
|
+
//#endregion
|
|
1607
|
+
export { type AddCommentInput, type AttachRunExecutionInput, BINDING_FILE_PATH, BOARD_ACTOR, BOARD_ERROR_RESPONSES, type BoardActiveRun, type BoardActor, type BoardApproval, type BoardCardWrite, type BoardColumnInput, type BoardColumnPatch, type BoardCopyCounts, BoardError, type BoardErrorCode, type BoardErrorResponse, type BoardLinkedPullRequest, type BoardOps, type BoardPullRequestStanding, type BoardRunProjection, type BoardRunProjectionScope, type BoardRunView, type BoardSlice, type BoardSprint, type BoardStore, type BoardTransactionMode, type BoardWorkspaceIdentity, type BoardWriteScope, type BulkUpdateCardsInput, type BulkUpdateCardsResult, CAPABILITIES_MANIFEST_VERSION, type CloseSprintResult, type CreateCardInput, type CreateCommentOnceInput, type CreateMilestoneInput, type CreateRelationInput, DEFAULT_BOARD_FILE_PATH, DEFAULT_STATUSES, ENTRY_RULES, ENTRY_RULE_DESCRIPTIONS, type EntryRule, type EntryRuleFacts, type ExternalSessionRef, type FinishRunInput, type Issue, type IssueActivityAction, type IssueActivityCommentView, type IssueActivityField, type IssueActivityFieldChangeView, type IssueActivityItemView, type IssueActivityLookup, type IssueActivityResolver, type IssueActivityValueToken, type IssueActivityValueView, type IssueActorKind, type IssueActorReference, type IssueComment, type IssueCommentAuthorView, type IssueCommentStore, type IssueContextRefStore, type IssueFieldChange, type IssueFieldChangeStore, type IssueMilestone, type IssueMilestoneStore, type IssueMutationActor, type IssuePullRequest, type IssuePullRequestStore, type IssueRelation, type IssueRelationCounterpart, type IssueRelationStore, type IssueRelationView, type IssueRowStore, type IssueRun, type IssueRunStore, type IssueStatus, type IssueStatusStore, type IssueView, KANBO_TOOL_CLI_EQUIVALENTS, KANBO_TOOL_NAMES, type KanbanMeta, type KanbanMetaStore, type KanboBinding, type KanboCapabilities, type KanboCapabilitiesPackage, type KanboCapabilitiesRoles, type KanboCapabilityCommand, type KanboCapabilityCommandArgument, type KanboCapabilityCommandOption, type KanboCapabilityEntryRule, type KanboCapabilityStorage, type KanboCapabilityTool, type KanboToolCliEquivalent, type KanboToolName, type MigrateCardsInput, type MigrateCardsResult, type PullRequestFactKeys, type StartRunInput, TRACKED_FIELDS, UNMET_ENTRY_RULE_REASONS, type UnmetEntryRule, type UpdateCardInput, type UpdateMilestoneInput, activityKindOrder, activityText, activityToken, buildCapabilitiesManifest, cardDisplayTitle, commentAuthorReference, createBoardOps, currentUnixSeconds, deleteBoardSlice, diffFieldChanges, emptyCopyCounts, evaluateEntryRules, formatActivityIssueReference, formatExternalSessionRef, formatIssueId, formatPlainActivityValue, ignoreBoardFile, isEmptyActivityValue, isOutsideWriter, maskDatabaseUrl, maskDatabaseUrls, nextIssueIdentity, nextIssueNumber, nextIssueOrder, normalizeCommentAuthorKind, normalizeStatusName, parseActivityStringArray, parseExternalSessionRef, pullRequestFactKeys, readBinding, readBoardSlice, readChangeSeq, readChecklist, readEntryRules, readIssuePrefix, readProjectBinding, readSystemCommentKind, renderCapabilitiesMarkdown, runBoardWrite, serializeEntryRules, toIssueView, writeBinding, writeBoardSlice };
|
|
1608
|
+
//# sourceMappingURL=index.d.mts.map
|