Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/annotator/src/adapters/react/visibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const WIRE = {
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
},
{
id: "b",
Expand All @@ -36,6 +37,7 @@ const WIRE = {
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
},
],
};
Expand Down
1 change: 1 addition & 0 deletions frontend/annotator/src/core/geometry/hitTest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function annotationOf(id: string, geometry: Geometry): Annotation {
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/annotator/src/core/input/_palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export function annotationOf(
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down
4 changes: 4 additions & 0 deletions frontend/annotator/src/core/interaction/draft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export function draftAnnotation(
geometry,
attributes: defaultAttributes(document, labelClass),
provenance: "human",
// Null until the server stamps it. The engine has no idea which job it is
// being driven inside — it takes a document, not a workflow — and inventing
// one here would be a client claiming provenance the service overwrites.
job_id: null,
model_ref: null,
confidence: null,
};
Expand Down
1 change: 1 addition & 0 deletions frontend/annotator/src/core/interaction/tags.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ function annotationOf(
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/annotator/src/core/state/_random.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function randomAnnotation(
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/annotator/src/core/state/_sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export function annotation(id: string, x = 0): Annotation {
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/annotator/src/core/state/document.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function annotation(id: string, overrides: Partial<Annotation> = {}): Annotation
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
...overrides,
};
}
Expand Down
13 changes: 13 additions & 0 deletions frontend/annotator/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@ export interface Annotation {
readonly provenance: Provenance;
readonly model_ref: string | null;
readonly confidence: number | null;
/**
* Which round of work produced this label, or `null` when nothing recorded it.
*
* Read-only here, and absent from both projections below for the reason
* `schema_version` is: the service stamps it with the job doing the writing,
* so a field a client could set would be one it never observes.
*
* `null` is a real answer rather than a gap in this build: a label written
* before the column existed, whose asset belonged to more than one job, could
* not be attributed by the migration — and guessing would have put a
* confident wrong answer where an honest absent one belongs.
*/
readonly job_id: string | null;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions frontend/annotator/src/core/wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const ANNOTATION_KEY_SET: Record<keyof Annotation, true> = {
provenance: true,
model_ref: true,
confidence: true,
job_id: true,
};

/** Exactly the keys of `Annotation`, in declaration order. */
Expand Down Expand Up @@ -358,6 +359,7 @@ export function parseAnnotation(value: unknown): Annotation {
model_ref: requireNullableString(value["model_ref"], "annotation.model_ref"),
confidence:
confidence === null ? null : requireNumber(confidence, "annotation.confidence"),
job_id: requireNullableString(value["job_id"], "annotation.job_id"),
};
}

Expand Down
2 changes: 2 additions & 0 deletions frontend/app/e2e/annotate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ async function serveApi(
asset_count: 2,
allowed_actions: batchActions(lifecycle.batch),
promoted_asset_count: 0,
parent_batch_id: null,
progress: {
unannotated: 2,
annotated: 0,
Expand Down Expand Up @@ -203,6 +204,7 @@ async function serveApi(
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
}),
);
return route.fulfill({ status: 201, json: { items: stored, total: stored.length } });
Expand Down
4 changes: 4 additions & 0 deletions frontend/app/e2e/gallery.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ async function serveApi(page: Page, sent: Request[], options: Options = {}): Pro
progress: counts,
allowed_actions: batchActions(current),
promoted_asset_count: 0,
parent_batch_id: null,
},
});
}
Expand Down Expand Up @@ -235,6 +236,7 @@ async function serveApi(page: Page, sent: Request[], options: Options = {}): Pro
progress: counts,
allowed_actions: batchActions(current),
promoted_asset_count: 0,
parent_batch_id: null,
},
});
}
Expand All @@ -256,6 +258,7 @@ async function serveApi(page: Page, sent: Request[], options: Options = {}): Pro
progress: counts,
allowed_actions: batchActions(current),
promoted_asset_count: 0,
parent_batch_id: null,
},
});
}
Expand Down Expand Up @@ -298,6 +301,7 @@ async function serveApi(page: Page, sent: Request[], options: Options = {}): Pro
geometry: { type: "bbox", x: 1, y: 1, width: 10, height: 10 },
attributes: {},
confidence: null,
job_id: null,
model_ref: null,
provenance: "human",
schema_version: 3,
Expand Down
1 change: 1 addition & 0 deletions frontend/app/e2e/navigation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ async function serveApi(page: Page): Promise<void> {
state: "in_annotation",
allowed_actions: batchActions("in_annotation"),
promoted_asset_count: 0,
parent_batch_id: null,
schema_version: 1,
asset_count: 1,
progress: { ...NO_PROGRESS, unannotated: 1, total: 1 },
Expand Down
1 change: 1 addition & 0 deletions frontend/app/e2e/viewport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ async function serveApi(page: Page): Promise<void> {
schema_version: 1,
allowed_actions: batchActions("in_annotation"),
promoted_asset_count: 0,
parent_batch_id: null,
asset_count: 1,
progress: NO_PROGRESS,
},
Expand Down
1 change: 1 addition & 0 deletions frontend/app/src/demo/benchScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ function annotationOf(id: string, labelClass: string, geometry: Annotation["geom
geometry,
attributes: {},
provenance: "human",
job_id: null,
model_ref: null,
confidence: null,
};
Expand Down
2 changes: 2 additions & 0 deletions frontend/ui-core/src/annotator/jobQueries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function loaded(id: string, labelClass = "vehicle"): WireAnnotation {
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down Expand Up @@ -70,6 +71,7 @@ describe("planSave", () => {
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
}),
);

Expand Down
10 changes: 10 additions & 0 deletions frontend/ui-core/src/annotator/jobQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ export interface WireAnnotation {
readonly provenance: string;
readonly model_ref: string | null;
readonly confidence: number | null;
/**
* Which round produced this label. Read but never sent — the service stamps it.
*
* Declared here even though nothing in this module uses it, because the
* annotator's own `parseAnnotation` checks the key set **exactly**: a payload
* carrying a field this mirror omits is refused outright rather than ignored.
* That is the point of the exact check, and it makes a server field additive
* only if both mirrors move together.
*/
readonly job_id: string | null;
}
export type SchemaVersion = components["schemas"]["SchemaVersionOut"];

Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/annotator/panel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function annotation(id: string, labelClass: string, type: "bbox" | "polygon"): u
provenance: "human",
model_ref: null,
confidence: null,
job_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/annotator/viewportFloor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ beforeEach(() => {
asset_count: 1,
allowed_actions: batchActions("in_annotation"),
promoted_asset_count: 0,
parent_batch_id: null,
progress: {
unannotated: 1,
annotated: 0,
Expand Down
4 changes: 4 additions & 0 deletions frontend/ui-core/src/generated/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1554,6 +1554,8 @@ export interface components {
* Format: uuid
*/
id: string;
/** Job Id */
job_id: string | null;
/** Label Class */
label_class: string;
/** Model Ref */
Expand Down Expand Up @@ -1796,6 +1798,8 @@ export interface components {
id: string;
/** Name */
name: string;
/** Parent Batch Id */
parent_batch_id: string | null;
progress: components["schemas"]["ProgressCounts"];
/**
* Project Id
Expand Down
4 changes: 2 additions & 2 deletions frontend/ui-core/src/generated/checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const checkPolygonBody: Check<Schemas["PolygonBody"]> =
/*#__PURE__*/ object({ "points": [true, arrayOf(tuple([isNumber, isNumber] as const))], "type": [true, lit("polygon")] } as const);

export const checkAnnotationOut: Check<Schemas["AnnotationOut"]> =
/*#__PURE__*/ object({ "asset_id": [true, isString], "attributes": [true, mapOf(either([isBoolean, isNumber, isString] as const))], "confidence": [true, either([isNumber, isNull] as const)], "geometry": [true, tagged("type", { "bbox": checkBboxBody, "classification_tag": checkClassificationBody, "polygon": checkPolygonBody })], "id": [true, isString], "label_class": [true, isString], "model_ref": [true, either([isString, isNull] as const)], "provenance": [true, oneOf(["human", "model", "import"] as const)], "schema_version": [true, isInteger] } as const);
/*#__PURE__*/ object({ "asset_id": [true, isString], "attributes": [true, mapOf(either([isBoolean, isNumber, isString] as const))], "confidence": [true, either([isNumber, isNull] as const)], "geometry": [true, tagged("type", { "bbox": checkBboxBody, "classification_tag": checkClassificationBody, "polygon": checkPolygonBody })], "id": [true, isString], "job_id": [true, either([isString, isNull] as const)], "label_class": [true, isString], "model_ref": [true, either([isString, isNull] as const)], "provenance": [true, oneOf(["human", "model", "import"] as const)], "schema_version": [true, isInteger] } as const);

export const checkAnnotationPage: Check<Schemas["AnnotationPage"]> =
/*#__PURE__*/ object({ "items": [true, arrayOf(checkAnnotationOut)], "total": [true, isInteger] } as const);
Expand Down Expand Up @@ -83,7 +83,7 @@ export const checkProgressCounts: Check<Schemas["ProgressCounts"]> =
/*#__PURE__*/ object({ "accepted": [true, isInteger], "annotated": [true, isInteger], "review_pending": [true, isInteger], "skipped": [true, isInteger], "total": [true, isInteger], "unannotated": [true, isInteger] } as const);

export const checkBatchOut: Check<Schemas["BatchOut"]> =
/*#__PURE__*/ object({ "allowed_actions": [true, arrayOf(checkBatchAction)], "asset_count": [true, isInteger], "id": [true, isString], "name": [true, isString], "progress": [true, checkProgressCounts], "project_id": [true, isString], "promoted_asset_count": [true, isInteger], "schema_version": [true, either([isInteger, isNull] as const)], "state": [true, checkBatchState] } as const);
/*#__PURE__*/ object({ "allowed_actions": [true, arrayOf(checkBatchAction)], "asset_count": [true, isInteger], "id": [true, isString], "name": [true, isString], "parent_batch_id": [true, either([isString, isNull] as const)], "progress": [true, checkProgressCounts], "project_id": [true, isString], "promoted_asset_count": [true, isInteger], "schema_version": [true, either([isInteger, isNull] as const)], "state": [true, checkBatchState] } as const);

export const checkBatchPage: Check<Schemas["BatchPage"]> =
/*#__PURE__*/ object({ "items": [true, arrayOf(checkBatchOut)], "total": [true, isInteger] } as const);
Expand Down
2 changes: 2 additions & 0 deletions frontend/ui-core/src/screens/batchLifecycle.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const DRAFT: Batch = {
asset_count: 48,
allowed_actions: batchActions("draft"),
promoted_asset_count: 0,
parent_batch_id: null,
progress: {
unannotated: 48,
annotated: 0,
Expand Down Expand Up @@ -167,6 +168,7 @@ describe("the approve dialog's refusals", () => {
schema_version: 3,
allowed_actions: batchActions("approved"),
promoted_asset_count: 0,
parent_batch_id: null,
},
});
const closed = vi.fn();
Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/screens/gallery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ function batch(overrides: Record<string, unknown> = {}): Record<string, unknown>
progress: { ...NO_PROGRESS, unannotated: 120, total: 120 },
allowed_actions: batchActions(state),
promoted_asset_count: 0,
parent_batch_id: null,
...overrides,
};
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/ui-core/src/screens/ingest.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,8 @@ describe("launching a run", () => {
status: 200,
body: {
items: [
{ id: "b1", project_id: PROJECT, name: "open", state: "draft", schema_version: null, asset_count: 4, progress: NO_PROGRESS, allowed_actions: batchActions("draft"), promoted_asset_count: 0 },
{ id: "b2", project_id: PROJECT, name: "frozen", state: "in_annotation", schema_version: 1, asset_count: 9, progress: NO_PROGRESS, allowed_actions: batchActions("in_annotation"), promoted_asset_count: 0 },
{ id: "b1", project_id: PROJECT, name: "open", state: "draft", schema_version: null, asset_count: 4, progress: NO_PROGRESS, allowed_actions: batchActions("draft"), promoted_asset_count: 0, parent_batch_id: null },
{ id: "b2", project_id: PROJECT, name: "frozen", state: "in_annotation", schema_version: 1, asset_count: 9, progress: NO_PROGRESS, allowed_actions: batchActions("in_annotation"), promoted_asset_count: 0, parent_batch_id: null },
],
total: 2,
},
Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/screens/navigation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ function answer(path: string): unknown {
progress: NO_PROGRESS,
allowed_actions: batchActions("in_annotation"),
promoted_asset_count: 0,
parent_batch_id: null,
};
}
if (path === `/batches/${BATCH}/assets`) return { items: [], total: 0 };
Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/screens/overview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ function batchOf(state: string): Record<string, unknown> {
},
allowed_actions: batchActions(state as BatchState),
promoted_asset_count: 0,
parent_batch_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/screens/promote.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ function batch(overrides: Partial<Batch> = {}): Batch {
},
allowed_actions: batchActions("completed"),
promoted_asset_count: 0,
parent_batch_id: null,
...overrides,
} as Batch;
}
Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/screens/readiness.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ function batchOf(state: string): Record<string, unknown> {
},
allowed_actions: batchActions(state as BatchState),
promoted_asset_count: 0,
parent_batch_id: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions frontend/ui-core/src/screens/screens.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,7 @@ describe("the project header", () => {
},
allowed_actions: batchActions(options.batchState as BatchState),
promoted_asset_count: 0,
parent_batch_id: null,
},
],
total: 1,
Expand Down
Loading
Loading