@capybara-hq/kernel 0.1.0-rc.24 → 0.1.0-rc.25

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 (140) hide show
  1. package/dist/admin/admin.module.js +2 -0
  2. package/dist/admin/health.service.d.ts +2 -2
  3. package/dist/admin/health.service.js +6 -2
  4. package/dist/agents/agents.module.js +3 -0
  5. package/dist/agents/agents.service.d.ts +6 -1
  6. package/dist/agents/agents.service.js +11 -2
  7. package/dist/catalog/catalog-import.module.js +0 -4
  8. package/dist/catalog/catalog-scope.service.d.ts +63 -26
  9. package/dist/catalog/catalog-scope.service.js +146 -71
  10. package/dist/catalog/catalog.module.js +4 -3
  11. package/dist/catalog/catalog.service.d.ts +11 -4
  12. package/dist/catalog/catalog.service.js +21 -5
  13. package/dist/catalog/cli.d.ts +4 -3
  14. package/dist/catalog/cli.js +8 -13
  15. package/dist/catalog/job-ids.d.ts +8 -20
  16. package/dist/catalog/job-ids.js +11 -16
  17. package/dist/catalog/marketplaces.service.d.ts +1 -1
  18. package/dist/catalog/org-plugin-uploads.d.ts +11 -4
  19. package/dist/catalog/org-plugin-uploads.js +21 -6
  20. package/dist/catalog/owned-items.d.ts +6 -13
  21. package/dist/catalog/owned-items.js +11 -29
  22. package/dist/catalog/owned-plugin-cleanup.d.ts +8 -17
  23. package/dist/catalog/owned-plugin-cleanup.js +12 -66
  24. package/dist/catalog/platform-components.d.ts +56 -34
  25. package/dist/catalog/platform-components.js +68 -78
  26. package/dist/catalog/plugin-import.d.ts +28 -25
  27. package/dist/catalog/plugin-import.js +90 -76
  28. package/dist/catalog/plugin-upgrade.d.ts +4 -4
  29. package/dist/catalog/plugin-upgrade.js +7 -19
  30. package/dist/catalog/scope-jobs.d.ts +59 -0
  31. package/dist/catalog/scope-jobs.js +65 -0
  32. package/dist/catalog/scope-sync-workers.d.ts +22 -0
  33. package/dist/catalog/scope-sync-workers.js +58 -2
  34. package/dist/catalog/scope-sync.d.ts +40 -65
  35. package/dist/catalog/scope-sync.js +114 -122
  36. package/dist/channels/inbound.js +2 -2
  37. package/dist/channels/threads.d.ts +4 -3
  38. package/dist/channels/threads.js +4 -3
  39. package/dist/conversations/conversations.controller.js +4 -2
  40. package/dist/conversations/conversations.service.d.ts +17 -5
  41. package/dist/conversations/conversations.service.js +17 -5
  42. package/dist/conversations/events.d.ts +21 -0
  43. package/dist/conversations/events.js +24 -1
  44. package/dist/conversations/source.d.ts +10 -0
  45. package/dist/conversations/source.js +17 -0
  46. package/dist/conversations/tree.d.ts +10 -0
  47. package/dist/conversations/tree.js +35 -0
  48. package/dist/db/kernel-schema.d.ts +9 -14
  49. package/dist/devices/devices.service.d.ts +11 -8
  50. package/dist/devices/devices.service.js +16 -23
  51. package/dist/evals/run-replay.d.ts +13 -2
  52. package/dist/evals/run-replay.js +28 -1
  53. package/dist/evals/snapshot.d.ts +7 -1
  54. package/dist/evals/snapshot.js +2 -1
  55. package/dist/extensions/hooks.d.ts +22 -3
  56. package/dist/extensions/hooks.js +15 -1
  57. package/dist/extensions/lifecycle-hooks.d.ts +99 -0
  58. package/dist/extensions/lifecycle-hooks.js +273 -0
  59. package/dist/extensions/org-config.d.ts +13 -1
  60. package/dist/extensions/org-config.js +19 -2
  61. package/dist/extensions/permission-view.d.ts +9 -5
  62. package/dist/extensions/permission-view.js +9 -4
  63. package/dist/extensions/point-defaults.d.ts +28 -1
  64. package/dist/extensions/point-defaults.js +44 -13
  65. package/dist/inbox/inbox.service.d.ts +6 -20
  66. package/dist/inbox/inbox.service.js +0 -3
  67. package/dist/inbox/org-notices.d.ts +1 -1
  68. package/dist/inbox/platform-inbox.service.d.ts +3 -32
  69. package/dist/inbox/platform-inbox.service.js +5 -54
  70. package/dist/infra/outbox/registry.d.ts +124 -0
  71. package/dist/infra/outbox/registry.js +126 -0
  72. package/dist/infra/queue/queue-names.d.ts +1 -1
  73. package/dist/infra/queue/queue-names.js +1 -0
  74. package/dist/orgs/directory-sync.js +1 -1
  75. package/dist/orgs/members.service.js +1 -1
  76. package/dist/orgs/offboarding.d.ts +50 -57
  77. package/dist/orgs/offboarding.js +117 -162
  78. package/dist/orgs/orgs.module.js +3 -0
  79. package/dist/orgs/orgs.service.d.ts +11 -5
  80. package/dist/orgs/orgs.service.js +15 -6
  81. package/dist/overrides.d.ts +3 -0
  82. package/dist/overrides.js +2 -0
  83. package/dist/platform/ops/inbox.ops.js +4 -20
  84. package/dist/platform/ops/platform.ops.d.ts +1 -0
  85. package/dist/platform/ops/platform.ops.js +6 -3
  86. package/dist/roles/worker-role.d.ts +10 -5
  87. package/dist/roles/worker-role.js +19 -9
  88. package/dist/roles/worker.module.js +2 -4
  89. package/dist/runtime/context/build.d.ts +3 -0
  90. package/dist/runtime/context/build.js +15 -0
  91. package/dist/runtime/context/plugin-context.d.ts +20 -0
  92. package/dist/runtime/context/plugin-context.js +30 -0
  93. package/dist/runtime/langgraph-loop.js +4 -0
  94. package/dist/runtime/loop.d.ts +8 -0
  95. package/dist/runtime/maintenance.d.ts +5 -3
  96. package/dist/runtime/maintenance.js +36 -11
  97. package/dist/runtime/model-call.d.ts +6 -1
  98. package/dist/runtime/model-call.js +1 -0
  99. package/dist/runtime/plugin-context.service.d.ts +69 -0
  100. package/dist/runtime/plugin-context.service.js +208 -0
  101. package/dist/runtime/run-control.d.ts +6 -1
  102. package/dist/runtime/run-control.js +13 -0
  103. package/dist/runtime/run-queue.d.ts +13 -0
  104. package/dist/runtime/run-queue.js +63 -0
  105. package/dist/runtime/run-worker.d.ts +22 -1
  106. package/dist/runtime/run-worker.js +107 -10
  107. package/dist/runtime/runtime.module.js +2 -0
  108. package/dist/runtime/subagents/dispatch.js +1 -0
  109. package/dist/runtime/subagents/skill-fork.js +3 -0
  110. package/dist/sandbox/jobs.d.ts +20 -10
  111. package/dist/sandbox/jobs.js +23 -17
  112. package/dist/schedules/fire.d.ts +25 -4
  113. package/dist/schedules/fire.js +87 -13
  114. package/dist/schedules/job-ids.d.ts +66 -17
  115. package/dist/schedules/job-ids.js +81 -13
  116. package/dist/schedules/run-tracker.js +2 -1
  117. package/dist/schedules/scan.job.d.ts +13 -32
  118. package/dist/schedules/scan.job.js +35 -144
  119. package/dist/schedules/scheduled-tasks.service.d.ts +6 -6
  120. package/dist/schedules/scheduled-tasks.service.js +17 -14
  121. package/dist/schedules/schedules.module.js +0 -4
  122. package/dist/skills/changes.controller.d.ts +1 -1
  123. package/dist/skills/changes.controller.js +1 -1
  124. package/dist/tools/approvals.service.d.ts +15 -4
  125. package/dist/tools/approvals.service.js +26 -10
  126. package/dist/tools/pipeline.d.ts +11 -2
  127. package/dist/tools/pipeline.js +5 -0
  128. package/dist/tools/questions.service.d.ts +15 -4
  129. package/dist/tools/questions.service.js +21 -19
  130. package/dist/tools/registry.d.ts +8 -1
  131. package/dist/tools/registry.js +9 -0
  132. package/package.json +3 -3
  133. package/src/migrations/0121_drop_platform_migration_runs.sql +12 -0
  134. package/src/migrations/0122_drop_scheduled_task_runs_rechecked_at.sql +5 -0
  135. package/src/migrations/0123_pgvector.sql +27 -0
  136. package/src/migrations/0124_conversation_source.sql +36 -0
  137. package/dist/catalog/platform-migration.d.ts +0 -115
  138. package/dist/catalog/platform-migration.js +0 -583
  139. package/dist/infra/queue/add-job-once.d.ts +0 -14
  140. package/dist/infra/queue/add-job-once.js +0 -16
@@ -17,7 +17,7 @@ import { Transactional } from "../infra/database/transactional.decorator.js";
17
17
  import { KERNEL_LOGGER } from "../infra/tokens.js";
18
18
  import { EffectiveConfigs } from "./effective-config.js";
19
19
  import { enabledExtensionsQuery, isExtensionEnabled } from "./enabled.js";
20
- import { OrgExtensionConfigs } from "./org-config.js";
20
+ import { OrgConfigInvalidError, OrgExtensionConfigs } from "./org-config.js";
21
21
  import { ExtensionRegistry } from "./registry.js";
22
22
  /** The extension points whose provider each org chooses (`selection: "org-default"`). */
23
23
  function selectionPoints() {
@@ -58,7 +58,7 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
58
58
  if (!hasSelection(point)) {
59
59
  throw new Error(`extension point ${point} has no org-default selection`);
60
60
  }
61
- const candidates = await this.candidates(orgId, point);
61
+ const { candidates } = await this.candidates(orgId, point);
62
62
  const chosen = await this.choose(orgId, point, candidates);
63
63
  if (!chosen.ok)
64
64
  return chosen;
@@ -71,12 +71,33 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
71
71
  config: c.config,
72
72
  };
73
73
  }
74
+ /**
75
+ * Every provider of `point` (the name without the major, e.g. `context`) that could serve
76
+ * `orgId` now, in extension-name order: the same candidates {@link resolve} chooses from (loaded
77
+ * here, enabled in the org, valid org and effective config, `configured()` not false), for
78
+ * points whose every enabled provider is used (no `selection`). `failed`: the providers enabled
79
+ * in the org whose status could not be read (reading a config or `configured()` threw, e.g. a
80
+ * transient database error); they are neither serving nor known to be off. An invalid stored
81
+ * org config ({@link OrgConfigInvalidError}) is not a read error: that provider is off.
82
+ */
83
+ async providersFor(orgId, point) {
84
+ const { candidates, failed } = await this.candidates(orgId, point);
85
+ return {
86
+ providers: candidates.map((c) => ({
87
+ extension: c.extension,
88
+ impl: c.impl,
89
+ orgConfig: c.orgConfig,
90
+ config: c.config,
91
+ })),
92
+ failed,
93
+ };
94
+ }
74
95
  /** Every `org-default` point with its candidates, stored default and effective provider. */
75
96
  async list(orgId) {
76
97
  const stored = await this.storedDefaults(orgId);
77
98
  const out = [];
78
99
  for (const point of selectionPoints()) {
79
- const candidates = await this.candidates(orgId, point);
100
+ const { candidates } = await this.candidates(orgId, point);
80
101
  const chosen = pick(candidates, stored.get(point));
81
102
  out.push({
82
103
  point,
@@ -128,7 +149,11 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
128
149
  detail: { point, extension, ...auditDetail },
129
150
  });
130
151
  }
131
- /** The candidates of `point` in `orgId`, by extension name. */
152
+ /**
153
+ * The candidates of `point` in `orgId`, by extension name, and the enabled providers whose status
154
+ * could not be read (a read or `configured()` threw: excluded, logged). A provider whose stored
155
+ * org config or effective config is invalid is excluded but not `failed`: it is known to be off.
156
+ */
132
157
  async candidates(orgId, point) {
133
158
  const db = this.kdb.db;
134
159
  const enabled = new Set((await db
@@ -141,18 +166,21 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
141
166
  providers.set(e.plugin, e.impl);
142
167
  }
143
168
  const out = [];
169
+ const failed = new Set();
144
170
  for (const [extension, impl] of providers) {
145
171
  let cfg;
146
172
  try {
147
173
  cfg = await this.orgConfigs.get(orgId, extension);
148
174
  }
149
175
  catch (err) {
150
- this.log.warn("org default provider: provider excluded, its org config is invalid", {
151
- orgId,
152
- point,
153
- extension,
154
- err,
155
- });
176
+ // a stored org config that no longer validates is a known state: the provider is off
177
+ // (as for an invalid effective config below); only a read that failed is `failed`
178
+ const invalid = err instanceof OrgConfigInvalidError;
179
+ this.log.warn(invalid
180
+ ? "extension point provider excluded, its stored org config is invalid"
181
+ : "extension point provider excluded, cannot read its org config", { orgId, point, extension, err });
182
+ if (!invalid)
183
+ failed.add(extension);
156
184
  continue;
157
185
  }
158
186
  if (!cfg?.enabled)
@@ -163,12 +191,13 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
163
191
  effective = await this.effective.get(orgId, extension);
164
192
  }
165
193
  catch (err) {
166
- this.log.warn("org default provider: provider excluded, cannot read its effective config", {
194
+ this.log.warn("extension point provider excluded, cannot read its effective config", {
167
195
  orgId,
168
196
  point,
169
197
  extension,
170
198
  err,
171
199
  });
200
+ failed.add(extension);
172
201
  continue;
173
202
  }
174
203
  if (!effective.ok)
@@ -181,12 +210,13 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
181
210
  ok = configured.call(impl, cfg.config, effective.config) !== false;
182
211
  }
183
212
  catch (err) {
184
- this.log.warn("org default provider: provider excluded, configured() threw", {
213
+ this.log.warn("extension point provider excluded, configured() threw", {
185
214
  orgId,
186
215
  point,
187
216
  extension,
188
217
  err,
189
218
  });
219
+ failed.add(extension);
190
220
  continue;
191
221
  }
192
222
  if (!ok)
@@ -194,7 +224,8 @@ let ExtensionPointDefaults = class ExtensionPointDefaults {
194
224
  }
195
225
  out.push({ extension, impl, orgConfig: cfg.config, config: effective.config });
196
226
  }
197
- return out.sort((a, b) => (a.extension < b.extension ? -1 : a.extension > b.extension ? 1 : 0));
227
+ out.sort((a, b) => (a.extension < b.extension ? -1 : a.extension > b.extension ? 1 : 0));
228
+ return { candidates: out, failed };
198
229
  }
199
230
  async choose(orgId, point, candidates) {
200
231
  if (candidates.length < 2)
@@ -6,34 +6,20 @@ import { ApprovalsService, type ApprovalView } from "../tools/approvals.service.
6
6
  import type { OrgNoticeDetails } from "./org-notices.js";
7
7
  /** The most open org notices one inbox read returns. */
8
8
  export declare const ORG_NOTICES_LIST_MAX = 100;
9
- /** The skill the platform components migration renamed (`skill_renamed`). */
10
- export interface SkillRenamedDetail {
11
- skillId: string;
12
- from: string;
13
- to: string;
14
- platformSkillId: string;
15
- plugin: string | null;
16
- }
17
9
  /**
18
- * A notice for the org's admins (`org_notices`), shown until one of them dismisses it; `kind`
19
- * picks the detail field that is set:
20
- * - `skill_renamed` (`skillRenamed`): the platform components migration renamed an org skill whose
21
- * name a platform skill on in the org has; agents keep it, by id;
22
- * - `item_shared`, `shared_item_updated`, `upload_confirmed`, `upload_rejected` (`detail`): the
23
- * shapes of {@link OrgNoticeDetails} (plugin scope phase 3, P3-22).
10
+ * A notice for the org's admins (`org_notices`), shown until one of them dismisses it:
11
+ * `item_shared`, `shared_item_updated`, `upload_confirmed`, `upload_rejected`, `detail` in the
12
+ * shape of {@link OrgNoticeDetails} (plugin scope phase 3, P3-22).
24
13
  */
25
14
  export type OrgNoticeView = {
26
15
  id: string;
27
16
  createdAt: string;
28
- } & ({
29
- kind: "skill_renamed";
30
- skillRenamed: SkillRenamedDetail;
31
- } | {
17
+ } & {
32
18
  [K in keyof OrgNoticeDetails]: {
33
19
  kind: K;
34
20
  detail: OrgNoticeDetails[K];
35
21
  };
36
- }[keyof OrgNoticeDetails]);
22
+ }[keyof OrgNoticeDetails];
37
23
  /** 收件箱一次最多返回的事项数。 */
38
24
  export declare const INBOX_MAX_ITEMS = 100;
39
25
  /**
@@ -51,7 +37,7 @@ export declare const INBOX_MAX_ITEMS = 100;
51
37
  * - `schedule_attention`: the current user's own scheduled task that needs them (spec §8): paused
52
38
  * for any reason but their own pause, its latest run failed, or its latest run was refused tools
53
39
  * or connections; derived live, gone once the task is resumed or runs clean;
54
- * - the org notices (`skill_renamed`, `item_shared`, `shared_item_updated`, `upload_confirmed`,
40
+ * - the org notices (`item_shared`, `shared_item_updated`, `upload_confirmed`,
55
41
  * `upload_rejected`; `type` = the notice's kind): for org admins, until one dismisses it
56
42
  * (`POST inbox/notices/:id/dismiss`).
57
43
  */
@@ -112,9 +112,6 @@ let InboxService = class InboxService {
112
112
  .execute();
113
113
  return rows.map((r) => {
114
114
  const base = { id: r.id, createdAt: r.created_at.toISOString() };
115
- if (r.kind === "skill_renamed") {
116
- return { ...base, kind: r.kind, skillRenamed: r.detail };
117
- }
118
115
  return { ...base, kind: r.kind, detail: r.detail };
119
116
  });
120
117
  }
@@ -1,7 +1,7 @@
1
1
  import { type OwnedRef, type Owner } from "../catalog/ownership.js";
2
2
  import type { KernelSchemaDb, OrgNoticeKind } from "../db/kernel-schema.js";
3
3
  export type { OrgNoticeKind };
4
- /** The `detail` of each notice kind except `skill_renamed` (written by the platform migration). */
4
+ /** The `detail` of each notice kind. */
5
5
  export interface OrgNoticeDetails {
6
6
  /** An org was added to the item's list, or its scope widened (`all_orgs`). */
7
7
  /** `displayName`: a plugin's display name, which the inbox names it by (null otherwise). */
@@ -8,11 +8,6 @@ import type { PlatformNoticeDetails } from "./platform-notices.js";
8
8
  export declare const PLATFORM_INBOX_MAX_ITEMS = 100;
9
9
  /** The most open scope sync failures one read takes. */
10
10
  export declare const SCOPE_SYNC_FAILURES_LIST_MAX = 200;
11
- /**
12
- * A platform components migration run unfinished this long after its start is stuck (its worker
13
- * stopped mid-run; a run takes seconds, and the next one starts at the next worker start or day).
14
- */
15
- export declare const MIGRATION_RUN_STUCK_MS: number;
16
11
  /**
17
12
  * An open failure of the plugin scope sync: its last attempt to install the plugin in the org, to
18
13
  * uninstall it, or to install the dependencies a platform update added (`dependencies`) failed,
@@ -34,18 +29,6 @@ export interface ScopeSyncFailureView {
34
29
  message: string;
35
30
  failedAt: string;
36
31
  }
37
- /**
38
- * The latest platform components migration run (`platform_migration_runs`) when it needs a look:
39
- * finished with catalog items whose components could not be written (`itemsFailed`,
40
- * `<name>@<version>`), or `stuck` (unfinished {@link MIGRATION_RUN_STUCK_MS} after its start).
41
- */
42
- export interface MigrationRunView {
43
- id: string;
44
- startedAt: string;
45
- finishedAt: string | null;
46
- stuck: boolean;
47
- itemsFailed: string[];
48
- }
49
32
  /**
50
33
  * One item of the super admin's inbox (by `type`). Nothing is decided in the inbox: each item is
51
34
  * acted on where it lives (the web links to it).
@@ -56,7 +39,6 @@ export interface MigrationRunView {
56
39
  * - `org_upload_pending`: an org-owned plugin whose uploaded version (with an extension) waits for
57
40
  * the super admin in 待确认 (ruling P3-22; confirmed or rejected there), `id` = the item's;
58
41
  * - `scope_sync_failed`: an open scope sync failure, `id` = `<itemId>/<orgId>`;
59
- * - `platform_migration`: the latest migration run, failed items or stuck, `id` = the run's;
60
42
  * - `ownership_transferred`: a deleted org's shared item now belongs to the platform, until a
61
43
  * super admin dismisses it (`POST admin/inbox/notices/:id/dismiss`).
62
44
  */
@@ -80,11 +62,6 @@ export type PlatformInboxItem = {
80
62
  id: string;
81
63
  createdAt: string;
82
64
  failure: ScopeSyncFailureView;
83
- } | {
84
- type: "platform_migration";
85
- id: string;
86
- createdAt: string;
87
- run: MigrationRunView;
88
65
  } | {
89
66
  type: "ownership_transferred";
90
67
  id: string;
@@ -92,7 +69,7 @@ export type PlatformInboxItem = {
92
69
  notice: PlatformNoticeView;
93
70
  };
94
71
  /** Every {@link PlatformInboxItem} type, in the order the admin overview lists them. */
95
- export declare const PLATFORM_INBOX_TYPES: readonly ["catalog_request", "permission_confirmation", "org_upload_pending", "scope_sync_failed", "platform_migration", "ownership_transferred"];
72
+ export declare const PLATFORM_INBOX_TYPES: readonly ["catalog_request", "permission_confirmation", "org_upload_pending", "scope_sync_failed", "ownership_transferred"];
96
73
  /** How many items of each type wait: every type, zeros included. */
97
74
  export type PlatformInboxCounts = Record<PlatformInboxItem["type"], number>;
98
75
  /** An open platform notice (`platform_notices`, kind `ownership_transferred`). */
@@ -116,8 +93,8 @@ export interface PlatformInboxView {
116
93
  /**
117
94
  * The super admin's inbox (plugin scope spec §5.1 rule 5, §13.5): what waits on the platform,
118
95
  * gathered from the sources the admin pages read (the 待确认 tab's requests and permission
119
- * confirmations), plus the scope sync's open failures and the platform components migration's
120
- * latest run. Stateless, read live from PG.
96
+ * confirmations), plus the scope sync's open failures and the platform notices. Stateless, read
97
+ * live from PG.
121
98
  */
122
99
  export declare class PlatformInboxService {
123
100
  private readonly requests;
@@ -148,10 +125,4 @@ export declare class PlatformInboxService {
148
125
  private countScopeSyncFailures;
149
126
  /** The open scope sync failures ({@link failureRows}), newest first. */
150
127
  private scopeSyncFailures;
151
- /**
152
- * The latest migration run when it needs a look (see {@link MigrationRunView}); null when it
153
- * finished without failed items, is still running, or there was none. An earlier run's failure
154
- * is not shown: each run tries every unwritten item again.
155
- */
156
- private migrationRun;
157
128
  }
@@ -17,11 +17,6 @@ import { KernelDb } from "../infra/database/kernel-db.js";
17
17
  export const PLATFORM_INBOX_MAX_ITEMS = 100;
18
18
  /** The most open scope sync failures one read takes. */
19
19
  export const SCOPE_SYNC_FAILURES_LIST_MAX = 200;
20
- /**
21
- * A platform components migration run unfinished this long after its start is stuck (its worker
22
- * stopped mid-run; a run takes seconds, and the next one starts at the next worker start or day).
23
- */
24
- export const MIGRATION_RUN_STUCK_MS = 60 * 60_000;
25
20
  /** Plugin install statuses of a plugin that is on in the org. */
26
21
  const LIVE_INSTALL = ["installing", "installed", "upgrading"];
27
22
  /** Every {@link PlatformInboxItem} type, in the order the admin overview lists them. */
@@ -30,14 +25,13 @@ export const PLATFORM_INBOX_TYPES = [
30
25
  "permission_confirmation",
31
26
  "org_upload_pending",
32
27
  "scope_sync_failed",
33
- "platform_migration",
34
28
  "ownership_transferred",
35
29
  ];
36
30
  /**
37
31
  * The super admin's inbox (plugin scope spec §5.1 rule 5, §13.5): what waits on the platform,
38
32
  * gathered from the sources the admin pages read (the 待确认 tab's requests and permission
39
- * confirmations), plus the scope sync's open failures and the platform components migration's
40
- * latest run. Stateless, read live from PG.
33
+ * confirmations), plus the scope sync's open failures and the platform notices. Stateless, read
34
+ * live from PG.
41
35
  */
42
36
  let PlatformInboxService = class PlatformInboxService {
43
37
  requests;
@@ -49,13 +43,12 @@ let PlatformInboxService = class PlatformInboxService {
49
43
  this.kdb = kdb;
50
44
  }
51
45
  async list() {
52
- const [requests, requestCount, pending, failures, failureCount, run, notices, noticeCount] = await Promise.all([
46
+ const [requests, requestCount, pending, failures, failureCount, notices, noticeCount] = await Promise.all([
53
47
  this.requests.listDeployment(),
54
48
  this.requests.countPendingDeployment(),
55
49
  this.catalog.list({ pending: true }),
56
50
  this.scopeSyncFailures(),
57
51
  this.countScopeSyncFailures(),
58
- this.migrationRun(),
59
52
  this.notices(),
60
53
  this.countNotices(),
61
54
  ]);
@@ -84,16 +77,6 @@ let PlatformInboxService = class PlatformInboxService {
84
77
  createdAt: n.createdAt,
85
78
  notice: n,
86
79
  })),
87
- ...(run === null
88
- ? []
89
- : [
90
- {
91
- type: "platform_migration",
92
- id: run.id,
93
- createdAt: run.finishedAt ?? run.startedAt,
94
- run,
95
- },
96
- ]),
97
80
  ];
98
81
  // newest first; equal times by id (a stable order)
99
82
  all.sort((a, b) => a.createdAt !== b.createdAt
@@ -111,7 +94,6 @@ let PlatformInboxService = class PlatformInboxService {
111
94
  permission_confirmation: pending.length - orgUploads,
112
95
  org_upload_pending: orgUploads,
113
96
  scope_sync_failed: failureCount,
114
- platform_migration: run === null ? 0 : 1,
115
97
  ownership_transferred: noticeCount,
116
98
  };
117
99
  const total = Object.values(byType).reduce((a, b) => a + b, 0);
@@ -123,14 +105,13 @@ let PlatformInboxService = class PlatformInboxService {
123
105
  * requests and the failures; the permission confirmations are the catalog's pending list).
124
106
  */
125
107
  async count() {
126
- const [requests, pending, failures, run, notices] = await Promise.all([
108
+ const [requests, pending, failures, notices] = await Promise.all([
127
109
  this.requests.countPendingDeployment(),
128
110
  this.catalog.list({ pending: true }),
129
111
  this.countScopeSyncFailures(),
130
- this.migrationRun(),
131
112
  this.countNotices(),
132
113
  ]);
133
- return requests + pending.length + failures + (run === null ? 0 : 1) + notices;
114
+ return requests + pending.length + failures + notices;
134
115
  }
135
116
  async countNotices() {
136
117
  const r = await this.kdb.db
@@ -240,36 +221,6 @@ let PlatformInboxService = class PlatformInboxService {
240
221
  failedAt: r.failed_at.toISOString(),
241
222
  }));
242
223
  }
243
- /**
244
- * The latest migration run when it needs a look (see {@link MigrationRunView}); null when it
245
- * finished without failed items, is still running, or there was none. An earlier run's failure
246
- * is not shown: each run tries every unwritten item again.
247
- */
248
- async migrationRun() {
249
- const run = await this.kdb.db
250
- .selectFrom("platform_migration_runs")
251
- .select(["id", "started_at", "finished_at", "stats"])
252
- .orderBy("started_at", "desc")
253
- .orderBy("id", "desc")
254
- .limit(1)
255
- .executeTakeFirst();
256
- if (run === undefined)
257
- return null;
258
- const failed = run.stats.itemsFailed;
259
- const itemsFailed = Array.isArray(failed)
260
- ? failed.filter((x) => typeof x === "string")
261
- : [];
262
- const stuck = run.finished_at === null && run.started_at.getTime() < Date.now() - MIGRATION_RUN_STUCK_MS;
263
- if (!stuck && (run.finished_at === null || itemsFailed.length === 0))
264
- return null;
265
- return {
266
- id: run.id,
267
- startedAt: run.started_at.toISOString(),
268
- finishedAt: run.finished_at?.toISOString() ?? null,
269
- stuck,
270
- itemsFailed,
271
- };
272
- }
273
224
  };
274
225
  PlatformInboxService = __decorate([
275
226
  Injectable(),
@@ -66,6 +66,37 @@ export declare const OUTBOX_JOBS: {
66
66
  readonly removeOnFail: true;
67
67
  };
68
68
  };
69
+ readonly "run-stop": {
70
+ readonly queue: "cap-kernel-maintenance";
71
+ readonly idempotent: "stopping a finished run is a no-op";
72
+ readonly processedIn: "packages/kernel/src/runtime/maintenance.ts";
73
+ readonly opts: {
74
+ readonly attempts: 5;
75
+ readonly backoff: {
76
+ readonly type: "exponential";
77
+ readonly delay: 5000;
78
+ };
79
+ readonly removeOnComplete: true;
80
+ readonly removeOnFail: {
81
+ readonly age: number;
82
+ readonly count: 1000;
83
+ };
84
+ };
85
+ };
86
+ readonly "sandbox-destroy-for": {
87
+ readonly queue: "cap-kernel-maintenance";
88
+ readonly idempotent: "destroying a destroyed device is a no-op";
89
+ readonly processedIn: "packages/kernel/src/runtime/maintenance.ts";
90
+ readonly opts: {
91
+ readonly attempts: 5;
92
+ readonly backoff: {
93
+ readonly type: "exponential";
94
+ readonly delay: 30000;
95
+ };
96
+ readonly removeOnComplete: true;
97
+ readonly removeOnFail: 100;
98
+ };
99
+ };
69
100
  readonly "deliver-to-parent": {
70
101
  readonly queue: "cap-kernel-maintenance";
71
102
  readonly idempotent: "the delivery's idempotency key is the child run id";
@@ -114,6 +145,99 @@ export declare const OUTBOX_JOBS: {
114
145
  readonly removeOnFail: true;
115
146
  };
116
147
  };
148
+ readonly "scope-item": {
149
+ readonly queue: "cap-kernel-plugin-scope";
150
+ readonly idempotent: "the sync converges each (item, org) from the scope, switches and installs it reads under the org's lock, and the installer re-checks under the org row lock, so a second run changes nothing";
151
+ readonly processedIn: "packages/kernel/src/catalog/scope-sync-workers.ts";
152
+ readonly opts: {
153
+ readonly attempts: 1;
154
+ readonly removeOnComplete: true;
155
+ readonly removeOnFail: true;
156
+ };
157
+ };
158
+ readonly "scope-item-backstop": {
159
+ readonly queue: "cap-kernel-plugin-scope";
160
+ readonly idempotent: "the sync converges each (item, org) from what it reads, as a scope-item job does, so a run after the immediate job changes nothing";
161
+ readonly processedIn: "packages/kernel/src/catalog/scope-sync-workers.ts";
162
+ readonly opts: {
163
+ readonly attempts: 5;
164
+ readonly backoff: {
165
+ readonly type: "exponential";
166
+ readonly delay: 60000;
167
+ };
168
+ readonly removeOnComplete: true;
169
+ readonly removeOnFail: true;
170
+ };
171
+ };
172
+ readonly "scope-org": {
173
+ readonly queue: "cap-kernel-plugin-scope";
174
+ readonly idempotent: "the sync converges each (item, org) of the org from what it reads, so a second run changes nothing";
175
+ readonly processedIn: "packages/kernel/src/catalog/scope-sync-workers.ts";
176
+ readonly opts: {
177
+ readonly attempts: 1;
178
+ readonly removeOnComplete: true;
179
+ readonly removeOnFail: true;
180
+ };
181
+ };
182
+ readonly "owned-plugin-cleanup": {
183
+ readonly queue: "cap-kernel-maintenance";
184
+ readonly idempotent: "the cleanup takes the extension out only while no live item uses it, and a missing install or a released claim changes nothing";
185
+ readonly processedIn: "packages/kernel/src/runtime/maintenance.ts";
186
+ readonly opts: {
187
+ readonly attempts: 3;
188
+ readonly backoff: {
189
+ readonly type: "exponential";
190
+ readonly delay: 5000;
191
+ };
192
+ readonly removeOnComplete: true;
193
+ readonly removeOnFail: true;
194
+ };
195
+ };
196
+ readonly "sched-fire": {
197
+ readonly queue: "cap-kernel-maintenance";
198
+ readonly idempotent: "a fire acts only on a pending task run, under its row lock; a retried start reuses what the first one made";
199
+ readonly processedIn: "packages/kernel/src/runtime/maintenance.ts";
200
+ readonly opts: {
201
+ readonly attempts: 3;
202
+ readonly backoff: {
203
+ readonly type: "exponential";
204
+ readonly delay: 2000;
205
+ };
206
+ readonly removeOnComplete: true;
207
+ readonly removeOnFail: true;
208
+ };
209
+ };
210
+ readonly "sched-settle": {
211
+ readonly queue: "cap-kernel-maintenance";
212
+ readonly idempotent: "a check acts only on a task run still pending (claimed for the claimed check, unclaimed for the unfired one), under the task and run row locks, so a run claimed, started, ended or skipped since is left as it is";
213
+ readonly processedIn: "packages/kernel/src/runtime/maintenance.ts";
214
+ readonly opts: {
215
+ readonly attempts: 5;
216
+ readonly backoff: {
217
+ readonly type: "exponential";
218
+ readonly delay: 5000;
219
+ };
220
+ readonly removeOnComplete: true;
221
+ readonly removeOnFail: true;
222
+ };
223
+ };
224
+ readonly lifecycle: {
225
+ readonly queue: "cap-kernel-lifecycle";
226
+ readonly idempotent: "lifecycle handlers must be idempotent (the SDK contract): they delete what the plugin holds for the removed member, agent or org, and deleting it again is a no-op";
227
+ readonly processedIn: "packages/kernel/src/extensions/lifecycle-hooks.ts";
228
+ readonly opts: {
229
+ readonly attempts: 15;
230
+ readonly backoff: {
231
+ readonly type: "exponential";
232
+ readonly delay: 2000;
233
+ };
234
+ readonly removeOnComplete: true;
235
+ readonly removeOnFail: {
236
+ readonly age: number;
237
+ readonly count: 1000;
238
+ };
239
+ };
240
+ };
117
241
  };
118
242
  export type OutboxJobName = keyof typeof OUTBOX_JOBS;
119
243
  /** The registry's BullMQ options of a job name (none for a name it does not list). */