From 120eac878a62a5e1fefc9bd899c41f57497cea0f Mon Sep 17 00:00:00 2001 From: Kartios Date: Wed, 19 Aug 2026 02:59:25 -0700 Subject: [PATCH] fix: align robot jobs with active HQ plans --- src/arena/officeJobs.ts | 8 ++-- src/arena/sourceHashes.ts | 4 +- src/offices/operations/lumbridge-hq.ts | 59 ++++++++++++-------------- src/offices/operations/mateo-court.ts | 20 +++++++-- src/offices/runtime.ts | 4 +- src/test/robotActivity.test.ts | 9 ++-- 6 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/arena/officeJobs.ts b/src/arena/officeJobs.ts index 08cfbe9..0f09986 100644 --- a/src/arena/officeJobs.ts +++ b/src/arena/officeJobs.ts @@ -84,22 +84,22 @@ const DEFINITIONS = [ { id: "train-sf-display-inspection", split: "train" as const, - parameters: { officeId: "lumbridge-hq" as const, robotId: "sf-l1-inspector", jobId: "sf-l1-inspect-display" }, + parameters: { officeId: "lumbridge-hq" as const, robotId: "sf-studio-activity-01", jobId: "sf-studio-inspect-display" }, }, { id: "train-la-directory-inspection", split: "train" as const, - parameters: { officeId: "mateo-court" as const, robotId: "la-l1-inspector", jobId: "la-l1-inspect-directory" }, + parameters: { officeId: "mateo-court" as const, robotId: "la-office-activity-01", jobId: "la-l1-inspect-directory" }, }, { id: "dev-sf-parcel-delivery", split: "dev" as const, - parameters: { officeId: "lumbridge-hq" as const, robotId: "sf-l1-courier", jobId: "sf-l1-deliver" }, + parameters: { officeId: "lumbridge-hq" as const, robotId: "sf-studio-activity-01", jobId: "sf-studio-deliver" }, }, { id: "dev-la-loft-delivery", split: "dev" as const, - parameters: { officeId: "mateo-court" as const, robotId: "la-l2-courier", jobId: "la-l2-deliver" }, + parameters: { officeId: "mateo-court" as const, robotId: "la-office-activity-02", jobId: "la-l2-deliver" }, }, ] as const; diff --git a/src/arena/sourceHashes.ts b/src/arena/sourceHashes.ts index 84fc793..fd3d5fb 100644 --- a/src/arena/sourceHashes.ts +++ b/src/arena/sourceHashes.ts @@ -14,8 +14,8 @@ export const ARENA_SOURCE_HASHES: Readonly> = simulator: "sha256:34bb82d70b471cb3734d196f6ad1c685b9154083cf7e319c6089127f7a87eaf3", }, "office-jobs-v1": { - environment: "sha256:525bdab6cdc5ea1ca684654d0745392936df68ecec415a145eb05a07c003d9bd", - simulator: "sha256:df19af3cd7f906c54dc87f15e4a6df0003bd585c13ccdb63ad3b5632e8c49200", + environment: "sha256:76cb8ec23745b05d1f9d408b948618d8fcbd93cf3ac46e018163702bffdc3e0f", + simulator: "sha256:aca85f5c0ec1430b8c5fab38233af757f93eefda1341c4c9d0fb5dfad24b0476", }, "crow-nav-v1": { environment: "sha256:141b1850ac01b1922a7db88ea6c30b15521302d720099de5f91c07472633f797", diff --git a/src/offices/operations/lumbridge-hq.ts b/src/offices/operations/lumbridge-hq.ts index 6762369..fa032df 100644 --- a/src/offices/operations/lumbridge-hq.ts +++ b/src/offices/operations/lumbridge-hq.ts @@ -1,46 +1,41 @@ import type { RobotOperationsDefinition } from "../../interiors/robotOperations.ts"; -/** Authored, seeded demonstration operations for the public Lumbridge HQ plan. */ +/** Authored, seeded demonstration operations for the compact SF studio. */ export const LUMBRIDGE_HQ_ROBOT_OPERATIONS = Object.freeze({ id: "lumbridge-hq-robot-operations", version: 1, officeId: "lumbridge-hq", disclosure: "Seeded robot simulation — no live people, company activity, or operational data.", stations: [ - { id: "sf-l1-dock", label: "Level 1 charge dock", role: "charge", anchor: { kind: "point", levelId: "level-1", position: { x: 9.2, z: 7.2 }, facing: { x: 1, z: 0 } } }, - { id: "sf-l1-lobby", label: "Lobby patrol point", role: "patrol", anchor: { kind: "room", roomId: "lobby" } }, - { id: "sf-l1-kitchen", label: "Kitchen patrol point", role: "patrol", anchor: { kind: "room", roomId: "kitchen" } }, - { id: "sf-l1-commons", label: "Commons patrol point", role: "patrol", anchor: { kind: "room", roomId: "commons" } }, - { id: "sf-l1-parcel-pickup", label: "Open floor parcel lockers", role: "pickup", anchor: { kind: "prop", propId: "open-locker-01", standoffM: 0.8 } }, - { id: "sf-l1-parcel-drop", label: "Facilities shelf", role: "dropoff", anchor: { kind: "prop", propId: "fac-shelf-01", standoffM: 0.82 } }, - { id: "sf-l1-display", label: "Open floor display", role: "inspect", anchor: { kind: "prop", propId: "open-display", standoffM: 0.72 } }, - { id: "sf-l1-board", label: "Workshop board", role: "inspect", anchor: { kind: "prop", propId: "shop-whiteboard", standoffM: 0.72 } }, - - { id: "sf-l2-dock", label: "Level 2 charge dock", role: "charge", anchor: { kind: "point", levelId: "level-2", position: { x: 5.0, z: 5.2 }, facing: { x: 1, z: 0 } } }, - { id: "sf-l2-landing", label: "Landing patrol point", role: "patrol", anchor: { kind: "room", roomId: "l2-landing" } }, - { id: "sf-l2-studio", label: "Studio patrol point", role: "patrol", anchor: { kind: "room", roomId: "l2-studio" } }, - { id: "sf-l2-gallery", label: "Gallery patrol point", role: "patrol", anchor: { kind: "room", roomId: "l2-gallery" } }, - { id: "sf-l2-parcel-pickup", label: "Library shelf", role: "pickup", anchor: { kind: "prop", propId: "l2-library-shelf-03", standoffM: 0.78, side: -1 } }, - { id: "sf-l2-parcel-drop", label: "Project shelf", role: "dropoff", anchor: { kind: "prop", propId: "l2-project-shelf-01", standoffM: 0.78, side: -1 } }, - { id: "sf-l2-board", label: "Studio board", role: "inspect", anchor: { kind: "prop", propId: "l2-studio-board", standoffM: 0.72 } }, - { id: "sf-l2-project-board", label: "Project board", role: "inspect", anchor: { kind: "prop", propId: "l2-project-board-02", standoffM: 0.72 } }, + { + id: "sf-studio-dock", + label: "Studio charge dock", + role: "charge", + anchor: { kind: "point", levelId: "level-1", position: { x: 5.65, z: 5.3 }, facing: { x: 1, z: 0 } }, + }, + { id: "sf-studio-entry", label: "Entry patrol point", role: "patrol", anchor: { kind: "point", levelId: "level-1", position: { x: 1.1, z: 7.5 }, facing: { x: 0, z: -1 } } }, + { id: "sf-studio-kitchen", label: "Kitchen patrol point", role: "patrol", anchor: { kind: "room", roomId: "kitchen" } }, + { id: "sf-studio-lounge", label: "Demo lounge patrol point", role: "patrol", anchor: { kind: "point", levelId: "level-1", position: { x: 7.0, z: 6.0 }, facing: { x: 1, z: 0 } } }, + { id: "sf-studio-pickup", label: "Entry shelf parcel pickup", role: "pickup", anchor: { kind: "prop", propId: "entry-shelf", standoffM: 0.8, side: -1 } }, + { id: "sf-studio-dropoff", label: "Lounge table parcel drop", role: "dropoff", anchor: { kind: "prop", propId: "lounge-table", standoffM: 0.8 } }, + { id: "sf-studio-display", label: "Demo display inspection", role: "inspect", anchor: { kind: "prop", propId: "open-display", standoffM: 0.72, side: -1 } }, + { id: "sf-studio-monitor", label: "Agent monitor inspection", role: "inspect", anchor: { kind: "prop", propId: "lobby-monitor", standoffM: 0.72, side: -1 } }, ], jobs: [ - { id: "sf-l1-patrol", label: "Level 1 safety patrol", kind: "patrol", stationIds: ["sf-l1-lobby", "sf-l1-kitchen", "sf-l1-commons"], dwellTicks: 6 }, - { id: "sf-l1-deliver", label: "Locker-to-facilities parcel", kind: "deliver", stationIds: ["sf-l1-parcel-pickup", "sf-l1-parcel-drop"], dwellTicks: 9 }, - { id: "sf-l1-inspect-display", label: "Display inspection", kind: "inspect", stationIds: ["sf-l1-display"], dwellTicks: 14 }, - { id: "sf-l1-inspect-board", label: "Workshop board inspection", kind: "inspect", stationIds: ["sf-l1-board"], dwellTicks: 12 }, - { id: "sf-l1-charge", label: "Level 1 charge cycle", kind: "charge", stationIds: ["sf-l1-dock"], dwellTicks: 1 }, - { id: "sf-l2-patrol", label: "Level 2 safety patrol", kind: "patrol", stationIds: ["sf-l2-landing", "sf-l2-studio", "sf-l2-gallery"], dwellTicks: 6 }, - { id: "sf-l2-deliver", label: "Library-to-project parcel", kind: "deliver", stationIds: ["sf-l2-parcel-pickup", "sf-l2-parcel-drop"], dwellTicks: 9 }, - { id: "sf-l2-inspect-studio", label: "Studio board inspection", kind: "inspect", stationIds: ["sf-l2-board"], dwellTicks: 14 }, - { id: "sf-l2-inspect-project", label: "Project board inspection", kind: "inspect", stationIds: ["sf-l2-project-board"], dwellTicks: 12 }, - { id: "sf-l2-charge", label: "Level 2 charge cycle", kind: "charge", stationIds: ["sf-l2-dock"], dwellTicks: 1 }, + { id: "sf-studio-patrol", label: "Studio safety patrol", kind: "patrol", stationIds: ["sf-studio-entry", "sf-studio-kitchen", "sf-studio-lounge"], dwellTicks: 6 }, + { id: "sf-studio-deliver", label: "Entry-to-lounge parcel", kind: "deliver", stationIds: ["sf-studio-pickup", "sf-studio-dropoff"], dwellTicks: 9 }, + { id: "sf-studio-inspect-display", label: "Demo display inspection", kind: "inspect", stationIds: ["sf-studio-display"], dwellTicks: 14 }, + { id: "sf-studio-inspect-monitor", label: "Agent monitor inspection", kind: "inspect", stationIds: ["sf-studio-monitor"], dwellTicks: 12 }, + { id: "sf-studio-charge", label: "Studio charge cycle", kind: "charge", stationIds: ["sf-studio-dock"], dwellTicks: 1 }, ], robots: [ - { id: "sf-l1-courier", label: "SF L1 courier", levelId: "level-1", spawnStationId: "sf-l1-dock", schedule: ["sf-l1-deliver", "sf-l1-patrol", "sf-l1-charge"], initialBattery: 0.7 }, - { id: "sf-l1-inspector", label: "SF L1 inspector", levelId: "level-1", spawnStationId: "sf-l1-lobby", schedule: ["sf-l1-inspect-display", "sf-l1-inspect-board", "sf-l1-patrol", "sf-l1-charge"], initialBattery: 0.48 }, - { id: "sf-l2-courier", label: "SF L2 courier", levelId: "level-2", spawnStationId: "sf-l2-dock", schedule: ["sf-l2-deliver", "sf-l2-patrol", "sf-l2-charge"], initialBattery: 0.66 }, - { id: "sf-l2-inspector", label: "SF L2 inspector", levelId: "level-2", spawnStationId: "sf-l2-landing", schedule: ["sf-l2-inspect-studio", "sf-l2-inspect-project", "sf-l2-patrol", "sf-l2-charge"], initialBattery: 0.44 }, + { + id: "sf-studio-activity-01", + label: "SF studio support robot", + levelId: "level-1", + spawnStationId: "sf-studio-dock", + schedule: ["sf-studio-deliver", "sf-studio-inspect-display", "sf-studio-inspect-monitor", "sf-studio-patrol", "sf-studio-charge"], + initialBattery: 0.72, + }, ], } satisfies RobotOperationsDefinition); diff --git a/src/offices/operations/mateo-court.ts b/src/offices/operations/mateo-court.ts index 2557d1c..23559f5 100644 --- a/src/offices/operations/mateo-court.ts +++ b/src/offices/operations/mateo-court.ts @@ -38,9 +38,21 @@ export const MATEO_COURT_ROBOT_OPERATIONS = Object.freeze({ { id: "la-l2-charge", label: "Loft charge cycle", kind: "charge", stationIds: ["la-l2-dock"], dwellTicks: 1 }, ], robots: [ - { id: "la-l1-courier", label: "LA L1 courier", levelId: "level-1", spawnStationId: "la-l1-dock", schedule: ["la-l1-deliver", "la-l1-patrol", "la-l1-charge"], initialBattery: 0.7 }, - { id: "la-l1-inspector", label: "LA L1 inspector", levelId: "level-1", spawnStationId: "la-l1-paseo", schedule: ["la-l1-inspect-directory", "la-l1-inspect-display", "la-l1-patrol", "la-l1-charge"], initialBattery: 0.48 }, - { id: "la-l2-courier", label: "LA L2 courier", levelId: "level-2", spawnStationId: "la-l2-dock", schedule: ["la-l2-deliver", "la-l2-patrol", "la-l2-charge"], initialBattery: 0.66 }, - { id: "la-l2-inspector", label: "LA L2 inspector", levelId: "level-2", spawnStationId: "la-l2-palmetto", schedule: ["la-l2-inspect-display", "la-l2-inspect-board", "la-l2-patrol", "la-l2-charge"], initialBattery: 0.44 }, + { + id: "la-office-activity-01", + label: "LA office operations robot", + levelId: "level-1", + spawnStationId: "la-l1-dock", + schedule: ["la-l1-deliver", "la-l1-inspect-directory", "la-l1-inspect-display", "la-l1-patrol", "la-l1-charge"], + initialBattery: 0.7, + }, + { + id: "la-office-activity-02", + label: "LA model review robot", + levelId: "level-2", + spawnStationId: "la-l2-dock", + schedule: ["la-l2-deliver", "la-l2-inspect-display", "la-l2-inspect-board", "la-l2-patrol", "la-l2-charge"], + initialBattery: 0.66, + }, ], } satisfies RobotOperationsDefinition); diff --git a/src/offices/runtime.ts b/src/offices/runtime.ts index 16d85d3..e8316f5 100644 --- a/src/offices/runtime.ts +++ b/src/offices/runtime.ts @@ -10,14 +10,14 @@ * robot-jobs runtime without changing stable robot ids. */ -import type { RobotSpec } from "../interiors/robots.ts"; import type { Office } from "../interiors/types.ts"; import type { ShippedOfficeId } from "./sites.ts"; export type OfficeRobotJobSet = "studio-support" | "office-operations" | "model-review"; -export interface OfficeActivityRobotSpec extends RobotSpec { +export interface OfficeActivityRobotSpec { id: string; + levelId: string; /** Stable per-robot seed for a future job scheduler or replay harness. */ seed: number; jobSet: OfficeRobotJobSet; diff --git a/src/test/robotActivity.test.ts b/src/test/robotActivity.test.ts index 153b6f3..57a10a6 100644 --- a/src/test/robotActivity.test.ts +++ b/src/test/robotActivity.test.ts @@ -46,14 +46,15 @@ describe("robot operations and routes", () => { }), /simulated/, ); + const laPlan = new Plan(MATEO_COURT, { warn: false }); assert.throws( - () => resolveRobotOperations(plan, { - ...LUMBRIDGE_HQ_ROBOT_OPERATIONS, + () => resolveRobotOperations(laPlan, { + ...MATEO_COURT_ROBOT_OPERATIONS, jobs: [{ id: "bad-route", label: "Bad route", kind: "deliver", - stationIds: ["sf-l1-parcel-pickup", "sf-l2-parcel-drop"], + stationIds: ["la-l1-parcel-pickup", "la-l2-parcel-drop"], dwellTicks: 1, }], robots: [], @@ -109,7 +110,7 @@ describe("robot activity determinism", () => { it("exposes deterministic blocked recovery for a controlled robot", () => { const plan = new Plan(LUMBRIDGE_HQ, { warn: false }); const operations = resolveRobotOperations(plan, LUMBRIDGE_HQ_ROBOT_OPERATIONS); - const id = "sf-l1-courier"; + const id = "sf-studio-activity-01"; const activity = createRobotActivity(plan, operations, { seed: 1, robotIds: [id],