@bevel-software/platform-shared 0.32.0 → 0.34.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.
@@ -101,6 +101,24 @@ export interface FsTreeChangedEvent {
101
101
  branch: string;
102
102
  }
103
103
 
104
+ /**
105
+ * A document's text could not be extracted, just now: the parser refused it,
106
+ * or the extraction outlived its budget. Emitted once per FRESH failure —
107
+ * never for one answered from memory — so a person looking at the file's row
108
+ * in the explorer is told in place, and nothing is kept for later.
109
+ *
110
+ * `reason` follows "Could not be read:" in the explorer's notice. It names the
111
+ * file and quotes the parser; like every kind that names a path on a
112
+ * workspace, it is delivered only to sessions whose person may read `path`
113
+ * (the events route's delivery rule, judged by the access rules).
114
+ */
115
+ export interface DocumentUnreadableEvent {
116
+ kind: 'document-unreadable';
117
+ workspaceId: string;
118
+ path: string;
119
+ reason: string;
120
+ }
121
+
104
122
  /**
105
123
  * A commit landed locally but could not be pushed to the remote.
106
124
  *
@@ -201,6 +219,12 @@ export interface AgentToolCallEvent {
201
219
 
202
220
  // ── Global ───────────────────────────────────────────────────────────────────
203
221
 
222
+ /**
223
+ * A change request was opened. Reaches EVERY session, so it says only that a
224
+ * request exists: its number, its branches and who opened it — no title and
225
+ * no paths, which a person may not be allowed to read. A reader fetches the
226
+ * request, and sees of it what the request routes show them.
227
+ */
204
228
  export interface ChangeRequestOpenedEvent {
205
229
  kind: 'change-request-opened';
206
230
  number: number;
@@ -208,7 +232,6 @@ export interface ChangeRequestOpenedEvent {
208
232
  target: string;
209
233
  /** Hash of the author's email (matches the marker in the CR body); null when unattributable. */
210
234
  authorIdHash: string | null;
211
- title: string;
212
235
  }
213
236
 
214
237
  export interface ChangeRequestMergedEvent {
@@ -221,6 +244,16 @@ export interface ChangeRequestRejectedEvent {
221
244
  number: number;
222
245
  }
223
246
 
247
+ /**
248
+ * A request's title or description was edited. Carries no text: every
249
+ * viewer re-reads the request through the list and detail endpoints it
250
+ * already uses, which apply its own read rules.
251
+ */
252
+ export interface ChangeRequestEditedEvent {
253
+ kind: 'change-request-edited';
254
+ number: number;
255
+ }
256
+
224
257
  /**
225
258
  * An apply did NOT land, announced to EVERY session — the counterpart of the
226
259
  * user-scoped `change-request-merge-failed` below, which only the clicker gets.
@@ -282,7 +315,14 @@ export interface ChangeRequestMergeFailedEvent {
282
315
  export interface ApprovalChangedEvent {
283
316
  kind: 'approval-changed';
284
317
  number: number;
318
+ /** The approved file, KB-repo-relative. */
285
319
  path: string;
320
+ /**
321
+ * The request's target branch: the event names a path, and whether a
322
+ * session's person may hear of it is judged by their read access to that
323
+ * path at the target — the same rule the request's own detail is scoped by.
324
+ */
325
+ targetBranch: string;
286
326
  approverUserId: string;
287
327
  change: 'added' | 'removed';
288
328
  }
@@ -341,6 +381,7 @@ export type WorkflowEventPayload =
341
381
  | LockAcquiredEvent
342
382
  | LockReleasedEvent
343
383
  | FsTreeChangedEvent
384
+ | DocumentUnreadableEvent
344
385
  | GitSyncFailedEvent
345
386
  | GitSyncRecoveredEvent
346
387
  | BranchSwitchedEvent
@@ -349,6 +390,7 @@ export type WorkflowEventPayload =
349
390
  | ChangeRequestOpenedEvent
350
391
  | ChangeRequestMergedEvent
351
392
  | ChangeRequestRejectedEvent
393
+ | ChangeRequestEditedEvent
352
394
  | ChangeRequestMergeFailedEvent
353
395
  | ChangeRequestApplyFailedEvent
354
396
  | ApprovalChangedEvent
@@ -366,6 +408,7 @@ export function isWorkspaceScoped(
366
408
  e.kind === 'lock-acquired' ||
367
409
  e.kind === 'lock-released' ||
368
410
  e.kind === 'fs-tree-changed' ||
411
+ e.kind === 'document-unreadable' ||
369
412
  e.kind === 'git-sync-failed' ||
370
413
  e.kind === 'git-sync-recovered'
371
414
  );
@@ -18,7 +18,7 @@
18
18
  */
19
19
 
20
20
  import type { AuthUser } from '../auth/types.js';
21
- import type { ChangeRequestApplyFailureKind } from '../git/pr.types.js';
21
+ import type { ChangeRequestApplyFailureKind, UpdateChangeRequestFields } from '../git/pr.types.js';
22
22
  import type {
23
23
  AcquireLockResult,
24
24
  Branch,
@@ -28,7 +28,6 @@ import type {
28
28
  Change,
29
29
  ChangeInput,
30
30
  ChangeRequest,
31
- ChangeRequestComment,
32
31
  ChangeRequestDetail,
33
32
  ChangeRequestUpdateResult,
34
33
  ChangeRequestState,
@@ -42,10 +41,9 @@ import type {
42
41
  MergeBranchOutcome,
43
42
  MergeChangeRequestOutcome,
44
43
  OpenChangeRequestInput,
45
- PostChangeRequestCommentInput,
46
44
  UpdateBranchOutcome,
47
45
  } from './types.js';
48
- import type { MergeResolution } from '../git/types.js';
46
+ import type { BranchCounts, MergeResolution } from '../git/types.js';
49
47
 
50
48
  export interface IWorkflowService {
51
49
  // ── Branches ──────────────────────────────────────────────────────────────
@@ -111,6 +109,12 @@ export interface IWorkflowService {
111
109
  // `createBranch` + URL navigation covers the "start a new draft" intent.
112
110
  /** Current branch's workspace status — currently just the branch name + upstream sync state. */
113
111
  branchStatus(workspaceId: string): Promise<BranchWorkspaceStatus>;
112
+ /**
113
+ * Commits the workspace's own branch is ahead of and behind its upstream
114
+ * (or, with none, the nearest protected branch); null when neither
115
+ * resolves. Counted for this one branch: a branch listing carries no counts.
116
+ */
117
+ branchCounts(workspaceId: string): Promise<BranchCounts>;
114
118
  // `discardWorkingChanges` removed: under save=share the working tree is
115
119
  // never dirty, so there is nothing for "undo my unsaved edits" to undo.
116
120
  /**
@@ -554,17 +558,6 @@ export interface IWorkflowService {
554
558
  number: number,
555
559
  ): Promise<ChangeRequestUpdateResult>;
556
560
 
557
- // Comments
558
- listComments(number: number): Promise<ChangeRequestComment[]>;
559
- postComment(
560
- number: number,
561
- user: AuthUser,
562
- input: PostChangeRequestCommentInput,
563
- headSha: string,
564
- ): Promise<ChangeRequestComment>;
565
- editComment(commentId: string, number: number, user: AuthUser, body: string): Promise<ChangeRequestComment>;
566
- deleteComment(commentId: string, number: number, user: AuthUser): Promise<void>;
567
-
568
561
  // Approvals — per-file, tied to the file's current change. New changes
569
562
  // invalidate approvals on the affected file.
570
563
  approveFile(
@@ -644,6 +637,18 @@ export interface IWorkflowService {
644
637
  */
645
638
  deleteChangeRequest(number: number, user: AuthUser): Promise<void>;
646
639
 
640
+ /**
641
+ * Change an OPEN request's title and/or description. Its author, an admin,
642
+ * or the holder of write on every changed file — the people who may close
643
+ * it; anyone else gets a worded 403, and a merged or closed request a
644
+ * worded 409.
645
+ */
646
+ updateChangeRequest(
647
+ number: number,
648
+ user: AuthUser,
649
+ input: UpdateChangeRequestFields,
650
+ ): Promise<ChangeRequest>;
651
+
647
652
  /**
648
653
  * Reject a change request without merging. Authorized for the author or
649
654
  * for users with write permission to every changed file on the target
@@ -22,14 +22,13 @@ import type {
22
22
  WorkingTreeStatus,
23
23
  } from '../git/types.js';
24
24
  import type {
25
+ AccessRequestLevel,
25
26
  CancelPrResult,
26
27
  FileApprovalState,
27
28
  MergePrResult,
28
29
  PullRequestDetail,
29
30
  PullRequestState,
30
31
  PullRequestSummary,
31
- PostPrCommentInput,
32
- PrReviewComment,
33
32
  PullRequestFile,
34
33
  } from '../git/pr.types.js';
35
34
 
@@ -147,8 +146,6 @@ export type ChangedFile = PullRequestFile;
147
146
  export type FileApproval = FileApprovalState;
148
147
  export type MergeChangeRequestResult = MergePrResult;
149
148
  export type CancelChangeRequestResult = CancelPrResult;
150
- export type ChangeRequestComment = PrReviewComment;
151
- export type PostChangeRequestCommentInput = PostPrCommentInput;
152
149
 
153
150
  /**
154
151
  * One open change request proposing files under a folder, as a folder delete
@@ -189,16 +186,23 @@ export interface FolderChangeRequestRemoval {
189
186
  * `targetBranch` into `sourceBranch` as part of opening, so callers don't
190
187
  * pass a head SHA — the workflow resolves the head itself.
191
188
  *
192
- * `title` + `description` are the change request's metadata; the description
193
- * is plain text (no GitHub-flavoured markdown affordances exposed at this
194
- * layer). The implementation may still render this as the PR body when the
195
- * underlying GitHub PR is created.
189
+ * `title` + `description` are the change request's metadata. The description
190
+ * is stored exactly as given and IS the request's body: Hexis appends nothing
191
+ * of its own to it.
196
192
  */
197
193
  export interface OpenChangeRequestInput {
198
194
  sourceBranch: string;
199
195
  targetBranch: string;
200
196
  title: string;
201
197
  description?: string;
198
+ /**
199
+ * The access-request flow's own facts about the request it opens: the level
200
+ * asked for and the person's note, kept on the request's row rather than in
201
+ * its prose. Only that flow sets it — the open route and the agent's
202
+ * `open_change_request` build their input field by field and never forward
203
+ * it.
204
+ */
205
+ accessRequest?: { level: AccessRequestLevel; note?: string };
202
206
  }
203
207
 
204
208
  /**
@@ -531,9 +531,18 @@ export function withLinkedSkillRoots(
531
531
  return out;
532
532
  }
533
533
 
534
+ /**
535
+ * Whether the repo-relative `path` is `root` itself or lies in the subtree
536
+ * `root` names — the one containment test for KB paths named by a list of
537
+ * roots (a plugin's linked skills, an agent configuration's entries).
538
+ */
539
+ export function pathUnderRoot(path: string, root: string): boolean {
540
+ return path === root || path.startsWith(`${root}/`);
541
+ }
542
+
534
543
  /** Whether `skillPath` (a skill folder) falls under `root` (a skill folder or a folder of skills). */
535
544
  export function skillUnderRoot(skillPath: string, root: string): boolean {
536
- return skillPath === root || skillPath.startsWith(`${root}/`);
545
+ return pathUnderRoot(skillPath, root);
537
546
  }
538
547
 
539
548
  /**