1
0

feat: add deterministic office robot jobs

This commit is contained in:
2026-08-19 02:54:49 -07:00
parent 0557a26e6b
commit e378a03740
18 changed files with 1937 additions and 1779 deletions
+14 -14
View File
@@ -96,9 +96,9 @@ import {
import {
createRobotLayer,
type RobotLayer,
type RobotSpec,
type RobotView,
} from "./robots.ts";
import type { RobotOperationsDefinition } from "./robotOperations.ts";
import type {
ScenePeers,
ScenePeersOptions,
@@ -220,17 +220,8 @@ export interface OfficeSceneOptions {
* those are the three things you actually feel.
*/
horizon?: { drop: number };
/**
* Humanoids to walk about the floor, one entry per robot.
*
* **Not gated on `depth`, unlike `presence`, and that asymmetry is the point.**
* The build-time-exclusion rule in this file's header is about *occupancy* — a
* `Presence` names a person and comes from an authenticated API, so the public
* office must not construct one. A robot is nobody: it carries no id anybody
* issued, no seat binding, and no data from anywhere. There is nothing to
* withhold, so a stranger gets them too.
*/
robots?: readonly RobotSpec[];
/** Authored seeded simulation; omitted means this office has no robot activity. */
robotOperations?: RobotOperationsDefinition;
/** Optional local walk actor. Constructed inactive unless `walker.active` says otherwise. */
walker?: OfficeWalkerOptions;
/** Full-depth-only authoritative remote actors/vehicles in local metre coordinates. */
@@ -319,6 +310,8 @@ export interface OfficeScene extends StageScene {
* The plan panel and the ceiling lights both consume it that way.
*/
robots(): readonly RobotView[];
/** Honest provenance for UI and diagnostics; null when no simulation is authored. */
robotActivityInfo(): { operationsId: string; disclosure: string; simulated: true } | null;
upsertRemoteSnapshot(snapshot: EntityPoseSnapshot): boolean;
removeRemoteEntity(id: string): boolean;
clearRemoteEntities(): void;
@@ -521,8 +514,8 @@ export function createOfficeScene(office: Office, options: OfficeSceneOptions):
const luminaires: Luminaires = createLuminaires(furnishings.luminaires);
const robots: RobotLayer | null =
options.robots && options.robots.length > 0
? createRobotLayer(plan, { materials, robots: options.robots })
options.robotOperations && options.robotOperations.robots.length > 0
? createRobotLayer(plan, { materials, operations: options.robotOperations })
: null;
const officeWalker = options.walker ? createOfficeWalker(plan, options.walker) : null;
if (officeWalker) scene.add(officeWalker.root);
@@ -856,6 +849,13 @@ export function createOfficeScene(office: Office, options: OfficeSceneOptions):
},
houseLevel: () => luminaires.houseLevel(),
robots: () => robots?.robots() ?? NO_ROBOTS,
robotActivityInfo: () => robots
? {
operationsId: options.robotOperations!.id,
disclosure: robots.disclosure,
simulated: true,
}
: null,
setWalkers(walkers) {
luminaires.setWalkers(walkers);
},