File size: 5,398 Bytes
c6253b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9af2b22
c6253b2
 
 
 
 
9af2b22
 
c6253b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb29daa
 
 
 
 
 
 
 
 
 
 
 
c6253b2
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Schedule / time-tracking

Additive Habit Journal feature: iOS-like day plan, thick block feedback, learned duration priors, Cursor agent pull/push, and OpenRouter/rules reschedule.

## P1 scope lock (hard)

Ship only: **day timeline + thick feedback (<20s) + priors/duration learning + yesterday-trigger / last-hour capacity cut.**

Do **not** implement as code:

- full PERMA
- ωEᵢ, δᵢ, or H=S+C+V
- hedonic δ as an explicit v1 term (learn later via would_repeat + falling fun)
- split feedback into Meaning vs Flow / “meaningful?” / “in the zone?”
- family/relationship tasks as a pillar to maximize
- schedule as a substitute for Daily or Log

### EV stays owned (no rewrite)

```
EV = P(done)*U + γ*I + η*Fun − λt*d_hat − λm*cost − λf*FSE
```

Seligman = **operators**, not a new religion:

- trigger day → raise λ_f and η; only P0 overrides cuts
- escape (porn / court / rerun binge) ≠ fun/explore
- fun/explore should yield data or skill contact

### Feedback fields (v1 — no extras)

`did` · `actual_min` · `quality` 1–5 · `fun` 1–5 · `energy_after` −2…+2 · `would_repeat` · `skip_reason` · money optional.

Later mapping from data only: quality+would_repeat ≈ meaning; fun+energy ≈ recovery. Do not ask PERMA questions in UI.

### Premortems (fail the PR if present)

Planning-as-avoidance · no feedback · OR thrash · overfull FSE day · schedule theater · guilt / duty-maximizer copy.

### P0 never silent-reschedule

Sleep, food, Spain/visa deadlines stay locked at their times.

## Nav IA (chosen)

`Home | Plan | (+) Log | Daily | Settings`

- Center FAB stays **Log** (one tap from every main screen).
- **History** remains at `#/history` and is reachable from Home (“See all” / History chip).

## Data

Under `DATA_ROOT/schedule/`:

| Path | Purpose |
|------|---------|
| `plan-YYYY-MM-DD.json` | Versioned day plan |
| `feedback.jsonl` | Block feedback rows |
| `priors.json` | Per-kind `d_hat`, `p_done`, fun, slip |
| `meta.json` | Last reschedule timestamp |

## Math (server-owned)

```
d_hat = (n/(n+m)) * mean_actual + (m/(n+m)) * prior_default
slip = actual_min - planned_min
p_done ≈ (N_done + α) / (N + α + β)
C_today cut if yesterday_trigger or last-hour urge/court/corn/rerun (P0 still allowed)
health = (strong_feedback / planned) * p0_done_rate * (1 if explore/fun done else 0)
```

Strong feedback = `did` in done|partial **and** actual_min, quality, fun present.  
LLM must not invent `p_helped`, rank, or %.

## Human API (session cookie)

- `GET/PUT /api/plan/{date}`
- `POST/PATCH/DELETE /api/plan/{date}/blocks[/{id}]`
- `POST /api/plan/{date}/blocks/{id}/feedback`
- `POST /api/plan/{date}/seed` — empty day → template starter (P0 locked; capacity cuts)
- `GET /api/schedule/priors`
- `GET /api/schedule/templates`
- `POST /api/plan/{date}/reschedule` `{ "reason", "force" }`
- `GET /api/plan/{date}/health`

`GET /api/plan/{date}` overlays live `capacity_hint`, `operators`, `risk_1h`, `triggers_yesterday`.

## Agent API

Set Space secret `AGENT_TOKEN`.

```bash
# Pull context
curl -s -H "Authorization: Bearer $AGENT_TOKEN" \
  "https://YOUR_SPACE/api/agent/context?day=2026-07-19"

# Push plan
curl -s -X PUT -H "Authorization: Bearer $AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source":"cursor","blocks":[{"date":"2026-07-19","start":"09:00","end":"09:45","title":"Earn one ship","kind":"earn_ship","intent":"duty","priority":"P1","planned_min":45,"status":"planned","locked":false,"notes":"","version_added":1,"source":"cursor"}]}' \
  "https://YOUR_SPACE/api/agent/plan/2026-07-19"
```

### Agent contract (one line)

Implement thin schedule loop + thick feedback + trigger capacity cuts. Seligman validates recovery and anti-duty-only design; do not expand the equation or feedback fields.

### Steps

1. `GET /api/agent/context?day=`
2. Build ≤ `max_blocks`, pad with `d_hat`, keep P0 locked, ≥1 explore/restore unless capacity very low
3. `PUT /api/agent/plan/{date}`
4. User completes blocks on phone (thick feedback)
5. Optional `POST /api/plan/{date}/reschedule` when missed/risk

Context includes `operators` and `capacity_hint`.

## Env

```
AGENT_TOKEN=...
OPENROUTER_API_KEY=...   # optional; rules backup if missing
RESCHEDULE_MIN_GAP_MIN=90
SCHEDULE_DAY_START=06:00
SCHEDULE_DAY_END=23:00
TZ / SCHEDULE_TIMEZONE=Africa/Dar_es_Salaam
```

## UI map

| Route | Role |
|-------|------|
| `#/plan` | Day timeline 06:00–23:00, now line, colored blocks |
| Block sheet | Complete with did / minutes / quality / fun (no PERMA Qs) |
| Home | Next 1–2 blocks + overdue feedback banner; empty → Paste plan CTA |
| Plan | Paste ChatPlan / Export for chat / checklist check-off / day review |

### ChatPlan loop (external AI)

- `POST /api/plan/{day}/import` — ChatPlan JSON (or `{plan, mode}`) → timetable
- `GET /api/plan/{day}/export` — filled ChatPlan in envelope
- `GET /api/plan/{day}/export.txt` — downloadable JSON attachment
- `POST /api/plan/{day}/blocks/{id}/check` — fast status without thick feedback
- `PATCH /api/plan/{day}/meta` — title / intention / constraints / day_review
- Feedback additive: `emotions[]`, `fse_event`, `intensity`


## Reschedule

- OpenRouter returns JSON blocks; P0 times preserved.
- Without API key / parse fail → `rules_backup_reschedule`.
- Cooldown `RESCHEDULE_MIN_GAP_MIN` unless `force`.