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.
- package/README.md +18 -4
- package/SETUP.md +156 -105
- package/dist/{audit-DNTFZOHH.js → audit-AQUBVWPA.js} +4 -3
- package/dist/{chunk-KZNY45XW.js → chunk-72NUDSOV.js} +126 -119
- package/dist/{chunk-GQ3NCWRT.js → chunk-ITUK7XKS.js} +6 -19
- package/dist/{chunk-KL6RU4XT.js → chunk-JTMBBUMD.js} +316 -10
- package/dist/chunk-QG4XXKBP.js +18 -0
- package/dist/chunk-U6EPOXEW.js +570 -0
- package/dist/{chunk-P3E2B2SD.js → chunk-WPXIQPYX.js} +1 -1
- package/dist/{chunk-6SMUSPZG.js → chunk-YPGKXTBX.js} +2 -2
- package/dist/cli.js +19 -12
- package/dist/{demo-TIIXODJG.js → demo-KE6WDWMA.js} +159 -37
- package/dist/{init-XDMAXU2S.js → init-5KJVHWJU.js} +41 -6
- package/dist/{seed-TWT7EDXJ.js → seed-T4VEY6DT.js} +4 -3
- package/dist/{server-WT4CQ3VX.js → server-FFRNYEAO.js} +2000 -743
- package/dist/{service-ZUHI3VKH.js → service-LQ46YRCZ.js} +7 -6
- package/package.json +6 -2
- package/prompts/README.md +20 -4
- package/prompts/assistant.md +7 -1
- package/prompts/morning-brief-personal.md +37 -0
- package/prompts/morning-brief-work.md +37 -0
- package/prompts/onboarding.md +41 -0
- package/public/app.js +806 -287
- package/public/fonts/IBMPlexSans-Variable.woff2 +0 -0
- package/public/fonts/IBMPlexSerif-Italic.woff2 +0 -0
- package/public/fonts/IBMPlexSerif-Medium.woff2 +0 -0
- package/public/fonts/IBMPlexSerif-Regular.woff2 +0 -0
- package/public/fonts/IBMPlexSerif-SemiBold.woff2 +0 -0
- package/public/fonts/OFL.txt +93 -0
- package/public/style.css +1686 -481
- package/dist/chunk-V2UN3JYL.js +0 -140
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
LAUNCH_SETTINGS,
|
|
2
3
|
loadConfig
|
|
3
|
-
} from "./chunk-
|
|
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
|
|
34
|
-
const value = env[key];
|
|
35
|
-
if (
|
|
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
|
|
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}`, "
|
|
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": "
|
|
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": "
|
|
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
|
|
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
|
|
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,
|
package/prompts/assistant.md
CHANGED
|
@@ -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.
|
|
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.
|