fix(awooop): keep closed work progress monotonic
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 6m10s
CD Pipeline / build-and-deploy (push) Successful in 8m50s
CD Pipeline / post-deploy-checks (push) Successful in 3m1s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 6m10s
CD Pipeline / build-and-deploy (push) Successful in 8m50s
CD Pipeline / post-deploy-checks (push) Successful in 3m1s
This commit is contained in:
@@ -33,6 +33,7 @@ import {
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { AutonomousRuntimeReceiptPanel } from "@/components/awooop/autonomous-runtime-receipt-panel";
|
||||
import { IncidentEvidenceHeader } from "@/components/awooop/incident-evidence-header";
|
||||
import { isMonotonicPriorityWorkOrderProjection } from "@/lib/priority-work-order-projection";
|
||||
import { getRuntimeApiBaseUrl } from "@/lib/runtime-api-base";
|
||||
import {
|
||||
AwoooPStatusChainPanel,
|
||||
@@ -12809,7 +12810,7 @@ export default function AwoooPWorkItemsPage() {
|
||||
for (const url of urls) {
|
||||
const nextPriorityWorkOrder =
|
||||
await fetchJson<PriorityWorkOrderResponse>(url, 12000);
|
||||
if (nextPriorityWorkOrder?.commander_inserted_requirement_work_items?.length) {
|
||||
if (isMonotonicPriorityWorkOrderProjection(nextPriorityWorkOrder)) {
|
||||
setPriorityWorkOrderReadback(nextPriorityWorkOrder);
|
||||
setPriorityWorkOrderLoading(false);
|
||||
return nextPriorityWorkOrder;
|
||||
@@ -12817,7 +12818,6 @@ export default function AwoooPWorkItemsPage() {
|
||||
}
|
||||
await new Promise((resolve) => window.setTimeout(resolve, 1200));
|
||||
}
|
||||
setPriorityWorkOrderLoading(false);
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
@@ -12964,7 +12964,23 @@ export default function AwoooPWorkItemsPage() {
|
||||
}, [effectiveFocusedIncidentId, projectId]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchPriorityWorkOrderReadback();
|
||||
let cancelled = false;
|
||||
let retryTimer: number | null = null;
|
||||
|
||||
const loadPriorityWorkOrder = async () => {
|
||||
const readback = await fetchPriorityWorkOrderReadback();
|
||||
if (!cancelled && !readback) {
|
||||
retryTimer = window.setTimeout(loadPriorityWorkOrder, 4000);
|
||||
}
|
||||
};
|
||||
|
||||
void loadPriorityWorkOrder();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
if (retryTimer !== null) {
|
||||
window.clearTimeout(retryTimer);
|
||||
}
|
||||
};
|
||||
}, [fetchPriorityWorkOrderReadback]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { isMonotonicPriorityWorkOrderProjection } from "../priority-work-order-projection";
|
||||
|
||||
const closedWorkItems = [
|
||||
"AIA-P0-001",
|
||||
"AIA-P0-011",
|
||||
"AIA-P0-002",
|
||||
"AIA-P0-003",
|
||||
"AIA-P0-004",
|
||||
"AIA-P0-005",
|
||||
].map((id) => ({ id, status: "done" }));
|
||||
|
||||
describe("isMonotonicPriorityWorkOrderProjection", () => {
|
||||
it("accepts the production-closed 30 percent projection", () => {
|
||||
expect(
|
||||
isMonotonicPriorityWorkOrderProjection({
|
||||
commander_inserted_requirement_work_items: [{}],
|
||||
ai_automation_program_ledger: {
|
||||
work_items: [...closedWorkItems, { id: "AIA-P0-006", status: "in_progress" }],
|
||||
summary: { done_count: 6, completion_percent: 30 },
|
||||
},
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects a transient zero projection that reopens closed work", () => {
|
||||
expect(
|
||||
isMonotonicPriorityWorkOrderProjection({
|
||||
commander_inserted_requirement_work_items: [{}],
|
||||
ai_automation_program_ledger: {
|
||||
work_items: closedWorkItems.map((item) => ({
|
||||
...item,
|
||||
status: "in_progress",
|
||||
})),
|
||||
summary: { done_count: 0, completion_percent: 0 },
|
||||
},
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts future progress above the current closure floor", () => {
|
||||
expect(
|
||||
isMonotonicPriorityWorkOrderProjection({
|
||||
commander_inserted_requirement_work_items: [{}],
|
||||
ai_automation_program_ledger: {
|
||||
work_items: [...closedWorkItems, { id: "AIA-P0-006", status: "done" }],
|
||||
summary: { done_count: 7, completion_percent: 35 },
|
||||
},
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
47
apps/web/src/lib/priority-work-order-projection.ts
Normal file
47
apps/web/src/lib/priority-work-order-projection.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
const MONOTONIC_CLOSED_PROGRAM_WORK_ITEM_IDS = [
|
||||
"AIA-P0-001",
|
||||
"AIA-P0-011",
|
||||
"AIA-P0-002",
|
||||
"AIA-P0-003",
|
||||
"AIA-P0-004",
|
||||
"AIA-P0-005",
|
||||
] as const;
|
||||
|
||||
type PriorityWorkOrderProjection = {
|
||||
commander_inserted_requirement_work_items?: unknown[] | null;
|
||||
ai_automation_program_ledger?: {
|
||||
work_items?: Array<{
|
||||
id?: string | null;
|
||||
status?: string | null;
|
||||
}> | null;
|
||||
summary?: {
|
||||
done_count?: number | null;
|
||||
completion_percent?: number | null;
|
||||
} | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export function isMonotonicPriorityWorkOrderProjection(
|
||||
projection: PriorityWorkOrderProjection | null | undefined
|
||||
): boolean {
|
||||
if (!projection?.commander_inserted_requirement_work_items?.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const program = projection.ai_automation_program_ledger;
|
||||
const workItems = program?.work_items ?? [];
|
||||
const statusById = new Map(
|
||||
workItems.map((item) => [item.id ?? "", item.status ?? ""])
|
||||
);
|
||||
const closureFloorSatisfied = MONOTONIC_CLOSED_PROGRAM_WORK_ITEM_IDS.every(
|
||||
(workItemId) => statusById.get(workItemId) === "done"
|
||||
);
|
||||
const doneCount = Number(program?.summary?.done_count ?? 0);
|
||||
const completionPercent = Number(program?.summary?.completion_percent ?? 0);
|
||||
|
||||
return (
|
||||
closureFloorSatisfied &&
|
||||
doneCount >= MONOTONIC_CLOSED_PROGRAM_WORK_ITEM_IDS.length &&
|
||||
completionPercent >= 30
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user