ShrubberyDocs
Sign in

Handshake Flow

Overview

The Handshake is the explicit consent event by which a Knight accepts a proposed Shrubbery from a Lead. It is the moment a commitment becomes load-bearing — until it happens, no Say-Do Ratio counts and no deadline is enforced. The flow ends in one of two terminal states: Active (Knight accepted) or Refused (Knight declined).

Actors

  • Lead — proposes the Shrubbery (always the assigner on the row).
  • Knight — receives the proposal, reviews it in the Accord, and accepts or refuses.
  • Squire (optional) — only present if the Shrubbery originated from Smart Paste; it drafted the row but does not participate in the Handshake itself.

Flow

  1. Lead sends a Shrubbery to the Knight — DraftPending_Handshake. A row appears in the Knight's Accord. An audit event is appended with actor_kind = user.
  2. Knight opens the Accord. The Shrubbery surfaces with its objective, deadline, source excerpt, and an Accept/Refuse pair.
  3. Knight accepts — Pending_HandshakeActive. The Shrubbery now contributes to the team CFS. Audit event: actor_kind = user, type handshake_accepted.
    • Or Knight refuses — Pending_HandshakeRefused. The row counts toward Ghost Rate. Audit event type: handshake_refused.
  4. Lead sees the result on the Garden card colour and the Knight's Dossier counter.

Edge cases

  • Stale Pending_Handshake — Inngest fires a Nudge after the configured stale threshold. The Shrubbery stays in Pending_Handshake; the Nudge does not auto-refuse.
  • Externally-sourced Shrubberies — when the Inbox API ingests a payload, the row starts in Pending_Handshake directly (not Draft), because the Lead's intent is already declared by the API Token mint. The Handshake step is otherwise identical.
  • Renegotiation — a substantive edit (deadline / wording) by the Lead on an Active Shrubbery emits a Renegotiated event and reverts state to Pending_Handshake, re-arming the flow. Non-substantive edits stay Active and only emit an Edited event.
  • Lead self-acceptance — disallowed. The Knight is always a different user from the Lead on a single Shrubbery row.
  • Concurrent accept + refuse — the database enforces a single terminal transition. Whichever request wins commits first; the loser receives a 409 and the UI refreshes.

Last updated: 17 May 2026