kanbo-cli 0.2.0 → 0.3.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/LICENSE +75 -21
  3. package/README.md +19 -48
  4. package/dist/{better-sqlite3-fU3G4xnX.cjs → better-sqlite3-DPdSZ6sH.cjs} +244 -247
  5. package/dist/cli-main.cjs +51208 -0
  6. package/dist/cli.cjs +32 -45216
  7. package/dist/dist-IHRTF-b5.cjs +2552 -0
  8. package/dist/lib/{tool-names-WfH4IURz.d.cts → approval-BsBk2xVr.d.cts} +72 -3
  9. package/dist/lib/{tool-names-3q_GEZej.d.mts → approval-LRZ6ontC.d.mts} +72 -3
  10. package/dist/lib/{board-store-BvWn9xTB.d.mts → board-store-D_Mpfb84.d.mts} +75 -2
  11. package/dist/lib/{board-store-BfszzAJB.d.cts → board-store-Dx-mw2I6.d.cts} +75 -2
  12. package/dist/lib/index.cjs +8 -2
  13. package/dist/lib/index.d.cts +202 -91
  14. package/dist/lib/index.d.mts +202 -91
  15. package/dist/lib/index.mjs +3 -3
  16. package/dist/lib/{manifest-RDyoGrVR.cjs → manifest-QPoQl8tn.cjs} +6881 -1556
  17. package/dist/lib/{manifest-BwpC-4BO.mjs → manifest-v2e9x_C8.mjs} +6795 -1556
  18. package/dist/lib/mcp/index.cjs +156 -21
  19. package/dist/lib/mcp/index.d.cts +140 -5
  20. package/dist/lib/mcp/index.d.mts +140 -5
  21. package/dist/lib/mcp/index.mjs +152 -22
  22. package/dist/lib/{migrate-DnMjTCvu.cjs → migrate-Dca5WdYd.cjs} +144 -14
  23. package/dist/lib/{migrate-BhYi9cXw.mjs → migrate-DtBeW3Fs.mjs} +134 -16
  24. package/dist/lib/{migrations-path-Ciwan537.mjs → migrations-path-ClaYRNwk.mjs} +5 -7
  25. package/dist/lib/{migrations-path-CZxVOgeD.cjs → migrations-path-DBCE17dT.cjs} +5 -7
  26. package/dist/lib/postgres/index.cjs +2 -4
  27. package/dist/lib/postgres/index.d.cts +2 -3
  28. package/dist/lib/postgres/index.d.mts +2 -3
  29. package/dist/lib/postgres/index.mjs +2 -4
  30. package/dist/lib/{roles.sql-CvyCGt38.mjs → roles.sql-BoOZSkBp.mjs} +96 -5
  31. package/dist/lib/{roles.sql-B9rt-x4o.cjs → roles.sql-E58x7mLS.cjs} +95 -4
  32. package/dist/lib/schema-D0MyXcej.d.cts +1 -2
  33. package/dist/lib/schema-D0MyXcej.d.mts +1 -2
  34. package/dist/lib/schema-epoch-ZyumVL_A.d.cts +1 -2
  35. package/dist/lib/schema-epoch-ZyumVL_A.d.mts +1 -2
  36. package/dist/lib/sqlite/index.cjs +2 -2
  37. package/dist/lib/sqlite/index.d.cts +3 -4
  38. package/dist/lib/sqlite/index.d.mts +3 -4
  39. package/dist/lib/sqlite/index.mjs +2 -2
  40. package/dist/lib/sqlite/schema.cjs +0 -2
  41. package/dist/lib/sqlite/schema.mjs +0 -2
  42. package/package.json +14 -11
  43. package/dist/better-sqlite3-fU3G4xnX.cjs.map +0 -1
  44. package/dist/cli.cjs.map +0 -1
  45. package/dist/dist-BsCwQFEl.cjs +0 -989
  46. package/dist/dist-BsCwQFEl.cjs.map +0 -1
  47. package/dist/lib/manifest-BwpC-4BO.mjs.map +0 -1
  48. package/dist/lib/manifest-RDyoGrVR.cjs.map +0 -1
  49. package/dist/lib/mcp/index.cjs.map +0 -1
  50. package/dist/lib/mcp/index.mjs.map +0 -1
  51. package/dist/lib/migrate-BhYi9cXw.mjs.map +0 -1
  52. package/dist/lib/migrate-DnMjTCvu.cjs.map +0 -1
  53. package/dist/lib/migrations-path-CZxVOgeD.cjs.map +0 -1
  54. package/dist/lib/migrations-path-Ciwan537.mjs.map +0 -1
  55. package/dist/lib/postgres/index.cjs.map +0 -1
  56. package/dist/lib/postgres/index.mjs.map +0 -1
  57. package/dist/lib/roles.sql-B9rt-x4o.cjs.map +0 -1
  58. package/dist/lib/roles.sql-CvyCGt38.mjs.map +0 -1
  59. package/dist/lib/sqlite/schema.cjs.map +0 -1
  60. package/dist/lib/sqlite/schema.mjs.map +0 -1
  61. package/drizzle-postgres/0000_board.sql +0 -135
  62. package/drizzle-postgres/0001_history_order.sql +0 -2
  63. package/drizzle-postgres/0002_issue_pull_requests.sql +0 -16
  64. package/drizzle-postgres/0003_milestone_start_date.sql +0 -1
  65. package/drizzle-postgres/0004_status_entry_rules.sql +0 -1
  66. package/drizzle-postgres/0005_run_external_session_ref.sql +0 -1
  67. package/drizzle-postgres/README.md +0 -61
  68. package/drizzle-postgres/meta/0000_snapshot.json +0 -1078
  69. package/drizzle-postgres/meta/0001_snapshot.json +0 -1090
  70. package/drizzle-postgres/meta/0002_snapshot.json +0 -1239
  71. package/drizzle-postgres/meta/0003_snapshot.json +0 -1245
  72. package/drizzle-postgres/meta/0004_snapshot.json +0 -1251
  73. package/drizzle-postgres/meta/0005_snapshot.json +0 -1257
  74. package/drizzle-postgres/meta/_journal.json +0 -48
  75. package/drizzle-sqlite/0000_board.sql +0 -133
  76. package/drizzle-sqlite/0001_issue_pull_requests.sql +0 -15
  77. package/drizzle-sqlite/0002_milestone_start_date.sql +0 -1
  78. package/drizzle-sqlite/0003_status_entry_rules.sql +0 -1
  79. package/drizzle-sqlite/0004_run_external_session_ref.sql +0 -1
  80. package/drizzle-sqlite/README.md +0 -67
  81. package/drizzle-sqlite/meta/0000_snapshot.json +0 -946
  82. package/drizzle-sqlite/meta/0001_snapshot.json +0 -1054
  83. package/drizzle-sqlite/meta/0002_snapshot.json +0 -1061
  84. package/drizzle-sqlite/meta/0003_snapshot.json +0 -1068
  85. package/drizzle-sqlite/meta/0004_snapshot.json +0 -1075
  86. package/drizzle-sqlite/meta/_journal.json +0 -41
@@ -1,6 +1,6 @@
1
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-D0MyXcej.cjs";
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-BfszzAJB.cjs";
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-WfH4IURz.cjs";
2
+ import { _ as IssueRunStore, a as BoardMilestoneCardCount, c as BoardStore, d as IssueContextRefStore, f as IssueFieldChangeStore, g as IssueRowStore, h as IssueRelationStore, i as BoardLinkedPullRequest, l as BoardTransactionMode, m as IssuePullRequestStore, n as BoardCardPage, o as BoardRunProjection, p as IssueMilestoneStore, r as BoardCardQuery, s as BoardRunProjectionScope, t as BoardActiveRun, u as IssueCommentStore, v as IssueStatusStore, y as KanbanMetaStore } from "./board-store-Dx-mw2I6.cjs";
3
+ import { C as readEntryRules, S as readChecklist, _ as EntryRule, a as IssueActorReference, b as UnmetEntryRule, c as isOutsideWriter, d as KANBO_TOOL_CLI_EQUIVALENTS, f as KANBO_TOOL_NAMES, g as ENTRY_RULE_DESCRIPTIONS, h as ENTRY_RULES, i as IssueActorKind, l as normalizeCommentAuthorKind, m as KanboToolName, n as CardAttention, o as IssueView, p as KanboToolCliEquivalent, r as CardLastComment, s as IssueWriterProvenance, t as BoardApproval, u as toIssueView, v as EntryRuleFacts, w as serializeEntryRules, x as evaluateEntryRules, y as UNMET_ENTRY_RULE_REASONS } from "./approval-BsBk2xVr.cjs";
4
4
  import { z } from "zod";
5
5
  //#region src/cli/output.d.ts
6
6
  /**
@@ -155,7 +155,11 @@ type KanboBinding = z.infer<typeof BindingSchema>;
155
155
  * leave a project bound to nothing.
156
156
  */
157
157
  export declare function readProjectBinding(projectDir: string): KanboBinding | null;
158
- /** The binding in that exact file, or `null` when there is none to read. */
158
+ /**
159
+ * The binding in that exact file, or `null` when there is none to read. A
160
+ * byte order mark an editor put at its start (Notepad does) is not part of the
161
+ * JSON.
162
+ */
159
163
  export declare function readBinding(path: string): KanboBinding | null;
160
164
  /**
161
165
  * Bind the project folder to a board.
@@ -197,51 +201,6 @@ export declare function ignoreBoardFile(projectDir: string, absoluteDbPath: stri
197
201
  */
198
202
  export declare const DEFAULT_BOARD_FILE_PATH: string;
199
203
  //#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
- export 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
- export 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
- export declare function isOutsideWriter(provenance: IssueWriterProvenance): provenance is IssueWriterProvenance & {
242
- authorId: string;
243
- };
244
- //#endregion
245
204
  //#region src/domain/numbering.d.ts
246
205
  /**
247
206
  * What numbering needs to know about a workspace: enough to build the key stem,
@@ -343,6 +302,29 @@ export declare function cardDisplayTitle(card: {
343
302
  description?: string | null;
344
303
  }): string;
345
304
  //#endregion
305
+ //#region src/domain/column-templates.d.ts
306
+ /**
307
+ * The column sets a new board can start with, as data.
308
+ *
309
+ * Every template has `To Do`: `kanbo ready` hands an agent its next card from
310
+ * that column (`ops/ready.ts`), so a board without one gives an agent nothing
311
+ * to take. The standard set is `DEFAULT_STATUSES` itself — what a board gets
312
+ * when nobody chose.
313
+ */
314
+ /** One column as a template describes it; the board gives it an id and a place. */
315
+ interface ColumnSpec {
316
+ name: string;
317
+ /** The one line an agent reads to know when a card belongs here. */
318
+ description: string | null;
319
+ color: string | null;
320
+ category: IssueStatus['category'];
321
+ }
322
+ export declare const COLUMN_TEMPLATE_IDS: readonly ['standard', 'simple', 'review-qa'];
323
+ type ColumnTemplateId = typeof COLUMN_TEMPLATE_IDS[number];
324
+ export declare const COLUMN_TEMPLATES: Record<ColumnTemplateId, readonly ColumnSpec[]>;
325
+ /** The ready-made columns a person picks from when they build their own set, in board order. */
326
+ export declare const COLUMN_CATALOGUE: readonly ColumnSpec[];
327
+ //#endregion
346
328
  //#region src/domain/database-url.d.ts
347
329
  /**
348
330
  * A board's connection string, as it may be said out loud.
@@ -384,7 +366,7 @@ export declare function maskDatabaseUrls(text: string): string;
384
366
  * (`../serve/board-error-responses.ts`), the one table `kanbo serve` and any app
385
367
  * serving the board over HTTP answer with.
386
368
  */
387
- type BoardErrorCode = 'board_approval_requires_user' | 'board_column_rules_requires_user' | 'board_column_rules_unmet' | 'board_entry_rule_invalid' | 'board_execution_mode_locked' | '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' | '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';
369
+ type BoardErrorCode = 'board_approval_requires_user' | 'board_column_name_taken' | 'board_column_not_empty' | 'board_column_ready_protected' | 'board_column_remove_target_invalid' | 'board_column_rules_requires_user' | 'board_column_structure_requires_user' | 'board_column_rules_unmet' | 'board_entry_rule_invalid' | 'board_execution_mode_locked' | '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' | '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';
388
370
  /** A board rule the caller broke, carrying the offending values in `details`. */
389
371
  export declare class BoardError extends Error {
390
372
  readonly code: BoardErrorCode;
@@ -472,6 +454,33 @@ export declare function isEmptyActivityValue(value: string | null): value is nul
472
454
  export declare function activityText(text: string | null): IssueActivityValueView | null;
473
455
  export declare function activityToken(token: IssueActivityValueToken): IssueActivityValueView;
474
456
  //#endregion
457
+ //#region src/domain/key-suggestion.d.ts
458
+ /**
459
+ * The card key a new board is offered, read off the project folder's name:
460
+ * `todo-list` → `TLI`, `react-native-shop` → `RNS`, `kanbo` → `KAN`.
461
+ *
462
+ * Letters are brought down to plain Latin first: accents dropped (`café` →
463
+ * `cafe`), ligatures split (`file` → `file`), and the letters no decomposition
464
+ * reaches spelled out (`straße` → `strasse`, `Æ` → `AE`, `ø` → `o`), so
465
+ * `ÆØÅ` reads as the one word `AEOA` and gives `AEO`.
466
+ *
467
+ * The name is split into words at `-`, `_`, spaces, dots and camelCase humps.
468
+ * Words that say nothing about the project — `app`, `the`, `project` — are
469
+ * dropped, unless nothing else is left. Three words or more give their first
470
+ * letters; two give the first letter of one and the first two of the other; one
471
+ * gives its first three letters. Digits at the start of a word are skipped, so
472
+ * the key never starts with one. The result is upper-case, padded with `X` to
473
+ * three characters, and is `APP` when the name has nothing to offer.
474
+ *
475
+ * It is always three letters or digits, so `readIssuePrefix` numbers cards with
476
+ * exactly this key.
477
+ */
478
+ /** What a card key must look like when a person types one: a letter, then two letters or digits. */
479
+ export declare const CARD_KEY_PATTERN: RegExp;
480
+ export declare function suggestCardKey(folderName: string): string;
481
+ /** Is this a card key a person may choose? Case does not matter; it is stored upper-case. */
482
+ export declare function isValidCardKey(key: string): boolean;
483
+ //#endregion
475
484
  //#region src/domain/pull-request-fact-keys.d.ts
476
485
  /**
477
486
  * The dedupe keys the facts about one pull request are written under on a card.
@@ -505,32 +514,32 @@ export declare function pullRequestFactKeys({ owner, repo, number }: {
505
514
  */
506
515
  export declare const DEFAULT_STATUSES: readonly [{
507
516
  readonly name: 'Backlog';
508
- readonly description: 'Idea captured, not ready to work on';
517
+ readonly description: 'Ideas and requests, not ready to start';
509
518
  readonly color: '#6b7280';
510
519
  readonly category: 'backlog';
511
520
  }, {
512
521
  readonly name: 'To Do';
513
- readonly description: 'Spelled out, ready to launch';
522
+ readonly description: 'Ready to start — agents take work from here';
514
523
  readonly color: '#9ca3af';
515
524
  readonly category: 'unstarted';
516
525
  }, {
517
526
  readonly name: 'In Progress';
518
- readonly description: 'The orchestrator and its agents are working';
527
+ readonly description: 'A person or an agent is working on it';
519
528
  readonly color: '#f59e0b';
520
529
  readonly category: 'started';
521
530
  }, {
522
531
  readonly name: 'In Review';
523
- readonly description: 'Work done; being checked or waiting for you';
532
+ readonly description: 'Work done; being checked, or waiting for a person';
524
533
  readonly color: '#8b5cf6';
525
534
  readonly category: 'started';
526
535
  }, {
527
536
  readonly name: 'Done';
528
- readonly description: 'Accepted';
537
+ readonly description: 'Finished and accepted';
529
538
  readonly color: '#22c55e';
530
539
  readonly category: 'completed';
531
540
  }, {
532
541
  readonly name: 'Canceled';
533
- readonly description: 'Canceled';
542
+ readonly description: 'Won\'t be done';
534
543
  readonly color: '#6b7280';
535
544
  readonly category: 'canceled';
536
545
  }];
@@ -696,6 +705,25 @@ interface CreateCommentOnceInput {
696
705
  actor: BoardActor;
697
706
  }
698
707
  //#endregion
708
+ //#region src/ops/card-query.d.ts
709
+ /**
710
+ * Cards picked by what they are, not by reading the board and sorting through
711
+ * it: every filter becomes part of one statement, so a question about five
712
+ * cards on a board of ten thousand reads five cards.
713
+ */
714
+ /** What `queryCards` takes: the store's query, with columns named the way a person or an agent names them. */
715
+ interface CardQueryInput extends Omit<BoardCardQuery, 'statusIds'> {
716
+ /** Cards in any of these columns, each by id or by any spelling of its name. */
717
+ columns?: readonly string[];
718
+ }
719
+ /** A page of cards, how many the query picks in all, and the board's columns read on the way. */
720
+ interface CardQueryResult {
721
+ cards: Issue[];
722
+ total: number;
723
+ /** The workspace's columns in board order — what a caller needs to name each card's column. */
724
+ columns: IssueStatus[];
725
+ }
726
+ //#endregion
699
727
  //#region src/ops/card-batch.d.ts
700
728
  /** The fields one change can set on many cards at once. */
701
729
  interface BulkUpdateCardsInput {
@@ -769,16 +797,6 @@ interface CreateRelationInput {
769
797
  type: IssueRelation['type'];
770
798
  }
771
799
  //#endregion
772
- //#region src/ops/approval.d.ts
773
- /** Where a card stands with the person who has to approve it. */
774
- interface BoardApproval {
775
- state: 'none' | 'pending' | 'approved' | 'returned';
776
- /** When the person decided, in unix seconds; `null` while nobody has. */
777
- decidedAt: number | null;
778
- /** What the person wrote alongside the decision, if anything. */
779
- comment: string | null;
780
- }
781
- //#endregion
782
800
  //#region src/ops/pull-requests.d.ts
783
801
  /**
784
802
  * A pull request a card names, with where it stands as the card's own facts
@@ -828,6 +846,73 @@ interface CloseSprintResult {
828
846
  closed: true;
829
847
  }
830
848
  //#endregion
849
+ //#region src/ops/columns.d.ts
850
+ /** What a column is made of, beyond the workspace it belongs to and its position. */
851
+ interface BoardColumnInput {
852
+ workspaceId: string;
853
+ name: string;
854
+ description?: string | null;
855
+ color?: string | null;
856
+ category?: IssueStatus['category'];
857
+ /** What a card must satisfy before an agent may put it here — `ENTRY_RULES`, none by default. */
858
+ entryRules?: readonly string[] | null;
859
+ }
860
+ /** What `updateColumn` may change about a column. */
861
+ interface BoardColumnPatch {
862
+ name?: string;
863
+ description?: string | null;
864
+ color?: string | null;
865
+ /** `ENTRY_RULES`; `null` or an empty list asks for nothing. */
866
+ entryRules?: readonly string[] | null;
867
+ }
868
+ /**
869
+ * How `applyColumnTemplate` treats a board: `seed` fills an empty board and
870
+ * leaves any other alone; `add-missing` adds the template's columns the board
871
+ * lacks and keeps every column it has — a person's change to the board's
872
+ * structure, so it names the person.
873
+ */
874
+ type ApplyColumnTemplateOptions = {
875
+ mode: 'seed';
876
+ } | {
877
+ mode: 'add-missing';
878
+ actor: BoardActor;
879
+ };
880
+ /** Where `moveColumn` puts a column: an end of the board, or next to another column. */
881
+ type ColumnPosition = 'first' | 'last' | {
882
+ before: string;
883
+ } | {
884
+ after: string;
885
+ };
886
+ /** What `addColumn` makes: a column's name and what it says, and where it goes. */
887
+ interface AddColumnInput {
888
+ name: string;
889
+ description?: string | null;
890
+ color?: string | null;
891
+ category?: IssueStatus['category'];
892
+ /**
893
+ * Where it goes. Left out: before the board's first completed column (Done),
894
+ * else before the first canceled one, else at the end — so work still to do
895
+ * stays on the left.
896
+ */
897
+ position?: ColumnPosition;
898
+ }
899
+ /** What `removeColumn` does with the cards still in the column. */
900
+ interface RemoveColumnOptions {
901
+ /** The column they move to, by id or any spelling of its name. Required when the column holds cards. */
902
+ moveCardsTo?: string | null;
903
+ }
904
+ /** What `removeColumn` did. */
905
+ interface RemoveColumnResult {
906
+ removed: IssueStatus;
907
+ movedCards: number;
908
+ movedTo: IssueStatus | null;
909
+ /** Moved cards that entered the target without meeting its entry rules — a person's move warns, it does not refuse. */
910
+ unmetRules?: Array<{
911
+ issueId: string;
912
+ unmet: UnmetEntryRule[];
913
+ }>;
914
+ }
915
+ //#endregion
831
916
  //#region src/ops/runs.d.ts
832
917
  /** What is known about a run when it starts. */
833
918
  interface StartRunInput {
@@ -889,26 +974,6 @@ interface IssueActivityResolver {
889
974
  resolveAgentName: (agentId: string) => Promise<string | null>;
890
975
  }
891
976
  //#endregion
892
- //#region src/ops/columns.d.ts
893
- /** What a column is made of, beyond the workspace it belongs to and its position. */
894
- interface BoardColumnInput {
895
- workspaceId: string;
896
- name: string;
897
- description?: string | null;
898
- color?: string | null;
899
- category?: IssueStatus['category'];
900
- /** What a card must satisfy before an agent may put it here — `ENTRY_RULES`, none by default. */
901
- entryRules?: readonly string[] | null;
902
- }
903
- /** What `updateColumn` may change about a column. */
904
- interface BoardColumnPatch {
905
- name?: string;
906
- description?: string | null;
907
- color?: string | null;
908
- /** `ENTRY_RULES`; `null` or an empty list asks for nothing. */
909
- entryRules?: readonly string[] | null;
910
- }
911
- //#endregion
912
977
  //#region src/ops/index.d.ts
913
978
  /**
914
979
  * Everything the board can be asked to do, bound to one store.
@@ -992,6 +1057,7 @@ export declare function createBoardOps<TStore extends BoardStore>(store: TStore)
992
1057
  waitingFor: "human" | null;
993
1058
  workspaceId: string;
994
1059
  }[]>;
1060
+ queryCards: (input: CardQueryInput) => Promise<CardQueryResult>;
995
1061
  bulkUpdateCards: (issueIds: string[], input: BulkUpdateCardsInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<BulkUpdateCardsResult>;
996
1062
  reorderCards: (workspaceId: string, orderedIds: string[], scope?: BoardWriteScope<TStore>) => Promise<void>;
997
1063
  migrateCards: (input: MigrateCardsInput) => Promise<MigrateCardsResult>;
@@ -1176,6 +1242,7 @@ export declare function createBoardOps<TStore extends BoardStore>(store: TStore)
1176
1242
  workspaceId: string;
1177
1243
  }>;
1178
1244
  readApproval: (issueId: string) => Promise<BoardApproval>;
1245
+ readCardAttention: (cards: readonly Issue[], running: readonly boolean[]) => Promise<CardAttention[]>;
1179
1246
  linkPullRequest: (issueId: string, urlOrRef: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
1180
1247
  createdAt: number;
1181
1248
  createdById: string | null;
@@ -1341,12 +1408,50 @@ export declare function createBoardOps<TStore extends BoardStore>(store: TStore)
1341
1408
  issueId: string;
1342
1409
  unmet: UnmetEntryRule[];
1343
1410
  }[]>;
1344
- deleteColumn: (statusId: string, scope?: BoardWriteScope<TStore>) => Promise<void>;
1345
- reorderColumns: (workspaceId: string, orderedIds: string[], scope?: BoardWriteScope<TStore>) => Promise<void>;
1346
- addStandardColumns: (workspaceId: string, scope?: BoardWriteScope<TStore>) => Promise<{
1411
+ deleteColumn: (statusId: string, scope?: BoardWriteScope<TStore>, actor?: BoardActor) => Promise<void>;
1412
+ reorderColumns: (workspaceId: string, orderedIds: string[], scope?: BoardWriteScope<TStore>, actor?: BoardActor) => Promise<void>;
1413
+ addStandardColumns: (workspaceId: string, scope?: BoardWriteScope<TStore>, actor?: BoardActor) => Promise<{
1347
1414
  statuses: IssueStatus[];
1348
1415
  added: string[];
1349
1416
  }>;
1417
+ addColumn: (workspaceId: string, input: AddColumnInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
1418
+ category: "backlog" | "canceled" | "completed" | "started" | "triage" | "unstarted";
1419
+ color: string | null;
1420
+ createdAt: number;
1421
+ description: string | null;
1422
+ entryRules: string | null;
1423
+ id: string;
1424
+ name: string;
1425
+ order: number;
1426
+ workspaceId: string;
1427
+ }>;
1428
+ applyColumnTemplate: (workspaceId: string, columns: readonly ColumnSpec[], options: ApplyColumnTemplateOptions, scope?: BoardWriteScope<TStore>) => Promise<{
1429
+ statuses: IssueStatus[];
1430
+ added: string[];
1431
+ }>;
1432
+ renameColumn: (workspaceId: string, nameOrId: string, newName: string, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
1433
+ category: "backlog" | "canceled" | "completed" | "started" | "triage" | "unstarted";
1434
+ color: string | null;
1435
+ createdAt: number;
1436
+ description: string | null;
1437
+ entryRules: string | null;
1438
+ id: string;
1439
+ name: string;
1440
+ order: number;
1441
+ workspaceId: string;
1442
+ }>;
1443
+ moveColumn: (workspaceId: string, nameOrId: string, position: ColumnPosition, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
1444
+ category: "backlog" | "canceled" | "completed" | "started" | "triage" | "unstarted";
1445
+ color: string | null;
1446
+ createdAt: number;
1447
+ description: string | null;
1448
+ entryRules: string | null;
1449
+ id: string;
1450
+ name: string;
1451
+ order: number;
1452
+ workspaceId: string;
1453
+ }[]>;
1454
+ removeColumn: (workspaceId: string, nameOrId: string, options: RemoveColumnOptions, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<RemoveColumnResult>;
1350
1455
  startRun: (issueId: string, input: StartRunInput, actor: BoardActor, scope?: BoardWriteScope<TStore>) => Promise<{
1351
1456
  agentId: string | null;
1352
1457
  agentName: string;
@@ -1486,6 +1591,11 @@ export declare function createBoardOps<TStore extends BoardStore>(store: TStore)
1486
1591
  waitingFor: "human" | null;
1487
1592
  workspaceId: string;
1488
1593
  }[]>;
1594
+ queryReady: (input: {
1595
+ workspaceId: string;
1596
+ limit?: number;
1597
+ offset?: number;
1598
+ }) => Promise<CardQueryResult>;
1489
1599
  buildPrimeText: (workspaceId: string) => Promise<string>;
1490
1600
  };
1491
1601
  /** The board's operations, as a type callers can name. */
@@ -1515,7 +1625,9 @@ interface BoardErrorResponse {
1515
1625
  * because the answer would have been yes a moment earlier. An agent putting a
1516
1626
  * card in a column whose entry rules it does not meet yet is 409 for the same
1517
1627
  * reason turned around: the answer will be yes once the card meets them, and
1518
- * `details.unmet` says what is missing.
1628
+ * `details.unmet` says what is missing. Deleting a column that still holds
1629
+ * cards is 409 too: it can be done once they are moved, and
1630
+ * `details.cardCount` says how many there are.
1519
1631
  *
1520
1632
  * A failure may also be renamed here: the package names its codes after the
1521
1633
  * board, while every error the `/issues` routes answer with is named after the
@@ -1524,5 +1636,4 @@ interface BoardErrorResponse {
1524
1636
  */
1525
1637
  export declare const BOARD_ERROR_RESPONSES: Record<BoardErrorCode, BoardErrorResponse>;
1526
1638
  //#endregion
1527
- export { type AddCommentInput, type AttachRunExecutionInput, type BoardActiveRun, type BoardActor, type BoardApproval, type BoardCardWrite, type BoardColumnInput, type BoardColumnPatch, type BoardErrorCode, type BoardErrorResponse, type BoardLinkedPullRequest, type BoardOps, type BoardPullRequestStanding, type BoardRunProjection, type BoardRunProjectionScope, type BoardRunView, type BoardSprint, type BoardStore, type BoardTransactionMode, type BoardWorkspaceIdentity, type BoardWriteScope, type BulkUpdateCardsInput, type BulkUpdateCardsResult, type CloseSprintResult, type CreateCardInput, type CreateCommentOnceInput, type CreateMilestoneInput, type CreateRelationInput, 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, UNMET_ENTRY_RULE_REASONS, type UnmetEntryRule, type UpdateCardInput, type UpdateMilestoneInput, evaluateEntryRules, readChecklist, readEntryRules, serializeEntryRules };
1528
- //# sourceMappingURL=index.d.cts.map
1639
+ export { type AddColumnInput, type AddCommentInput, type ApplyColumnTemplateOptions, type AttachRunExecutionInput, type BoardActiveRun, type BoardActor, type BoardApproval, type BoardCardPage, type BoardCardQuery, type BoardCardWrite, type BoardColumnInput, type BoardColumnPatch, type BoardErrorCode, type BoardErrorResponse, type BoardLinkedPullRequest, type BoardMilestoneCardCount, type BoardOps, type BoardPullRequestStanding, type BoardRunProjection, type BoardRunProjectionScope, type BoardRunView, type BoardSprint, type BoardStore, type BoardTransactionMode, type BoardWorkspaceIdentity, type BoardWriteScope, type BulkUpdateCardsInput, type BulkUpdateCardsResult, type CardAttention, type CardLastComment, type CardQueryInput, type CardQueryResult, type CloseSprintResult, type ColumnPosition, type ColumnSpec, type ColumnTemplateId, type CreateCardInput, type CreateCommentOnceInput, type CreateMilestoneInput, type CreateRelationInput, 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 RemoveColumnOptions, type RemoveColumnResult, type StartRunInput, UNMET_ENTRY_RULE_REASONS, type UnmetEntryRule, type UpdateCardInput, type UpdateMilestoneInput, evaluateEntryRules, isOutsideWriter, normalizeCommentAuthorKind, readChecklist, readEntryRules, serializeEntryRules, toIssueView };