PlanOmatic Operations · agent console

Zillow Floorplan Agent

Access is enforced on the server per role. This screen only signs you in; it does not decide what you may reach.
Security

Set a new password

Your account requires a password change before you can continue.
PlanOmatic Operations
0/0 wired · 0 dead
—
Admin
Zillow Floor Plan
Post-Processing QA
Zillow safety state Workflow … Vision API spend … PlanoQ writes … Full automation … Fire limit …

What this tab is for: a PlanOmatic admin assigns people to roles and decides which tabs each role can see, across BOTH agent boards. Roles are fully configurable here — create, rename, delete, and re-grant. Access is enforced on the server per role; hiding a tab in the UI is not access control.

Roles & page accessi

Fully configurable. Add a role, rename or delete one, and tick to grant a page. Roles are referenced internally by a stable ID, so a rename only changes the label.
GET/api/roles · /api/pages
CRUDPOST /api/roles · PUT /api/roles/{role_id} · DELETE /api/roles/{role_id}
GRANTGET/PUT /api/roles/{role_id}/tabs (stable ID, never a name)
Sourceroles, role_tab_grants (config)
Effectserver-side gates each route per role, every request, FAIL-CLOSED
Statepending

Peoplei

Add a user, assign a role, or deactivate. Access follows from the assigned role.
GET/api/users
CRUDPOST /api/users · PUT /api/users/{id}/role · POST /api/users/{id}/deactivate
Sourceusers, roles (config)
Effectsets the user's role; tab access derives from the grants
Statepending

Operations Dashboard

Agent operations for the PlanOmatic Operations team.

HITL is the queue of everything an agent could not finish on its own, and the tab to check first each day. Configs holds the switches and the QA checks; a change there takes effect on the agent’s next run, not just on this screen.

What this tab is for: how the agent is performing — how much it processed, how good its QA calls turned out to be, and where it needs tuning. Everything here is read-only.

Time window
i

Month over monthi

Processed volume by month, split pass / review / fail (last 12 months).
passedreviewfailed
GET/api/metrics/timeseries?bucket=month&months=12
Sourceqa_results
Effectrenders monthly series
Statepending

QA check performancei

Per-check flag volume, trend, and how often a human upheld the agent's flag. This is where to look to improve QA.
#CheckFlags (window)6-mo trend Human agreement i
GET/api/metrics/checks?window=&trend=6mo
Sourceqa_results.check_results ⋈ operator outcomes
Effectrenders per-check volume + agreement
Statepending

QA calibration — the agent's report cardi

Agent verdict (cf 73) versus the operator's final action (cf 70). Green cells are agreement; red cells are the misses to watch.
GET/api/metrics/calibration?window=
Sourceqa_results.cf73 ⋈ jobs.cf70 (Order cf 2)
Effectrenders matrix + derived rates
Statepending

Lifecycle state (cf 70)i

What the agent’s QA verdict implies for Floor Plan Status. Projected from our own results, not read back from PlanoQ. Hover any state for what it means.
GET/api/jobs?group=fp_status
Sourcejobs.cf70
Effectrenders counts
Statepending

What this tab is for: the settings that change how the agent behaves. Every control below is genuinely wired to the config key the agent reads live each run — a save here changes what the agent does on its next run, not just this screen. Run mode (REVIEW_MODE / DRAFT_ONLY) has been retired: Master Controls below gives the same staged-rollout control more directly.

Rollout modei

How floor plan jobs get run.
How many jobs to firei
Full automation stops after this many jobs. 0 means unlimited. Changing the number restarts the count.
The agent takes the jobs you can actually review first, so setting 3 gives you three graded floor plans to check.
✓ saved
Vision jobs per dayi
Roughly 5.5c per plan. 0 means unlimited. Resets itself at midnight, so there is nothing to clear.
✓ saved
Day resets at midnight ini
The team's own timezone, so the day ends when their day does.
✓ saved

Master controlsi

The three gates on real spend and writes.
Agent workflow
Master power for the whole agent. Off means nothing runs, scheduled or fired.
Loading…
LLM (Vision API) spend
Lets the agent call the vision model to grade floor plans. The money gate. Cost is capped and measured (~5.5c per floor plan).
Turning on enables billable vision calls
Loading…
PlanoQ writes
Lets the agent write the floor plan and its fields back onto real PlanoQ job cards.
Turning on modifies live client job cards
Loading…

Poll cadencei

How often the agent checks the Zillow inbox.
Fixed at 15 minutes today, shown for information only — the poller does not yet re-read an editable interval per cycle.

Matching & timeoutsi

The address bridge and the two watchdogs. The matcher is deterministic: house number + street name must agree after normalization. There is no similarity score and no confidence threshold — the normalization tolerance table is the only matching tunable, and it is shared across agents rather than independently editable here.
GET/PUT/api/controls/marked_addressed_return_hours
Sourcemarked_addressed_return_hours → escalations view bucketing (§9a)
Effectgenuinely changes dashboard behavior on save; address normalization tolerance is shown read-only (shared, not per-agent)
Statepending

QA check severity & enablementi

Set each check to Fail (marks the floorplan failed) or Review (sends it to a person), or switch it off. Human-only checks always go to a person — the agent can't judge them from the image — so their severity is locked at Review.
#CheckSeverityEnabled i
GET/PUT/api/controls/{qa.check.<id>.severity, qa.check.<id>.enabled}
Sourcethe QA engine's RuleExecutor reads these same dotted keys on every run (19 checks)
Effecta severity change moves whether the check fails or reviews the plan; disabling a check stands it down entirely
Statepending

Label dictionaries & termsi

Editable lists the QA engine reads live.
GET/PUT/api/controls/{qa.dict.room_dictionary, qa.dict.unique_labels, qa.dict.repeatable_labels, qa.term_to_avoid.terms, qa.dims_missing.exempt_labels, qa.dims_missing.non_exempt_labels, qa.disclaimer.reference_text}
Sourcethe QA engine reads these same dotted keys on every run
Effecta save changes what the QA engine checks against on its next run
Statepending
Change history

Who changed a Master Controls switch, when, and to what. Newest first.

Agent workflow

Every time the whole agent was started or stopped, from the Agent workflow switch above. Who, when, and which direction. Newest first.
GET/api/run-state/history
Sourceaction_log (auth_agent_run_state_change)
Effectread-only; the audit row this tab's toggle already writes
Statepending

LLM (Vision API) spend

Every time vision spend was turned on or off, from the LLM (Vision API) spend switch above. Who, when, and which direction. Newest first.
GET/api/vision-spend/history
Sourceaction_log (auth_vision_spend_change)
Effectread-only; the audit row this tab's toggle already writes
Statepending

PlanoQ writes

Every time PlanoQ card writes were turned on or off, from the PlanoQ writes switch above. Who, when, and which direction. Newest first.
GET/api/write-enable/history
Sourceaction_log (auth_master_write_enable_change)
Effectread-only; the audit row this tab's toggle already writes
Statepending

What this tab is for: every floorplan-eligible PlanoQ job as a thin line item with status and a link out. Click a row to expand its detail; click a job's issue number to open it in PlanoQ. This page can also fire jobs: selecting rows and pressing Fire selected writes the stored QA verdict onto those live PlanoQ cards immediately — there is no queue and no confirmation step after the button. Nothing else on this page writes anything.

0 selected Writes to live PlanoQ cards. Nothing is re-analysed; the stored verdict is committed.
Issue ID Address Project Card status QA status Created Updated Agent wrote Fire
GET/api/jobs?limit=&offset=&sort=&dir=&q=&created_since=&created_until=
GET (expand)/api/jobs/{issue_id}
Sourcejobs, joined with the agent-store fp_status projection; expand adds latest_qa_verdict + bound_tours
Effectrenders the real job list a page at a time, server-sorted/filtered/searched; PlanoQ link built client-side from issue_id, no write of any kind
Statepending

What this tab is for: one place to see everything the agent couldn't finish on its own, centralized across PlanOq and Zillow 3D. This board is read-only toward PlanOq — your team keeps working in PlanOq and the Zillow 3D dashboard exactly as today, and nothing here writes to PlanOq. Most items clear themselves once the agent sees the real status change. A tour with no address cannot: no signal will ever arrive for it, so it waits for a person.

How an item moves: Active→ a user taps Mark addressed → Marked addressed→ agent sees the real status change → Resolved · or after the configured window with no real resolution, it drops back to Active (only the agent confirms Resolved)

Issue queuei

Read-only toward PlanOq. Link out to do the actual work in PlanOq or Zillow 3D; the board updates itself when the status changes.
GET/api/escalations?view={active|addressed|resolved}
MARKPOST /api/escalations/{id}/addressed · POST /api/escalations/{id}/active — agent store ONLY (never PlanOq)
Sourcetour_items, jobs.cf70, qa_results — derived, read-only; re-derived from PlanOq saves + Zillow emails via receiver
Effectself-clears on status change; addressed auto-returns after marked_addressed_return_hours; agent sets Resolved; NO PlanOq write
Statepending

QA vieweri

Opened from any escalation or job.
GET/api/qa/{job_id}
Sourceqa_results, floorplans
Effectrenders image + per-check results
Statepending

What this tab is for: browse EVERY job's full agent result, beyond the aggregate calibration matrix and the escalations subset. Filter by agreement outcome (including the critical false-pass cell), by per-check firing, and by date window. Read-only: this table never writes, never mutates a job, and offers no approve or advance action of any kind.

Browse-all audit tablei

Rows reflect the derived, append-only source (action_log + the §5a closure tuples) exactly. Not-yet-closed rows are visible but unlabeled, never asserted resolved. Zero rows under a filter shows zero rows and the filter, never sample data. Rows deep-link to the per-job QA drill-in on the HITL tab.
GET/api/audit/orders?agreement&check&check_status&false_pass&from&to&date_field — the ONLY method under /api/audit
Sourceqa_results ⋈ qa_check_results ⋈ action_log ⋈ §5a closure tuples — derived, read-only; the closure tuple's self-label scores agreement, the run verdict governs the qa_review bar
Effectfilterable browse-all (client-side sort/page); bad filter → server 400 surfaced; ZERO writes by construction
Statepending
Phase-5 dashboard · built to Interface Contract Rev 11 (contract wins on conflict; mockup is the visual reference) Wiring state: proven by live round-trip against the backend · 0 wired · 0 dead

UI wiring ledger

0 wired · 0 dead

Every interactive element, traced element → endpoint → handler → data source → runtime effect → live round-trip state. State reflects the LAST real request, never a design-time assertion: live (data rendered), empty (endpoint returned nothing — honest empty-state), refused (server 401/403 reflected), pending (not yet exercised), not wired (the round-trip can succeed, but no code path this agent runs actually reads the key back, so editing it cannot change real behavior; ROUTING 157 audit).

ElementEndpointHandler / sourceRuntime effectState