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
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ function ensureRoomDesignGoal(req: ChatRequest, intent: AecTaskIntentV1, roomNum
const objective = intent.evidence.user_text.trim() || `Lay out receptacles in Room ${roomNumber}.`;
const active = getActiveGoalForSession(req.session_id);
const sameObjective = !!active && active.objective.trim().toLocaleLowerCase() === objective.toLocaleLowerCase();
const replaceableAutoGoal = !!active && active.created_by === "auto_goal:chat" && sameObjective && active.work_items.length === 0 && active.evidence_log.length === 0 && active.action_log.length === 0 && active.validation_log.length === 0;
const context = req.context && typeof req.context === "object" && !Array.isArray(req.context) ? req.context as Record<string, unknown> : null;
const ui = context?.ui && typeof context.ui === "object" && !Array.isArray(context.ui) ? context.ui as Record<string, unknown> : null;
const authoritative = typeof ui?.authoritative_user_text === "string" ? ui.authoritative_user_text.trim() : "";
const replaceableAutoGoal = !!active && active.created_by === "auto_goal:chat" && active.related_session_id === req.session_id && (sameObjective || authoritative === objective) && active.work_items.length === 0 && active.evidence_log.length === 0 && active.action_log.length === 0 && active.validation_log.length === 0;
if (active && !replaceableAutoGoal) return;
setAgentGoal(req.session_id, {
title: `Design receptacle layout in Room ${roomNumber}`,
Expand Down
26 changes: 25 additions & 1 deletion apps/operator-backend/test/room_receptacle_analog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import test, { after, before } from "node:test";
import { OPERATOR_BACKEND_CONTRACT_VERSION, type ChatRequest, type ToolResult } from "../src/contracts.js";
import { __testOnlyVerifiedAnalogApplyReceipt, maybeRunDeterministicRoomReceptacleAnalog } from "../src/deterministic/room_receptacle_analog.js";
import { AEC_TASK_INTENT_V1_SCHEMA, type AecTaskIntentV1 } from "../src/aec_task_intent.js";
import { getActiveGoalForSession } from "../src/goals/service.js";
import { getActiveGoalForSession, setAgentGoal } from "../src/goals/service.js";

const previousWorkspace = process.env.OPERATOR_WORKSPACE_ROOT;
let testWorkspace = "";
Expand Down Expand Up @@ -140,6 +140,30 @@ test("room design persists target, selected precedent, exact apply evidence, and
assert.match(completed?.progress_summary ?? "", /Room 407 apply and native persistent readback passed/);
});

test("authoritative room request replaces only an empty model-expanded auto goal", () => {
const session = "room-authoritative-auto-goal";
const prompt = "Layout receptacles in room 403.";
setAgentGoal(session, {
title: "Expanded room plan",
objective: "Inspect Room 403, place and circuit devices, save the model, and report all locations.",
success_criteria: ["Complete or block truthfully."],
created_by: "auto_goal:chat",
current_phase: "observe",
current_step: "preflight"
} as any);
const req = sessionRequest(session, prompt);
req.context = { ui: { authoritative_user_text: prompt } };
const intent = layoutIntent();
intent.evidence.user_text = prompt;
const response = maybeRunDeterministicRoomReceptacleAnalog(req, intent);
assert.deepEqual(response?.actions.map(action => action.path), ["/revit/plan-room-receptacles-from-analog"]);
const goal = getActiveGoalForSession(session);
assert.equal(goal?.objective, prompt);
assert.equal(goal?.work_budget?.mode, "room_receptacle_design");
assert.equal(goal?.work_budget?.conversational_permission_loops, 0);
assert.equal(goal?.work_items.find(item => item.id === "target.inspect")?.scope?.room_number, "403");
});

test("completion receipt requires exact current-run ids plus type, room, host, position, and orientation evidence", () => {
const valid = appliedReceipt([1700001], [{ familyType: "Duplex Receptacle|Standard", count: 1 }]);
assert.ok(__testOnlyVerifiedAnalogApplyReceipt(valid));
Expand Down
Loading