daily-focus 1.2.0-dev.9 → 2.0.0-dev.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +18 -4
  2. package/SETUP.md +156 -105
  3. package/dist/{audit-DNTFZOHH.js → audit-AQUBVWPA.js} +4 -3
  4. package/dist/{chunk-KZNY45XW.js → chunk-72NUDSOV.js} +126 -119
  5. package/dist/{chunk-GQ3NCWRT.js → chunk-ITUK7XKS.js} +6 -19
  6. package/dist/{chunk-KL6RU4XT.js → chunk-JTMBBUMD.js} +316 -10
  7. package/dist/chunk-QG4XXKBP.js +18 -0
  8. package/dist/chunk-U6EPOXEW.js +570 -0
  9. package/dist/{chunk-P3E2B2SD.js → chunk-WPXIQPYX.js} +1 -1
  10. package/dist/{chunk-6SMUSPZG.js → chunk-YPGKXTBX.js} +2 -2
  11. package/dist/cli.js +19 -12
  12. package/dist/{demo-TIIXODJG.js → demo-KE6WDWMA.js} +159 -37
  13. package/dist/{init-XDMAXU2S.js → init-5KJVHWJU.js} +41 -6
  14. package/dist/{seed-TWT7EDXJ.js → seed-T4VEY6DT.js} +4 -3
  15. package/dist/{server-WT4CQ3VX.js → server-FFRNYEAO.js} +2000 -743
  16. package/dist/{service-ZUHI3VKH.js → service-LQ46YRCZ.js} +7 -6
  17. package/package.json +6 -2
  18. package/prompts/README.md +20 -4
  19. package/prompts/assistant.md +7 -1
  20. package/prompts/morning-brief-personal.md +37 -0
  21. package/prompts/morning-brief-work.md +37 -0
  22. package/prompts/onboarding.md +41 -0
  23. package/public/app.js +806 -287
  24. package/public/fonts/IBMPlexSans-Variable.woff2 +0 -0
  25. package/public/fonts/IBMPlexSerif-Italic.woff2 +0 -0
  26. package/public/fonts/IBMPlexSerif-Medium.woff2 +0 -0
  27. package/public/fonts/IBMPlexSerif-Regular.woff2 +0 -0
  28. package/public/fonts/IBMPlexSerif-SemiBold.woff2 +0 -0
  29. package/public/fonts/OFL.txt +93 -0
  30. package/public/style.css +1686 -481
  31. package/dist/chunk-V2UN3JYL.js +0 -140
@@ -1,6 +1,7 @@
1
1
  import {
2
+ LAUNCH_SETTINGS,
2
3
  loadConfig
3
- } from "./chunk-KZNY45XW.js";
4
+ } from "./chunk-72NUDSOV.js";
4
5
  import {
5
6
  IN_NPX_CACHE,
6
7
  PACKAGED,
@@ -30,9 +31,9 @@ function servicePath(path, nodeDir) {
30
31
  }
31
32
  function serviceEnvironment(env, nodeDir) {
32
33
  const kept2 = { PATH: servicePath(env.PATH ?? "", nodeDir) };
33
- for (const key of Object.keys(env).sort()) {
34
- const value = env[key];
35
- if (key.startsWith("DAILY_FOCUS_") && value !== void 0) kept2[key] = value;
34
+ for (const key of LAUNCH_SETTINGS) {
35
+ const value = env[key]?.trim();
36
+ if (value) kept2[key] = value;
36
37
  }
37
38
  return kept2;
38
39
  }
@@ -180,9 +181,9 @@ async function main(args) {
180
181
  if (found.dataDir === config.dataDir) {
181
182
  bad(`this dashboard is already running at ${url}${by}`, "stop the one started by hand, then run this again");
182
183
  } else if (found.dataDir) {
183
- bad(`port ${config.port} is taken by the dashboard for ${tilde(found.dataDir)}${by}`, "give one of them its own DAILY_FOCUS_PORT");
184
+ bad(`port ${config.port} is taken by the dashboard for ${tilde(found.dataDir)}${by}`, "give one of them its own --port");
184
185
  } else {
185
- bad(`port ${config.port} is taken by something else${by}`, "set DAILY_FOCUS_PORT to a free one");
186
+ bad(`port ${config.port} is taken by something else${by}`, "give it a free one with --port");
186
187
  }
187
188
  console.log();
188
189
  return 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daily-focus",
3
- "version": "1.2.0-dev.9",
3
+ "version": "2.0.0-dev.15",
4
4
  "description": "An interactive dashboard of what you should focus on today at work",
5
5
  "keywords": [
6
6
  "dashboard",
@@ -28,6 +28,7 @@
28
28
  "public/index.html",
29
29
  "public/style.css",
30
30
  "public/app.js",
31
+ "public/fonts/",
31
32
  "prompts/",
32
33
  "schema/",
33
34
  "tools/dfcal/build.sh",
@@ -40,7 +41,7 @@
40
41
  },
41
42
  "daily-focus": {
42
43
  "appInterface": 1,
43
- "appSource": "288797ddc9f77355cc5ec176f1f21452d49fd3ae"
44
+ "appSource": "a55e34e63517a3bb93c1352c48df2c6417f021d8"
44
45
  },
45
46
  "scripts": {
46
47
  "start": "node src/server.ts",
@@ -66,5 +67,8 @@
66
67
  "happy-dom": "20.14.5",
67
68
  "preact": "10.29.8",
68
69
  "typescript": "7.0.2"
70
+ },
71
+ "allowScripts": {
72
+ "esbuild": true
69
73
  }
70
74
  }
package/prompts/README.md CHANGED
@@ -5,12 +5,13 @@
5
5
  | [`morning-brief-work.md`](./morning-brief-work.md) | The prompt for the work briefing agent, run once every workday morning. |
6
6
  | [`morning-brief-personal.md`](./morning-brief-personal.md) | The prompt for the personal briefing agent: email, family calendars, Apple Reminders, Apple Messages, e-Boks and the user's own GitHub projects. |
7
7
  | [`assistant.md`](./assistant.md) | The instructions for the on-demand assistant, which the server runs headless when the user presses Ask on a row. One file for both profiles. Linked into the store as `assistant.md`. |
8
+ | [`onboarding.md`](./onboarding.md) | The instructions for the setup screen's CLI sessions, one per question, which propose the answer a new user most likely wants. Not linked into the store: the server reads it from the running copy and inlines it, as it does the assistant's. |
8
9
 
9
- All three are **nothing but prompt** — each is read verbatim by its agent, so anything
10
+ All four are **nothing but prompt** — each is read verbatim by its agent, so anything
10
11
  else in there is either noise the agent has to skip or, worse, an instruction it
11
12
  might try to act on. Notes about the prompts belong in this file instead.
12
13
 
13
- The assistant's file differs from the other two in one way: the server does read it.
14
+ The assistant's file differs from the briefing prompts in one way: the server does read it.
14
15
  It is the server that starts the assistant, so it is the server that inlines these
15
16
  instructions ahead of the row and the request on the first turn of a session. The
16
17
  quick actions the panel offers are sentences in `src/assistant.ts`, not in the
@@ -32,14 +33,16 @@ alongside `items.schema.json`, so a run only ever names a path inside the store:
32
33
  ~/.daily-focus/
33
34
  prompt.md → prompts/morning-brief-work.md (symlink, made by the dashboard at start)
34
35
  items.schema.json → schema/items.schema.json (symlink, made by the dashboard at start)
35
- focus.md you write it, in the dashboard or by hand
36
- sources.md you write it, in the dashboard or by hand
36
+ focus.md you write it, on the setup screen, in the dashboard or by hand
37
+ sources.md you write it, on the setup screen, in the dashboard or by hand
37
38
  settings.json the dashboard writes: what you set on its settings page
39
+ agent-settings.json the dashboard writes before every run: the settings the agent reads
38
40
  items.json the agent writes it
39
41
  actions.jsonl the dashboard appends
40
42
  agent.jsonl the dashboard appends: every run, its report, and the questions asked of it
41
43
  archive/ the dashboard writes
42
44
  prs.json the dashboard writes: its last fetch of the user's open pull requests
45
+ onboarding.json the dashboard writes: the setup screen's answers, and what was proposed for them
43
46
  ```
44
47
 
45
48
  That boundary is the point, and it is worth being strict about. A prompt that reaches
@@ -69,6 +72,19 @@ it. Nothing else is handed over: no extra instructions, no checkout, no copy of
69
72
  prompt. Everything that evolves lives in the prompt, in git, where a change to it is
70
73
  reviewable, and the wrapper should never need editing.
71
74
 
75
+ A setting that changes how the agent gathers, such as searching deleted mail, reaches
76
+ it the same way everything else does: through the store. Before each run the dashboard
77
+ writes `agent-settings.json` with the values it is running with, as saved on the
78
+ settings page, and both prompts say what each key means.
79
+ The wrapper stays the same whatever the settings are.
80
+
81
+ The prompt has the agent hand the reading of its sources to subagents, which share
82
+ its working directory and what its CLI allows it, so the prompt also tells it to
83
+ tell them that they only read. The judging and the writing stay with the agent. The
84
+ run's panel shows each subagent under the step that started it: Claude Code reports
85
+ them in its output, and for Codex the dashboard reads Codex's own session files
86
+ (`src/codexsessions.ts`).
87
+
72
88
  Which days it runs is `DAILY_FOCUS_AGENT_DAYS` — cron-numbered, so `1-5` is Mon–Fri
73
89
  and `0-4` is the Sun–Thu week — and Mon–Fri when unset. The same schedule drives the
74
90
  staleness banner, which turns red once the brief is more than 24 *working* hours old,
@@ -42,7 +42,13 @@ status comment on a ticket, a message. The user posts it, not you.
42
42
  ## How to answer
43
43
 
44
44
  Lead with the answer. If the question was "is this review right", the first line says
45
- whether it is. Then the evidence, as short as it can be. Use Markdown: short
45
+ whether it is. Then the evidence, as short as it can be.
46
+
47
+ Make the first line the verdict, on a line of its own, in under fifteen words: "Two
48
+ of Alice's three comments are right; the cap is a judgment call." or "Flaky, not
49
+ yours: the Safari job timed out on a step this change doesn't touch." The dashboard
50
+ may ask you a quick action on its own, before the user has looked, and shows that
51
+ line alone on the item's row. The rest is read only by someone who opens the panel. Use Markdown: short
46
52
  paragraphs, a list where there are parallel points, a code block for anything meant
47
53
  to be pasted. No headings; the panel is narrow.
48
54
 
@@ -24,6 +24,10 @@ not for you.
24
24
  gather and how to judge it; that file says *who* and *where*.
25
25
  - `items.schema.json` — **you only ever read this.** The machine-readable shape of
26
26
  `items.json`. Validate against it in step 5 if you can.
27
+ - `agent-settings.json` — **you only ever read this.** The choices the user made on
28
+ the dashboard's settings page about how you gather, rewritten by the dashboard
29
+ before every run. Each key is explained where it applies below; a missing file or
30
+ key means that key's default.
27
31
  - `prs.json` — **you only ever read this.** The dashboard's own cache of the pull
28
32
  requests the user has open, refreshed while the dashboard is in use. Facts only —
29
33
  reviews, checks, who last acted — with no judgement attached; use it if it helps,
@@ -100,6 +104,33 @@ Otherwise, each source's window starts three days before the previous brief's
100
104
 
101
105
  ### Step 2 — Gather
102
106
 
107
+ #### Hand the reading to subagents
108
+
109
+ Read the sources in parallel rather than one after another: hand each source to a
110
+ subagent of its own, or a few small ones to one subagent, so the slowest source sets
111
+ the pace rather than the sum of them. Run up to three at a time, starting the next as
112
+ one finishes. The reading is all you hand out. Step 1, the judging in step 3, the
113
+ writing in step 4 and the checks in step 5 stay with you, because they need
114
+ everything in one place.
115
+
116
+ A subagent may not see this file, so give it what it needs in its task: its source's
117
+ section of this step in full, with the value of any setting from `agent-settings.json`
118
+ that the section names; the rules under "Across every source" below; the window from
119
+ step 1; and the ids from the previous brief that came from its source and are still
120
+ open, so it looks at each again. Name each after its source — `calendar`, `email`, `eboks` — since
121
+ the dashboard shows the user which is which while you work.
122
+
123
+ Ask for evidence, not decisions. For each thing that might be an item: its upstream id
124
+ or key, its link, who and what it is about, its dates, and what the source shows about
125
+ whether it is still open. Then what it could not read, why, and the link. Merging
126
+ duplicates, ranking and wording are yours. When an answer is missing something its
127
+ source should have had, ask again or read it yourself.
128
+
129
+ A subagent only reads, and tell it so: it writes no file, `items.json` least of all,
130
+ and changes nothing in any source.
131
+
132
+ If you cannot start subagents, read the sources yourself, one after another.
133
+
103
134
  #### Across every source
104
135
 
105
136
  **Use a connector, API, MCP server or CLI as the evidence source.** `sources.md` says
@@ -148,6 +179,12 @@ and anything filters moved out of the inbox, included. Mail the user filed is no
148
179
  mail they finished with. **Do not limit the search to unread mail**: the things that
149
180
  rot are the ones the user opened, meant to deal with, and didn't.
150
181
 
182
+ Mail the user deleted is mail they finished with, so leave Trash out unless
183
+ `searchTrash` in `agent-settings.json` is `true` (default `false`). A search with no
184
+ `in:` operator already covers archived mail and skips Trash and Spam; when the
185
+ setting is off, don't widen it with `in:anywhere` or a trash option. When it is on,
186
+ search Trash as well, and still never Spam.
187
+
151
188
  **On a first run, search the last 90 days.** The point of that run is to find what
152
189
  fell through the cracks: a reply the user owes, a bill, a form, a booking to confirm,
153
190
  a promise they made in a thread. Afterwards, use the normal window from step 1.
@@ -22,6 +22,10 @@ not for you.
22
22
  how to judge it; that file says *who* and *where*.
23
23
  - `items.schema.json` — **you only ever read this.** The machine-readable shape of
24
24
  `items.json`. Validate against it in step 5 if you can.
25
+ - `agent-settings.json` — **you only ever read this.** The choices the user made on
26
+ the dashboard's settings page about how you gather, rewritten by the dashboard
27
+ before every run. Each key is explained where it applies below; a missing file or
28
+ key means that key's default.
25
29
 
26
30
  There is also an `archive/` directory of dated past briefs. The dashboard maintains
27
31
  it; you never write to it. Read it if you want history — it is how the dashboard
@@ -107,6 +111,33 @@ a recent query alone make unfinished work disappear.
107
111
 
108
112
  ### Step 2 — Gather
109
113
 
114
+ #### Hand the reading to subagents
115
+
116
+ Read the sources in parallel rather than one after another: hand each source to a
117
+ subagent of its own, or a few small ones to one subagent, so the slowest source sets
118
+ the pace rather than the sum of them. Run up to three at a time, starting the next as
119
+ one finishes. The reading is all you hand out. Step 1, the judging in step 3, the
120
+ writing in step 4 and the checks in step 5 stay with you, because they need
121
+ everything in one place.
122
+
123
+ A subagent may not see this file, so give it what it needs in its task: its source's
124
+ section of this step in full, with the value of any setting from `agent-settings.json`
125
+ that the section names; the rules under "Across every source" below; the window from
126
+ step 1; and the ids from the previous brief that came from its source and are still
127
+ open, so it looks at each again. Name each after its source — `calendar`, `gmail`, `github` — since
128
+ the dashboard shows the user which is which while you work.
129
+
130
+ Ask for evidence, not decisions. For each thing that might be an item: its upstream id
131
+ or key, its link, who and what it is about, its dates, and what the source shows about
132
+ whether it is still open. Then what it could not read, why, and the link. Merging
133
+ duplicates, ranking and wording are yours. When an answer is missing something its
134
+ source should have had, ask again or read it yourself.
135
+
136
+ A subagent only reads, and tell it so: it writes no file, `items.json` least of all,
137
+ and changes nothing in any source.
138
+
139
+ If you cannot start subagents, read the sources yourself, one after another.
140
+
110
141
  #### Across every source
111
142
 
112
143
  **Use a connector, API or CLI as the evidence source.** A browser may only help you
@@ -167,6 +198,12 @@ the user's filters moved out of the inbox, included. Mail they filed is not mail
167
198
  finished with, and a label records how they sorted something, not whether they dealt
168
199
  with it.
169
200
 
201
+ Mail the user deleted is mail they finished with, so leave Trash out unless
202
+ `searchTrash` in `agent-settings.json` is `true` (default `false`). A search with no
203
+ `in:` operator already covers archived mail and skips Trash and Spam; when the
204
+ setting is off, don't widen it with `in:anywhere` or a trash option. When it is on,
205
+ search Trash as well, and still never Spam.
206
+
170
207
  Prioritise direct requests, deadlines, decisions, travel and logistics,
171
208
  finance/legal/security, and anyone plausibly waiting on a reply. **Do not limit
172
209
  continuity-sensitive searches to unread mail** — the things that rot are usually the
@@ -0,0 +1,41 @@
1
+ # Setting up Daily Focus
2
+
3
+ You are helping someone set up Daily Focus, a dashboard that has a coding-agent CLI
4
+ write them a short brief each morning: what needs to get done today, from their
5
+ mail, calendar, pull requests, tickets and documents.
6
+
7
+ They are on the setup screen now. It asks them one question at a time, and each
8
+ question comes with the answer they most likely want already ticked, so most of
9
+ the time all they do is confirm. Your job in this session is that one question,
10
+ named below: find out enough to propose the answer, and say why in a sentence.
11
+
12
+ ## How to work
13
+
14
+ - **Only read.** Never send, post, create, edit, move or delete anything,
15
+ anywhere: no mail, no drafts, no calendar changes, no comments, no files.
16
+ - **Be quick.** Someone is waiting on this. A few well-chosen lookups, then
17
+ answer. If something would take long to find out, make the likely guess and
18
+ say it is a guess.
19
+ - **Nobody can answer you mid-turn.** Never ask a question; the screen does the
20
+ asking. If a tool or account isn't reachable, work with what is and say what
21
+ you couldn't check.
22
+ - **Guess well.** A question for the *work* profile wants work accounts,
23
+ calendars and projects; for *personal*, everything else. Lean towards what the
24
+ morning brief needs and away from noise.
25
+ - **Say why in one or two short sentences**, under 40 words, in the first
26
+ person and plain text, no Markdown: "These are on your northwind.dev account,
27
+ where most of this week's meetings are." Cite what you saw, never invent it.
28
+ Say what you guessed, but not every lookup that failed. Never quote private
29
+ content such as mail subjects or meeting titles; counts and account names are
30
+ fine.
31
+ - **Answer with the JSON the schema asks for**, and nothing else. Use an empty
32
+ string, not null, for anything unknown.
33
+ - **Your why describes the answer you give, and nothing more.** The screen
34
+ shows the two side by side. Never say you included something the answer
35
+ doesn't hold; if the user asks for something it has no place for, say so.
36
+
37
+ ## When the user writes back
38
+
39
+ They may tell you what to change ("also the on-call rota", "that's my old
40
+ address"). Do what they ask, check what you need to, and answer with the whole
41
+ proposal again, in the same JSON.