fix(cases): בל"מ badge reads proceeding_type, not just appeal_subtype
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 43s

After the proceeding_type field landed, users started flipping cases
to בל"מ via the edit dialog. But the case-header badge + cases-table
filter were still gated on isBlamSubtype(appeal_subtype), so the badge
didn't appear when only the proceeding_type changed. Now the badge
shows when either proceeding_type === 'בל"מ' OR appeal_subtype is an
extension_request_* variant — the legacy path stays so existing rows
that never got a proceeding_type still render correctly.

Also regen types.ts from prod (proceeding_type now in OpenAPI schema)
and register the one-shot process_pending_blam.py script.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 09:34:23 +00:00
parent d359ab9884
commit ac3ed455cf
5 changed files with 593 additions and 5 deletions

View File

@@ -63,7 +63,7 @@ export function CaseHeader({ data }: { data?: CaseDetail }) {
)}
</Badge>
)}
{isBlamSubtype(data?.appeal_subtype) && (
{(data?.proceeding_type === 'בל"מ' || isBlamSubtype(data?.appeal_subtype)) && (
<Badge
variant="outline"
className="rounded-full px-2.5 py-0.5 text-[0.72rem] font-bold bg-warn/10 text-warn-deep border-warn/40"

View File

@@ -55,7 +55,7 @@ const columns: ColumnDef<Case>[] = [
header: "כותרת",
cell: ({ row }) => (
<div className="text-ink max-w-[420px] truncate flex items-center gap-2" title={row.original.title}>
{isBlamSubtype(row.original.appeal_subtype) && (
{(row.original.proceeding_type === 'בל"מ' || isBlamSubtype(row.original.appeal_subtype)) && (
<Badge
variant="outline"
className="rounded-full px-1.5 py-0 text-[0.65rem] font-bold bg-warn/10 text-warn-deep border-warn/40 shrink-0"
@@ -113,8 +113,10 @@ export function CasesTable({
const data = useMemo(() => {
const all = cases ?? [];
if (blamFilter === "blam") return all.filter((c) => isBlamSubtype(c.appeal_subtype));
if (blamFilter === "regular") return all.filter((c) => !isBlamSubtype(c.appeal_subtype));
const isBlam = (c: Case) =>
c.proceeding_type === 'בל"מ' || isBlamSubtype(c.appeal_subtype);
if (blamFilter === "blam") return all.filter(isBlam);
if (blamFilter === "regular") return all.filter((c) => !isBlam(c));
return all;
}, [cases, blamFilter]);

View File

@@ -777,6 +777,48 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/cases/{case_number}/aggregate-arguments": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Api Aggregate Arguments
* @description Aggregate raw claims into distinct legal arguments via Claude.
*
* Runs as a BackgroundTask because the LLM pass can take 30-90 seconds.
*/
post: operations["api_aggregate_arguments_api_cases__case_number__aggregate_arguments_post"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/cases/{case_number}/legal-arguments": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Api Get Legal Arguments
* @description Return aggregated legal arguments for a case, grouped by party.
*/
get: operations["api_get_legal_arguments_api_cases__case_number__legal_arguments_get"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/cases/{case_number}/direction": {
parameters: {
query?: never;
@@ -2255,6 +2297,75 @@ export interface paths {
patch: operations["halacha_update_api_halachot__halacha_id__patch"];
trace?: never;
};
"/api/missing-precedents": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Missing Precedents List
* @description List missing precedents, optionally filtered by status / case.
*/
get: operations["missing_precedents_list_api_missing_precedents_get"];
put?: never;
/**
* Missing Precedent Create
* @description Log a new missing precedent (status='open'). Dedupes by
* (citation, cited_in_case_id) — duplicate POST returns the existing row.
*/
post: operations["missing_precedent_create_api_missing_precedents_post"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/missing-precedents/{mp_id}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Missing Precedent Get */
get: operations["missing_precedent_get_api_missing_precedents__mp_id__get"];
put?: never;
post?: never;
/** Missing Precedent Delete */
delete: operations["missing_precedent_delete_api_missing_precedents__mp_id__delete"];
options?: never;
head?: never;
/** Missing Precedent Update */
patch: operations["missing_precedent_update_api_missing_precedents__mp_id__patch"];
trace?: never;
};
"/api/missing-precedents/{mp_id}/upload": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Missing Precedent Upload
* @description Upload the decision file behind a missing-precedent and link it.
*
* Routes to ingest_internal_decision if the citation looks like a
* committee decision (ערר / בל"מ prefix), otherwise to ingest_precedent.
* Once the case_law row is created, the missing_precedents row is marked
* status='closed' with linked_case_law_id pointing to the new row.
*/
post: operations["missing_precedent_upload_api_missing_precedents__mp_id__upload_post"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
}
export type webhooks = Record<string, never>;
export interface components {
@@ -2388,6 +2499,81 @@ export interface components {
*/
summary: string;
};
/** Body_missing_precedent_upload_api_missing_precedents__mp_id__upload_post */
Body_missing_precedent_upload_api_missing_precedents__mp_id__upload_post: {
/** File */
file: string;
/**
* Case Number
* @default
*/
case_number: string;
/**
* Chair Name
* @default
*/
chair_name: string;
/**
* District
* @default
*/
district: string;
/**
* Case Name
* @default
*/
case_name: string;
/**
* Court
* @default
*/
court: string;
/**
* Decision Date
* @default
*/
decision_date: string;
/**
* Practice Area
* @default
*/
practice_area: string;
/**
* Appeal Subtype
* @default
*/
appeal_subtype: string;
/**
* Subject Tags
* @default []
*/
subject_tags: string;
/**
* Is Binding
* @default true
*/
is_binding: boolean;
/**
* Headnote
* @default
*/
headnote: string;
/**
* Summary
* @default
*/
summary: string;
/**
* Precedent Level
* @default
*/
precedent_level: string;
/**
* Source Type
* @default
*/
source_type: string;
};
/** Body_precedent_library_upload_api_precedent_library_upload_post */
Body_precedent_library_upload_api_precedent_library_upload_post: {
/** File */
@@ -2507,7 +2693,7 @@ export interface components {
expected_outcome: string;
/**
* Practice Area
* @default appeals_committee
* @default
*/
practice_area: string;
/**
@@ -2515,6 +2701,11 @@ export interface components {
* @default
*/
appeal_subtype: string;
/**
* Proceeding Type
* @default
*/
proceeding_type: string;
};
/** CaseUpdateRequest */
CaseUpdateRequest: {
@@ -2555,6 +2746,25 @@ export interface components {
* @default
*/
expected_outcome: string;
/** Appellants */
appellants?: string[] | null;
/** Respondents */
respondents?: string[] | null;
/**
* Property Address
* @default
*/
property_address: string;
/**
* Permit Number
* @default
*/
permit_number: string;
/**
* Proceeding Type
* @default
*/
proceeding_type: string;
};
/** ChairPositionRequest */
ChairPositionRequest: {
@@ -2681,6 +2891,57 @@ export interface components {
/** Value */
value: unknown;
};
/** MissingPrecedentCreate */
MissingPrecedentCreate: {
/** Citation */
citation: string;
/**
* Case Number
* @default
*/
case_number: string;
/** Cited In Document Id */
cited_in_document_id?: string | null;
/**
* Cited By Party
* @default unknown
* @enum {string}
*/
cited_by_party: "appellant" | "respondent" | "committee" | "permit_applicant" | "unknown";
/** Cited By Party Name */
cited_by_party_name?: string | null;
/** Legal Topic */
legal_topic?: string | null;
/** Legal Issue */
legal_issue?: string | null;
/** Claim Quote */
claim_quote?: string | null;
/** Case Name */
case_name?: string | null;
/** Notes */
notes?: string | null;
};
/** MissingPrecedentPatch */
MissingPrecedentPatch: {
/** Legal Topic */
legal_topic?: string | null;
/** Legal Issue */
legal_issue?: string | null;
/** Notes */
notes?: string | null;
/** Cited By Party */
cited_by_party?: ("appellant" | "respondent" | "committee" | "permit_applicant" | "unknown") | null;
/** Cited By Party Name */
cited_by_party_name?: string | null;
/** Case Name */
case_name?: string | null;
/** Status */
status?: ("open" | "uploaded" | "closed" | "irrelevant") | null;
/** Citation */
citation?: string | null;
/** Claim Quote */
claim_quote?: string | null;
};
/** OutcomeRequest */
OutcomeRequest: {
/** Outcome */
@@ -2768,6 +3029,10 @@ export interface components {
precedent_level?: string | null;
/** Is Binding */
is_binding?: boolean | null;
/** District */
district?: string | null;
/** Chair Name */
chair_name?: string | null;
};
/** ReviseRequest */
ReviseRequest: {
@@ -3908,6 +4173,72 @@ export interface operations {
};
};
};
api_aggregate_arguments_api_cases__case_number__aggregate_arguments_post: {
parameters: {
query?: {
force?: boolean;
};
header?: never;
path: {
case_number: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
api_get_legal_arguments_api_cases__case_number__legal_arguments_get: {
parameters: {
query?: {
party?: string;
};
header?: never;
path: {
case_number: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
api_set_direction_api_cases__case_number__direction_post: {
parameters: {
query?: never;
@@ -6333,4 +6664,205 @@ export interface operations {
};
};
};
missing_precedents_list_api_missing_precedents_get: {
parameters: {
query?: {
status?: string;
case_id?: string;
case_number?: string;
legal_topic?: string;
limit?: number;
offset?: number;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
missing_precedent_create_api_missing_precedents_post: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["MissingPrecedentCreate"];
};
};
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
missing_precedent_get_api_missing_precedents__mp_id__get: {
parameters: {
query?: never;
header?: never;
path: {
mp_id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
missing_precedent_delete_api_missing_precedents__mp_id__delete: {
parameters: {
query?: never;
header?: never;
path: {
mp_id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
missing_precedent_update_api_missing_precedents__mp_id__patch: {
parameters: {
query?: never;
header?: never;
path: {
mp_id: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["MissingPrecedentPatch"];
};
};
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
missing_precedent_upload_api_missing_precedents__mp_id__upload_post: {
parameters: {
query?: never;
header?: never;
path: {
mp_id: string;
};
cookie?: never;
};
requestBody: {
content: {
"multipart/form-data": components["schemas"]["Body_missing_precedent_upload_api_missing_precedents__mp_id__upload_post"];
};
};
responses: {
/** @description Successful Response */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Validation Error */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
}