@camstack/addon-post-analysis 1.2.351 → 1.2.352

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-DPlNaYLS.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-DFfu0TT0.mjs} +2 -2
  10. package/dist/pipeline-analytics/index.js +677 -941
  11. package/dist/pipeline-analytics/index.mjs +677 -941
  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
@@ -5449,7 +5449,7 @@ var ZodIssueCode = {
5449
5449
  var ZodFirstPartyTypeKind;
5450
5450
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5451
5451
  //#endregion
5452
- //#region ../types/dist/sleep-r3RWkGVx.mjs
5452
+ //#region ../types/dist/sleep-CI0n5D44.mjs
5453
5453
  /**
5454
5454
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5455
5455
  * window to float samples (D455).
@@ -9939,6 +9939,16 @@ var CompositionSchema = object({
9939
9939
  seen.add(feature.cap);
9940
9940
  });
9941
9941
  });
9942
+ var NodeColorIdSchema = _enum([
9943
+ "node-a",
9944
+ "node-b",
9945
+ "node-c",
9946
+ "node-d",
9947
+ "node-e",
9948
+ "node-f",
9949
+ "node-g",
9950
+ "node-h"
9951
+ ]);
9942
9952
  var OWNER_TYPES = new Set([
9943
9953
  "track",
9944
9954
  "face",
@@ -28950,24 +28960,69 @@ var RetrainFrameListSchema = object({
28950
28960
  /** What the page pre-selects — the native key frame when one survives. */
28951
28961
  autoPickMediaId: number().int().optional()
28952
28962
  });
28963
+ /** Exclusive partition of a corpus copy's annotation progress (design §4.2). */
28964
+ var RetrainFrameWorkStateSchema = _enum([
28965
+ "unannotated",
28966
+ "annotated",
28967
+ "complete"
28968
+ ]);
28969
+ /**
28970
+ * Filters for paginated corpus list, KPI, and matching export (design §4.4).
28971
+ * Every narrowing field is ANDed; omitted fields impose no constraint.
28972
+ */
28973
+ var RetrainCorpusFilterSchema = object({
28974
+ workState: RetrainFrameWorkStateSchema.optional(),
28975
+ deviceIds: array(number()).max(500).optional(),
28976
+ /** When set, only frames in this named collection. */
28977
+ collectionId: string().optional(),
28978
+ /** Frames that carry at least one saved annotation in one of these classes. */
28979
+ classes: array(RetrainMacroClassSchema).optional(),
28980
+ page: number().int().positive().default(1),
28981
+ pageSize: number().int().positive().max(100).default(50)
28982
+ });
28983
+ var RetrainCorpusPageSchema = object({
28984
+ frames: array(RetrainFrameSchema.extend({ workState: RetrainFrameWorkStateSchema })).readonly(),
28985
+ total: number().int().nonnegative(),
28986
+ page: number().int().positive(),
28987
+ pageSize: number().int().positive()
28988
+ });
28989
+ var RetrainCorpusKpiCameraRowSchema = object({
28990
+ deviceId: number(),
28991
+ unannotated: number().int().nonnegative(),
28992
+ annotated: number().int().nonnegative(),
28993
+ complete: number().int().nonnegative(),
28994
+ /** This camera's `complete` count divided by corpus `total`, in `[0,1]`.
28995
+ * `null` when the corpus is empty (no ratio). */
28996
+ pctOfCorpus: number().min(0).max(1).nullable()
28997
+ });
28998
+ var RetrainCorpusKpiSchema = object({
28999
+ total: number().int().nonnegative(),
29000
+ unannotated: number().int().nonnegative(),
29001
+ annotated: number().int().nonnegative(),
29002
+ complete: number().int().nonnegative(),
29003
+ cameras: array(RetrainCorpusKpiCameraRowSchema).readonly()
29004
+ });
28953
29005
  /**
28954
29006
  * Which frames an annotated export carries. Every field narrows; an empty
28955
- * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
28956
- * list owned by whoever trains (the training orchestrator), so `frameIds` is
28957
- * the primitive a version export uses; `batchId` re-selects what an earlier
28958
- * export carried (`exportedInBatch`).
29007
+ * filter is every annotated copy. `frameIds` is the primitive a job or
29008
+ * download uses; `batchId` re-selects what an earlier export carried
29009
+ * (`exportedInBatch`). Frozen dataset versions were removed — live selection
29010
+ * resolves to `frameIds` at plan/start.
28959
29011
  */
28960
29012
  var RetrainExportFilterSchema = object({
28961
29013
  deviceIds: array(number()).optional(),
28962
29014
  frameIds: array(string()).max(2e4).optional(),
28963
29015
  /** Only frames in at least one of these named collections. */
28964
29016
  collectionIds: array(string()).max(200).optional(),
28965
- /** Exactly the frames of this dataset version (and its completeOnly). An
28966
- * unknown id selects nothing. */
28967
- datasetVersionId: string().optional(),
29017
+ /** Single collection (Frames filter bar). ANDed with `collectionIds` when both set. */
29018
+ collectionId: string().optional(),
28968
29019
  batchId: string().optional(),
28969
29020
  /** Only frames the operator marked complete (all subjects boxed). */
28970
- completeOnly: boolean().optional()
29021
+ completeOnly: boolean().optional(),
29022
+ /** Exclusive work-state partition (`workStateOf`); same as the corpus list. */
29023
+ workState: RetrainFrameWorkStateSchema.optional(),
29024
+ /** Frames with at least one saved annotation in one of these classes. */
29025
+ classes: array(RetrainMacroClassSchema).optional()
28971
29026
  });
28972
29027
  /**
28973
29028
  * `frames`: the full frame copies, boxes in `annotations.json`.
@@ -29167,8 +29222,7 @@ var RetrainDatasetStatsSchema = object({
29167
29222
  completeFrames: number().int()
29168
29223
  })).readonly()
29169
29224
  });
29170
- /** An immutable dataset version, without its frame list. */
29171
- var RetrainDatasetVersionSchema = object({
29225
+ object({
29172
29226
  id: string(),
29173
29227
  name: string(),
29174
29228
  createdAt: number(),
@@ -29176,22 +29230,33 @@ var RetrainDatasetVersionSchema = object({
29176
29230
  layout: RetrainExportLayoutSchema,
29177
29231
  completeOnly: boolean(),
29178
29232
  frameCount: number().int(),
29179
- /** sha256 of what the frames taught when the version was frozen. */
29180
29233
  annotationHash: string(),
29181
- /** The export manifest schema the version was cut under. */
29182
29234
  manifestSchema: string(),
29183
29235
  stats: RetrainDatasetStatsSchema
29184
29236
  });
29185
- var CreateRetrainDatasetVersionResultSchema = discriminatedUnion("kind", [object({
29186
- kind: literal("created"),
29187
- version: RetrainDatasetVersionSchema
29237
+ /**
29238
+ * Live training corpus criteria — same shape as `TrainingCorpusSelection` on
29239
+ * the training cap. Resolved here so plan/start and the annotated export share
29240
+ * one definition of "the frames" (`buildRetrainExportPlan`).
29241
+ */
29242
+ var RetrainTrainingCorpusSelectionSchema = object({
29243
+ collectionIds: array(string()).min(1),
29244
+ workState: _enum([
29245
+ "complete",
29246
+ "annotated_or_complete",
29247
+ "any_annotated"
29248
+ ]).default("complete")
29249
+ });
29250
+ var RetrainTrainingCorpusResolveResultSchema = discriminatedUnion("kind", [object({
29251
+ kind: literal("resolved"),
29252
+ frameIds: array(string()).max(2e4).readonly(),
29253
+ stats: RetrainDatasetStatsSchema,
29254
+ annotationHash: string(),
29255
+ layout: RetrainExportLayoutSchema
29188
29256
  }), object({
29189
29257
  kind: literal("refused"),
29190
- reason: _enum([
29191
- "empty-name",
29192
- "duplicate-name",
29193
- "no-frames"
29194
- ])
29258
+ reason: _enum(["unknown-collection", "no-frames"]),
29259
+ detail: string()
29195
29260
  })]);
29196
29261
  /** The outcome of a lifecycle move owned by the retrain page. */
29197
29262
  var RetrainTransitionResultSchema = object({
@@ -30367,6 +30432,26 @@ var pipelineAnalyticsCapability = {
30367
30432
  auth: "admin"
30368
30433
  }),
30369
30434
  /**
30435
+ * Paginated corpus copies for the Frames grid — index reads only.
30436
+ *
30437
+ * Filters AND (`workState`, cameras, one collection, annotated classes).
30438
+ * An answered empty match is `{ frames: [], total: 0, … }` (D315), never a
30439
+ * pending masquerade. Classification uses `workStateOf` (annotation count
30440
+ * wins over a stray `complete` flag).
30441
+ */
30442
+ listRetrainCorpusPage: method(RetrainCorpusFilterSchema, RetrainCorpusPageSchema, {
30443
+ kind: "query",
30444
+ auth: "admin"
30445
+ }),
30446
+ /**
30447
+ * Global + per-camera corpus KPI. Unfiltered totals; `%` on a camera row is
30448
+ * `complete(camera) / corpus total`, or `null` when the corpus is empty.
30449
+ */
30450
+ getRetrainCorpusKpi: method(object({}), RetrainCorpusKpiSchema, {
30451
+ kind: "query",
30452
+ auth: "admin"
30453
+ }),
30454
+ /**
30370
30455
  * What a track can contribute, and what it already has.
30371
30456
  *
30372
30457
  * `candidates` are the track's whole, unannotated frames — index rows only,
@@ -30593,53 +30678,6 @@ var pipelineAnalyticsCapability = {
30593
30678
  auth: "admin",
30594
30679
  timeoutMs: 12e4
30595
30680
  }),
30596
- /** The counts a selection would freeze — class × camera × day/night,
30597
- * completeness — without freezing anything. Index reads only. */
30598
- previewRetrainDataset: method(object({
30599
- selection: RetrainDatasetSelectionSchema,
30600
- completeOnly: boolean().optional()
30601
- }), RetrainDatasetStatsSchema, {
30602
- kind: "query",
30603
- auth: "admin"
30604
- }),
30605
- /**
30606
- * Freeze a dataset version: the frames the selection yields (the same plan
30607
- * the annotated export builds), the hash of what they teach, the export
30608
- * parameters and the counts. Immutable — a different selection is a new
30609
- * version. Export it with `getRetrainExportUrl({ datasetVersionId })`.
30610
- */
30611
- createRetrainDatasetVersion: method(object({
30612
- name: string().max(120),
30613
- selection: RetrainDatasetSelectionSchema,
30614
- layout: RetrainExportLayoutSchema,
30615
- completeOnly: boolean()
30616
- }), CreateRetrainDatasetVersionResultSchema, {
30617
- kind: "mutation",
30618
- auth: "admin",
30619
- timeoutMs: 12e4
30620
- }),
30621
- /** Every dataset version, newest first. */
30622
- listRetrainDatasetVersions: method(object({}), array(RetrainDatasetVersionSchema).readonly(), {
30623
- kind: "query",
30624
- auth: "admin"
30625
- }),
30626
- /** Delete a version. Its frames stay in the dataset. */
30627
- deleteRetrainDatasetVersion: method(object({ id: string() }), object({ deleted: boolean() }), {
30628
- kind: "mutation",
30629
- auth: "admin"
30630
- }),
30631
- /** Does the corpus still teach what the version froze? `missingFrames`
30632
- * counts frames that left the dataset (or lost every box and tick). */
30633
- verifyRetrainDatasetVersion: method(object({ id: string() }), object({
30634
- found: boolean(),
30635
- annotationHash: string(),
30636
- matches: boolean(),
30637
- missingFrames: number().int()
30638
- }), {
30639
- kind: "query",
30640
- auth: "admin",
30641
- timeoutMs: 12e4
30642
- }),
30643
30681
  /** The enabled, vision-capable LLM profiles, each saying whether a frame
30644
30682
  * sent to it leaves the house. */
30645
30683
  listRetrainAssistProfiles: method(object({}), array(RetrainAssistProfileSchema).readonly(), {
@@ -30686,6 +30724,16 @@ var pipelineAnalyticsCapability = {
30686
30724
  kind: "query",
30687
30725
  auth: "admin"
30688
30726
  }),
30727
+ /**
30728
+ * Resolve a live training corpus selection to frame ids + stats (index
30729
+ * reads only). Same plan the annotated export builds — training plan/start
30730
+ * calls this instead of a frozen dataset version.
30731
+ */
30732
+ resolveRetrainTrainingCorpus: method(RetrainTrainingCorpusSelectionSchema, RetrainTrainingCorpusResolveResultSchema, {
30733
+ kind: "query",
30734
+ auth: "admin",
30735
+ timeoutMs: 6e4
30736
+ }),
30689
30737
  renameRetrainCollection: method(object({
30690
30738
  id: string(),
30691
30739
  name: string().max(120)
@@ -31639,11 +31687,14 @@ var HardwareClassIdSchema = _enum([
31639
31687
  "intel-n-series",
31640
31688
  "apple-m-base",
31641
31689
  "apple-m-pro",
31690
+ "amd-phoenix",
31642
31691
  "unknown"
31643
31692
  ]);
31644
31693
  var AcceleratorKindSchema = _enum([
31645
31694
  "intel-npu",
31646
31695
  "intel-igpu",
31696
+ "amd-igpu",
31697
+ "amd-npu",
31647
31698
  "x86-cpu",
31648
31699
  "arm-cpu",
31649
31700
  "apple-ane",
@@ -33779,6 +33830,8 @@ var AgentPipelineSettingsSchema = object({
33779
33830
  * address is wrong (multi-homed host, NAT, custom interface).
33780
33831
  */
33781
33832
  reachableHost: string().optional(),
33833
+ /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
33834
+ color: NodeColorIdSchema.optional(),
33782
33835
  /**
33783
33836
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
33784
33837
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
@@ -34505,8 +34558,9 @@ var pipelineOrchestratorCapability = {
34505
34558
  */
34506
34559
  setAgentReachableHost: method(object({
34507
34560
  agentNodeId: string(),
34508
- reachableHost: string().nullable()
34509
- }), object({ success: literal(true) }), {
34561
+ reachableHost: string().nullable().optional(),
34562
+ color: NodeColorIdSchema.nullable().optional()
34563
+ }).refine((v) => v.reachableHost !== void 0 || v.color !== void 0, { message: "reachableHost or color required" }), object({ success: literal(true) }), {
34510
34564
  kind: "mutation",
34511
34565
  auth: "admin"
34512
34566
  }),
@@ -45610,7 +45664,15 @@ var GpuInfoSchema = object({
45610
45664
  name: string(),
45611
45665
  memoryMB: number().optional()
45612
45666
  });
45613
- var NpuInfoSchema = object({ type: _enum(["apple-ane", "intel-npu"]) });
45667
+ var NpuInfoSchema = object({
45668
+ type: _enum([
45669
+ "apple-ane",
45670
+ "intel-npu",
45671
+ "amd-xdna"
45672
+ ]),
45673
+ name: string().optional(),
45674
+ generation: _enum(["xdna1", "xdna2"]).optional()
45675
+ });
45614
45676
  var CoralInfoSchema = object({
45615
45677
  type: literal("coral-edgetpu"),
45616
45678
  bus: string().optional()
@@ -50987,9 +51049,11 @@ var zoneRulesCapability = {
50987
51049
  * once is what makes a second provider (RunPod, a local NVIDIA node) a new
50988
51050
  * manifest entry and nothing else.
50989
51051
  *
50990
- * Collection, routed by the `addonId` in every single-row input (the `llm` /
50991
- * `notification-output` posture); `describe` concat-fans across providers.
50992
- * Every method is `admin`: these spend money.
51052
+ * Collection of provider **types** (addons). Each addon owns zero or more
51053
+ * **entries** (credentials + defaults). Concat-fans: `describe`,
51054
+ * `describeTypes`, `listEntries`, `listJobs`. Single-row work is keyed by
51055
+ * `entryId`; callers also pass the owning `addonId` as the collection
51056
+ * selector (broker posture). Every method is `admin`: these spend money.
50993
51057
  *
50994
51058
  * Every cloud object a provider creates is tagged with the orchestrator's
50995
51059
  * `jobKey`, so a retried submit finds the job it already started instead of
@@ -51013,8 +51077,8 @@ var TrainingRegionOptionSchema = object({
51013
51077
  priceMultiplier: number().positive()
51014
51078
  });
51015
51079
  /**
51016
- * The provider's per-account settings, as the orchestrator reads them. They
51017
- * live in the PROVIDER addon's settings (operator decision 2026-10-08: they
51080
+ * The provider's per-entry settings, as the orchestrator reads them. They
51081
+ * live on the PROVIDER addon's entry (operator decision 2026-10-08: they
51018
51082
  * depend on the user's account), never hard-coded in the orchestrator.
51019
51083
  */
51020
51084
  var TrainingProviderDefaultsSchema = object({
@@ -51025,9 +51089,32 @@ var TrainingProviderDefaultsSchema = object({
51025
51089
  /** Hours a FAILED job's cloud dataset is kept for debugging; 0 = delete at once. */
51026
51090
  failedDatasetGraceHours: number().nonnegative()
51027
51091
  });
51092
+ /** One creatable provider type, for the Add-entry dialog. */
51093
+ var TrainingProviderTypeSchema = object({
51094
+ typeId: string(),
51095
+ label: string(),
51096
+ /** Path under the addon package (e.g. `assets/training-modal/icon.svg`). */
51097
+ iconAsset: string(),
51098
+ /** Owning `training-provider` addon — collection selector for createEntry. */
51099
+ addonId: string()
51100
+ });
51101
+ /** One configured account / workspace under a provider type. */
51102
+ var TrainingProviderEntrySchema = object({
51103
+ entryId: string(),
51104
+ typeId: string(),
51105
+ name: string(),
51106
+ addonId: string(),
51107
+ /** Credentials are present — never the values. */
51108
+ configured: boolean()
51109
+ });
51028
51110
  var TrainingProviderDescriptorSchema = object({
51029
51111
  addonId: string(),
51030
- /** `modal`, `runpod`, `fake`, … */
51112
+ entryId: string(),
51113
+ typeId: string(),
51114
+ /** Operator-chosen entry name. */
51115
+ name: string(),
51116
+ iconAsset: string(),
51117
+ /** `modal`, `runpod`, `fake`, … — same as typeId for current providers. */
51031
51118
  kind: string(),
51032
51119
  label: string(),
51033
51120
  gpuTypes: array(TrainingGpuOptionSchema).readonly(),
@@ -51091,8 +51178,9 @@ var TrainerSourceRefSchema = object({
51091
51178
  /** A commit sha (never a branch) — the job must be reproducible. */
51092
51179
  revision: string().regex(/^[0-9a-f]{7,64}$/)
51093
51180
  });
51181
+ /** Cloud job identity — route with the owning addon's `addonId` selector. */
51094
51182
  var JobRef = {
51095
- addonId: string(),
51183
+ entryId: string().min(1),
51096
51184
  jobKey: string().uuid()
51097
51185
  };
51098
51186
  var TrainingLogLineSchema = object({
@@ -51105,17 +51193,37 @@ var trainingProviderCapability = {
51105
51193
  mode: "collection",
51106
51194
  internal: true,
51107
51195
  methods: {
51108
- /** Every provider's offer and settings. Concat-fans across providers. */
51196
+ /** Every entry's offer and settings. Concat-fans across providers. */
51109
51197
  describe: method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "admin" }),
51110
- /** Call the provider with the stored credentials. Never returns them. */
51111
- validateCredentials: method(object({ addonId: string() }), TrainingCredentialCheckSchema, {
51198
+ /** Creatable types for the Add-entry dialog. Concat-fans. */
51199
+ describeTypes: method(object({}), array(TrainingProviderTypeSchema).readonly(), { auth: "admin" }),
51200
+ /** Configured entries (pills). Concat-fans. */
51201
+ listEntries: method(object({}), array(TrainingProviderEntrySchema).readonly(), { auth: "admin" }),
51202
+ /**
51203
+ * Create an entry under this provider type. Pin with `{ addonId }` of the
51204
+ * type's owning addon (from describeTypes).
51205
+ */
51206
+ createEntry: method(object({
51207
+ typeId: string().min(1),
51208
+ name: string().min(1)
51209
+ }), object({ entryId: string() }), {
51210
+ kind: "mutation",
51211
+ auth: "admin"
51212
+ }),
51213
+ /** Delete an entry. Pin with the owning `{ addonId }`. */
51214
+ deleteEntry: method(object({ entryId: string().min(1) }), object({ ok: literal(true) }), {
51215
+ kind: "mutation",
51216
+ auth: "admin"
51217
+ }),
51218
+ /** Call the provider with the entry's stored credentials. Never returns them. */
51219
+ validateCredentials: method(object({ entryId: string().min(1) }), TrainingCredentialCheckSchema, {
51112
51220
  kind: "mutation",
51113
51221
  auth: "admin",
51114
51222
  timeoutMs: 3e4
51115
51223
  }),
51116
51224
  /** USD range for a run of `gpuSeconds` on `gpuType` in `region`. */
51117
51225
  estimateJob: method(object({
51118
- addonId: string(),
51226
+ entryId: string().min(1),
51119
51227
  gpuType: string(),
51120
51228
  region: string(),
51121
51229
  datasetBytes: number().int().nonnegative(),
@@ -51211,8 +51319,11 @@ var trainingProviderCapability = {
51211
51319
  auth: "admin",
51212
51320
  timeoutMs: 5 * 6e4
51213
51321
  }),
51214
- /** Every job the provider can still see — the orphan sweep diffs it against our records. */
51215
- listJobs: method(object({ addonId: string() }), array(ProviderJobStatusSchema).readonly(), {
51322
+ /**
51323
+ * Jobs this provider can still see. Optional `entryId` filters; omit to
51324
+ * list every entry (orphan sweep). Pin with `{ addonId }`.
51325
+ */
51326
+ listJobs: method(object({ entryId: string().min(1).optional() }), array(ProviderJobStatusSchema).readonly(), {
51216
51327
  auth: "admin",
51217
51328
  timeoutMs: 2 * 6e4
51218
51329
  })
@@ -51224,20 +51335,31 @@ var trainingProviderCapability = {
51224
51335
  *
51225
51336
  * It owns what every provider must agree on, written once:
51226
51337
  *
51227
- * - **Dataset versions.** Taken over from pipeline-analytics (D796): the rows
51228
- * live here (D808); pipeline-analytics still CUTS a version (it owns the corpus and
51229
- * the export plan) and reaches this store through the five row methods
51230
- * below, so the Retrain page and the export did not change.
51231
51338
  * - **Jobs.** A persisted state machine, a reconcile loop against the
51232
51339
  * provider, a cost guard, a daily orphan sweep and the retention rules.
51233
51340
  * - **The return flow.** Verified artefacts → Model Studio
51234
51341
  * (`custom-model-registry.importModelBundle`) → canary on cameras →
51235
51342
  * rollback. Nothing is ever registered automatically.
51236
51343
  *
51344
+ * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
51345
+ * work-state rule); frame ids are resolved via pipeline-analytics at that
51346
+ * moment and snapshotted on the job. No frozen dataset version.
51347
+ *
51237
51348
  * Every method is `admin`.
51238
51349
  */
51239
- /** A version WITH its frame list — what the export and a job read. */
51240
- var TrainingDatasetVersionRowSchema = RetrainDatasetVersionSchema.omit({ frameCount: true }).extend({ frameIds: array(string()).max(2e4).readonly() });
51350
+ /**
51351
+ * Live corpus criteria for plan/start (design §5.2). Default is complete-only.
51352
+ * Frame ids are resolved at plan/start — never a frozen version id.
51353
+ */
51354
+ var TrainingCorpusSelectionSchema = object({
51355
+ collectionIds: array(string()).min(1),
51356
+ /** Default complete-only for v1 */
51357
+ workState: _enum([
51358
+ "complete",
51359
+ "annotated_or_complete",
51360
+ "any_annotated"
51361
+ ]).default("complete")
51362
+ });
51241
51363
  /** A base model a detector job can fine-tune, and the baseline it is judged against. */
51242
51364
  var TrainingBaseModelSchema = object({
51243
51365
  modelId: string(),
@@ -51255,9 +51377,13 @@ var TrainingPresetSchema = _enum([
51255
51377
  "thorough"
51256
51378
  ]);
51257
51379
  var TrainingJobRequestSchema = object({
51258
- datasetVersionId: string().min(1),
51259
- /** The `training-provider` addon that runs it. */
51260
- addonId: string().min(1),
51380
+ /** Live collection + work-state criteria; resolved at plan/start. */
51381
+ selection: TrainingCorpusSelectionSchema,
51382
+ /**
51383
+ * The provider **entry** that runs it (credentials + defaults).
51384
+ * Resolve to an owning addon via `training-provider.describe` / `listEntries`.
51385
+ */
51386
+ entryId: string().min(1),
51261
51387
  gpuType: string().min(1),
51262
51388
  region: string(),
51263
51389
  baseModelId: string().min(1),
@@ -51316,6 +51442,7 @@ var TrainingJobPlanSchema = object({
51316
51442
  * result lives after the operator acted on it.
51317
51443
  */
51318
51444
  var TrainingJobStateSchema = _enum([
51445
+ "queued",
51319
51446
  "uploading",
51320
51447
  "submitted",
51321
51448
  "starting",
@@ -51369,6 +51496,11 @@ var TrainingJobSchema = object({
51369
51496
  createdAt: number(),
51370
51497
  updatedAt: number(),
51371
51498
  state: TrainingJobStateSchema,
51499
+ /**
51500
+ * Shared by every job enqueued together via `startJobBatch`.
51501
+ * `null` for a lone `startJob`. The engine advances queued siblings by this id.
51502
+ */
51503
+ batchId: string().nullable().default(null),
51372
51504
  stage: TrainingStageSchema.nullable(),
51373
51505
  failure: object({
51374
51506
  reason: TrainingFailureReasonSchema,
@@ -51380,6 +51512,12 @@ var TrainingJobSchema = object({
51380
51512
  maxRuntimeSec: number().int().positive(),
51381
51513
  trainer: TrainerSourceRefSchema,
51382
51514
  datasetLayout: RetrainExportLayoutSchema,
51515
+ /** Frame count snapshotted when the job started (audit; equals `frameIds.length`). */
51516
+ frameCount: number().int().nonnegative(),
51517
+ /** Resolved frame ids at start — the archive ships exactly these. */
51518
+ frameIds: array(string()).max(2e4).readonly(),
51519
+ /** Hash of what those frames taught at start (trainer `dataset.annotationHash`). */
51520
+ annotationHash: string(),
51383
51521
  dataset: object({
51384
51522
  bytes: number().int(),
51385
51523
  sha256: string(),
@@ -51427,19 +51565,6 @@ var trainingCapability = {
51427
51565
  mode: "singleton",
51428
51566
  mount: { kind: "hub-only" },
51429
51567
  methods: {
51430
- /** Store a version once. `stored: false` = that id already exists (immutable). */
51431
- putDatasetVersion: method(TrainingDatasetVersionRowSchema, object({ stored: boolean() }), {
51432
- kind: "mutation",
51433
- auth: "admin"
51434
- }),
51435
- getDatasetVersion: method(IdInput, TrainingDatasetVersionRowSchema.nullable(), { auth: "admin" }),
51436
- /** Every version without its frame list, newest first. */
51437
- listDatasetVersions: method(object({}), array(RetrainDatasetVersionSchema).readonly(), { auth: "admin" }),
51438
- findDatasetVersionIdByName: method(object({ name: string() }), object({ id: string().nullable() }), { auth: "admin" }),
51439
- removeDatasetVersion: method(IdInput, object({ removed: boolean() }), {
51440
- kind: "mutation",
51441
- auth: "admin"
51442
- }),
51443
51568
  listBaseModels: method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" }),
51444
51569
  /** Split, estimate, defaults and any named refusal — nothing is started. */
51445
51570
  planJob: method(TrainingJobRequestSchema, TrainingJobPlanSchema, {
@@ -51468,6 +51593,32 @@ var trainingCapability = {
51468
51593
  auth: "admin",
51469
51594
  timeoutMs: 12e4
51470
51595
  }),
51596
+ /**
51597
+ * Enqueue one job per base model (same selection, entry, caps). The first
51598
+ * becomes `uploading`; the rest stay `queued` until the prior job settles.
51599
+ * One ACTIVE job at a time — a parallel `startJob` still gets
51600
+ * `job-already-running`. The same `idempotencyKey` returns the batch it
51601
+ * already started.
51602
+ */
51603
+ startJobBatch: method(TrainingJobRequestSchema.omit({ baseModelId: true }).extend({
51604
+ baseModelIds: array(string().min(1)).min(1),
51605
+ name: string().min(1).max(120),
51606
+ maxCostUsd: number().positive(),
51607
+ maxRuntimeSec: number().int().positive(),
51608
+ idempotencyKey: string().min(8).max(80)
51609
+ }), discriminatedUnion("kind", [object({
51610
+ kind: literal("started"),
51611
+ batchId: string(),
51612
+ jobs: array(TrainingJobSchema).min(1).readonly()
51613
+ }), object({
51614
+ kind: literal("refused"),
51615
+ reason: TrainingRefusalReasonSchema,
51616
+ detail: string()
51617
+ })]), {
51618
+ kind: "mutation",
51619
+ auth: "admin",
51620
+ timeoutMs: 12e4
51621
+ }),
51471
51622
  listJobs: method(object({}), array(TrainingJobSchema).readonly(), { auth: "admin" }),
51472
51623
  getJob: method(IdInput, TrainingJobSchema.nullable(), { auth: "admin" }),
51473
51624
  cancelJob: method(IdInput, TrainingJobSchema, {
@@ -56826,12 +56977,6 @@ Object.freeze({
56826
56977
  addonId: null,
56827
56978
  access: "create"
56828
56979
  },
56829
- "pipelineAnalytics.createRetrainDatasetVersion": {
56830
- capName: "pipeline-analytics",
56831
- capScope: "device",
56832
- addonId: null,
56833
- access: "create"
56834
- },
56835
56980
  "pipelineAnalytics.deleteDeviceEvents": {
56836
56981
  capName: "pipeline-analytics",
56837
56982
  capScope: "device",
@@ -56844,12 +56989,6 @@ Object.freeze({
56844
56989
  addonId: null,
56845
56990
  access: "delete"
56846
56991
  },
56847
- "pipelineAnalytics.deleteRetrainDatasetVersion": {
56848
- capName: "pipeline-analytics",
56849
- capScope: "device",
56850
- addonId: null,
56851
- access: "delete"
56852
- },
56853
56992
  "pipelineAnalytics.deleteTracks": {
56854
56993
  capName: "pipeline-analytics",
56855
56994
  capScope: "device",
@@ -56952,6 +57091,12 @@ Object.freeze({
56952
57091
  addonId: null,
56953
57092
  access: "view"
56954
57093
  },
57094
+ "pipelineAnalytics.getRetrainCorpusKpi": {
57095
+ capName: "pipeline-analytics",
57096
+ capScope: "device",
57097
+ addonId: null,
57098
+ access: "view"
57099
+ },
56955
57100
  "pipelineAnalytics.getRetrainExportUrl": {
56956
57101
  capName: "pipeline-analytics",
56957
57102
  capScope: "device",
@@ -57072,7 +57217,7 @@ Object.freeze({
57072
57217
  addonId: null,
57073
57218
  access: "view"
57074
57219
  },
57075
- "pipelineAnalytics.listRetrainDatasetVersions": {
57220
+ "pipelineAnalytics.listRetrainCorpusPage": {
57076
57221
  capName: "pipeline-analytics",
57077
57222
  capScope: "device",
57078
57223
  addonId: null,
@@ -57126,12 +57271,6 @@ Object.freeze({
57126
57271
  addonId: null,
57127
57272
  access: "create"
57128
57273
  },
57129
- "pipelineAnalytics.previewRetrainDataset": {
57130
- capName: "pipeline-analytics",
57131
- capScope: "device",
57132
- addonId: null,
57133
- access: "view"
57134
- },
57135
57274
  "pipelineAnalytics.proposeRetrainAnnotations": {
57136
57275
  capName: "pipeline-analytics",
57137
57276
  capScope: "device",
@@ -57210,6 +57349,12 @@ Object.freeze({
57210
57349
  addonId: null,
57211
57350
  access: "create"
57212
57351
  },
57352
+ "pipelineAnalytics.resolveRetrainTrainingCorpus": {
57353
+ capName: "pipeline-analytics",
57354
+ capScope: "device",
57355
+ addonId: null,
57356
+ access: "view"
57357
+ },
57213
57358
  "pipelineAnalytics.restageRetrainTrack": {
57214
57359
  capName: "pipeline-analytics",
57215
57360
  capScope: "device",
@@ -57270,12 +57415,6 @@ Object.freeze({
57270
57415
  addonId: null,
57271
57416
  access: "create"
57272
57417
  },
57273
- "pipelineAnalytics.verifyRetrainDatasetVersion": {
57274
- capName: "pipeline-analytics",
57275
- capScope: "device",
57276
- addonId: null,
57277
- access: "view"
57278
- },
57279
57418
  "pipelineAnalytics.wipeAllAnalytics": {
57280
57419
  capName: "pipeline-analytics",
57281
57420
  capScope: "device",
@@ -59670,18 +59809,6 @@ Object.freeze({
59670
59809
  addonId: null,
59671
59810
  access: "create"
59672
59811
  },
59673
- "training.findDatasetVersionIdByName": {
59674
- capName: "training",
59675
- capScope: "system",
59676
- addonId: null,
59677
- access: "view"
59678
- },
59679
- "training.getDatasetVersion": {
59680
- capName: "training",
59681
- capScope: "system",
59682
- addonId: null,
59683
- access: "view"
59684
- },
59685
59812
  "training.getJob": {
59686
59813
  capName: "training",
59687
59814
  capScope: "system",
@@ -59700,12 +59827,6 @@ Object.freeze({
59700
59827
  addonId: null,
59701
59828
  access: "view"
59702
59829
  },
59703
- "training.listDatasetVersions": {
59704
- capName: "training",
59705
- capScope: "system",
59706
- addonId: null,
59707
- access: "view"
59708
- },
59709
59830
  "training.listJobs": {
59710
59831
  capName: "training",
59711
59832
  capScope: "system",
@@ -59718,54 +59839,66 @@ Object.freeze({
59718
59839
  addonId: null,
59719
59840
  access: "view"
59720
59841
  },
59721
- "training.putDatasetVersion": {
59842
+ "training.registerResult": {
59722
59843
  capName: "training",
59723
59844
  capScope: "system",
59724
59845
  addonId: null,
59725
59846
  access: "create"
59726
59847
  },
59727
- "training.registerResult": {
59848
+ "training.rollbackCanary": {
59728
59849
  capName: "training",
59729
59850
  capScope: "system",
59730
59851
  addonId: null,
59731
59852
  access: "create"
59732
59853
  },
59733
- "training.removeDatasetVersion": {
59854
+ "training.startJob": {
59734
59855
  capName: "training",
59735
59856
  capScope: "system",
59736
59857
  addonId: null,
59737
- access: "delete"
59858
+ access: "create"
59738
59859
  },
59739
- "training.rollbackCanary": {
59860
+ "training.startJobBatch": {
59740
59861
  capName: "training",
59741
59862
  capScope: "system",
59742
59863
  addonId: null,
59743
59864
  access: "create"
59744
59865
  },
59745
- "training.startJob": {
59746
- capName: "training",
59866
+ "trainingProvider.cancelJob": {
59867
+ capName: "training-provider",
59747
59868
  capScope: "system",
59748
59869
  addonId: null,
59749
59870
  access: "create"
59750
59871
  },
59751
- "trainingProvider.cancelJob": {
59872
+ "trainingProvider.cleanupJob": {
59752
59873
  capName: "training-provider",
59753
59874
  capScope: "system",
59754
59875
  addonId: null,
59755
59876
  access: "create"
59756
59877
  },
59757
- "trainingProvider.cleanupJob": {
59878
+ "trainingProvider.createEntry": {
59758
59879
  capName: "training-provider",
59759
59880
  capScope: "system",
59760
59881
  addonId: null,
59761
59882
  access: "create"
59762
59883
  },
59884
+ "trainingProvider.deleteEntry": {
59885
+ capName: "training-provider",
59886
+ capScope: "system",
59887
+ addonId: null,
59888
+ access: "delete"
59889
+ },
59763
59890
  "trainingProvider.describe": {
59764
59891
  capName: "training-provider",
59765
59892
  capScope: "system",
59766
59893
  addonId: null,
59767
59894
  access: "view"
59768
59895
  },
59896
+ "trainingProvider.describeTypes": {
59897
+ capName: "training-provider",
59898
+ capScope: "system",
59899
+ addonId: null,
59900
+ access: "view"
59901
+ },
59769
59902
  "trainingProvider.estimateJob": {
59770
59903
  capName: "training-provider",
59771
59904
  capScope: "system",
@@ -59778,6 +59911,12 @@ Object.freeze({
59778
59911
  addonId: null,
59779
59912
  access: "view"
59780
59913
  },
59914
+ "trainingProvider.listEntries": {
59915
+ capName: "training-provider",
59916
+ capScope: "system",
59917
+ addonId: null,
59918
+ access: "view"
59919
+ },
59781
59920
  "trainingProvider.listJobEvents": {
59782
59921
  capName: "training-provider",
59783
59922
  capScope: "system",
@@ -63414,6 +63553,11 @@ Object.freeze({
63414
63553
  form: "array",
63415
63554
  optional: false
63416
63555
  }],
63556
+ "pipelineAnalytics.listRetrainCorpusPage": [{
63557
+ name: "deviceIds",
63558
+ form: "array",
63559
+ optional: true
63560
+ }],
63417
63561
  "pipelineAnalytics.listRetrainStaging": [{
63418
63562
  name: "deviceIds",
63419
63563
  form: "array",