Ideation / Change brief

Offline drafts for Field Notes

Losing signal on a trail loses the note you were writing.

offline-drafts · revision 2

This agreement stays visible as work progresses. Open /ideation in Pi for run controls.

The change

Before

Field Notes needs a connection to save. Drop signal mid-sentence and the draft is gone.

Proposed change

After

Notes save on the device first, sync when signal returns, and flag conflicts instead of overwriting.

The existing experience → the agreed outcome. Read together with the invariants and boundaries below.

Revision delta · 1 → 2

4 changed areas. Review changed boundaries and criteria before any new approval.

outOfScope

Previous

[
  "Real-time collaboration"
]

Current

[
  "Real-time collaboration",
  "Syncing attachments"
]
decisions

Previous

[
  {
    "decision": "How is “the offline indicator feels right” checked? A test for the state, plus your airplane-mode walkthrough",
    "reason": "A test proves the state; only a person can judge whether it feels right."
  }
]

Current

[
  {
    "decision": "How is “the offline indicator feels right” checked? A test for the state, plus your airplane-mode walkthrough",
    "reason": "A test proves the state; only a person can judge whether it feels right."
  },
  {
    "decision": "Keep both versions when edits conflict",
    "reason": "Silently picking a winner is the failure this change exists to fix.",
    "rejected": "Last write wins"
  }
]
acceptance

Previous

[
  {
    "id": "draft-store",
    "criterion": "Drafts persist across a restart with no network",
    "check": {
      "cmd": "pnpm test src/drafts"
    }
  },
  {
    "id": "sync-queue",
    "criterion": "Queued edits sync in order when signal returns",
    "check": {
      "cmd": "pnpm test src/sync"
    }
  },
  {
    "id": "conflicts",
    "criterion": "A conflicting edit shows a banner instead of overwriting",
    "check": {
      "cmd": "pnpm test src/conflicts"
    }
  },
  {
    "id": "status",
    "criterion": "The offline indicator reflects real connectivity",
    "check": {
      "cmd": "pnpm test src/status"
    }
  },
  {
    "id": "full-suite",
    "criterion": "The whole test suite passes",
    "check": {
      "cmd": "pnpm test"
    }
  },
  {
    "id": "typecheck",
    "criterion": "Type checking passes",
    "check": {
      "cmd": "pnpm typecheck"
    }
  },
  {
    "id": "calm",
    "criterion": "Writing in airplane mode feels calm",
    "check": {
      "judgment": "In airplane mode, write a note, reconnect, and confirm nothing was lost."
    }
  }
]

Current

[
  {
    "id": "draft-store",
    "criterion": "Drafts persist across a restart with no network",
    "check": {
      "cmd": "pnpm test src/drafts"
    }
  },
  {
    "id": "sync-queue",
    "criterion": "Queued edits sync in order when signal returns",
    "check": {
      "cmd": "pnpm test src/sync"
    }
  },
  {
    "id": "conflicts",
    "criterion": "A conflicting edit keeps both versions and shows a banner",
    "check": {
      "cmd": "pnpm test src/conflicts"
    }
  },
  {
    "id": "status",
    "criterion": "The offline indicator reflects real connectivity",
    "check": {
      "cmd": "pnpm test src/status"
    }
  },
  {
    "id": "full-suite",
    "criterion": "The whole test suite passes",
    "check": {
      "cmd": "pnpm test"
    }
  },
  {
    "id": "typecheck",
    "criterion": "Type checking passes",
    "check": {
      "cmd": "pnpm typecheck"
    }
  },
  {
    "id": "calm",
    "criterion": "Writing in airplane mode feels calm",
    "check": {
      "judgment": "In airplane mode, write a note, reconnect, and confirm nothing was lost."
    }
  }
]
units

Previous

[
  {
    "id": "store",
    "title": "Local draft store",
    "goal": "Persist drafts on the device before any network call.",
    "risk": "low",
    "needs": [],
    "acceptanceIds": [
      "draft-store"
    ]
  },
  {
    "id": "queue",
    "title": "Sync queue",
    "goal": "Replay queued edits in order when connectivity returns.",
    "risk": "medium",
    "needs": [
      "store"
    ],
    "acceptanceIds": [
      "sync-queue"
    ]
  },
  {
    "id": "conflicts",
    "title": "Conflict banner",
    "goal": "Surface conflicting edits rather than overwriting.",
    "risk": "medium",
    "needs": [
      "queue"
    ],
    "acceptanceIds": [
      "conflicts"
    ]
  },
  {
    "id": "status",
    "title": "Offline indicator",
    "goal": "Show real connectivity state.",
    "risk": "low",
    "needs": [],
    "acceptanceIds": [
      "status",
      "full-suite",
      "typecheck",
      "calm"
    ]
  }
]

Current

[
  {
    "id": "store",
    "title": "Local draft store",
    "goal": "Persist drafts on the device before any network call.",
    "risk": "low",
    "needs": [],
    "acceptanceIds": [
      "draft-store"
    ]
  },
  {
    "id": "queue",
    "title": "Sync queue",
    "goal": "Replay queued edits in order when connectivity returns.",
    "risk": "medium",
    "needs": [
      "store"
    ],
    "acceptanceIds": [
      "sync-queue"
    ]
  },
  {
    "id": "conflicts",
    "title": "Conflict banner",
    "goal": "Keep both versions of a conflicting edit and say so, rather than overwriting either.",
    "risk": "medium",
    "needs": [
      "queue"
    ],
    "acceptanceIds": [
      "conflicts"
    ]
  },
  {
    "id": "status",
    "title": "Offline indicator",
    "goal": "Show real connectivity state.",
    "risk": "low",
    "needs": [],
    "acceptanceIds": [
      "status",
      "full-suite",
      "typecheck",
      "calm"
    ]
  }
]

Run status

Accepted

The run records explicit human acceptance. This does not mean merged or deployed.

Recorded snapshot only; source freshness is compared with the run’s recorded fingerprint, not the live workspace.

Run provenance
Run
offline-drafts-f8599f30
State
accepted
Workspace
.git/ideation/workspaces/offline-drafts-f8599f30
Branch
ideation/offline-drafts-f8599f30
Base revision
9d27a61f0c4b8e53d1a2f6c90b7e4d3a18c5f207
Source revision
c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92
Updated
2026-09-24T15:40:02Z
Tokens
118905

Must hold

How the work connects

Arrows run from prerequisite to dependent deliverable. These are dependencies, not a timeline.

store → queuequeue → conflicts
  1. Local draft storeCompleted · low risk · Independent starting point
  2. Sync queueCompleted · medium risk · Needs: store
  3. Conflict bannerCompleted · medium risk · Needs: queue
  4. Offline indicatorCompleted · low risk · Independent starting point

Acceptance criteria

Verification record · Latest recorded evidence, checked against this brief and the recorded source.

Read each row from commitment → check → evidence state. Grouped by the deliverable responsible for it.

Local draft store

store
Deliverable intent

Persist drafts on the device before any network call.

draft-store

Drafts persist across a restart with no network

Command
pnpm test src/drafts
passedRecorded result
Check & evidence

Recorded status: passed

Source revision: c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92

pnpm test src/drafts
6 tests passed

Duration: 1800 ms

Sync queue

queue
Deliverable intent

Replay queued edits in order when connectivity returns.

sync-queue

Queued edits sync in order when signal returns

Command
pnpm test src/sync
passedRecorded result
Check & evidence

Recorded status: passed

Source revision: c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92

pnpm test src/sync
9 tests passed

Duration: 3170 ms

Conflict banner

conflicts
Deliverable intent

Keep both versions of a conflicting edit and say so, rather than overwriting either.

conflicts

A conflicting edit keeps both versions and shows a banner

Command
pnpm test src/conflicts
passedRecorded result
Check & evidence

Recorded status: passed

Source revision: c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92

pnpm test src/conflicts
12 tests passed

Duration: 4540 ms

Offline indicator

status
Deliverable intent

Show real connectivity state.

status

The offline indicator reflects real connectivity

Command
pnpm test src/status
passedRecorded result
Check & evidence

Recorded status: passed

Source revision: c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92

pnpm test src/status
15 tests passed

Duration: 5910 ms

full-suite

The whole test suite passes

Command
pnpm test
passedRecorded result
Check & evidence

Recorded status: passed

Source revision: c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92

pnpm test
18 tests passed

Duration: 7280 ms

typecheck

Type checking passes

Command
pnpm typecheck
passedRecorded result
Check & evidence

Recorded status: passed

Source revision: c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92

pnpm typecheck
Found 0 errors.

Duration: 8650 ms

calm

Writing in airplane mode feels calm

Human judgment

In airplane mode, write a note, reconnect, and confirm nothing was lost.

pendingAwaiting human review

Human judgment required.

Work & remaining obligations

Local draft store

completed

Persist drafts on the device before any network call. Reviewed independently.

Attempts: 1 · Review: passed · Local commit: 5eedbed

Sync queue

completed

Replay queued edits in order when connectivity returns. Reviewed independently.

Attempts: 1 · Review: passed · Local commit: 5f0cf94

Conflict banner

completed

Keep both versions of a conflicting edit and say so, rather than overwriting either. Reviewed independently.

Attempts: 1 · Review: passed · Local commit: 5f2c33b

Offline indicator

completed

Show real connectivity state. Reviewed independently.

Attempts: 1 · Review: passed · Local commit: 5f4b6e2

Conversation with this run

Annotations reach the coordinating session, not the builder. Feedback never changes approval, scope, or acceptance automatically. Use explicit Pi controls to pause or stop.

No feedback recorded. When served by the artifacts extension, use its Review panel to send questions or suggestions.

Run decisions

[
  {
    "type": "accept",
    "sourceRevision": "c41e09d7b2a8f3615e0d2b9c7a4f18e3d5b60a92",
    "judgments": [
      "calm"
    ],
    "at": "2026-09-24T15:40:02Z"
  }
]

Boundaries & choices

Out of scope

  • Real-time collaboration
  • Syncing attachments

Delegated

None specified.

Decisions & rationale

How is “the offline indicator feels right” checked? A test for the state, plus your airplane-mode walkthrough

A test proves the state; only a person can judge whether it feels right.

Keep both versions when edits conflict

Silently picking a winner is the failure this change exists to fix.

Rejected: Last write wins

Execution boundaries & mechanics

Execution mode: strict. Independent review remains required. These are requested boundaries, not proof of approval.

Writable paths

  • src/

Exact files or trailing-slash directory prefixes. “.” covers ordinary project files only; protected internals and dependency manifests/lockfiles remain excluded.

Exact commands

pnpm test src/drafts
pnpm test src/sync
pnpm test src/conflicts
pnpm test src/status
pnpm test
pnpm typecheck

Commands must assert success with exit 0. Expected outcomes are explanatory. Approved scripts execute project code: tool policy is not an OS sandbox.

No time, token or attempt budget applies: work continues until it is verified, you pause or stop it, or it stops to ask because a check keeps failing.

Host-managed local commit: permitted. No push, merge, or deploy.

Units

Local draft store low

Persist drafts on the device before any network call.

store · needs: none · criteria: draft-store

Sync queue medium

Replay queued edits in order when connectivity returns.

queue · needs: store · criteria: sync-queue

Conflict banner medium

Keep both versions of a conflicting edit and say so, rather than overwriting either.

conflicts · needs: queue · criteria: conflicts

Offline indicator low

Show real connectivity state.

status · needs: none · criteria: status, full-suite, typecheck, calm

Brief fingerprint

f8599f30b7856bd019505905e8ae5410420b52b214f9f0e46987b7591e93e01a