@camstack/addon-post-analysis 1.2.351 → 1.2.353

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 (15) hide show
  1. package/dist/{clip-model-registry-DI12tTgY.js → clip-model-registry-CPNsQNt5.js} +302 -158
  2. package/dist/{clip-model-registry-CC-BJYiK.mjs → clip-model-registry-VI28etdt.mjs} +302 -158
  3. package/dist/embedding-encoder/index.js +1 -1
  4. package/dist/embedding-encoder/index.mjs +1 -1
  5. package/dist/pipeline-analytics/_stub.js +2 -2
  6. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-5v6z6gQL.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Cfcb9thb.mjs} +2 -2
  7. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-N64PaPIw.mjs +26 -0
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Clwp5JZq.mjs +26 -0
  9. package/dist/pipeline-analytics/{hostInit-BKDWAGHG.mjs → hostInit-DpCJPMQZ.mjs} +2 -2
  10. package/dist/pipeline-analytics/index.js +678 -942
  11. package/dist/pipeline-analytics/index.mjs +678 -942
  12. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  13. package/package.json +1 -1
  14. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Du_tzgi2.mjs +0 -26
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQOJKiwa.mjs +0 -26
@@ -5480,7 +5480,7 @@ var ZodIssueCode = {
5480
5480
  var ZodFirstPartyTypeKind;
5481
5481
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5482
5482
  //#endregion
5483
- //#region ../types/dist/sleep-r3RWkGVx.mjs
5483
+ //#region ../types/dist/sleep-CI0n5D44.mjs
5484
5484
  /**
5485
5485
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5486
5486
  * window to float samples (D455).
@@ -9970,6 +9970,16 @@ var CompositionSchema = object({
9970
9970
  seen.add(feature.cap);
9971
9971
  });
9972
9972
  });
9973
+ var NodeColorIdSchema = _enum([
9974
+ "node-a",
9975
+ "node-b",
9976
+ "node-c",
9977
+ "node-d",
9978
+ "node-e",
9979
+ "node-f",
9980
+ "node-g",
9981
+ "node-h"
9982
+ ]);
9973
9983
  var OWNER_TYPES = new Set([
9974
9984
  "track",
9975
9985
  "face",
@@ -28981,24 +28991,69 @@ var RetrainFrameListSchema = object({
28981
28991
  /** What the page pre-selects — the native key frame when one survives. */
28982
28992
  autoPickMediaId: number().int().optional()
28983
28993
  });
28994
+ /** Exclusive partition of a corpus copy's annotation progress (design §4.2). */
28995
+ var RetrainFrameWorkStateSchema = _enum([
28996
+ "unannotated",
28997
+ "annotated",
28998
+ "complete"
28999
+ ]);
29000
+ /**
29001
+ * Filters for paginated corpus list, KPI, and matching export (design §4.4).
29002
+ * Every narrowing field is ANDed; omitted fields impose no constraint.
29003
+ */
29004
+ var RetrainCorpusFilterSchema = object({
29005
+ workState: RetrainFrameWorkStateSchema.optional(),
29006
+ deviceIds: array(number()).max(500).optional(),
29007
+ /** When set, only frames in this named collection. */
29008
+ collectionId: string().optional(),
29009
+ /** Frames that carry at least one saved annotation in one of these classes. */
29010
+ classes: array(RetrainMacroClassSchema).optional(),
29011
+ page: number().int().positive().default(1),
29012
+ pageSize: number().int().positive().max(100).default(50)
29013
+ });
29014
+ var RetrainCorpusPageSchema = object({
29015
+ frames: array(RetrainFrameSchema.extend({ workState: RetrainFrameWorkStateSchema })).readonly(),
29016
+ total: number().int().nonnegative(),
29017
+ page: number().int().positive(),
29018
+ pageSize: number().int().positive()
29019
+ });
29020
+ var RetrainCorpusKpiCameraRowSchema = object({
29021
+ deviceId: number(),
29022
+ unannotated: number().int().nonnegative(),
29023
+ annotated: number().int().nonnegative(),
29024
+ complete: number().int().nonnegative(),
29025
+ /** This camera's `complete` count divided by corpus `total`, in `[0,1]`.
29026
+ * `null` when the corpus is empty (no ratio). */
29027
+ pctOfCorpus: number().min(0).max(1).nullable()
29028
+ });
29029
+ var RetrainCorpusKpiSchema = object({
29030
+ total: number().int().nonnegative(),
29031
+ unannotated: number().int().nonnegative(),
29032
+ annotated: number().int().nonnegative(),
29033
+ complete: number().int().nonnegative(),
29034
+ cameras: array(RetrainCorpusKpiCameraRowSchema).readonly()
29035
+ });
28984
29036
  /**
28985
29037
  * Which frames an annotated export carries. Every field narrows; an empty
28986
- * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
28987
- * list owned by whoever trains (the training orchestrator), so `frameIds` is
28988
- * the primitive a version export uses; `batchId` re-selects what an earlier
28989
- * export carried (`exportedInBatch`).
29038
+ * filter is every annotated copy. `frameIds` is the primitive a job or
29039
+ * download uses; `batchId` re-selects what an earlier export carried
29040
+ * (`exportedInBatch`). Frozen dataset versions were removed — live selection
29041
+ * resolves to `frameIds` at plan/start.
28990
29042
  */
28991
29043
  var RetrainExportFilterSchema = object({
28992
29044
  deviceIds: array(number()).optional(),
28993
29045
  frameIds: array(string()).max(2e4).optional(),
28994
29046
  /** Only frames in at least one of these named collections. */
28995
29047
  collectionIds: array(string()).max(200).optional(),
28996
- /** Exactly the frames of this dataset version (and its completeOnly). An
28997
- * unknown id selects nothing. */
28998
- datasetVersionId: string().optional(),
29048
+ /** Single collection (Frames filter bar). ANDed with `collectionIds` when both set. */
29049
+ collectionId: string().optional(),
28999
29050
  batchId: string().optional(),
29000
29051
  /** Only frames the operator marked complete (all subjects boxed). */
29001
- completeOnly: boolean().optional()
29052
+ completeOnly: boolean().optional(),
29053
+ /** Exclusive work-state partition (`workStateOf`); same as the corpus list. */
29054
+ workState: RetrainFrameWorkStateSchema.optional(),
29055
+ /** Frames with at least one saved annotation in one of these classes. */
29056
+ classes: array(RetrainMacroClassSchema).optional()
29002
29057
  });
29003
29058
  /**
29004
29059
  * `frames`: the full frame copies, boxes in `annotations.json`.
@@ -29198,8 +29253,7 @@ var RetrainDatasetStatsSchema = object({
29198
29253
  completeFrames: number().int()
29199
29254
  })).readonly()
29200
29255
  });
29201
- /** An immutable dataset version, without its frame list. */
29202
- var RetrainDatasetVersionSchema = object({
29256
+ object({
29203
29257
  id: string(),
29204
29258
  name: string(),
29205
29259
  createdAt: number(),
@@ -29207,22 +29261,33 @@ var RetrainDatasetVersionSchema = object({
29207
29261
  layout: RetrainExportLayoutSchema,
29208
29262
  completeOnly: boolean(),
29209
29263
  frameCount: number().int(),
29210
- /** sha256 of what the frames taught when the version was frozen. */
29211
29264
  annotationHash: string(),
29212
- /** The export manifest schema the version was cut under. */
29213
29265
  manifestSchema: string(),
29214
29266
  stats: RetrainDatasetStatsSchema
29215
29267
  });
29216
- var CreateRetrainDatasetVersionResultSchema = discriminatedUnion("kind", [object({
29217
- kind: literal("created"),
29218
- version: RetrainDatasetVersionSchema
29268
+ /**
29269
+ * Live training corpus criteria — same shape as `TrainingCorpusSelection` on
29270
+ * the training cap. Resolved here so plan/start and the annotated export share
29271
+ * one definition of "the frames" (`buildRetrainExportPlan`).
29272
+ */
29273
+ var RetrainTrainingCorpusSelectionSchema = object({
29274
+ collectionIds: array(string()).min(1),
29275
+ workState: _enum([
29276
+ "complete",
29277
+ "annotated_or_complete",
29278
+ "any_annotated"
29279
+ ]).default("complete")
29280
+ });
29281
+ var RetrainTrainingCorpusResolveResultSchema = discriminatedUnion("kind", [object({
29282
+ kind: literal("resolved"),
29283
+ frameIds: array(string()).max(2e4).readonly(),
29284
+ stats: RetrainDatasetStatsSchema,
29285
+ annotationHash: string(),
29286
+ layout: RetrainExportLayoutSchema
29219
29287
  }), object({
29220
29288
  kind: literal("refused"),
29221
- reason: _enum([
29222
- "empty-name",
29223
- "duplicate-name",
29224
- "no-frames"
29225
- ])
29289
+ reason: _enum(["unknown-collection", "no-frames"]),
29290
+ detail: string()
29226
29291
  })]);
29227
29292
  /** The outcome of a lifecycle move owned by the retrain page. */
29228
29293
  var RetrainTransitionResultSchema = object({
@@ -30398,6 +30463,26 @@ var pipelineAnalyticsCapability = {
30398
30463
  auth: "admin"
30399
30464
  }),
30400
30465
  /**
30466
+ * Paginated corpus copies for the Frames grid — index reads only.
30467
+ *
30468
+ * Filters AND (`workState`, cameras, one collection, annotated classes).
30469
+ * An answered empty match is `{ frames: [], total: 0, … }` (D315), never a
30470
+ * pending masquerade. Classification uses `workStateOf` (annotation count
30471
+ * wins over a stray `complete` flag).
30472
+ */
30473
+ listRetrainCorpusPage: method(RetrainCorpusFilterSchema, RetrainCorpusPageSchema, {
30474
+ kind: "query",
30475
+ auth: "admin"
30476
+ }),
30477
+ /**
30478
+ * Global + per-camera corpus KPI. Unfiltered totals; `%` on a camera row is
30479
+ * `complete(camera) / corpus total`, or `null` when the corpus is empty.
30480
+ */
30481
+ getRetrainCorpusKpi: method(object({}), RetrainCorpusKpiSchema, {
30482
+ kind: "query",
30483
+ auth: "admin"
30484
+ }),
30485
+ /**
30401
30486
  * What a track can contribute, and what it already has.
30402
30487
  *
30403
30488
  * `candidates` are the track's whole, unannotated frames — index rows only,
@@ -30624,53 +30709,6 @@ var pipelineAnalyticsCapability = {
30624
30709
  auth: "admin",
30625
30710
  timeoutMs: 12e4
30626
30711
  }),
30627
- /** The counts a selection would freeze — class × camera × day/night,
30628
- * completeness — without freezing anything. Index reads only. */
30629
- previewRetrainDataset: method(object({
30630
- selection: RetrainDatasetSelectionSchema,
30631
- completeOnly: boolean().optional()
30632
- }), RetrainDatasetStatsSchema, {
30633
- kind: "query",
30634
- auth: "admin"
30635
- }),
30636
- /**
30637
- * Freeze a dataset version: the frames the selection yields (the same plan
30638
- * the annotated export builds), the hash of what they teach, the export
30639
- * parameters and the counts. Immutable — a different selection is a new
30640
- * version. Export it with `getRetrainExportUrl({ datasetVersionId })`.
30641
- */
30642
- createRetrainDatasetVersion: method(object({
30643
- name: string().max(120),
30644
- selection: RetrainDatasetSelectionSchema,
30645
- layout: RetrainExportLayoutSchema,
30646
- completeOnly: boolean()
30647
- }), CreateRetrainDatasetVersionResultSchema, {
30648
- kind: "mutation",
30649
- auth: "admin",
30650
- timeoutMs: 12e4
30651
- }),
30652
- /** Every dataset version, newest first. */
30653
- listRetrainDatasetVersions: method(object({}), array(RetrainDatasetVersionSchema).readonly(), {
30654
- kind: "query",
30655
- auth: "admin"
30656
- }),
30657
- /** Delete a version. Its frames stay in the dataset. */
30658
- deleteRetrainDatasetVersion: method(object({ id: string() }), object({ deleted: boolean() }), {
30659
- kind: "mutation",
30660
- auth: "admin"
30661
- }),
30662
- /** Does the corpus still teach what the version froze? `missingFrames`
30663
- * counts frames that left the dataset (or lost every box and tick). */
30664
- verifyRetrainDatasetVersion: method(object({ id: string() }), object({
30665
- found: boolean(),
30666
- annotationHash: string(),
30667
- matches: boolean(),
30668
- missingFrames: number().int()
30669
- }), {
30670
- kind: "query",
30671
- auth: "admin",
30672
- timeoutMs: 12e4
30673
- }),
30674
30712
  /** The enabled, vision-capable LLM profiles, each saying whether a frame
30675
30713
  * sent to it leaves the house. */
30676
30714
  listRetrainAssistProfiles: method(object({}), array(RetrainAssistProfileSchema).readonly(), {
@@ -30717,6 +30755,16 @@ var pipelineAnalyticsCapability = {
30717
30755
  kind: "query",
30718
30756
  auth: "admin"
30719
30757
  }),
30758
+ /**
30759
+ * Resolve a live training corpus selection to frame ids + stats (index
30760
+ * reads only). Same plan the annotated export builds — training plan/start
30761
+ * calls this instead of a frozen dataset version.
30762
+ */
30763
+ resolveRetrainTrainingCorpus: method(RetrainTrainingCorpusSelectionSchema, RetrainTrainingCorpusResolveResultSchema, {
30764
+ kind: "query",
30765
+ auth: "admin",
30766
+ timeoutMs: 6e4
30767
+ }),
30720
30768
  renameRetrainCollection: method(object({
30721
30769
  id: string(),
30722
30770
  name: string().max(120)
@@ -31670,11 +31718,14 @@ var HardwareClassIdSchema = _enum([
31670
31718
  "intel-n-series",
31671
31719
  "apple-m-base",
31672
31720
  "apple-m-pro",
31721
+ "amd-phoenix",
31673
31722
  "unknown"
31674
31723
  ]);
31675
31724
  var AcceleratorKindSchema = _enum([
31676
31725
  "intel-npu",
31677
31726
  "intel-igpu",
31727
+ "amd-igpu",
31728
+ "amd-npu",
31678
31729
  "x86-cpu",
31679
31730
  "arm-cpu",
31680
31731
  "apple-ane",
@@ -33810,6 +33861,8 @@ var AgentPipelineSettingsSchema = object({
33810
33861
  * address is wrong (multi-homed host, NAT, custom interface).
33811
33862
  */
33812
33863
  reachableHost: string().optional(),
33864
+ /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
33865
+ color: NodeColorIdSchema.optional(),
33813
33866
  /**
33814
33867
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
33815
33868
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
@@ -34536,8 +34589,9 @@ var pipelineOrchestratorCapability = {
34536
34589
  */
34537
34590
  setAgentReachableHost: method(object({
34538
34591
  agentNodeId: string(),
34539
- reachableHost: string().nullable()
34540
- }), object({ success: literal(true) }), {
34592
+ reachableHost: string().nullable().optional(),
34593
+ color: NodeColorIdSchema.nullable().optional()
34594
+ }).refine((v) => v.reachableHost !== void 0 || v.color !== void 0, { message: "reachableHost or color required" }), object({ success: literal(true) }), {
34541
34595
  kind: "mutation",
34542
34596
  auth: "admin"
34543
34597
  }),
@@ -45641,7 +45695,15 @@ var GpuInfoSchema = object({
45641
45695
  name: string(),
45642
45696
  memoryMB: number().optional()
45643
45697
  });
45644
- var NpuInfoSchema = object({ type: _enum(["apple-ane", "intel-npu"]) });
45698
+ var NpuInfoSchema = object({
45699
+ type: _enum([
45700
+ "apple-ane",
45701
+ "intel-npu",
45702
+ "amd-xdna"
45703
+ ]),
45704
+ name: string().optional(),
45705
+ generation: _enum(["xdna1", "xdna2"]).optional()
45706
+ });
45645
45707
  var CoralInfoSchema = object({
45646
45708
  type: literal("coral-edgetpu"),
45647
45709
  bus: string().optional()
@@ -51018,9 +51080,11 @@ var zoneRulesCapability = {
51018
51080
  * once is what makes a second provider (RunPod, a local NVIDIA node) a new
51019
51081
  * manifest entry and nothing else.
51020
51082
  *
51021
- * Collection, routed by the `addonId` in every single-row input (the `llm` /
51022
- * `notification-output` posture); `describe` concat-fans across providers.
51023
- * Every method is `admin`: these spend money.
51083
+ * Collection of provider **types** (addons). Each addon owns zero or more
51084
+ * **entries** (credentials + defaults). Concat-fans: `describe`,
51085
+ * `describeTypes`, `listEntries`, `listJobs`. Single-row work is keyed by
51086
+ * `entryId`; callers also pass the owning `addonId` as the collection
51087
+ * selector (broker posture). Every method is `admin`: these spend money.
51024
51088
  *
51025
51089
  * Every cloud object a provider creates is tagged with the orchestrator's
51026
51090
  * `jobKey`, so a retried submit finds the job it already started instead of
@@ -51044,8 +51108,8 @@ var TrainingRegionOptionSchema = object({
51044
51108
  priceMultiplier: number().positive()
51045
51109
  });
51046
51110
  /**
51047
- * The provider's per-account settings, as the orchestrator reads them. They
51048
- * live in the PROVIDER addon's settings (operator decision 2026-10-08: they
51111
+ * The provider's per-entry settings, as the orchestrator reads them. They
51112
+ * live on the PROVIDER addon's entry (operator decision 2026-10-08: they
51049
51113
  * depend on the user's account), never hard-coded in the orchestrator.
51050
51114
  */
51051
51115
  var TrainingProviderDefaultsSchema = object({
@@ -51056,9 +51120,32 @@ var TrainingProviderDefaultsSchema = object({
51056
51120
  /** Hours a FAILED job's cloud dataset is kept for debugging; 0 = delete at once. */
51057
51121
  failedDatasetGraceHours: number().nonnegative()
51058
51122
  });
51123
+ /** One creatable provider type, for the Add-entry dialog. */
51124
+ var TrainingProviderTypeSchema = object({
51125
+ typeId: string(),
51126
+ label: string(),
51127
+ /** Path under the addon package (e.g. `assets/training-modal/icon.svg`). */
51128
+ iconAsset: string(),
51129
+ /** Owning `training-provider` addon — collection selector for createEntry. */
51130
+ addonId: string()
51131
+ });
51132
+ /** One configured account / workspace under a provider type. */
51133
+ var TrainingProviderEntrySchema = object({
51134
+ entryId: string(),
51135
+ typeId: string(),
51136
+ name: string(),
51137
+ addonId: string(),
51138
+ /** Credentials are present — never the values. */
51139
+ configured: boolean()
51140
+ });
51059
51141
  var TrainingProviderDescriptorSchema = object({
51060
51142
  addonId: string(),
51061
- /** `modal`, `runpod`, `fake`, … */
51143
+ entryId: string(),
51144
+ typeId: string(),
51145
+ /** Operator-chosen entry name. */
51146
+ name: string(),
51147
+ iconAsset: string(),
51148
+ /** `modal`, `runpod`, `fake`, … — same as typeId for current providers. */
51062
51149
  kind: string(),
51063
51150
  label: string(),
51064
51151
  gpuTypes: array(TrainingGpuOptionSchema).readonly(),
@@ -51122,8 +51209,9 @@ var TrainerSourceRefSchema = object({
51122
51209
  /** A commit sha (never a branch) — the job must be reproducible. */
51123
51210
  revision: string().regex(/^[0-9a-f]{7,64}$/)
51124
51211
  });
51212
+ /** Cloud job identity — route with the owning addon's `addonId` selector. */
51125
51213
  var JobRef = {
51126
- addonId: string(),
51214
+ entryId: string().min(1),
51127
51215
  jobKey: string().uuid()
51128
51216
  };
51129
51217
  var TrainingLogLineSchema = object({
@@ -51136,17 +51224,37 @@ var trainingProviderCapability = {
51136
51224
  mode: "collection",
51137
51225
  internal: true,
51138
51226
  methods: {
51139
- /** Every provider's offer and settings. Concat-fans across providers. */
51227
+ /** Every entry's offer and settings. Concat-fans across providers. */
51140
51228
  describe: method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "admin" }),
51141
- /** Call the provider with the stored credentials. Never returns them. */
51142
- validateCredentials: method(object({ addonId: string() }), TrainingCredentialCheckSchema, {
51229
+ /** Creatable types for the Add-entry dialog. Concat-fans. */
51230
+ describeTypes: method(object({}), array(TrainingProviderTypeSchema).readonly(), { auth: "admin" }),
51231
+ /** Configured entries (pills). Concat-fans. */
51232
+ listEntries: method(object({}), array(TrainingProviderEntrySchema).readonly(), { auth: "admin" }),
51233
+ /**
51234
+ * Create an entry under this provider type. Pin with `{ addonId }` of the
51235
+ * type's owning addon (from describeTypes).
51236
+ */
51237
+ createEntry: method(object({
51238
+ typeId: string().min(1),
51239
+ name: string().min(1)
51240
+ }), object({ entryId: string() }), {
51241
+ kind: "mutation",
51242
+ auth: "admin"
51243
+ }),
51244
+ /** Delete an entry. Pin with the owning `{ addonId }`. */
51245
+ deleteEntry: method(object({ entryId: string().min(1) }), object({ ok: literal(true) }), {
51246
+ kind: "mutation",
51247
+ auth: "admin"
51248
+ }),
51249
+ /** Call the provider with the entry's stored credentials. Never returns them. */
51250
+ validateCredentials: method(object({ entryId: string().min(1) }), TrainingCredentialCheckSchema, {
51143
51251
  kind: "mutation",
51144
51252
  auth: "admin",
51145
51253
  timeoutMs: 3e4
51146
51254
  }),
51147
51255
  /** USD range for a run of `gpuSeconds` on `gpuType` in `region`. */
51148
51256
  estimateJob: method(object({
51149
- addonId: string(),
51257
+ entryId: string().min(1),
51150
51258
  gpuType: string(),
51151
51259
  region: string(),
51152
51260
  datasetBytes: number().int().nonnegative(),
@@ -51242,8 +51350,11 @@ var trainingProviderCapability = {
51242
51350
  auth: "admin",
51243
51351
  timeoutMs: 5 * 6e4
51244
51352
  }),
51245
- /** Every job the provider can still see — the orphan sweep diffs it against our records. */
51246
- listJobs: method(object({ addonId: string() }), array(ProviderJobStatusSchema).readonly(), {
51353
+ /**
51354
+ * Jobs this provider can still see. Optional `entryId` filters; omit to
51355
+ * list every entry (orphan sweep). Pin with `{ addonId }`.
51356
+ */
51357
+ listJobs: method(object({ entryId: string().min(1).optional() }), array(ProviderJobStatusSchema).readonly(), {
51247
51358
  auth: "admin",
51248
51359
  timeoutMs: 2 * 6e4
51249
51360
  })
@@ -51255,20 +51366,31 @@ var trainingProviderCapability = {
51255
51366
  *
51256
51367
  * It owns what every provider must agree on, written once:
51257
51368
  *
51258
- * - **Dataset versions.** Taken over from pipeline-analytics (D796): the rows
51259
- * live here (D808); pipeline-analytics still CUTS a version (it owns the corpus and
51260
- * the export plan) and reaches this store through the five row methods
51261
- * below, so the Retrain page and the export did not change.
51262
51369
  * - **Jobs.** A persisted state machine, a reconcile loop against the
51263
51370
  * provider, a cost guard, a daily orphan sweep and the retention rules.
51264
51371
  * - **The return flow.** Verified artefacts → Model Studio
51265
51372
  * (`custom-model-registry.importModelBundle`) → canary on cameras →
51266
51373
  * rollback. Nothing is ever registered automatically.
51267
51374
  *
51375
+ * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
51376
+ * work-state rule); frame ids are resolved via pipeline-analytics at that
51377
+ * moment and snapshotted on the job. No frozen dataset version.
51378
+ *
51268
51379
  * Every method is `admin`.
51269
51380
  */
51270
- /** A version WITH its frame list — what the export and a job read. */
51271
- var TrainingDatasetVersionRowSchema = RetrainDatasetVersionSchema.omit({ frameCount: true }).extend({ frameIds: array(string()).max(2e4).readonly() });
51381
+ /**
51382
+ * Live corpus criteria for plan/start (design §5.2). Default is complete-only.
51383
+ * Frame ids are resolved at plan/start — never a frozen version id.
51384
+ */
51385
+ var TrainingCorpusSelectionSchema = object({
51386
+ collectionIds: array(string()).min(1),
51387
+ /** Default complete-only for v1 */
51388
+ workState: _enum([
51389
+ "complete",
51390
+ "annotated_or_complete",
51391
+ "any_annotated"
51392
+ ]).default("complete")
51393
+ });
51272
51394
  /** A base model a detector job can fine-tune, and the baseline it is judged against. */
51273
51395
  var TrainingBaseModelSchema = object({
51274
51396
  modelId: string(),
@@ -51286,9 +51408,13 @@ var TrainingPresetSchema = _enum([
51286
51408
  "thorough"
51287
51409
  ]);
51288
51410
  var TrainingJobRequestSchema = object({
51289
- datasetVersionId: string().min(1),
51290
- /** The `training-provider` addon that runs it. */
51291
- addonId: string().min(1),
51411
+ /** Live collection + work-state criteria; resolved at plan/start. */
51412
+ selection: TrainingCorpusSelectionSchema,
51413
+ /**
51414
+ * The provider **entry** that runs it (credentials + defaults).
51415
+ * Resolve to an owning addon via `training-provider.describe` / `listEntries`.
51416
+ */
51417
+ entryId: string().min(1),
51292
51418
  gpuType: string().min(1),
51293
51419
  region: string(),
51294
51420
  baseModelId: string().min(1),
@@ -51347,6 +51473,7 @@ var TrainingJobPlanSchema = object({
51347
51473
  * result lives after the operator acted on it.
51348
51474
  */
51349
51475
  var TrainingJobStateSchema = _enum([
51476
+ "queued",
51350
51477
  "uploading",
51351
51478
  "submitted",
51352
51479
  "starting",
@@ -51400,6 +51527,11 @@ var TrainingJobSchema = object({
51400
51527
  createdAt: number(),
51401
51528
  updatedAt: number(),
51402
51529
  state: TrainingJobStateSchema,
51530
+ /**
51531
+ * Shared by every job enqueued together via `startJobBatch`.
51532
+ * `null` for a lone `startJob`. The engine advances queued siblings by this id.
51533
+ */
51534
+ batchId: string().nullable().default(null),
51403
51535
  stage: TrainingStageSchema.nullable(),
51404
51536
  failure: object({
51405
51537
  reason: TrainingFailureReasonSchema,
@@ -51411,6 +51543,12 @@ var TrainingJobSchema = object({
51411
51543
  maxRuntimeSec: number().int().positive(),
51412
51544
  trainer: TrainerSourceRefSchema,
51413
51545
  datasetLayout: RetrainExportLayoutSchema,
51546
+ /** Frame count snapshotted when the job started (audit; equals `frameIds.length`). */
51547
+ frameCount: number().int().nonnegative(),
51548
+ /** Resolved frame ids at start — the archive ships exactly these. */
51549
+ frameIds: array(string()).max(2e4).readonly(),
51550
+ /** Hash of what those frames taught at start (trainer `dataset.annotationHash`). */
51551
+ annotationHash: string(),
51414
51552
  dataset: object({
51415
51553
  bytes: number().int(),
51416
51554
  sha256: string(),
@@ -51458,19 +51596,6 @@ var trainingCapability = {
51458
51596
  mode: "singleton",
51459
51597
  mount: { kind: "hub-only" },
51460
51598
  methods: {
51461
- /** Store a version once. `stored: false` = that id already exists (immutable). */
51462
- putDatasetVersion: method(TrainingDatasetVersionRowSchema, object({ stored: boolean() }), {
51463
- kind: "mutation",
51464
- auth: "admin"
51465
- }),
51466
- getDatasetVersion: method(IdInput, TrainingDatasetVersionRowSchema.nullable(), { auth: "admin" }),
51467
- /** Every version without its frame list, newest first. */
51468
- listDatasetVersions: method(object({}), array(RetrainDatasetVersionSchema).readonly(), { auth: "admin" }),
51469
- findDatasetVersionIdByName: method(object({ name: string() }), object({ id: string().nullable() }), { auth: "admin" }),
51470
- removeDatasetVersion: method(IdInput, object({ removed: boolean() }), {
51471
- kind: "mutation",
51472
- auth: "admin"
51473
- }),
51474
51599
  listBaseModels: method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" }),
51475
51600
  /** Split, estimate, defaults and any named refusal — nothing is started. */
51476
51601
  planJob: method(TrainingJobRequestSchema, TrainingJobPlanSchema, {
@@ -51499,6 +51624,32 @@ var trainingCapability = {
51499
51624
  auth: "admin",
51500
51625
  timeoutMs: 12e4
51501
51626
  }),
51627
+ /**
51628
+ * Enqueue one job per base model (same selection, entry, caps). The first
51629
+ * becomes `uploading`; the rest stay `queued` until the prior job settles.
51630
+ * One ACTIVE job at a time — a parallel `startJob` still gets
51631
+ * `job-already-running`. The same `idempotencyKey` returns the batch it
51632
+ * already started.
51633
+ */
51634
+ startJobBatch: method(TrainingJobRequestSchema.omit({ baseModelId: true }).extend({
51635
+ baseModelIds: array(string().min(1)).min(1),
51636
+ name: string().min(1).max(120),
51637
+ maxCostUsd: number().positive(),
51638
+ maxRuntimeSec: number().int().positive(),
51639
+ idempotencyKey: string().min(8).max(80)
51640
+ }), discriminatedUnion("kind", [object({
51641
+ kind: literal("started"),
51642
+ batchId: string(),
51643
+ jobs: array(TrainingJobSchema).min(1).readonly()
51644
+ }), object({
51645
+ kind: literal("refused"),
51646
+ reason: TrainingRefusalReasonSchema,
51647
+ detail: string()
51648
+ })]), {
51649
+ kind: "mutation",
51650
+ auth: "admin",
51651
+ timeoutMs: 12e4
51652
+ }),
51502
51653
  listJobs: method(object({}), array(TrainingJobSchema).readonly(), { auth: "admin" }),
51503
51654
  getJob: method(IdInput, TrainingJobSchema.nullable(), { auth: "admin" }),
51504
51655
  cancelJob: method(IdInput, TrainingJobSchema, {
@@ -56857,12 +57008,6 @@ Object.freeze({
56857
57008
  addonId: null,
56858
57009
  access: "create"
56859
57010
  },
56860
- "pipelineAnalytics.createRetrainDatasetVersion": {
56861
- capName: "pipeline-analytics",
56862
- capScope: "device",
56863
- addonId: null,
56864
- access: "create"
56865
- },
56866
57011
  "pipelineAnalytics.deleteDeviceEvents": {
56867
57012
  capName: "pipeline-analytics",
56868
57013
  capScope: "device",
@@ -56875,12 +57020,6 @@ Object.freeze({
56875
57020
  addonId: null,
56876
57021
  access: "delete"
56877
57022
  },
56878
- "pipelineAnalytics.deleteRetrainDatasetVersion": {
56879
- capName: "pipeline-analytics",
56880
- capScope: "device",
56881
- addonId: null,
56882
- access: "delete"
56883
- },
56884
57023
  "pipelineAnalytics.deleteTracks": {
56885
57024
  capName: "pipeline-analytics",
56886
57025
  capScope: "device",
@@ -56983,6 +57122,12 @@ Object.freeze({
56983
57122
  addonId: null,
56984
57123
  access: "view"
56985
57124
  },
57125
+ "pipelineAnalytics.getRetrainCorpusKpi": {
57126
+ capName: "pipeline-analytics",
57127
+ capScope: "device",
57128
+ addonId: null,
57129
+ access: "view"
57130
+ },
56986
57131
  "pipelineAnalytics.getRetrainExportUrl": {
56987
57132
  capName: "pipeline-analytics",
56988
57133
  capScope: "device",
@@ -57103,7 +57248,7 @@ Object.freeze({
57103
57248
  addonId: null,
57104
57249
  access: "view"
57105
57250
  },
57106
- "pipelineAnalytics.listRetrainDatasetVersions": {
57251
+ "pipelineAnalytics.listRetrainCorpusPage": {
57107
57252
  capName: "pipeline-analytics",
57108
57253
  capScope: "device",
57109
57254
  addonId: null,
@@ -57157,12 +57302,6 @@ Object.freeze({
57157
57302
  addonId: null,
57158
57303
  access: "create"
57159
57304
  },
57160
- "pipelineAnalytics.previewRetrainDataset": {
57161
- capName: "pipeline-analytics",
57162
- capScope: "device",
57163
- addonId: null,
57164
- access: "view"
57165
- },
57166
57305
  "pipelineAnalytics.proposeRetrainAnnotations": {
57167
57306
  capName: "pipeline-analytics",
57168
57307
  capScope: "device",
@@ -57241,6 +57380,12 @@ Object.freeze({
57241
57380
  addonId: null,
57242
57381
  access: "create"
57243
57382
  },
57383
+ "pipelineAnalytics.resolveRetrainTrainingCorpus": {
57384
+ capName: "pipeline-analytics",
57385
+ capScope: "device",
57386
+ addonId: null,
57387
+ access: "view"
57388
+ },
57244
57389
  "pipelineAnalytics.restageRetrainTrack": {
57245
57390
  capName: "pipeline-analytics",
57246
57391
  capScope: "device",
@@ -57301,12 +57446,6 @@ Object.freeze({
57301
57446
  addonId: null,
57302
57447
  access: "create"
57303
57448
  },
57304
- "pipelineAnalytics.verifyRetrainDatasetVersion": {
57305
- capName: "pipeline-analytics",
57306
- capScope: "device",
57307
- addonId: null,
57308
- access: "view"
57309
- },
57310
57449
  "pipelineAnalytics.wipeAllAnalytics": {
57311
57450
  capName: "pipeline-analytics",
57312
57451
  capScope: "device",
@@ -59701,18 +59840,6 @@ Object.freeze({
59701
59840
  addonId: null,
59702
59841
  access: "create"
59703
59842
  },
59704
- "training.findDatasetVersionIdByName": {
59705
- capName: "training",
59706
- capScope: "system",
59707
- addonId: null,
59708
- access: "view"
59709
- },
59710
- "training.getDatasetVersion": {
59711
- capName: "training",
59712
- capScope: "system",
59713
- addonId: null,
59714
- access: "view"
59715
- },
59716
59843
  "training.getJob": {
59717
59844
  capName: "training",
59718
59845
  capScope: "system",
@@ -59731,12 +59858,6 @@ Object.freeze({
59731
59858
  addonId: null,
59732
59859
  access: "view"
59733
59860
  },
59734
- "training.listDatasetVersions": {
59735
- capName: "training",
59736
- capScope: "system",
59737
- addonId: null,
59738
- access: "view"
59739
- },
59740
59861
  "training.listJobs": {
59741
59862
  capName: "training",
59742
59863
  capScope: "system",
@@ -59749,54 +59870,66 @@ Object.freeze({
59749
59870
  addonId: null,
59750
59871
  access: "view"
59751
59872
  },
59752
- "training.putDatasetVersion": {
59873
+ "training.registerResult": {
59753
59874
  capName: "training",
59754
59875
  capScope: "system",
59755
59876
  addonId: null,
59756
59877
  access: "create"
59757
59878
  },
59758
- "training.registerResult": {
59879
+ "training.rollbackCanary": {
59759
59880
  capName: "training",
59760
59881
  capScope: "system",
59761
59882
  addonId: null,
59762
59883
  access: "create"
59763
59884
  },
59764
- "training.removeDatasetVersion": {
59885
+ "training.startJob": {
59765
59886
  capName: "training",
59766
59887
  capScope: "system",
59767
59888
  addonId: null,
59768
- access: "delete"
59889
+ access: "create"
59769
59890
  },
59770
- "training.rollbackCanary": {
59891
+ "training.startJobBatch": {
59771
59892
  capName: "training",
59772
59893
  capScope: "system",
59773
59894
  addonId: null,
59774
59895
  access: "create"
59775
59896
  },
59776
- "training.startJob": {
59777
- capName: "training",
59897
+ "trainingProvider.cancelJob": {
59898
+ capName: "training-provider",
59778
59899
  capScope: "system",
59779
59900
  addonId: null,
59780
59901
  access: "create"
59781
59902
  },
59782
- "trainingProvider.cancelJob": {
59903
+ "trainingProvider.cleanupJob": {
59783
59904
  capName: "training-provider",
59784
59905
  capScope: "system",
59785
59906
  addonId: null,
59786
59907
  access: "create"
59787
59908
  },
59788
- "trainingProvider.cleanupJob": {
59909
+ "trainingProvider.createEntry": {
59789
59910
  capName: "training-provider",
59790
59911
  capScope: "system",
59791
59912
  addonId: null,
59792
59913
  access: "create"
59793
59914
  },
59915
+ "trainingProvider.deleteEntry": {
59916
+ capName: "training-provider",
59917
+ capScope: "system",
59918
+ addonId: null,
59919
+ access: "delete"
59920
+ },
59794
59921
  "trainingProvider.describe": {
59795
59922
  capName: "training-provider",
59796
59923
  capScope: "system",
59797
59924
  addonId: null,
59798
59925
  access: "view"
59799
59926
  },
59927
+ "trainingProvider.describeTypes": {
59928
+ capName: "training-provider",
59929
+ capScope: "system",
59930
+ addonId: null,
59931
+ access: "view"
59932
+ },
59800
59933
  "trainingProvider.estimateJob": {
59801
59934
  capName: "training-provider",
59802
59935
  capScope: "system",
@@ -59809,6 +59942,12 @@ Object.freeze({
59809
59942
  addonId: null,
59810
59943
  access: "view"
59811
59944
  },
59945
+ "trainingProvider.listEntries": {
59946
+ capName: "training-provider",
59947
+ capScope: "system",
59948
+ addonId: null,
59949
+ access: "view"
59950
+ },
59812
59951
  "trainingProvider.listJobEvents": {
59813
59952
  capName: "training-provider",
59814
59953
  capScope: "system",
@@ -63445,6 +63584,11 @@ Object.freeze({
63445
63584
  form: "array",
63446
63585
  optional: false
63447
63586
  }],
63587
+ "pipelineAnalytics.listRetrainCorpusPage": [{
63588
+ name: "deviceIds",
63589
+ form: "array",
63590
+ optional: true
63591
+ }],
63448
63592
  "pipelineAnalytics.listRetrainStaging": [{
63449
63593
  name: "deviceIds",
63450
63594
  form: "array",