← Back to documentation

Edge Contract Specification

Version: 0.1 (Draft)
Date: March 2026
Status: Proposal
Depends on: Stroke Format Spec, Visual Primitives Spec
Implements: BOOX Edge, reMarkable Edge, iPad Edge, Web Edge


1. Overview

The Edge Contract defines what any Edge implementation must support to be a valid FreakingGenius "paper" device.

An Edge is dumb by design. It captures strokes, renders primitives, reports its state. It does not interpret math, make pedagogical decisions, or generate audio.

Edge is paper. Paper doesn't think.

1.1 Contract Scope

This spec defines:

This spec does NOT define:

1.2 Reference Implementations

Platform Status Notes
BOOX (Android e-ink) Primary target v1
reMarkable 2 Planned Pending platform access
iPad Future High-refresh LCD
Web Future Fallback, reduced capability

2. Capability Model

2.1 Capability Declaration

At session start, Edge sends its capabilities to Tutor (via Bridge):

{
  "type": "CAPABILITIES",
  "device": {
    "id": "dev_abc123",
    "platform": "boox",
    "model": "Tab Ultra C",
    "edgeVersion": "1.0.0",
    "protocolVersion": 1
  },
  "display": {
    "width": 2480,
    "height": 1860,
    "colorDepth": 16,
    "refreshRate": "medium",
    "colorSupport": true
  },
  "input": {
    "stylus": true,
    "stylusPressure": true,
    "stylusTilt": true,
    "touch": true,
    "samplingRate": 120
  },
  "features": {
    "audio": false,
    "camera": false,
    "haptics": false,
    "offlineStorage": "2GB"
  }
}

2.2 Capability Fields

Device Info

Field Type Required Description
id string Unique device identifier
platform enum boox, remarkable, ipad, android, web
model string Device model name
edgeVersion semver Edge app version
protocolVersion int Contract version implemented

Display

Field Type Required Values
width int Pixels
height int Pixels
colorDepth int 1 (B&W), 4 (grayscale), 16 (color)
refreshRate enum slow (e-ink), medium, fast (LCD)
colorSupport bool Can render color

Input

Field Type Required Description
stylus bool Has stylus input
stylusPressure bool Pressure sensitivity
stylusTilt bool Tilt detection
touch bool Finger touch support
samplingRate int Input samples per second

Features

Field Type Description
audio bool Can play/record audio (rare for tablet Edge)
camera bool Has camera access
haptics bool Vibration feedback
offlineStorage string Available offline cache size

2.3 Capability Negotiation

┌─────────┐                    ┌─────────┐
│  Edge   │                    │  Tutor  │
└────┬────┘                    └────┬────┘
     │                              │
     │   CAPABILITIES               │
     │─────────────────────────────►│
     │                              │
     │   SESSION_CONFIG             │
     │◄─────────────────────────────│
     │                              │
     │   (session active)           │

Tutor (via Bridge) responds with configuration based on capabilities:

{
  "type": "SESSION_CONFIG",
  "sessionId": "sess_xyz789",
  "renderMode": {
    "color": true,
    "animations": false,
    "refreshStrategy": "partial"
  },
  "strokeConfig": {
    "batchIntervalMs": 200,
    "format": "binary",
    "includePressure": true
  },
  "features": {
    "hintsEnabled": true,
    "guidesEnabled": true
  }
}

3. Message Protocol

3.1 Message Envelope

All messages wrapped in standard envelope:

{
  "version": 1,
  "timestamp": 1711670400000,
  "type": "MESSAGE_TYPE",
  "payload": { ... }
}

3.2 Messages: Edge → Tutor

CAPABILITIES

Sent at session start. See section 2.1.

STROKE_BATCH

Stroke data per Stroke Format Spec.

{
  "type": "STROKE_BATCH",
  "payload": {
    "sessionId": "sess_xyz789",
    "seq": 42,
    "strokes": [ ... ],
    "partial": { ... }
  }
}

GESTURE

User gesture detected.

{
  "type": "GESTURE",
  "payload": {
    "gesture": "undo",
    "timestamp": 1711670450000
  }
}
Gesture Meaning
undo Undo last stroke
redo Redo undone stroke
erase_area Erased region (include bounds)
next Request next exercise
previous Request previous exercise
submit Student indicates "done"
help Student requests hint

HEARTBEAT

Periodic status (every 30s).

{
  "type": "HEARTBEAT",
  "payload": {
    "sessionId": "sess_xyz789",
    "battery": 78,
    "connectivity": "strong",
    "activeZone": "work_zone",
    "strokeCount": 142,
    "lastActivityMs": 1200
  }
}
Field Type Description
battery int Percentage (0-100)
connectivity enum strong, weak, offline
activeZone string Current INPUT_ZONE id, if any
strokeCount int Total strokes this session
lastActivityMs int Ms since last stroke

ZONE_ACTIVITY

Fired when student enters/exits an input zone.

{
  "type": "ZONE_ACTIVITY",
  "payload": {
    "zoneId": "answer_zone",
    "action": "enter",
    "timestamp": 1711670500000
  }
}
Action Meaning
enter Stroke started in zone
exit Stroke ended, left zone

ERROR

Edge encountered an error.

{
  "type": "ERROR",
  "payload": {
    "code": "RENDER_FAILED",
    "message": "Failed to render MATH_BLOCK: unsupported format",
    "primitiveId": "math_001"
  }
}

3.3 Messages: Tutor → Edge

SESSION_CONFIG

Session configuration. See section 2.3.

LOAD_EXERCISE

Load new exercise content.

{
  "type": "LOAD_EXERCISE",
  "payload": {
    "exerciseId": "ex_4521",
    "primitives": [ ... ],
    "clearStrokes": true
  }
}
Field Type Description
exerciseId string Exercise identifier
primitives array Content primitives per Visual Primitives Spec
clearStrokes bool Clear existing strokes (default true)

PRIMITIVE

Single primitive command.

{
  "type": "PRIMITIVE",
  "payload": {
    "type": "HIGHLIGHT",
    "id": "hl_001",
    ...
  }
}

PRIMITIVE_BATCH

Multiple primitives at once.

{
  "type": "PRIMITIVE_BATCH",
  "payload": {
    "primitives": [ ... ]
  }
}

CLEAR

Clear primitives or strokes.

{
  "type": "CLEAR",
  "payload": {
    "target": "annotations"
  }
}
Target Effect
annotations Clear annotation layer
hints Clear hint primitives
feedback Clear marks, pulses
strokes Clear student strokes
all Full reset

STROKE_ACK

Acknowledge received strokes.

{
  "type": "STROKE_ACK",
  "payload": {
    "ackSeq": 42
  }
}

Edge can discard buffered batches ≤ ackSeq.

SESSION_END

End the session.

{
  "type": "SESSION_END",
  "payload": {
    "reason": "completed",
    "summary": {
      "duration": 2700,
      "exercisesCompleted": 5,
      "strokeCount": 487
    }
  }
}
Reason Meaning
completed Normal end
timeout Inactivity timeout
error Error forced end
user_exit User closed app

4. Session State Machine

                    ┌─────────────┐
                    │   IDLE      │
                    │  (app open, │
                    │ not paired) │
                    └──────┬──────┘
                           │ Pairing initiated
                           ▼
                    ┌─────────────┐
                    │  PAIRING    │
                    │             │
                    └──────┬──────┘
                           │ CAPABILITIES sent, SESSION_CONFIG received
                           ▼
                    ┌─────────────┐
                    │   ACTIVE    │◄─────────────────────┐
                    │             │                      │
                    │ • Streaming │  LOAD_EXERCISE       │
                    │   strokes   │──────────────────────┘
                    │ • Rendering │
                    │   primitives│
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
              ▼            ▼            ▼
       ┌──────────┐ ┌──────────┐ ┌──────────┐
       │  PAUSED  │ │RECONNECT │ │  ENDED   │
       │          │ │          │ │          │
       │ (user    │ │ (conn    │ │ (session │
       │  paused) │ │  lost)   │ │  over)   │
       └────┬─────┘ └────┬─────┘ └──────────┘
            │            │
            │  Resume    │  Connection restored
            └────────────┴───────► ACTIVE

4.1 State Descriptions

State Description Edge Behavior
IDLE App open, no active session Show pairing UI
PAIRING Connecting to Tutor Send CAPABILITIES, wait for config
ACTIVE Session in progress Stream strokes, render primitives
PAUSED User paused session Stop streaming, retain state
RECONNECTING Connection lost Buffer strokes, attempt reconnect
ENDED Session complete Show summary, return to IDLE

4.2 Reconnection Behavior

When connection drops:

  1. Edge enters RECONNECTING state
  2. Continue capturing strokes to local buffer
  3. Attempt reconnect every 2s (exponential backoff to 30s max)
  4. On reconnect:
  5. If offline > 5 minutes: prompt user, offer to save locally

5. Rendering Requirements

5.1 Content Layer

Edge MUST:

Edge SHOULD:

5.2 Stroke Layer

Edge MUST:

Edge SHOULD:

5.3 Annotation Layer

Edge MUST:

Edge SHOULD:

5.4 Refresh Strategy

For e-ink displays:

Scenario Strategy
Stroke rendering Fast/partial refresh (ghosting OK)
LOAD_EXERCISE Full refresh
Annotation added Partial refresh
TRANSITION received Honor hint field
Idle > 30s Full refresh to clear ghosting

6. Stroke Capture Requirements

6.1 Sampling

Edge MUST:

6.2 Batching

Edge MUST:

6.3 Gesture Detection

Edge MUST detect and report:

Edge SHOULD detect:


7. Offline Behavior

7.1 Minimum Offline Capability

Edge MUST:

7.2 Extended Offline (Future)

Edge MAY:


8. UI Requirements

8.1 Required UI Elements

Element Purpose
Connection indicator Show paired/unpaired/reconnecting
Session status Active exercise, time elapsed
Undo button Trigger GESTURE:undo
Done button Trigger GESTURE:submit

8.2 Optional UI Elements

Element Purpose
Hint button Request hint (GESTURE:help)
Navigation Previous/next exercise
Pause button Pause session
Settings Stylus calibration, preferences

8.3 UI Principles


9. Security Requirements

9.1 Communication

9.2 Local Storage

9.3 Privacy


10. Testing Requirements

Edge implementations must pass:

10.1 Capability Tests

10.2 Stroke Tests

10.3 Rendering Tests

10.4 Session Tests

10.5 Edge Cases


11. Implementation Checklist

For each new Edge platform:

Phase 1: Core

Phase 2: Content

Phase 3: Annotation

Phase 4: Polish


Appendix A: Protocol Version History

Version Date Changes
1 March 2026 Initial spec

Appendix B: Message Type Reference

Edge → Tutor

Type Required Description
CAPABILITIES Device capabilities at session start
STROKE_BATCH Batched stroke data
GESTURE User gesture detected
HEARTBEAT Periodic status
ZONE_ACTIVITY Enter/exit input zone
ERROR Error report

Tutor → Edge

Type Required Description
SESSION_CONFIG Session configuration
LOAD_EXERCISE Load exercise content
PRIMITIVE Single visual primitive
PRIMITIVE_BATCH Multiple primitives
CLEAR Clear content/annotations
STROKE_ACK Acknowledge strokes
SESSION_END End session

Appendix C: Error Codes

Code Meaning
RENDER_FAILED Could not render primitive
UNSUPPORTED_PRIMITIVE Unknown primitive type
UNSUPPORTED_FORMAT Unknown math format
STORAGE_FULL Local buffer exhausted
CONNECTION_FAILED Could not connect to Tutor
SESSION_EXPIRED Session timed out

This completes Phase 1: Foundation specs. Next: Bridge Protocol (Phase 2).