Skip to content

Atoms mode

Purpose

Atoms mode is the configuration of Sea Suite for businesses whose management layer lives in shifts, locations, inventory, equipment, and safety rules rather than tickets and pull requests. This document specifies what changes: the Org Model extensions, the scheduling solver's inputs, constraints, and objective, the shift lifecycle, the exact SMS conversations for swaps and call-outs, location-level health, checklist and compliance cadences, inventory and equipment signals, the voice line, the POS/time-clock/scheduling integrations, and the safety escalation path. The Chonks are the same; the surface moves to phones and the floor, and the math moves into the scheduling solver.

Scope / Non-scope

In scope

  • Org Model extensions for locations, shifts, skills, availability, labor rules, checklists, equipment, and inventory.
  • The scheduling solver as a function service: inputs, hard and soft constraints, objective, outputs, explanation, and re-solve triggers.
  • The shift state machine and the autonomy class of every transition.
  • SMS conversation flows for swaps, call-outs, open shifts, and no-shows, including message text.
  • Location-level health, checklist and compliance cadences, inventory and equipment signals.
  • The voice line for deskless staff.
  • Integration contracts for POS, time clocks, scheduling platforms, and IoT feeds, with system-of-record rules.
  • The safety escalation path.

Non-scope

  • General communication rules, caps, and tone (see Communication Engine); this document only adds Atoms-specific flows.
  • Connector authentication and API specifics (see Integrations Spec).
  • Payroll computation. Sea Suite exports hours and premiums; the payroll system is the system of record.
  • Legal determination of which labor rules apply to a tenant. Rule sets are configured at onboarding under counsel review; this document specifies how they are represented and enforced.
  • The demand forecasting model's internals; this document specifies its interface.

What changes in Atoms mode

Dimension Bits (default) Atoms
Primary IC surface Slack/Teams thread SMS thread; voice line; app optional
Unit of work Ticket, PR, project Shift, checklist, station
Unit of org Team Location (and station within it)
Capacity Person-hours per week from allocation Scheduled hours from the solver against a demand forecast
Stall detection Unreviewed PR, bouncing ticket Uncovered shift, missed checklist, late punch, cold fridge
Function services added — Scheduling solver, demand forecast interface, labor-rule engine, checklist engine
Integrations added — POS, time clock, scheduling platform, IoT/sensors
Manager of record Department lead Location lead (per location), with a backup
Listening period Read systems, meet everyone Same, plus one full schedule cycle observed before the solver publishes
Graduation Per function per org Per function per location; the solver starts in SHADOW (produces schedules that are compared to the human's, not published)

Everything in Atoms mode is per location. A tenant with three restaurants has three locations, three location leads, three labor-rule resolutions, and three graduation states, sharing one Org Model.

Org Model extensions

type Location = {
  id: LocationId; org: OrgId;
  name: string; tz: string; address: Address;
  jurisdiction: JurisdictionId;           // resolves the labor rule set
  hours: Array<{ day: 0|1|2|3|4|5|6; open: "HH:MM"; close: "HH:MM" }>;
  stations: StationId[];
  lead: PersonId; backupLead: PersonId;   // manager of record for the location
  minStaffing: Array<{ station: StationId; window: TimeWindow; headcount: number }>;
  keyholderRequired: boolean;
};

type Station = { id: StationId; location: LocationId; name: string; requiredSkills: SkillId[] };
type Skill = { id: SkillId; name: string; certification?: { kind: string; expiresField: true } };

type Availability = {
  person: PersonId;
  recurring: Array<{ day: 0|1|2|3|4|5|6; from: "HH:MM"; to: "HH:MM"; preference: "prefer" | "available" | "avoid" }>;
  exceptions: Array<{ date: Date; from?: "HH:MM"; to?: "HH:MM"; kind: "unavailable" | "available" }>;
  maxHoursPerWeek?: number;               // the person's own cap, may be below the legal one
  minHoursPerWeek?: number;               // the person's stated target
  locations: LocationId[];                // shared staff work at more than one
  offHoursShiftAlerts: boolean;           // consent to open-shift SMS during quiet hours
  updatedAt: Instant; actor: PersonId;    // availability is always the person's own edit
};

type Shift = {
  id: ShiftId; location: LocationId; station: StationId;
  start: Instant; durationMin: number;    // absolute duration; local start is derived
  assignee?: PersonId;
  status: ShiftStatus;                    // see state machine
  requiredSkills: SkillId[];
  premiums: Array<{ kind: "overtime" | "clopening" | "predictability" | "reporting_time" | "split"; amount?: Money; ruleId: string }>;
  history: Array<{ at: Instant; from: ShiftStatus; to: ShiftStatus; actor: PersonId | ChonkId; reason: string }>;
  publishedAt?: Instant; version: number;
};

type LaborRuleSet = {
  jurisdiction: JurisdictionId; version: string; reviewedBy: string; reviewedAt: Date;
  rules: LaborRule[];
};
type LaborRule =
  | { kind: "max_hours_day"; hours: number; appliesTo?: "minor" | "all" }
  | { kind: "max_hours_week"; hours: number; appliesTo?: "minor" | "all" }
  | { kind: "min_rest_between_shifts"; hours: number; consentAllowed: boolean; premium?: Money }
  | { kind: "meal_break"; afterHours: number; durationMin: number; paid: boolean }
  | { kind: "rest_break"; everyHours: number; durationMin: number }
  | { kind: "overtime"; dailyAfter?: number; weeklyAfter: number; multiplier: number; approvalRequired: boolean }
  | { kind: "minor_hours"; schoolDay: { earliest: "HH:MM"; latest: "HH:MM"; maxHours: number }; nonSchoolDay: { earliest: "HH:MM"; latest: "HH:MM"; maxHours: number } }
  | { kind: "predictive_notice"; days: number; changePremium: Money; reportingTimePayHours: number }
  | { kind: "max_consecutive_days"; days: number }
  | { kind: "collective_agreement"; ref: string; constraints: string[] };   // compiled per agreement

type TimePunch = { person: PersonId; location: LocationId; kind: "in" | "out" | "break_start" | "break_end"; at: Instant; source: "clock" | "app" | "sms" | "manual"; shift?: ShiftId };

type Checklist = { id: string; location: LocationId; kind: "opening" | "closing" | "food_safety" | "equipment" | "custom"; items: ChecklistItem[]; cadence: CadenceRef; assigneeRole: StationId | "lead"; evidence: "tap" | "photo" | "reading" };
type ChecklistItem = { id: string; text: string; evidence: "tap" | "photo" | "reading"; reading?: { unit: string; min?: number; max?: number } ; critical: boolean };

type Equipment = { id: string; location: LocationId; name: string; sensors?: SensorRef[]; serviceVendor?: VendorId; thresholds: Array<{ metric: string; min?: number; max?: number; durationMin: number; severity: "info" | "warn" | "critical" }> };
type InventoryItem = { id: string; location: LocationId; sku: string; onHand: number; par: number; reorderLeadDays: number; source: "pos" | "count" | "manual"; observedAt: Instant };

Rules that follow from the schema:

  • Availability is edited only by the person (or by an admin with reason and the person notified). The manager never edits someone's availability.
  • Shift.start is absolute and durationMin is absolute; paid hours, rest gaps, and overtime are computed in absolute time, which makes DST correct by construction (EC-SCHED-004).
  • LaborRuleSet carries reviewedBy and reviewedAt. A location with an unreviewed rule set cannot leave SHADOW.
  • A minor is represented by Person.minor: boolean and Person.minorUntil: Date, derived from the HRIS at sync and never displayed beyond the scheduling constraint.

Scheduling solver

The solver is a deterministic function service. The Chief Operating Orca calls it, explains its output, and never overrides it in prose. Every solve is replayable from its inputs.

Inputs

type SolveRequest = {
  location: LocationId;
  horizon: { from: Date; to: Date };                  // typically 2 weeks, aligned to the notice rule
  demand: DemandForecast;                             // from the forecast interface, below
  people: Array<{ person: PersonId; skills: SkillId[]; availability: Availability; hoursThisWeek: number; recentShifts: Shift[]; wage: Money; minor: boolean; certifications: Array<{ skill: SkillId; expires: Date }> }>;
  rules: LaborRuleSet;
  policy: { overtimeApprovalRequired: boolean; maxLaborCostPct?: number; fairness: FairnessWeights; lockedShifts: ShiftId[] };
  existing: Shift[];                                  // published shifts inside the horizon (locked unless consented)
  seed: number;                                       // determinism
};

type DemandForecast = {
  location: LocationId;
  granularityMin: 30;
  series: Array<{ start: Instant; expected: number; p10: number; p90: number; drivers: string[] }>;  // expected transactions or covers
  staffingCurve: Array<{ station: StationId; perUnitDemand: number; minimum: number }>;          // demand → required headcount per station
  source: { model: string; version: string; trainedThrough: Date; inputs: string[] };
  confidence: number;                                 // calibration engine, not model-stated
};

type FairnessWeights = { hoursTargetGap: number; weekendSpread: number; closingSpread: number; preferenceHonored: number; consecutiveDays: number };

The demand forecast is produced by a separate service from POS history, reservations, weather, local events, and the location's hours. Its interface is the DemandForecast above; the solver treats it as data. When forecast confidence is below 0.5 for a window, the solver uses the location's minStaffing for that window and the schedule is annotated "forecast low-confidence; minimum staffing used."

Constraints

Hard constraints are never violated; the solver returns INFEASIBLE with the binding constraints named rather than relax them. Soft constraints carry weights in the objective.

Constraint Kind Source Notes
Person available for the whole shift Hard Availability Exceptions override recurring
Required skills held, certifications unexpired Hard Station, Person Expiring within horizon → warning, not violation
Keyholder on every open and close, if required Hard Location
Minimum staffing per station per window Hard Location.minStaffing Below this the location is "short," see health
Max hours per day and per week (legal) Hard LaborRuleSet Minor-specific limits when minor
Minor hours windows and school-day limits Hard LaborRuleSet School calendar per jurisdiction fixture
Minimum rest between shifts Hard, or consent-gated where the rule allows LaborRuleSet Consent flow in swaps; premium recorded
Meal and rest breaks schedulable within the shift Hard LaborRuleSet Break slots are emitted with the shift
Max consecutive days Hard LaborRuleSet
Published shifts inside the notice window unchanged Hard predictive_notice Changes only through consented swaps
No overlapping shifts across locations Hard Availability.locations Shared staff
Overtime only if policy allows without approval Hard when approvalRequired, else soft Policy Overtime shifts are emitted as pending_approval
Person's own max hours Hard Availability The person's cap is honored even below legal
Collective agreement constraints Hard LaborRuleSet Compiled per agreement, e.g., seniority ordering for preferred shifts
Locked shifts Hard Policy Lead-locked assignments
Demand coverage above minimum Soft (high weight) DemandForecast Under-coverage cost per 30-minute slot
Labor cost within budget Soft (high weight) Policy, ledger Overrun cost per unit
Hours target gap (person min/max targets) Soft Availability, fairness
Weekend and closing spread Soft Fairness Rolling 8-week fairness window
Preference honored (prefer/avoid) Soft Availability
Consecutive days below fatigue threshold Soft Fairness Below the legal max
Schedule stability vs last published Soft Existing Penalize churn

Objective

minimize  w_cover  · Σ_slots  underCoverage(slot)
        + w_cost   · max(0, laborCost − budget)
        + w_fair   · Σ_people ( a·|hours − target| + b·weekendShare² + c·closingShare² + d·avoidedShifts )
        + w_pref   · Σ_people preferMisses
        + w_churn  · Σ_shifts changedFromPublished
        + w_ot     · overtimeHours                    // when overtime is allowed but discouraged
subject to all hard constraints

Weights are tenant policy with defaults w_cover = 100, w_cost = 40, w_fair = 10, w_pref = 5, w_churn = 8, w_ot = 20. The owner can change weights in the direction editor; the solver refuses weights that zero out coverage or fairness (an IC protection floor, as in EC-ADV-007).

Output and explanation

type SolveResult = {
  status: "FEASIBLE" | "INFEASIBLE" | "TIMEOUT";
  shifts: Shift[];                                       // status = draft
  breaks: Array<{ shift: ShiftId; start: Instant; durationMin: number; kind: "meal" | "rest" }>;
  pendingApprovals: Array<{ shift: ShiftId; reason: "overtime" | "budget" | "consent_rest" }>;
  metrics: { coverage: number; laborCost: Money; laborCostPct: number; fairness: Record<PersonId, { hours: number; weekends: number; closings: number }>; churn: number };
  explanations: Array<{ shift: ShiftId; why: string[]; alternativesConsidered: number }>;   // deterministic templates, not model prose
  bindingConstraints?: string[];                         // on INFEASIBLE
  inputsHash: string; seed: number; solverVersion: string;
};

Explanations are templated from the solver's own trace ("Sam on Saturday close: Sam is available, holds bar and keyholder, is 4 hours under target this week, and has had 1 of the last 4 Saturday closes; Alex was considered and is at 38 hours"). The Chief Operating Orca may reword an explanation at the tone level but may not add reasons the trace does not contain.

Solve cadence and re-solve triggers

Trigger Horizon touched Autonomy of the result
Weekly planning cadence (default Tuesday 10:00 local) Next unpublished period PROPOSE_CONFIRM to the location lead until the location's scheduling function graduates to AUTONOMOUS; then AUTONOMOUS publish with the lead notified
Availability change Unpublished periods only Same as above
Forecast update beyond ±15% for a window Unpublished periods; published periods produce open-shift or swap proposals, never silent changes AUTONOMOUS for unpublished; consented flows for published
Call-out or no-show Single shift AUTONOMOUS open-shift flow
Closure Whole day(s) PROPOSE_CONFIRM (EC-SCHED-006)
Labor rule set update Everything unpublished; published shifts checked, violations flagged to the lead PROPOSE_CONFIRM

Re-solves are damped like re-plans (EC-PLAN-002): more than two forecast-driven re-solves in a week fold into the weekly cadence unless coverage would drop below minimum staffing.

Solver pseudocode

solve(req):
  model = new CPModel(seed = req.seed)
  vars  = { assign[p][s] ∈ {0,1} for p in people, s in candidateShifts(req.demand, req.location) }
  for each hard constraint in table: model.add(constraint(vars, req))
  model.minimize(objective(vars, req))
  result = model.solve(timeLimit = 60s)
  if result == INFEASIBLE:
     core = model.irreducibleInfeasibleSubset()
     return { status: INFEASIBLE, bindingConstraints: describe(core) }
  shifts = materialize(vars, breaks = scheduleBreaks(vars, req.rules))
  return { status: FEASIBLE, shifts, explanations: explain(model.trace), metrics: score(shifts, req), inputsHash: hash(req) }

Shift lifecycle

stateDiagram-v2
    [*] --> draft: solver output
    draft --> published: lead confirms (PROPOSE_CONFIRM) or graduated publish (AUTONOMOUS)
    draft --> [*]: discarded on re-solve
    published --> swap_requested: assignee requests swap (AUTONOMOUS)
    swap_requested --> covered: eligible taker accepts, validation passes (AUTONOMOUS) or lead approves premium (PROPOSE_CONFIRM)
    swap_requested --> published: no taker; request expires; original assignee keeps it
    published --> open: call-out (AUTONOMOUS) or no-show at T+15 (AUTONOMOUS)
    open --> covered: taker accepts broadcast (AUTONOMOUS)
    open --> short: no taker after 2 rounds; lead decides to run short (PROPOSE_CONFIRM)
    covered --> published: taker withdraws before T-2h, original re-notified
    published --> worked: clock-in and clock-out recorded
    covered --> worked: clock-in and clock-out recorded
    short --> worked: shift time passes (recorded as unstaffed)
    published --> cancelled: closure confirmed (PROPOSE_CONFIRM) or lead cancels
    covered --> cancelled: closure confirmed
    worked --> reconciled: punches matched, breaks verified, premiums computed, exported
    worked --> disputed: punch mismatch or missing punch
    disputed --> reconciled: lead resolves (HUMAN_ONLY for pay-affecting edits)
    reconciled --> [*]
    cancelled --> reconciled: reporting-time pay computed if owed

Transition rules

Transition Actor Autonomy Validation Notifications
draft → published Location lead, or the harness after graduation PROPOSE_CONFIRM / AUTONOMOUS Notice window respected; every hard constraint re-checked at publish Every assignee by SMS: shifts for the period with a link; changes vs previous publish highlighted
published → swap_requested Assignee AUTONOMOUS Shift is more than 2 hours away Eligible takers per the swap flow
swap_requested → covered Taker, then validator AUTONOMOUS unless premium or overtime → PROPOSE_CONFIRM to lead All hard constraints for the taker; overtime and rest rules on projected hours (EC-SCHED-003) Both parties; lead if approval was needed
published → open (call-out) Assignee AUTONOMOUS None; a call-out is always accepted as stated Lead; eligible takers via broadcast
published → open (no-show) Harness AUTONOMOUS No punch at T+15; one check-in SMS sent at T+15 before opening Lead; broadcast
open → short Location lead PROPOSE_CONFIRM Two broadcast rounds exhausted Lead's decision recorded with options shown
worked → reconciled Harness AUTONOMOUS Punch pairs match shift within tolerance (±15 min); breaks present; premiums computed by the rule engine Payroll export; person sees their hours in the thread
worked → disputed Harness AUTONOMOUS flag; HUMAN_ONLY edit Any pay-affecting edit is made by the lead with a reason and is visible to the person Person and lead
any → cancelled Lead or closure flow PROPOSE_CONFIRM Reporting-time pay computed if the rule applies Every assignee by SMS, then voice if unacknowledged within 30 minutes and the shift is within 12 hours

Every transition appends to Shift.history with actor and reason. A shift's history is visible to its assignee on the "what my manager knows" page.

Swaps and call-outs by SMS

All flows run in the person's SMS thread with the location's manager Chonk (the Chief Operating Orca by default; tenants can assign a different persona per location). Every inbound is matched against the keyword grammar first and a classifier second; ambiguous inbounds get one clarifying question and then a human. STOP and HELP are honored at the carrier layer before anything else.

Keyword grammar

Inbound Meaning Notes
SWAP or SWAP <date> Request a swap for the next shift, or the shift on that date Date formats per locale; "SWAP SAT" resolves to the next Saturday
SICK, OUT, CANT, CAN'T MAKE IT Call out of the next shift Never asks why
TAKE or TAKE <n> Accept an open or swap shift (nth in the last list)
PASS Decline the current offer Also any silence past the offer window
SCHED Send my shifts for the next 7 days
HOURS Send my hours this week and projected
LATE <min> Running late by n minutes Lead informed; no-show timer extended
HUMAN or LEAD Escalate to the location lead Cannot be suppressed
PLAIN / OTTER Set my tone ceiling
STOP / HELP Carrier keywords STOP is permanent for that number

Swap flow

sequenceDiagram
    participant A as Assignee (SMS)
    participant O as Orca (harness)
    participant T as Eligible takers (SMS)
    participant L as Location lead
    A->>O: SWAP SAT
    O->>A: Got it. Sat 14 Sep 16:00–23:00, Bar. Offering it to 4 people who are eligible. I'll tell you when someone takes it. You still own it until then.
    O->>T: Open swap: Sat 14 Sep 16:00–23:00, Bar, Harbor. Reply TAKE to claim, PASS to skip. Offer closes 20:00 tonight.
    T-->>O: TAKE
    O->>O: validate(taker): skills, availability, rest, hours, minor, notice, cross-location overlap
    alt passes, no premium
        O->>T: It's yours. Sat 14 Sep 16:00–23:00, Bar. Added to your schedule.
        O->>A: Jordan took Sat 16:00–23:00. You're off it. Schedule updated.
        O->>L: FYI swap: Sat Bar 16:00–23:00, Sam → Jordan. No premium.
    else passes with overtime or rest premium
        O->>L: Swap needs your OK: Sat Bar 16:00–23:00, Sam → Jordan. Jordan would be at 42h (2h OT, est. $54). Reply YES or NO.
        L-->>O: YES
        O->>T: Approved. Sat 14 Sep 16:00–23:00, Bar is yours.
        O->>A: Jordan took Sat 16:00–23:00.
    else fails
        O->>T: Can't give you this one: it would break the 8-hour rest rule after your Friday close. I'll offer the next one that fits.
    end

Rules:

  • The taker list is computed by the solver's validator: skills, availability, projected hours, rest, minor rules, notice-window consent, cross-location overlap, not on leave, not STOPed. The list is ordered by fairness (most under target first), then by preference.
  • Offers go out in rounds of up to 4 people, each round open for 2 hours or until the shift is within 6 hours, whichever comes first, maximum 2 rounds (EC-SCHED-009). Off-hours rounds go only to people with offHoursShiftAlerts = true.
  • The requester owns the shift until it is covered. The message says so every time.
  • A swap is one-directional (give-away). Trades ("I'll take your Tuesday if you take my Saturday") are two linked swaps validated together and committed atomically.
  • Names are shared between the two parties and the lead only; broadcast messages never say who is giving the shift away.

Call-out flow (including the 05:00 sick call)

sequenceDiagram
    participant A as Opener (SMS)
    participant O as Orca (harness)
    participant T as Eligible keyholders (SMS)
    participant L as Location lead (SMS + voice)
    A->>O: sick
    O->>A: Got it, you're off today's 06:00–14:00. Feel better. Nothing else needed from you. (05:02:40)
    O->>O: shift → open; compute takers: keyholder skill, available, rest OK, hours OK, offHoursShiftAlerts = true
    O->>T: Open shift now: today 06:00–14:00, Opener/keyholder, Harbor. Reply TAKE to claim. Closes 05:30.
    alt taker by 05:30
        T-->>O: TAKE
        O->>T: It's yours. Today 06:00–14:00, keyholder. Code box is 4471. Thank you.
        O->>L: Covered: today's open, Jordan for Sam. No OT.
    else no taker by 05:30
        O->>L: Today's 06:00 open is uncovered. Options: (1) Alex can take it at 2h OT, est. $54, reply 1; (2) open at 08:00 with you, reply 2; (3) something else, reply LEAD. I'll call you in 5 min if no reply.
        L-->>O: 1
        O->>T: (to Alex) Open shift approved for you: today 06:00–14:00, keyholder. OT approved by Riley.
        O->>L: Done. Alex is opening. Logged.
    end

Rules:

  • Acknowledgement within 60 seconds, always, before any other processing. The acknowledgement never asks for a reason, a note, or an ETA to return (EC-SCHED-002). If tenant policy requires documentation after a threshold of absences, that request is a quiet-HR flow initiated by the lead, HUMAN_ONLY.
  • The broadcast bypasses quiet hours only for offHoursShiftAlerts = true. Everyone else is not messaged.
  • At T-30 minutes uncovered, the lead is messaged with numbered options that include the cost delta from the ledger. If the lead does not reply in 5 minutes, the voice line calls them. The lead decides. The manager never decides to run short, open late, or authorize overtime on its own.
  • Overtime cover is PROPOSE_CONFIRM to the lead in every case where the policy has overtimeApprovalRequired = true, regardless of graduation.
  • The call-out is recorded factually on the shift history: "call_out, 05:02, by assignee." No pattern commentary is ever sent to the person; patterns are a lead-facing packet (EC-SCHED-005).

Open shift broadcast (from forecast or lead)

Same mechanics as the call-out broadcast, without the urgency: two rounds of up to 4 people, each open 4 hours, then the lead's options. Messages name the shift and the station, never the reason it is open.

No-show

T+15, no punch:
  O→A: "Your 14:00 shift started 15 minutes ago and I don't see a clock-in. Are you okay? Reply LATE <minutes> or OUT."
  no reply by T+25 → shift → open; broadcast; lead informed: "No-show at Bar 14:00, no reply to check-in. Broadcasting."
  reply LATE 20 → lead informed; no-show timer extended; no broadcast

Failure handling

Situation Behaviour
Unverified number sends SWAP Reply with verification only ("Reply with your first name and the last 4 of the phone number on file"); no schedule data until verified
Reply is ambiguous ("maybe," "idk") One clarifying question with the keyword options; on a second ambiguous reply, the lead is informed and the flow pauses
Two people TAKE within the same second First write wins at the harness; the second gets "Someone else got it first; I'll offer you the next one that fits"
Taker withdraws after acceptance and before T-2h Shift returns to published with the original assignee re-notified; the withdrawal is recorded factually
Taker withdraws inside T-2h Treated as a call-out by the taker
STOP received mid-flow Flow aborts for that number; the lead is informed; the person's schedule stands
Carrier outage Voice line calls with the same content; app push if installed; lead informed if any shift within 12 hours is affected

Location-level health

Location health is computed hourly by the capacity model and the checklist engine and shown in the Owner Console with reasons, never only a color.

Component Signal Green Amber Red
Coverage Scheduled vs required headcount per slot, next 7 days ≥ 100% all slots Any slot 80–99% Any slot < 80% or below minStaffing
Coverage risk Open shifts and unanswered swaps within 72 hours 0 1–2 ≥ 3 or any within 12 hours
Labor cost Actual + scheduled vs budget for the period ≤ 100% 100–105% > 105% or unapproved overtime present
Compliance Rule violations in the last 14 days (rest, breaks, minors, notice) 0 1 flagged and resolved Any unresolved or any minor-rule violation
Checklists Completion of critical items on time, last 7 days 100% 1 miss, resolved Any critical miss unresolved or any food-safety reading out of range
Equipment Sensor thresholds and open service tickets None open Warn-level open Critical open
Inventory Items below par with lead time exceeding days of cover None 1–3 > 3 or any critical SKU at zero
Punctuality and attendance No-shows and late punches > 15 min, last 14 days, location-level rate < 2% 2–5% > 5%
Staff signal Reply rate to briefs and swap offers, tone downgrades, escalations to lead Baseline Reply rate down > 20% Any escalation about the manager, or a safety event

Rules:

  • Attendance and punctuality are reported at the location level. Person-level attendance is visible to the lead in the reconciliation view and to the person in their thread, and appears nowhere else.
  • Health reasons are templated from the signals ("Red: Friday 18:00–21:00 is at 60% of required Bar headcount; two open shifts unanswered").
  • The weekly owner update rolls locations up with the same components; the portfolio view (OW-5) rolls tenants up.

Checklist and compliance cadences

Checklists are Cadence objects owned by the Chief Security Officer's charter, executed at the location by the assigned station or the lead, with evidence.

Checklist Cadence Assignee Evidence Critical items (examples) On miss
Opening Daily at open − 30 min Opener (keyholder) Tap per item; photo for critical Alarm disarmed and logged; walk-in cooler temp; hand-wash stations stocked; cash drawer count Reminder at open − 10; lead informed at open + 15 if critical items incomplete
Closing Daily at close Closer (keyholder) Tap; photo for critical; reading for temps Equipment off; temps logged; cash reconciled; doors and alarm Lead informed at close + 30; opener's brief next day includes the miss
Food safety (temperature log) Every 4 hours during open, per unit Station on duty Reading Each cooler and hot-hold within range Out-of-range → immediate corrective-action prompt with the location's SOP; lead informed; second consecutive out-of-range → equipment ticket and HUMAN_ONLY disposal decision packet
Equipment Weekly, and on sensor event Lead or designated station Tap; photo Hood filter; fire suppression tag date; slicer guard Service vendor chase (vendor cadence); lead informed
Cash and deposit Daily at close Closer Reading (POS reconciliation) Variance within tolerance Variance beyond tolerance → lead packet; never a message to the closer implying blame
Custom (tenant SOPs) Configured Configured Configured Configured Configured within the same escalation ladder

Rules:

  • A checklist reminder is a brief-class message on SMS and app; it never goes to a public channel.
  • Misses are stated factually to the assignee once, then to the lead. No streaks, no leaderboards, no per-person completion rates in any group surface.
  • Readings are validated against the item's range at entry; out-of-range readings prompt the SOP step and cannot be dismissed without a reason.
  • Cadences never silently skip. A checklist that did not run because the location was closed is recorded as skipped: closure; one that did not run for any other reason is a missed cadence and is escalated (reliability requirement).
  • Compliance reporting (the 14-day violation list, temperature logs, break records) is exportable per location for inspections, and the export is an audit event.

Inventory and equipment signals

Inventory and equipment are signals into the management layer, not a replacement for the inventory or maintenance system.

Signal Source Threshold Action Autonomy
Item below par with days-of-cover < reorder lead time POS depletion, counts Per item Reorder packet to the lead with quantity and vendor; if the vendor and amount are within policy, the Chief Fin Officer pre-approves PROPOSE_CONFIRM (reorder), AUTONOMOUS (in-policy pre-approval)
Critical SKU at zero during open hours POS Immediate Lead informed; menu or service impact noted in the shift brief AUTONOMOUS notify
Count variance vs POS-implied on-hand > tolerance Counts Per item class Lead packet; never a person-level accusation AUTONOMOUS flag
Cooler temperature out of range for > durationMin IoT sensor Equipment thresholds Corrective-action prompt to the station on duty; lead informed; equipment ticket; food-safety HUMAN_ONLY packet if the excursion exceeds the SOP limit AUTONOMOUS prompt and ticket; HUMAN_ONLY disposal
Sensor offline > 30 min IoT Lead informed; manual reading requested in the next temperature-log slot AUTONOMOUS
Equipment failure reported (SMS "BROKEN ") Staff Ticket; service vendor chase; lead informed; schedule impact assessed (e.g., station cannot open) AUTONOMOUS ticket and chase; PROPOSE_CONFIRM any schedule change
Service vendor unresponsive Vendor chase cadence 3 attempts / 5 business days Options packet to the lead (EC-BLOCK-003) PROPOSE_CONFIRM
Fire suppression, gas, electrical, or structural fault Sensor or staff report Immediate Safety escalation path (below) HUMAN_ONLY

Inventory and equipment facts carry observedAt and the staleness rules in EC-DATA-001; a count more than 7 days old is shown as stale in health.

Voice line for deskless staff

The voice line is a phone number per location that connects to the location's manager Chonk. It exists for people who do not have or will not use an app, and for moments when typing is not possible (driving, gloves, no signal for data).

Capabilities

Caller says The line does Autonomy
"What's my schedule" Reads the caller's next 7 days; offers SMS copy AUTONOMOUS
"I'm sick" / "I can't come in" Runs the call-out flow; confirms by SMS AUTONOMOUS
"Can I swap Saturday" Starts the swap flow; confirms by SMS AUTONOMOUS
"I'm running late" Records LATE; informs the lead AUTONOMOUS
"Take the open shift" Runs the TAKE validation; confirms by SMS AUTONOMOUS
"How many hours am I at" Reads hours this week and projected AUTONOMOUS
"I need Friday off" (future) Records an availability exception; confirms by SMS AUTONOMOUS
"Something is broken" Records the equipment report; asks which unit AUTONOMOUS
"I want to talk to a person" / "lead" / any frustration Transfers to the lead; if unanswered, leaves the lead a page and tells the caller the SLA Cannot be suppressed
Anything about pay rates, discipline, another person, HR policy beyond a document link "That's one for [lead name]; I've let them know you called about it" Routed; never answered by the line
Anything indicating danger or injury Safety path HUMAN_ONLY

Rules

  • Verification first. Caller ID matched to the number on file plus a spoken PIN, or a callback to the number on file. Nothing personal is read before verification (EC-ADV-006).
  • Own data only. The line never speaks another person's schedule, hours, contact details, or location.
  • Scripted plus constrained. Turns are scripted for the flows above; free-form Q&A is limited to the caller's own schedule and hours and to policy documents (read a paragraph, then SMS the link). The line does not persuade, negotiate, or discuss performance.
  • Read-back. Every action is read back ("You're off Saturday 16:00 to 23:00; I'm offering it to four people. Right?") and confirmed by SMS after the call.
  • Transcript. The call transcript is stored in the caller's thread, visible to them; the audio is not retained beyond transcription unless the tenant's retention policy says otherwise.
  • Persona. The voice line caps at tone 2 by default. Level 3–4 synthesized character voices are an opt-in per tenant and never apply to the safety path.
  • Languages. Per location, the line offers the languages the location's staff have on file; unsupported languages transfer to the lead.

Integrations

Atoms mode adds four integration families. Each has a system-of-record rule; Sea Suite is the system of record for nothing in this table except the schedule when the tenant has no scheduling platform.

Family Targets (v1) Reads Writes System of record Sync
POS Square, Toast, Shopify POS Transactions per 30-min slot, items sold, refunds, cash reconciliation, labor % where exposed Nothing POS for sales; Sea Suite derives demand history Webhook plus 15-min poll; nightly reconciliation
Time clock Deputy, When I Work, 7shifts, Homebase, standalone clocks, POS-integrated clocks Punches, breaks, geofence flags Shift schedule (for clock enforcement), approved hours after reconciliation Time clock for punches; payroll for pay Webhook; reconciliation at shift end and nightly
Scheduling platform Deputy, When I Work, 7shifts, Homebase Existing schedules, availability, roles, locations Drafts and published schedules; swaps; open shifts Configurable: the platform (Sea Suite pushes) or Sea Suite (platform mirrors); never both Bidirectional with version vectors; conflicts below
IoT / sensors Temperature probes, door sensors, equipment monitors via MQTT/HTTP Readings, offline events Nothing Sensor platform Streaming with 5-min heartbeat

Conflict resolution

  • Schedule. One system of record per tenant. If the platform is the record, a change made in the platform wins and Sea Suite re-validates it against rules, flagging violations to the lead rather than reverting (the harness never silently undoes a human's edit). If Sea Suite is the record, the platform is a mirror and its edits are rejected with a message to the editor.
  • Availability. The person's most recent edit wins wherever it was made; both systems are updated; the person is shown the result.
  • Punches. The time clock is authoritative. Sea Suite's reconciliation flags mismatches; edits happen in the time clock or through the lead's HUMAN_ONLY reconciliation with a reason, and are written back.
  • Demand history. POS is authoritative; Sea Suite stores derived series with the source snapshot hash.

Failure modes

Failure Behaviour
POS outage Forecast uses history; health shows "sales data stale since
Time clock outage Shifts stay worked not reconciled; SMS "reply IN/OUT" fallback is offered only where the tenant enabled SMS punches; lead informed
Scheduling platform outage Publishes queue; swaps and call-outs still run in Sea Suite and sync when the platform returns; the lead is told which shifts changed during the gap
Sensor offline Manual reading requested; equipment health amber
Webhook gap Backfill before acting (EC-DATA-004)

Safety escalation path

Safety is HUMAN_ONLY in every deployment mode, at every graduation level, and for every persona. The manager's job in a safety event is containment and notification, never decision.

Triggers

  • Any inbound (SMS, voice, app, checklist note) classified as injury, medical emergency, violence or threat, fire, gas, structural hazard, food-safety event with customer impact, or harassment.
  • Sensor events at critical severity for fire suppression, gas, or CO.
  • A staff report using HELP-adjacent language on the voice line or SMS, or the keyword SAFETY.
  • Repeated impersonation attempts targeting one person on the voice line (EC-ADV-006).

The classifier is tuned for recall. False positives cost a page to the lead; false negatives are unacceptable.

Flow

flowchart TD
    A["Trigger classified as safety"] --> B["Scripted reply to reporter: the jurisdiction's emergency number, then 'I have alerted Riley, the location lead, and their backup.'"]
    B --> C["Page location lead: SMS + voice + app, bypassing quiet hours and caps"]
    C --> D{"Lead acknowledges within 5 min?"}
    D -- No --> E["Page backup lead, then owner; keep paging every 5 min until acknowledged"]
    D -- Yes --> F["Lead is the human in charge. Manager stops all non-safety outreach to the location for 2 hours or until the lead clears it"]
    E --> F
    F --> G["Manager records: trigger time, who was paged, who acknowledged, when. Nothing else is summarized into memory."]
    G --> H["Lead records the outcome and any incident report in the HRIS or safety system. Sea Suite links the record ID; it does not author the report."]
    H --> I["Chief Security Officer charter review within 1 business day: was the path followed? Learn step updates classifier fixtures and the catalog."]

Rules

  1. The scripted reply is human-written, reviewed by counsel per jurisdiction, localized, and identical at every tone level. It contains the local emergency number, states who has been alerted, and nothing else. The persona does not appear.
  2. Paging bypasses everything: quiet hours, caps, leave (the backup is paged instead), incident mode, and channel preferences. Voice is always attempted.
  3. The manager does not triage. It does not ask the reporter questions beyond the script, does not assess severity, does not tell anyone to do anything except the lead ("please respond"), and does not contact emergency services itself; the script tells the reporter how to.
  4. The manager does not decide anything afterward. Whether the location closes, whether a person goes home, whether an incident report is filed, whether anyone is disciplined: all human. The manager prepares a packet only if the lead asks for one, and the packet contains facts from the systems (who was scheduled, sensor readings, checklist state), never a narrative of what happened.
  5. Data minimization. The event record holds timestamps and who was paged. The content of the report is retained in the thread under the tenant's retention policy and is excluded from people memory, feedback evidence, calibration, and health computation, except that the location's health shows "safety event this week" without detail.
  6. Escalation is a right. The reporter can reach the lead directly at any time with LEAD or by voice; the safety flow never replaces that path.
  7. Test every path in the sim. chowder-house includes a safety fixture per trigger type; the test asserts the scripted reply verbatim, paging order and timing, the outreach freeze, and the absence of any analysis in memory (EC-HUMAN-004).

Risk controls

Uncovered critical shift

  • Detect. Open shift with keyholderRequired or a minStaffing breach within 12 hours. Owner: Chief Operating Orca charter. Metric: critical shifts uncovered at T-30 per location per month.
  • Contain. Broadcast rounds; lead options packet at T-30; voice page.
  • Correct. Lead decides; the solver re-solves the rest of the day.
  • Learn. If the same slot goes uncovered twice in a month, the solver raises its coverage buffer for that slot and the owner sees a staffing-level signal.

Labor rule violation reaches a published schedule

  • Detect. Publish-time validation or reconciliation finds a violation. Owner: Chief Security Officer charter. Metric: violations per 1,000 shifts; target 0 for minor rules.
  • Contain. Freeze scheduling for the location to PROPOSE; flag every affected shift to the lead.
  • Correct. Fix the rule set or the validator; re-validate the horizon.
  • Learn. Add the rule fixture to the sim; catalog entry if novel; counsel review of the rule set version.

Food-safety excursion missed

  • Detect. Out-of-range reading with no corrective action within the SOP window, or a sensor excursion without a prompt. Owner: Chief Security Officer charter. Metric: excursions without corrective action per month; target 0.
  • Contain. Immediate prompt to the station and the lead; disposal decision packet (HUMAN_ONLY).
  • Correct. Repair the cadence or sensor threshold.
  • Learn. Adjust thresholds and add the excursion pattern to the sim.

SMS flow misfire

  • Detect. A swap or call-out results in a wrong assignment, a duplicate cover, or a message to a STOPed or unverified number. Owner: Chief Operating Orca charter. Metric: misfires per 1,000 flows.
  • Contain. Freeze SMS flows for the location to PROPOSE; lead runs swaps manually with the packet.
  • Correct. Fix the grammar, the validator, or the race handling.
  • Learn. Add the transcript to the sim as a fixture; catalog entry.

Open questions

  • Which scheduling platform is the system of record by default when the tenant has one? Pushing to the platform preserves the tenant's existing workflows; making Sea Suite the record avoids two-way conflicts. The minimum viable Atoms deployment question in the PRD depends on this.
  • Should the demand forecast be a Sea Suite service or a pluggable interface with the tenant's own forecast (some POS vendors ship one)? The interface in this document allows either.
  • The 4-person, 2-round broadcast defaults are guesses. What are the right values for a 60-person location versus a 12-person one, and should rounds scale with eligible-pool size?
  • Off-hours shift alerts require explicit consent. Should consent expire and be re-asked (e.g., every 6 months), given how easy it is to forget having opted in?
  • Should the voice line support a spoken PIN at all, given shoulder-surfing on a floor, or only callback verification?
  • Reporting-time pay and predictability premiums vary widely by jurisdiction. Should the labor-rule engine ship with a curated rule set per jurisdiction (with counsel review per release), or should every tenant configure from a template?
  • Portfolio-level health for multi-location owners (OW-5) needs a normalization for locations of very different sizes. Which components normalize per headcount and which per revenue?