{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://storm-charles.promptugal.news/data/flows/schema.json",
  "title": "A flow of the team's work (flows/v1)",
  "description": "One small format for a flow: who took part (actors), what each did and when (steps, each with its evidence), who spoke to whom (edges, counted from the steps) and the gaps with nothing on record (pauses). Made by tools/flows-build.mjs from the record, or from a path of incident.storyteller@ (story/paths/*.md); drawn by app/flows/player.js. Documented in flows/README.md; the primitives agreed with story/primitives.md.",
  "by": "incident.motion@web-summit.dinis",
  "updated": "2026-11-11T11:48:00Z",
  "type": "object",
  "required": ["schema", "id", "kind", "title", "actors", "steps", "experiment"],
  "properties": {
    "schema": { "const": "flows/v1" },
    "id": { "type": "string", "pattern": "^[a-z0-9-]+$", "description": "Permanent: the file is data/flows/<id>.json, the embed app/flows/embed.html?flow=<id>." },
    "told_by": { "type": "string", "description": "For a path: the agent that told it." },
    "kind": { "enum": ["wake", "handover", "night", "hour", "path", "trace"], "description": "hour: every agent that pushed in the last 60 minutes of the record; wake: one agent's wake end to end; handover: one session to the next; night: one agent by its sessions; path: a path told by incident.storyteller@ (story/paths/*.json); trace: a trace of incident.reporter@ (reporter/traces/*.json, sc-trace/1)." },
    "title": { "type": "string" },
    "summary": { "type": "string", "description": "One sentence: what the flow shows, with its counts and times." },
    "experiment": { "const": true, "description": "Every flow is an experiment until said otherwise, and every view says so." },
    "recipe": { "type": "object", "description": "For a flow made by recipe: kind, agent, and n or at. The browser makes the same flow from the same record (app/flows/core.js)." },
    "source": { "type": "string", "description": "For a path: the markdown file it was read from." },
    "built_from": { "type": "array", "items": { "type": "string" }, "description": "The tracked files the flow was made from." },
    "window": { "type": "object", "properties": { "from": { "type": ["string", "null"] }, "to": { "type": ["string", "null"] } } },
    "record": { "type": "object", "description": "The record read: head (the latest commit in it) and updated." },
    "actors": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "kind", "label"],
        "properties": {
          "id": { "type": "string", "description": "a-<agent> for an agent, s-<agent>-<n> for its nth session, p-<name> for a person, o-<name> for an outside body, t-<name> for a thing (a file, a page, a data set, a key)." },
          "kind": { "enum": ["person", "agent", "session", "outside", "machine", "thing"] },
          "icon": { "type": "string", "description": "The glyph (story/cast.json icon.glyph, or the kind); the view draws the kind's shape, never colour alone." },
          "glyph": { "type": "string" },
          "emoji": { "type": "string", "description": "The cast's emoji, shown in the tooltip." },
          "mark": { "type": "string", "maxLength": 3, "description": "Up to three letters inside the icon." },
          "label": { "type": "string" },
          "name": { "type": "string", "description": "An agent's full name." },
          "of": { "type": "string", "description": "A session: the agent actor it belongs to." },
          "evidence": { "$ref": "#/$defs/evidence" }
        }
      }
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["t", "actor", "verb", "object", "evidence"],
        "properties": {
          "t": { "type": "string", "format": "date-time", "description": "UTC, as recorded." },
          "drawn": { "type": "string", "description": "Present when the time is not recorded and was drawn from a neighbouring fact; says how. Drawn steps are dashed in every view." },
          "actor": { "type": "string" },
          "verb": { "enum": ["wake", "read", "write", "commit", "push", "release", "publish", "capture", "hand-over", "seal", "message", "ask", "answer", "instruct", "route", "correct", "pause"], "description": "The steps of story/primitives.md (incident.storyteller@): its words win." },
          "object": { "type": "string", "description": "What: a commit's subject, a file, a page, a sentence; short." },
          "said": { "type": "string", "description": "A trace step's own word for what happened (its kind), kept as written; the verb is the nearest primitive." },
          "to": { "type": "array", "items": { "type": "string" }, "description": "The actors it is addressed to or acts on (an arrow in the view)." },
          "files": { "type": "array", "items": { "type": "string" } },
          "n_files": { "type": "integer" },
          "n": { "type": "integer", "description": "When one step stands for several (an hour's commits folded): how many." },
          "evidence": { "$ref": "#/$defs/evidence" }
        }
      }
    },
    "edges": { "type": "array", "items": { "type": "object", "required": ["from", "to", "verb", "n"], "properties": { "from": { "type": "string" }, "to": { "type": "string" }, "verb": { "type": "string" }, "n": { "type": "integer" } } } },
    "pauses": { "type": "array", "items": { "type": "object", "required": ["from", "to", "minutes"], "properties": { "from": { "type": "string" }, "to": { "type": "string" }, "minutes": { "type": "integer" }, "actor": { "type": "string" }, "why": { "type": "string" } } } },
    "by": { "type": "string" },
    "updated": { "type": ["string", "null"], "description": "The time of the flow's last step (no clock: the same record gives the same bytes)." }
  },
  "$defs": {
    "evidence": {
      "type": "object",
      "minProperties": 1,
      "properties": {
        "commit": { "type": "string", "description": "The first 8 hex of a commit on dev." },
        "url": { "type": "string", "pattern": "^https://" },
        "file": { "type": "string", "description": "A tracked file (or folder, ending in /)." },
        "run": { "type": "integer", "description": "A CI run number." },
        "key": { "type": "string", "description": "An id in data/keys.json." },
        "signal": { "type": "string", "description": "A timeline row id, s-<MMDD>T<HHMM>." },
        "note": { "type": "string", "description": "When nothing is on record: says so." }
      }
    }
  }
}
