All releases
July 2026

July 2026 Updates

OTR System Revenue dashboard replaces the external labor tracker, AegisDoc invoice & estimate templates go live, and a large legacy frontend cleanup lands.

Newsletter status: In progress. See README.md for conversion guide.

v2607.31.0 — July 31, 2026

MRs: !2220, !2222, !2223, !2224

Highlights

Server-side Neo4j read timeouts prevent report-driven database saturation (!2220, closes #6573) Dynamic reports and dashboard widgets that ran long could hold Neo4j read transactions open indefinitely, causing daily DB load spikes that degraded the whole system. Read transactions are now capped at 55s for interactive (frontend-driven) requests and 30 min for background tasks, aligning with the 60s ingress proxy timeout so orphaned queries can’t outlive the client. When a request does time out, the frontend now shows a context-specific, actionable message (“Try a shorter date range”) instead of a generic 504.

Aegis document templates: shared pricing table, per-event subtotals, and inventory notes (!2223, closes #6582) All seven Aegis pricing-table templates (estimates, invoices, receipts) now share a single context-builder pricing model, so multi-event jobs print a per-event subtotal row — the legacy PandaDoc behaviour that was silently missing. The fix also restores free-text inventory notes on estimates (dropped during the PandaDoc migration), renders applied discounts as their own section, and corrects an under-reported total on jobs with damage charges. Customer-facing “To” fields now use a consistent displayName.

Features

  • CSV data export on the OTR-Labor Tracker dashboard with a drill-down report; export button is blocked when stale data is present (!2224, closes #6598)
  • Centralized pricing resolve key in the Aegis context builder carrying grouped charges, per-event subtotals, applied discounts, tax breakdown, and totals — consumed by all seven pricing-table templates (!2223)
  • customer.displayName field for consistent document addressee (“To”) rendering across templates (!2223)
  • MoveDescriptionSimple slimmed move-description step for the streamlined intake flow when VOSE scheduling is skipped (!2222)
  • Dashboard error icons now expose the specific error message via tooltip with keyboard accessibility (role/tabindex, Enter/Space handlers) (!2220)

Fixes

  • Intake scheduling no longer fabricates VOSE availability slots when real estimator availability is empty or the fetch times out — the fallback used the customer’s local timezone instead of the estimator’s, so customers could book times no estimator could work. The scheduling step is now skipped entirely when no windows are available, advancing to move description with contactMethod=ASAP so the relocation team schedules manually (!2222)
  • Aegis estimates now display inventory notes (free-text inventory.notes and inventory.customerSummary), matching PandaDoc’s composite Job.Notes rendering across all four estimate templates (!2223, closes #6582)
  • Aegis invoice/estimate total no longer under-reports jobs with damage charges — estimates computed Total as the sum of charge.total, which zeroes damage charges; now reduces over event.total like PandaDoc (!2223)
  • Zero-value discount rows are now hidden in Aegis document pricing tables (!2223)
  • Aegis notification entity escaping fixed (!2223)
  • Invoice summary table styling corrected (!2223)
  • Dashboard error icons pointed at the wrong error keys: reloadEventsHappening stored failures in eventsCreatedError (lit the wrong widget), and activityViewModel$ never exposed error so the Activity widget’s error icon could never render — both fixed (!2220)
  • Preview-dynamic-report’s bare 504 path fell through to the generic toast because notifyPreviewError only checked GraphQL errors — timeout verdict now passed in explicitly so the timeout copy is reachable (!2220)
  • YMM estimates gated their Inventory section on rooms alone, hiding notes on jobs with notes but no itemized rooms; estimate-standard was not resolving inventory at all — both fixed (!2223)
  • Legacy “Apartment / Condo” building-type inputs with whitespace around slashes are normalized to the canonical “Apartment/Condo” (!2222)

Other

  • Aegis bumped to 0.1.16 (additive notes/customerSummary context fields) (!2223)
  • functions/version.txt set to 2607.30.0 to ship the Aegis template rewrites to Cloudflare R2 via the deploy-functions CI job (!2223)
  • Standard document templates adopt pure black (#000000) for primary body text, renaming SLATEBODY_TEXT for contrast and legibility (!2223)
  • docs/pandadoc-mcp.md documents the PandaDoc MCP footguns and template-ID lookup workflow for the PandaDoc → Aegis migration (!2223)
  • AGENTS.md documents the two-gate deploy policy for functions/ (version.txt change creates the job; hotfix label or release commit satisfies the gate) (!2223)
  • summaryPlainText() shared helper parses the Quill delta for job summaries — the text mirror is absent on 58% of jobs, so reading it silently blanks the summary (!2223)
  • English/Spanish/French intake localization catalogs updated (!2222)

v2607.29.2 — July 29, 2026 [hotfix]

Fixes

  • Fixed NullInjectorError: No provider for ViewArtifactsGQL on the job page — a codegen run dropped the @Injectable({ providedIn: 'root' }) decorator from ViewArtifactsGQL (and 3 other generated GQL classes), causing the refreshDocument effect to crash on injection. Regenerated the file to restore all decorators.
  • Fixed TypeError: Cannot read properties of undefined (reading 'startsWith') in the unsaved-changes banner selector — selectUrl returns undefined before the first navigation completes, so url.startsWith() threw on initial load. Added optional-chaining guards.

v2607.29.1 — July 29, 2026

MRs: !2216, !2221

Highlights

Aegis documents now support interactive input fields with autosave (!2216) Customers and staff can now fill in text, date, and checkbox fields directly on an Aegis document during e-signature — no separate form needed. Inputs are role-scoped (each signer only edits their own fields), debounced autosave over a new versioned WebSocket protocol persists drafts to Neo4j with Redis-backed idempotency receipts, and reloading a document restores any in-progress input. The signing ceremony was reworked around checkpointed drafts and role-scoped “signing coverage” so the system knows exactly which fields each role must complete before signing, with resume/repair on reconnect.

Streamlined intake form UX fixes from CX meeting feedback (!2221) Funnel analysis showed a ~19% drop-off at the scheduling step. The copy is now less imperative (“When are you going to be home?” instead of “You must be home at the time you pick”), the “Call me ASAP” escape hatch uses the accent color so it no longer looks grayed out, and small moves that skip VOSE scheduling now land on a slimmed “Tell us about your move” step instead of jumping straight to contact info.

Features

  • Role-bound input-field (text/date/checkbox) support in Aegis templates with displayName and “sealed” read-only rendering for roles that have already signed (!2216)
  • Resilient browser autosave for Aegis inputs: per-field debounced updates over Aegis WebSocket, acknowledged via correlated field.update/field.acknowledged messages, persisted as Neo4j draft fields with Redis receipt idempotency and /drafts hydration on reload (!2216)
  • Versioned Aegis WebSocket protocol with backend upgrade routing: session initialize/ready handshake, ack correlation, reconnect-safe resend, heartbeat/idle + rate/size/backpressure limits (!2216)
  • Two-phase signing ceremony with generation pinning + CAS-based projection updates, repair/resume, and clear superseded/exhausted outcomes (!2216)
  • Aegis lifecycle “rules triggers” for document automation (created/opened/fields-ready/sent/signed/completed/regenerated/generation-failed) with once-only dedup (!2216)
  • New MoveDescriptionSimple component — a single description textarea step for the streamlined intake flow when VOSE scheduling is skipped (!2221)

Fixes

  • E-sign trust/verification tightened toward DRAW,PHOTO only — removed legacy OTP/payment intent paths and updated tamper-evidence to sign a canonical signing statement (!2216)
  • “Call me ASAP” escape-hatch button in the intake form no longer looks muted/grayed out — now uses accent color with readable contrasting text (!2221)
  • readableTextColor now computes actual WCAG contrast ratio for accent text backgrounds instead of guessing, with safe fallback for invalid hex (!2221)
  • Legacy “Apartment / Condo” building-type inputs with whitespace around slashes are now normalized to the canonical “Apartment/Condo” (!2221)

Other

  • English/Spanish/French localization catalogs updated for new and changed intake copy (!2221)

v2607.29.0 — July 29, 2026

MRs: !2213, !2214, !2215, !2217, !2218, !2219

Highlights

Split PF revenue across multiple franchises in the calculator (!2217, closes #6517) You can now distribute a single job’s PF (franchise partner) revenue across more than one franchise, with cent-level precision. The calculator fields show a per-franchise split table so ops can allocate the split exactly as the business arrangement requires, and the result flows through to the OTR revenue reports.

Fixed job totals being silently overwritten during slow updateJobs calls (!2214) A race condition allowed JobTotals to be overwritten with stale data when an updateJobs call took 15+ seconds and a later estimate pull read totals from the recalculation in flight. Totals are now recalculated and persisted atomically so financials in MR and Estimate always match.

Performance

  • Added a forecast-extract CLI tool that exports Prophet forecast data to Neo4j for ad-hoc analysis without hitting the production database (!2213)

Features

  • Zone admins can now share events, including jobs associated with local locations (!2219, closes #6587)
  • OTR revenue dashboard results now include only jobs whose current stage is “Booking” or “Invoice”, with a job-stage filter applied to the FP revenue split table as well (!2218, closes #6585)
  • Per-location minimumConfidence override added to ProphetDiscountConfig so ops can tune the forecast-quality gate for individual franchises (e.g. Kansas City) without lowering the network-wide default (!2213)

Fixes

  • Job totals were silently overwritten with stale data when updateJobs took 15+ seconds and a subsequent estimate read pulled totals mid-recalculation — totals are now recalculated and persisted atomically (!2214)
  • Square payment link is now sent via email in addition to SMS, and decimal travel time is allowed in the single-units calculator (!2215)

Other

  • Prophet forecast-quality label accessibility fix in the forecast-extract tool (!2213)

v2607.27.0 — July 27, 2026

MRs: !2208, !2209, !2210, !2211, !2212

Highlights

Streamlined virtual estimate scheduling step redesigned to reduce drop-off (!2211) The scheduling step was the biggest funnel leak (~25% drop-off). The redesign pre-expands Today’s time slots, shows recommended next-available times as one-tap buttons, adds a “Call me ASAP” escape hatch, and falls back to generic business-hours slots when the availability API fails. Also skips the step entirely for small moves so yembos aren’t overbooked, and fixes a race condition where stale config could show the step for zones with no virtual estimators.

Aegis estimates now recognized in Ops Readiness dashboard (!2210, closes #6530) Signed Aegis estimates were showing as “Not Signed” in the Ops Readiness dashboard because of a case mismatch in the Cypher query (PandaDoc uses 'Estimate', Aegis uses 'estimate'). Fixed all three docType filters to use case-insensitive matching and handle Aegis’s JSON-stringified eventIds. Also surfaces Ops Notes as a read-only “Ops Summary” card on the job overview page.

Fixes

  • Abandoned calls report couldn’t be opened on Neo4j 4.x — used Neo4j 5-only syntax (!2208, closes #6491)
  • Movers Assistance estimate date now uses the job timeline instead of the event move date (!2209, closes #6546)
  • setup-maps-key.sh apex referrer pattern fixed (*domain.com/* matches both apex and subdomains) and auto-sets per-minute API quotas (!2212)
  • VOSE scheduling: race condition on destination auto-advance could show the step for zones with no virtual estimators (!2211)
  • VOSE scheduling: small moves (below largeMoveSize threshold) no longer show the scheduling step, preventing yembo overbooking (!2211)
  • VOSE scheduling: “Virtual Walkthrough” renamed to “Video Estimate” throughout the scheduling UI (!2211)

Other

  • Address autocomplete biased toward dock location for better pickup suggestions (!2212)
  • Local dev intake setup documentation added (docs/local-dev-intake-setup.md) (!2211)

v2607.24.0 — July 24, 2026

MRs: !2205, !2206, !2207

Highlights

Virtual estimate booking hardened against unavailable estimators (!2205) The intake form now correctly shows “No times available” when the only configured virtual estimator has no availability template, instead of falling back to generic slots that booked a VOSE without an assigned estimator. The backend also defensively skips VOSE event creation when no estimator asset is resolved, so a virtual estimate can never be booked without an estimator.

Fixes

  • Fixed VOSE (virtual estimate) being booked without an estimator asset when the configured estimator has no availability template — the intake frontend no longer falls back to generic slots for virtual estimates, and the backend skips event creation when virtualEstimateAssetId is empty (!2205)
  • Fixed AI prompt showing raw Unix epoch timestamps for calendar events — event start, end, and created times are now formatted as human-readable strings with timezone in the ask-bee YAML context (!2205)
  • Fixed intake.virtualEstimators UUIDs not being resolved to estimator asset names before querying availability (!2205)
  • Fixed spurious “Calculator failed to load” banner flashing on job open when the calculator URL is configured but not yet loaded — the script fetch is now deferred until config is available and re-evaluated if the URL is missing on first pass (!2206)
  • Fixed notification leak into the crew pay tab in the OTR Labor Tracking dashboard (!2207, closes #6539)

Features

  • OTR Labor Tracking dashboard now provides visual feedback when document tracking columns are edited — changes show inline confirmation instead of silently saving (!2207, closes #6539)

Other

  • Added visual feedback (loading/confirmation indicators) to job page and dashboard edits (!2207)

v2607.22.1 — July 22, 2026 [hotfix]

MRs: !2201, !2203, !2204

Fixes

  • Fixed leadsource tokens with null expiration being rejected as expired — null is now treated as “never expires” (!2201)
  • Fixed intake form crash when a zone config value has the wrong format (e.g. a UUID stored in an array field) — getZoneConfigValues now falls back to the default instead of throwing a 500 (!2201)
  • Fixed QuickJS calculator showing a blank screen in production when the script fails to load — the error is now cleaned up after loading (!2204)

Features

  • The streamlined intake form now skips the virtual estimate scheduling step for zones with no intake.virtualEstimators configured. The config is re-fetched with origin/destination after the destination step so the check uses the resolved zone, not just the domain zone (!2203)

Other

  • Added --rebuild flag to es-jobs-load CLI to drop and recreate the jobs index and reset migration flags for a clean re-index (!2201)

v2607.22.0 — July 22, 2026

MRs: !2193, !2194, !2195, !2196, !2197, !2198, !2199, !2200

Highlights

Elasticsearch-powered global search (!2193) The top-bar search now runs on a dedicated Elasticsearch jobs index, replacing the old database-backed autocomplete. Results rank by relevance with boosted name matches, recency, and open-job status, and the redesigned results dropdown shows customer name, status pill, zone, job code, subtotal, and additional contacts. Selecting a job opens it in the side panel or edit page without losing your search context.

Promotional materials in Aegis documents (!2195) Estimates and other Aegis documents can now append branded promotional pages (e.g. mover testimonials, service area photos) as attached PDF pages. Promotional PDFs are sanitized of active content, fetched with a timeout, and size-limited per document. A new Vancouver Island estimate template ships with promotional materials baked in.

Streamlined intake form is now the default (!2194) The A/B test is over — the streamlined intake form is the only variant. This release polishes it with a “Less than 5 items” card, wrapped mobile progress indicators, fixed virtual-estimate booking flow, expanded time slots, and completed French/Spanish translations.

Performance

  • New Elasticsearch jobs index with write-through indexing on job lifecycle and user edit, bulk-load CLI, and relevance scoring that boosts names, recency, and open jobs (!2193)

Features

  • OTR Labor Tracking dashboard now includes columns for crew document compliance tracking (!2198, closes #6539)
  • System Revenue dashboard updated to match the OTR System Revenue layout including the local column (!2199, closes #6537)
  • Document settings table now shows the Aegis migration rate per document type (!2197)
  • Promotional pages support for Aegis documents with sanitized PDF ingestion, timeout, and size limits (!2195)

Fixes

  • Fixed job comments silently failing to submit — the mutation now retries and surfaces errors instead of leaving the button stuck (!2196, closes #6533)
  • Fixed AI sending redundant estimate-signing reminders because the hasSignedEstimate doc-type check was case-sensitive — now resolved case-insensitively (!2193)
  • Fixed Aegis documents showing the estimate date instead of the actual move date — the job move date is now promoted into the document context (!2200, closes #6530, closes #6546)
  • Fixed cancelled events and line items rendering in generated documents — they are now excluded (!2200)
  • Fixed state persistence issues with stale local-storage versions and false-positive Datadog logs for discarded comment mutations (!2194)
  • Fixed calculator showing an infinite skeleton loader when the script fails to load — now displays an error message (!2193)

Other

  • @move-right/aegis bumped to 0.1.14 (mirror pipeline auto-publishes to the GitLab Package Registry) (!2195, !2200)
  • Functions bundle redeployed for promotional page support and the new Vancouver Island estimate template (!2195)

v2607.17.0 — July 17, 2026

MRs: !2189, !2190, !2191, !2192

Highlights

Custom Vancouver Island invoice + Customer Satisfaction Release documents (!2189, !2191) Two new AegisDoc templates ship this release. The YMM Vancouver Island invoice has its own branded layout with payment-terms notice, conditional tax breakdowns, and correct “Prepared By” company name sourced from zone config. A new signable Customer Satisfaction Release of Liability Agreement supports customer and employee signatures for goodwill settlements — registered for ymm-relentless and available through Aegis.

System Revenue dashboard drill-down fix (!2190, closes #6521) Clicking the drill-down in the System Revenue dashboard no longer crashes when the linked report sorts by saleAgent but doesn’t include that column. The link now includes the column, and the preview component guards against invalid columns and falls back to default sorting with a user notification.

Features

  • New YMM Vancouver Island invoice template with Vancouver Island–specific branding, payment-terms notice, and conditional tax/total sections (!2189)
  • New signable Customer Satisfaction Release of Liability Agreement template for goodwill settlements, registered for ymm-relentless via Aegis (!2191)
  • Invoice header block now displays the invoice number (!2189)

Fixes

  • Fixed abandoned-call comment not being recorded and automation not triggering when Dialpad sends events in a different order — parent comment and abandoned reply are now handled across the queued/ringing/hangup event sequence (!2192, closes #6528)
  • Fixed Vancouver Island invoice address formatting to include country and grouped region-zip, and corrected event billing/coverage checks (!2189)
  • Standardized franchise operating name display on documents (!2189)
  • Fixed invoice line item totals to use gross pre-tax subTotal so discounts/taxes render correctly (!2189)
  • Switched to narrow currency symbols for consistent display across documents (!2189)
  • Corrected additionalProperties typo in document schemas (!2189)

Other

  • @move-right/aegis bumped through 0.1.11 → 0.1.13 (mirror pipeline auto-publishes each to the GitLab Package Registry) (!2189, !2191)
  • Functions bundle redeployed for the new Vancouver Island invoice and Customer Satisfaction Release templates (!2189, !2191)

v2607.16.0 — July 16, 2026

MRs: !2183, !2184, !2185, !2188

Highlights

Redesigned Estimate & Receipt templates match the Invoice look (!2183) The standard Estimate and Receipt document templates have been redesigned to match the Invoice template’s layout, typography, and color palette. Shared styling constants and helper functions keep the customer-facing financial documents visually consistent, improving brand cohesion across estimates, receipts, and invoices.

Percentage formatting for Dynamic Report columns (!2184, closes #6515) Dynamic Report columns can now be formatted as percentages. Numeric values (e.g. 0.125) and numeric strings are rendered with two decimal places and a trailing %, and null/undefined values display as None so reports stay readable when data is missing.

Fixes

  • Movers Assistance estimate now displays complete origin, destination, and additional-stop addresses, including address lines one and two (previously only city, jurisdiction, and country were shown) (!2185)
  • Aegis document events now appear in their intended sequential order, and charge line items can be sorted by line-item order or category, fixing estimates/receipts that rendered charges out of order (!2188, closes #6520)

Other

  • The safeColor utility now validates CSS named colors against a comprehensive list of standard names, rejecting invalid color values. transparent is intentionally excluded so accented headings remain visible (!2183)

v2607.15.0 — July 15, 2026

MRs: !2173, !2177, !2178, !2179, !2180, !2181, !2182

Highlights

Document settings page for Aegis rollout management (!2181) Admins can now view and manage document generation at /business/documents — see how many documents have been generated via Aegis vs. PandaDoc per document type, swap engines in one click, and set template URLs. This gives ops full visibility and control over the Aegis migration without touching config files.

Grouped report pagination fix (!2178, closes #6497) Grouped dynamic reports (e.g. groupBy: Job) were silently dropping records when a group appeared many times — the paginator’s total was lower than actual rows, so LIMIT cut off the oldest records with no way to reach them. The query now uses DISTINCT on group keys so each group appears once, and pagination works correctly.

Features

  • New /business/documents settings page showing per-document-type generation counts (Aegis vs. PandaDoc), inline engine switching, and template URL editing (!2181)
  • Canonical document type classification system with backfill migration and database indexes for the document settings report (!2181)
  • Estimate template now displays job timeline for unscheduled moving events instead of showing a blank date (!2181)

Fixes

  • Fixed report period parsing from dashboard drilldown links — period=Custom&customPeriod=... from a link was being overwritten by a default, showing the wrong date range (!2182, closes #6498)
  • Fixed grouped dynamic report fanout pagination silently dropping records when groups spanned multiple underlying rows (!2178, closes #6497)
  • Fixed daily summary calendar showing data shifted by one day — truck utilization for “today” was displaying yesterday’s data (!2177, closes #6495)
  • Fixed crew availability being erased when mass-editing crew via CSV upload — availability columns are now only updated when a value is present (!2173, closes #6490)
  • Removed AI instruction that caused premature autodial scheduling after a call was already initiated but not yet connected (!2180)

Other

  • Restored legacy job workflow GraphQL fragments that were accidentally removed during the frontend cleanup, fixing npm run codegen (!2179)
  • Added database indexes on document type and document settings for faster settings queries (!2181)

v2607.08.1 — July 8, 2026

MRs: !2146, !2168, !2171, !2172

Highlights

New OTR Labor Tracking dashboard (!2146, closes #6281) Ops can now manage paid vs. unpaid labor at the job × crew member level directly in Move Right, replacing the external spreadsheet workflow. Edit paid amounts, mark rows “paid in full,” and use bulk “Pay all jobs in this group” scoped to a payout period — saving triggers a server-side calculator run to refresh totals. Payout period grouping and unpaid-overdue highlighting make it easy to see which jobs need attention.

Streamlined virtual estimate booking flow (!2171) A new streamlined-estimate-booking intake variant (inactive by default, reachable via ?streamlined URL param) removes the photo upload and text/email-only steps, moving date selection up right after move size. A new StreamlinedDateSelector shows a flat list of available dates with expandable time slots and explanatory virtual walkthrough copy — reducing friction for customers booking virtual estimates.

Abandoned call double-text fix (!2171) Dialpad fires hangup events on both call-center and user targets for inbound calls, which was creating duplicate abandoned comments and double-sending the abandoned-call text. A Redis dedup lock now ensures only the first hangup is processed, matching the existing transcript dedup pattern.

Features

  • New Call/Job reporting columns for abandoned-call analytics: callAbandoned, jobHadAbandonedCall, jobOriginIsInboundCall, jobAbandonedThenConnected, plus a more robust callDirection derivation across Dialpad/Twilio (!2171)
  • Zone-scoped virtual estimator filtering (intake.virtualEstimators) restricts which estimators appear for virtual availability per zone (!2171)
  • Configurable exception email allowlist (jobs.autoAssignAgentExceptionEmails) allows protected-role unassignment under specific configured conditions (!2168)

Fixes

  • Fixed CSV upload error when crew members without emails are present and edited to add an email (!2172)
  • Fixed Dialpad abandoned call double-processing causing duplicate comments and double texts (!2171)
  • Restricted unassign of Sales Agent / Estimator to admins and sales managers, closing a loophole where agents could strip protected roles via removeUsers (!2168, closes #6481)

Other

  • Removed jobAgent.reassign from AGENT_PERMISSIONS; admins and sales managers now inherit it via MANAGER_PERMISSIONS (!2168)
  • French translation fixes: “Seleccionado” → “Sélectionné”, “using” → “à l’aide de” (!2171)

v2607.08.0 — July 8, 2026

MRs: !2169, !2167, !2166, !1898

Highlights

Forwarded customer email replies now create job comments (!1898, closes #5367) When a single-unit inbox ignores the reply-to address and a customer reply lands back at moveright.info, staff can now forward that reply to a zone-specific +reply@ address and Move Right will automatically parse it, find the right job by customer email, and add the reply as a comment — then notify all job watchers. This closes a long-standing gap where replies from certain single-unit inboxes were lost.

Aegis document completion emails refined (!2167, closes #6480, #6464, #6461) Signature-request emails no longer attach the PDF (so customers must sign via the link), while completed documents now automatically email a signed PDF copy to signer roles and job watchers. Estimate visibility on the Work Orders tab is fixed, and invoice display names now read “Invoice” + invoice number with the remaining balance on a separate line.

OTR System Revenue drill-down improvements (!2169) Drill-down cells in the OTR System Revenue dashboard are now clickable links that open the underlying reports in a new tab, and headers now match calculator labels for less confusion. CSV/clipboard exports preserve readable cell text for linked values.

Features

  • Configurable text parts for the intake form, initially configured for Turpin (!2166, closes #6447)

Fixes

  • Fixed estimates not showing on the Work Orders tab (!2167, closes #6464)
  • Fixed invoice display name and balance formatting (!2167, closes #6461)
  • Signature-request emails no longer attach the PDF, ensuring customers sign via the link (!2167, closes #6480)
  • Signed PDF copy now sent to signer roles and job watchers on Aegis document completion (!2167)
  • Fixed document container alignment (!2167)

Other

  • Hotfix functions deploy trigger for v2607.06.0 (!2165)

v2607.06.0 — July 6, 2026

MRs: !2164, !2163, !2162, !2160, !2158, !2157, !2156, !2155, !2154, !2153, !2152, !2151, !2150, !2149, !2148, !2147, !2145, !2144, !2143, !2142, !2141, !2140, !2139, !2138, !2137, !2136, !2135, !2134, !2133, !2132

Highlights

OTR System Revenue dashboard replaces the external labor tracker (!2136, closes #6280) The OTR (Operations Tracking & Revenue) dashboard now lives inside Move Right instead of an external spreadsheet. You can see system revenue, labor tracking, and per-franchise breakdowns filtered by zone and period, with drill-down links into the underlying reports. This is the first dashboard built on the new dynamic-reports engine.

Movers Assistance estimate & standard invoice templates in AegisDoc (!2163, !2139) We added a branded Movers Assistance estimate template and a dynamically branded standard invoice template, both rendered through AegisDoc. The old PandaDoc-based flow is now fully replaced for these document types, with clickable contact info, conditional discount totals, and improved PDF pagination.

Legacy frontend code removed (!2155) The jobsv2, jobsv3, and legacy Estimates modules are gone. Job pages now live under a single job/ module, the schedule is booking-schedule, and shared Quill/template tooling moved to shared/. This deletes thousands of lines of dead code and makes the job page noticeably faster to load and navigate.

Performance

  • Dynamic-reports engine powers the new OTR dashboards and filters — aggregated queries now use valid output aliases for ORDER BY (!2160)
  • Prophet dynamic pricing retuned to use real capacity and keep raw q10, sharpening the discount gate (!2152)

Features

  • OTR System Revenue dashboard with zone-scoped reports, job-count column, and drill-down links (!2136, closes #6280)
  • Movers Assistance estimate template with brand color support (!2163)
  • Dynamically branded standard invoice template; receipts and invoices now render via AegisDoc (!2139, !2163)
  • Job area filter added to dynamic reports (!2154)
  • New calculator columns available in dynamic reports for the OTR dashboards
  • Manager role now has dispatch permissions (!2150, closes #6453)
  • Autodial time improvements (!2140, closes #6429)

Fixes

  • Fixed duplicate SMS comments showing in the UI when sending texts (!2156, closes #6458)
  • Fixed password-update cypher query failing for certain users (!2157, closes #6426, #6463, #6456, #6455)
  • Fixed Ask-Bee scheduling next-day calls within business hours (!2153)
  • Fixed Yembo sync search logic and added handler for smart_consult_scheduled (!2151, closes #6376)
  • Fixed jobs not searchable by customer email after the email is updated from the Job Page (!2145, closes #6445, #6444)
  • Fixed errors when an inventory room or item is not found (!2144)
  • Fixed Aegis estimates missing the “View as” option in the Documents tab (!2143, closes #6472)
  • Fixed watchers not notified when a customer replies to an email with a document (!2137)
  • Fixed “Cannot set quantity of undefined” on inventory (!2144)
  • Fixed new-opportunity location wizard not persisting unsaved changes (!2135)
  • Added a warning tooltip when the Continue button is disabled in intake (!2134, closes #6421)
  • Corrected floor options and added a Storage Unit building type prompt (!2132)
  • Fixed percentage rates defaulting to 0 in the Movers Assistance estimate (!2163)
  • Fixed transparent accent colors hiding template headers (!2163)
  • Fixed Anthropic prompt caching via anthropic-beta header (!2162)
  • Added anchor tag and clickable link/website support in Aegis documents (!2139, !2149)
  • Improved estimate and invoice template layout density and balanced two-column inventory (!2158, !2149)
  • Narrowed BaseUser fragment and patched node-fetch for Node v24 compatibility (!2138)
  • Fixed backup script shell quoting and added --backup-file flag (!2133)

Other

  • New CI deploy policy: pushes to app only deploy on a release version-bump commit or an MR merged with the hotfix label. See docs/ci-deploy-policy.md.
  • Large legacy code cleanup: jobsv2/jobsv3job, schedule-v3booking-schedule, Quill template helpers → shared/ (!2155)
  • Frontend tests added to CI/CD with Google Chrome replacing Chromium for Karma (!2147)
  • Dockerfile fix for CI test environment (!2164)
  • Removed legacy EstimateHelperService, add-event-button, and Estimating menu item (!2155)
  • Standardized job module import paths and removed version suffixes (!2155)
  • Functions bundle deployed to Cloudflare R2 via the deploy-functions job (!2148, !2141)
  • mirror-aegis triggered for the new AegisDoc template releases (!2142)