daily-focus 1.1.1-dev.2 → 1.2.0-dev.10

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.
@@ -1,15 +1,19 @@
1
1
  import {
2
- QUICK_ACTIONS
3
- } from "./chunk-GFCWPYEI.js";
2
+ QUICK_ACTIONS,
3
+ actionOf,
4
+ autoKeys,
5
+ judge
6
+ } from "./chunk-ODJGQCM3.js";
4
7
  import {
5
8
  dateFromNow,
6
9
  sampleBrief,
7
10
  sampleGeneratedAt
8
- } from "./chunk-Q5OKXJXT.js";
11
+ } from "./chunk-64XB7UDN.js";
12
+ import "./chunk-RZNQJ6UG.js";
9
13
  import {
10
14
  PROFILES,
11
15
  localDateKey
12
- } from "./chunk-OPASVYLR.js";
16
+ } from "./chunk-J7ZYVUG6.js";
13
17
  import "./chunk-BC2W7NND.js";
14
18
 
15
19
  // src/demo.ts
@@ -77,7 +81,6 @@ function demoEnv(base, store, profile) {
77
81
  DAILY_FOCUS_WORK_START: "",
78
82
  DAILY_FOCUS_WORK_END: "",
79
83
  DAILY_FOCUS_MIN_FREE_WINDOW: "",
80
- DAILY_FOCUS_SESSION_MINUTES: "",
81
84
  DAILY_FOCUS_STALE_AFTER_HOURS: ""
82
85
  };
83
86
  }
@@ -119,6 +122,7 @@ function demoPulls(profile, now = /* @__PURE__ */ new Date()) {
119
122
  reviewDecision: "REVIEW_REQUIRED",
120
123
  checks: "failure",
121
124
  failingChecks: ["unit-tests (node-20)"],
125
+ headSha: "9c41e07d2b5f3a8e6d1c0b4a7f2e9d8c5b3a1f60",
122
126
  mergeStateStatus: "UNSTABLE",
123
127
  lastActivityByYou: hoursAgo(now, 3),
124
128
  requestedReviewers: ["eli"]
@@ -156,7 +160,7 @@ function demoPulls(profile, now = /* @__PURE__ */ new Date()) {
156
160
  lastActivityByYou: daysAgo(now, 1),
157
161
  lastActivityByOthers: { at: hoursAgo(now, 2), login: "chris", kind: "review" }
158
162
  }),
159
- // Waiting on reviewers: one long enough to ask, one fresh.
163
+ // Waiting on reviewers: one long enough to ask, one fresh, and one nudged this morning.
160
164
  pull({
161
165
  repo: "acme/webapp",
162
166
  number: 3395,
@@ -175,6 +179,15 @@ function demoPulls(profile, now = /* @__PURE__ */ new Date()) {
175
179
  requestedReviewers: ["dana", "eli"],
176
180
  mergeStateStatus: "BLOCKED"
177
181
  }),
182
+ pull({
183
+ repo: "acme/webapp",
184
+ number: 3405,
185
+ title: "Sample session replays by route",
186
+ createdAt: daysAgo(now, 2),
187
+ reviewDecision: "REVIEW_REQUIRED",
188
+ requestedReviewers: ["chris"],
189
+ mergeStateStatus: "BLOCKED"
190
+ }),
178
191
  // Waiting on the merge gate: approved, and the repository's own policy check still pending.
179
192
  pull({
180
193
  repo: "acme/webapp",
@@ -250,6 +263,7 @@ function personalPulls(now) {
250
263
  createdAt: daysAgo(now, 2),
251
264
  checks: "failure",
252
265
  failingChecks: ["build (macos)"],
266
+ headSha: "3e8a1c5f9b2d7e4a6c0f1b8d3e5a7c9f2b4d6e81",
253
267
  mergeStateStatus: "UNSTABLE",
254
268
  lastActivityByYou: hoursAgo(now, 15)
255
269
  }),
@@ -321,12 +335,26 @@ function ticket(key, summary, workflowStatus, issueType, prs) {
321
335
  allPrsClosed: prs === "closed"
322
336
  };
323
337
  }
324
- function demoTickets() {
338
+ function demoTickets(now = /* @__PURE__ */ new Date()) {
325
339
  return {
326
340
  tickets: [
327
341
  // Every pull request closed, and the ticket not Done.
328
342
  ticket("PROJ-8842", "Add trace context to outgoing fetches", "In Review", "Task", "closed"),
329
- ticket("PLAT-311", "Remove the legacy beacon endpoint", "In Progress", "Task", "closed"),
343
+ // The same, known only from GitHub: Jira still has the pull request open.
344
+ {
345
+ ...ticket("PLAT-311", "Remove the legacy beacon endpoint", "In Progress", "Task", "closed"),
346
+ pulls: [
347
+ {
348
+ repo: "acme/infra",
349
+ number: 514,
350
+ title: "PLAT-311: drop the /v1/beacon route",
351
+ url: "https://github.com/acme/infra/pull/514",
352
+ state: "merged",
353
+ closedAt: hoursAgo(now, 5)
354
+ }
355
+ ],
356
+ fromGitHub: true
357
+ },
330
358
  // A pull request open while the status says the work has not begun.
331
359
  ticket("PROJ-8871", "Instrument long tasks on the main thread", "To Do", "Story", "open"),
332
360
  ticket("PROJ-8877", "Document the sampling knobs", "To Do", "Task", "open"),
@@ -345,7 +373,7 @@ function demoTickets() {
345
373
  statuses: Object.fromEntries(Object.entries(TICKET_STATUSES).map(([project, names]) => [project, [...names]]))
346
374
  };
347
375
  }
348
- function demoIntegrations(profile) {
376
+ function demoIntegrations(profile, now = /* @__PURE__ */ new Date()) {
349
377
  const world = demoTickets();
350
378
  return {
351
379
  github: {
@@ -356,7 +384,7 @@ function demoIntegrations(profile) {
356
384
  return "demo";
357
385
  },
358
386
  async fetch() {
359
- return { login: LOGIN, pulls: demoPulls(profile, /* @__PURE__ */ new Date()), warnings: [], orgs: {}, rateLimitRemaining: null };
387
+ return { login: LOGIN, pulls: demoPulls(profile, now), warnings: [], orgs: {}, rateLimitRemaining: null };
360
388
  }
361
389
  },
362
390
  jira: {
@@ -366,6 +394,10 @@ function demoIntegrations(profile) {
366
394
  async fetch() {
367
395
  return { tickets: world.tickets.map((entry) => ({ ...entry })), statuses: world.statuses, warnings: [] };
368
396
  },
397
+ // The sample tickets already carry what GitHub would have added.
398
+ async linked() {
399
+ return { byKey: /* @__PURE__ */ new Map(), complete: true, warnings: [] };
400
+ },
369
401
  async transition(_acli, key, status) {
370
402
  const found = world.tickets.find((entry) => entry.key === key);
371
403
  if (!found) throw new Error(`no work item ${key} in the sample data`);
@@ -551,6 +583,7 @@ function demoActions(profile, now) {
551
583
  { id: "github:pr:acme/webapp#3360", action: "note", text: "Revisit after the v6 cut", at: daysAgo(now, 1) },
552
584
  { id: "github:pr:acme/webapp#3360", action: "snooze", until: until(30), at: daysAgo(now, 1) },
553
585
  { id: "jira:PROJ-8865", action: "note", text: "Docs only \u2014 no pull request expected", at: daysAgo(now, 1) },
586
+ { id: "github:pr:acme/webapp#3405", action: "nudge", at: hoursAgo(now, 3) },
554
587
  { id: "github:pr:acme/webapp#3430", action: "done", at: minutesAgo(now, 140) },
555
588
  { id: "email:thread:18f31c0d9e", action: "note", text: "Registration runs to the 28th; no rush", at: minutesAgo(now, 131) },
556
589
  { id: "email:thread:18f31c0d9e", action: "snooze", until: until(7), at: minutesAgo(now, 130) },
@@ -578,23 +611,6 @@ function demoActions(profile, now) {
578
611
  ];
579
612
  return actions.sort((a, b) => a.at.localeCompare(b.at));
580
613
  }
581
- function demoSessions(profile, now) {
582
- const session = (id, title, startMinutesAgo, actualMinutes, advancesObjective, endedBy) => ({
583
- id,
584
- title,
585
- startedAt: minutesAgo(now, startMinutesAgo),
586
- endedAt: minutesAgo(now, startMinutesAgo - actualMinutes),
587
- plannedMinutes: 25,
588
- actualMinutes,
589
- reachedTarget: actualMinutes >= 25,
590
- advancesObjective,
591
- endedBy
592
- });
593
- return profile === "work" ? [
594
- session("github:pr:acme/webapp#3402", "CI failing on your PR: Add trace context to fetch instrumentation", 190, 22, false, "away"),
595
- session("gtasks:task:MTU3NDkyODkwMjE2NDcx", "Write up the staging repro steps for the checkout breakage", 150, 42, true, "user")
596
- ] : [session("email:thread:19a0c4e2f1", "Chase Nordvarme for the loft insulation quote", 80, 18, true, "user")];
597
- }
598
614
  function runLines(seed) {
599
615
  const endedAt = new Date(new Date(seed.startedAt).getTime() + seed.seconds * 1e3).toISOString();
600
616
  const lines2 = [{ event: "started", run: seed.id, cli: "codex", trigger: seed.trigger, at: seed.startedAt }];
@@ -727,6 +743,8 @@ function demoAgentLog(profile, now) {
727
743
  ];
728
744
  return runs.flatMap(runLines);
729
745
  }
746
+ var call = (text, detail, state = "done") => ({ kind: "tool", text, detail, state });
747
+ var said = (text) => ({ kind: "message", text, detail: null, state: "done" });
730
748
  function turnLines(seed) {
731
749
  const quick = seed.action ? QUICK_ACTIONS.find((candidate) => candidate.id === seed.action) : void 0;
732
750
  const request = quick ? seed.text ? `${quick.request}
@@ -734,10 +752,27 @@ function turnLines(seed) {
734
752
  ${seed.text}` : quick.request : seed.text ?? "";
735
753
  const endedAt = new Date(new Date(seed.at).getTime() + seed.seconds * 1e3).toISOString();
736
754
  return [
737
- { event: "started", turn: seed.id, item: seed.item, agent: "claude", request, action: quick?.id ?? null, at: seed.at },
738
- { event: "finished", turn: seed.id, sessionId: `sample-${seed.item}`, reply: seed.reply, at: endedAt }
755
+ {
756
+ event: "started",
757
+ turn: seed.id,
758
+ item: seed.item,
759
+ agent: "claude",
760
+ request,
761
+ action: quick?.id ?? null,
762
+ ...seed.auto ? { auto: seed.auto } : {},
763
+ at: seed.at
764
+ },
765
+ { event: "finished", turn: seed.id, sessionId: `sample-${seed.item}`, reply: seed.reply, steps: seed.steps, at: endedAt }
739
766
  ];
740
767
  }
768
+ function aheadKey(profile, now, id, action) {
769
+ const pr = demoPulls(profile, now).find((candidate) => candidate.id === id);
770
+ if (!pr) throw new Error(`the demo has no pull request ${id}`);
771
+ const row = { ...pr, ...judge(pr, now, null), status: "open", notes: [] };
772
+ const key = autoKeys(row).find((candidate) => actionOf(candidate) === action);
773
+ if (!key) throw new Error(`the demo's ${id} calls for no ${action} ahead`);
774
+ return key;
775
+ }
741
776
  function demoAssistantLog(profile, now) {
742
777
  const fence = "```";
743
778
  const turns = profile === "work" ? [
@@ -747,6 +782,12 @@ function demoAssistantLog(profile, now) {
747
782
  action: "summarise-pr",
748
783
  at: minutesAgo(now, 46),
749
784
  seconds: 52,
785
+ steps: [
786
+ call("View the pull request", "gh pr view 3421 --repo acme/webapp --json title,body,files,reviews"),
787
+ call("Read the diff", "gh pr diff 3421 --repo acme/webapp"),
788
+ said("Four files. The recorder change is the substance; the rest is its tests and a type."),
789
+ call("Read the issue it closes", "gh issue view 3388 --repo acme/webapp --comments")
790
+ ],
750
791
  reply: [
751
792
  "**What it changes.** Session replay keeps every recorded mutation batch in an array on the recorder for the life of the tab, and only ever appends; on a tab left open for a day that is hundreds of megabytes. The change caps the buffer per tab, drops batches once the ingest endpoint has acknowledged them, and holds DOM node references through a `WeakRef` so a detached subtree can be collected.",
752
793
  "",
@@ -768,6 +809,11 @@ function demoAssistantLog(profile, now) {
768
809
  text: "Is the Safari fallback actually reachable?",
769
810
  at: minutesAgo(now, 44),
770
811
  seconds: 31,
812
+ steps: [
813
+ call("Find where the fallback is chosen", 'gh search code "WeakRef" --repo acme/webapp'),
814
+ call("Read the SDK docs on browser support", "gh api repos/acme/sdk-docs/contents/support.md", "failed"),
815
+ call("Read the webapp's copy of the support matrix", "gh api repos/acme/webapp/contents/docs/browser-support.md")
816
+ ],
771
817
  reply: "Only on Safari 14.0 and below, which the SDK\u2019s support matrix dropped in v5. Under the current matrix the branch is dead code. I would ask Alice to remove it rather than test it."
772
818
  },
773
819
  {
@@ -776,19 +822,55 @@ function demoAssistantLog(profile, now) {
776
822
  action: "draft-reply",
777
823
  at: minutesAgo(now, 38),
778
824
  seconds: 64,
825
+ steps: [
826
+ call("Gmail: get thread", '{"threadId":"18f2a9c4b7"}'),
827
+ call("Gmail: search threads", '{"query":"Q4 planning doc headcount"}'),
828
+ said("Bob wants numbers per team with a reason each. The planning doc has both."),
829
+ call("Gmail: create draft", '{"threadId":"18f2a9c4b7"}')
830
+ ],
779
831
  reply: [
780
832
  "I read the thread \u2014 four messages, Bob twice. He wants the Q4 team split: how many of the six open roles go to Platform and how many to Webapp, with a line of justification each, by the end of the week so it lands in the planning deck.",
781
833
  "",
782
- "I have created a Gmail draft on the thread, from you, proposing four Platform and two Webapp with the reasons from the planning doc, and asking whether the deck can carry a footnote that the SDK hire depends on the Q3 numbers. It is **not sent**; it is waiting on the thread when you open it."
834
+ "I have created a Gmail draft on the thread, from you, proposing four Platform and two Webapp with the reasons from the planning doc, and asking whether the deck can carry a footnote that the SDK hire depends on the Q3 numbers. It is **not sent**; it is waiting on the thread when you open it.",
835
+ "",
836
+ "Created: [Gmail draft](https://mail.google.com/mail/u/0/#drafts?compose=18f2a9c4b7)"
837
+ ].join("\n")
838
+ },
839
+ {
840
+ id: "turn-d1",
841
+ item: "github:pr:acme/webapp#3398",
842
+ action: "assess-review",
843
+ auto: aheadKey(profile, now, "github:pr:acme/webapp#3398", "assess-review"),
844
+ at: minutesAgo(now, 172),
845
+ seconds: 47,
846
+ steps: [
847
+ call("Read the review comments", "gh pr view 3398 --repo acme/webapp --comments"),
848
+ call("Read the diff", "gh pr diff 3398 --repo acme/webapp")
849
+ ],
850
+ reply: [
851
+ "Dana is right: the backoff never resets after a send succeeds.",
852
+ "",
853
+ "She commented on `beacon.ts:41` that `attempt` is only zeroed on page load. The diff bears her out: after one failed send, every later failure waits longer, for the life of the tab. Reset `attempt` in the success branch of `sendBeacon` and add a test where a success between two failures starts the delay over.",
854
+ "",
855
+ "Her second point, capping the delay at 30 seconds rather than 60, is a preference. Sixty is defensible for a beacon nobody waits on; say so and leave it."
783
856
  ].join("\n")
784
857
  },
785
858
  {
786
859
  id: "turn-c1",
787
860
  item: "github:pr:acme/webapp#3402",
788
861
  action: "explain-ci",
862
+ auto: aheadKey(profile, now, "github:pr:acme/webapp#3402", "explain-ci"),
789
863
  at: minutesAgo(now, 20),
790
864
  seconds: 58,
865
+ steps: [
866
+ call("List the checks", "gh pr checks 3402 --repo acme/webapp"),
867
+ call("Read the failing job\u2019s log", "gh run view 9182734 --repo acme/webapp --log-failed"),
868
+ said("One failure, in tracing/fetch.spec.ts. Reading the retry path it exercises."),
869
+ call("Read the retry code", "gh api repos/acme/webapp/contents/src/tracing/fetch.ts")
870
+ ],
791
871
  reply: [
872
+ "Yours, not flaky: the retry path drops the trace headers.",
873
+ "",
792
874
  "The failing check is `unit-tests (node-20)`, in `tracing/fetch.spec.ts`:",
793
875
  "",
794
876
  fence,
@@ -807,6 +889,10 @@ function demoAssistantLog(profile, now) {
807
889
  action: "summarise-pr",
808
890
  at: minutesAgo(now, 52),
809
891
  seconds: 47,
892
+ steps: [
893
+ call("View the pull request", "gh pr view 47 --repo mara-l/pedalboard --json title,body,files,commits"),
894
+ call("Read the diff", "gh pr diff 47 --repo mara-l/pedalboard")
895
+ ],
810
896
  reply: [
811
897
  "Tomas adds MIDI clock sync to the looper: the transport listens for MIDI clock at 24 pulses per quarter note and for start and stop, derives the tempo, and quantises the loop start to the next beat. +212/\u221218 across three files, with a test for the tempo derivation.",
812
898
  "",
@@ -819,13 +905,31 @@ function demoAssistantLog(profile, now) {
819
905
  "A kind review that asks for the first two and lets the third go is probably right for a first contribution."
820
906
  ].join("\n")
821
907
  },
908
+ {
909
+ id: "turn-p3",
910
+ item: "github:pr:mara-l/pedalboard#51",
911
+ action: "explain-ci",
912
+ auto: aheadKey(profile, now, "github:pr:mara-l/pedalboard#51", "explain-ci"),
913
+ at: minutesAgo(now, 64),
914
+ seconds: 39,
915
+ steps: [
916
+ call("List the checks", "gh pr checks 51 --repo mara-l/pedalboard"),
917
+ call("Read the failing job\u2019s log", "gh run view 4471920 --repo mara-l/pedalboard --log-failed")
918
+ ],
919
+ reply: [
920
+ "Not your change: the macOS runner could not download the JUCE cache.",
921
+ "",
922
+ "The `build (macos)` job stops in its setup step with a 503 from the cache server, before any of your code is compiled. The Linux and Windows builds of the same commit pass. Rerun the job; if it fails the same way, the cache key in `.github/workflows/build.yml` can fall back to a fresh download."
923
+ ].join("\n")
924
+ },
822
925
  {
823
926
  id: "turn-p2",
824
927
  item: "email:thread:19a0c4e2f1",
825
928
  action: "draft-reply",
826
929
  at: minutesAgo(now, 30),
827
930
  seconds: 41,
828
- reply: "The thread is three messages: your request on the 28th, their \u201Cwithin the week\u201D on the 29th, and nothing since. I have created a Gmail draft on it that asks, briefly and politely, whether the quote is still coming this week, and says the other quotes are in and you would like to decide by Friday. It is **not sent**; open the thread to read it."
931
+ steps: [call("Gmail: get thread", '{"threadId":"19a0c4e2f1"}'), call("Gmail: create draft", '{"threadId":"19a0c4e2f1"}')],
932
+ reply: "The thread is three messages: your request on the 28th, their \u201Cwithin the week\u201D on the 29th, and nothing since. I have created a Gmail draft on it that asks, briefly and politely, whether the quote is still coming this week, and says the other quotes are in and you would like to decide by Friday. It is **not sent**; open the thread to read it.\n\nCreated: [Gmail draft](https://mail.google.com/mail/u/0/#drafts?compose=19a0c4e2f1)"
829
933
  }
830
934
  ];
831
935
  return turns.flatMap(turnLines);
@@ -844,7 +948,6 @@ async function writeDemoStore(store, profile, now = /* @__PURE__ */ new Date())
844
948
  await writeFile(join(store, "focus.md"), FOCUS[profile], "utf8");
845
949
  await writeFile(join(store, "sources.md"), SOURCES[profile], "utf8");
846
950
  await writeFile(join(store, "actions.jsonl"), lines(demoActions(profile, now)), "utf8");
847
- await writeFile(join(store, "sessions.jsonl"), lines(demoSessions(profile, now)), "utf8");
848
951
  await writeFile(join(store, "agent.jsonl"), lines(demoAgentLog(profile, now)), "utf8");
849
952
  await writeFile(join(store, "assistant.jsonl"), lines(demoAssistantLog(profile, now)), "utf8");
850
953
  }
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-QKT2FAB5.js";
9
9
  import {
10
10
  loadConfig
11
- } from "./chunk-OPASVYLR.js";
11
+ } from "./chunk-J7ZYVUG6.js";
12
12
  import {
13
13
  PACKAGED,
14
14
  command
@@ -78,15 +78,7 @@ for (const outcome of await linkStore(config)) {
78
78
  section("Files you do not own");
79
79
  kept("items.json", "the briefing agent writes it; absent reads as no brief yet");
80
80
  kept("actions.jsonl", "the dashboard appends to it as you action things");
81
- kept("sessions.jsonl", "the dashboard appends to it as you run focus sessions");
82
81
  kept("assistant.jsonl", "the dashboard appends to it as you ask the assistant for help");
83
- if (platform() !== "darwin") {
84
- section("Note");
85
- kept(
86
- "idle detection is macOS-only",
87
- "focus sessions still work; they just fall back to the two-hour backstop instead of closing when you walk away"
88
- );
89
- }
90
82
  var next = [];
91
83
  if (wroteFocus) next.push(`Edit ${config.focusFile} \u2014 say what you are trying to achieve.`);
92
84
  if (wroteSources) next.push(`Edit ${config.sourcesFile} \u2014 say where to look.`);
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  sampleBrief
3
- } from "./chunk-Q5OKXJXT.js";
3
+ } from "./chunk-64XB7UDN.js";
4
4
  import {
5
5
  Store
6
- } from "./chunk-UM2EPNWR.js";
6
+ } from "./chunk-RZNQJ6UG.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-OPASVYLR.js";
9
+ } from "./chunk-J7ZYVUG6.js";
10
10
  import {
11
11
  command
12
12
  } from "./chunk-BC2W7NND.js";