claude-alfred 0.5.3 → 0.5.4

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 (52) hide show
  1. package/dist/cli.mjs +3 -3
  2. package/dist/{directives-BM9nkHZV.mjs → directives-DLIMozEm.mjs} +1 -1
  3. package/dist/{dispatcher-us-cOlZZ.mjs → dispatcher-DdpodHtR.mjs} +4 -4
  4. package/dist/{post-tool-DK48fw3G.mjs → post-tool-0hPkxEeL.mjs} +3 -3
  5. package/dist/{post-tool-CPUtuUxb.mjs → post-tool-CX9gx971.mjs} +2 -12
  6. package/dist/{pre-compact-DBnEMJwf.mjs → pre-compact-DtSNYDqr.mjs} +1 -1
  7. package/dist/{server-BVV-C9mF.mjs → server-CDS36bqe.mjs} +81 -0
  8. package/dist/{server-Ciof8e8X.mjs → server-DH1JBP9G.mjs} +3 -3
  9. package/dist/{session-start-vtNhjJdP.mjs → session-start-H2v1gmUg.mjs} +2 -2
  10. package/dist/{user-prompt-n5VcQmRT.mjs → user-prompt-pZkrTHTQ.mjs} +2 -2
  11. package/package.json +1 -1
  12. package/web/dist/assets/activity-DkLCJ-SB.js +1 -0
  13. package/web/dist/assets/{utils-CXfoJANe.js → api-SvfW-eaA.js} +1936 -1934
  14. package/web/dist/assets/badge-DQiF8V-T.js +1 -0
  15. package/web/dist/assets/butler-empty-DJDx_tIO.js +1 -0
  16. package/web/dist/assets/detail-drawer-Do5HDzQb.js +1 -0
  17. package/web/dist/assets/dist-CioCuCJo.js +1 -0
  18. package/web/dist/assets/es2015-Ba4HP1JV.js +41 -0
  19. package/web/dist/assets/index-BBJYZWxd.css +1 -0
  20. package/web/dist/assets/index-COtBBKDa.js +14 -0
  21. package/web/dist/assets/knowledge-DsfI7R0j.js +14 -0
  22. package/web/dist/assets/{lib-BDTjEd1Q.js → lib-CAPAdKcl.js} +3 -3
  23. package/web/dist/assets/link-BUI8NSjI.js +1 -0
  24. package/web/dist/assets/preload-helper-DGQaynfd.js +1 -0
  25. package/web/dist/assets/projects-CnKo47ec.js +1 -0
  26. package/web/dist/assets/routes-BvudKljh.js +1 -0
  27. package/web/dist/assets/skeleton-DaiiWyRB.js +9 -0
  28. package/web/dist/assets/status-badge-lw-4vLCz.js +6 -0
  29. package/web/dist/assets/tasks-Dsm1XJYf.js +1 -0
  30. package/web/dist/assets/tasks._slug-CYp5o6TD.js +51 -0
  31. package/web/dist/assets/tooltip-x6PhARM5.js +1 -0
  32. package/web/dist/assets/use-view-mode-dARkzdlU.js +1 -0
  33. package/web/dist/assets/wave-timeline-DhKSaNPe.js +1 -0
  34. package/web/dist/index.html +8 -8
  35. package/web/dist/assets/activity-DS8gsAtD.js +0 -1
  36. package/web/dist/assets/api-CVUS-Ce3.js +0 -3
  37. package/web/dist/assets/badge-D8mApPpI.js +0 -1
  38. package/web/dist/assets/butler-empty-C3mWnDYa.js +0 -1
  39. package/web/dist/assets/dist-lzHifHMP.js +0 -1
  40. package/web/dist/assets/index-DgRGKS9D.js +0 -14
  41. package/web/dist/assets/index-DvBh5daN.css +0 -1
  42. package/web/dist/assets/knowledge-Cu6MXPyf.js +0 -14
  43. package/web/dist/assets/link-ahHmGL6O.js +0 -1
  44. package/web/dist/assets/preload-helper-BIScuso2.js +0 -1
  45. package/web/dist/assets/projects-9xEJb6MC.js +0 -1
  46. package/web/dist/assets/routes-C8fI2lxb.js +0 -1
  47. package/web/dist/assets/skeleton-CEUF44ae.js +0 -9
  48. package/web/dist/assets/status-badge-BcYaeEpe.js +0 -6
  49. package/web/dist/assets/tasks-auOZy7oP.js +0 -1
  50. package/web/dist/assets/tasks._slug-B48aNnrZ.js +0 -51
  51. package/web/dist/assets/tooltip-B_wZunY1.js +0 -41
  52. /package/web/dist/assets/{format-CY2ohS0a.js → format-yfPPmP4I.js} +0 -0
package/dist/cli.mjs CHANGED
@@ -371,7 +371,7 @@ const main = defineCommand({
371
371
  async run() {
372
372
  const { Store } = await import("./store-BhCFm1Tb.mjs").then((n) => (n.t(), n.r));
373
373
  const { Embedder } = await import("./embedder-9lsjLVC6.mjs");
374
- const { serveMCP } = await import("./server-Ciof8e8X.mjs");
374
+ const { serveMCP } = await import("./server-DH1JBP9G.mjs");
375
375
  const store = Store.openDefault();
376
376
  let emb = null;
377
377
  try {
@@ -401,7 +401,7 @@ const main = defineCommand({
401
401
  const { join } = await import("node:path");
402
402
  const { Store } = await import("./store-BhCFm1Tb.mjs").then((n) => (n.t(), n.r));
403
403
  const { Embedder } = await import("./embedder-9lsjLVC6.mjs");
404
- const { startDashboard } = await import("./server-BVV-C9mF.mjs");
404
+ const { startDashboard } = await import("./server-CDS36bqe.mjs");
405
405
  const { resolveOrRegisterProject } = await import("./project-DKLV_Zw3.mjs").then((n) => (n.n(), n.a));
406
406
  const { syncAllProjectSpecs } = await import("./spec-sync-BYLLyRG3.mjs");
407
407
  const cwd = process.cwd();
@@ -431,7 +431,7 @@ const main = defineCommand({
431
431
  description: "Event name"
432
432
  } },
433
433
  async run({ args }) {
434
- const { runHook } = await import("./dispatcher-us-cOlZZ.mjs").then((n) => (n.i(), n.t));
434
+ const { runHook } = await import("./dispatcher-DdpodHtR.mjs").then((n) => (n.i(), n.t));
435
435
  await runHook(args.event);
436
436
  }
437
437
  }),
@@ -3,7 +3,7 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import { a as getKnowledgeByIDs, l as incrementHitCount, p as searchKnowledgeKeyword, u as init_knowledge } from "./knowledge-7gqtk8yz.mjs";
4
4
  import { r as vectorSearchKnowledge, t as init_vectors } from "./vectors-BVQ0dz9J.mjs";
5
5
  import { a as subTypeBoost, o as subTypeHalfLife, r as searchKnowledgeFTS, t as init_fts } from "./fts-CG3NjtDr.mjs";
6
- import { i as init_dispatcher, n as emitAdditionalContext } from "./dispatcher-us-cOlZZ.mjs";
6
+ import { i as init_dispatcher, n as emitAdditionalContext } from "./dispatcher-DdpodHtR.mjs";
7
7
  //#region src/mcp/helpers.ts
8
8
  function truncate(s, maxLen) {
9
9
  const runes = [...s];
@@ -89,19 +89,19 @@ async function runHook(event) {
89
89
  }
90
90
  }
91
91
  async function handleSessionStart(ev, signal) {
92
- const { sessionStart } = await import("./session-start-vtNhjJdP.mjs");
92
+ const { sessionStart } = await import("./session-start-H2v1gmUg.mjs");
93
93
  await sessionStart(ev, signal);
94
94
  }
95
95
  async function handlePreCompact(ev, signal) {
96
- const { preCompact } = await import("./pre-compact-DBnEMJwf.mjs");
96
+ const { preCompact } = await import("./pre-compact-DtSNYDqr.mjs");
97
97
  await preCompact(ev, signal);
98
98
  }
99
99
  async function handleUserPromptSubmit(ev, signal) {
100
- const { userPromptSubmit } = await import("./user-prompt-n5VcQmRT.mjs");
100
+ const { userPromptSubmit } = await import("./user-prompt-pZkrTHTQ.mjs");
101
101
  await userPromptSubmit(ev, signal);
102
102
  }
103
103
  async function handlePostToolUse(ev, signal) {
104
- const { postToolUse } = await import("./post-tool-DK48fw3G.mjs");
104
+ const { postToolUse } = await import("./post-tool-0hPkxEeL.mjs");
105
105
  await postToolUse(ev, signal);
106
106
  }
107
107
  async function handlePreToolUse(ev, _signal) {
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import "./types-BucChDqv.mjs";
3
3
  import "./audit-tp3tpgzR.mjs";
4
- import "./dispatcher-us-cOlZZ.mjs";
5
- import "./directives-BM9nkHZV.mjs";
6
- import { a as postToolUse, n as init_post_tool } from "./post-tool-CPUtuUxb.mjs";
4
+ import "./dispatcher-DdpodHtR.mjs";
5
+ import "./directives-DLIMozEm.mjs";
6
+ import { a as postToolUse, n as init_post_tool } from "./post-tool-CX9gx971.mjs";
7
7
  import "./store-BhCFm1Tb.mjs";
8
8
  import "./review-gate-PHUE_mEA.mjs";
9
9
  import "./state-7-p9AqA6.mjs";
@@ -6,8 +6,8 @@ import { f as promoteSubType, h as upsertKnowledge, i as getKnowledgeByID, o as
6
6
  import { o as subTypeHalfLife, r as searchKnowledgeFTS, t as init_fts } from "./fts-CG3NjtDr.mjs";
7
7
  import { n as init_project, s as resolveOrRegisterProject } from "./project-DKLV_Zw3.mjs";
8
8
  import { n as init_user, t as getGitUserName } from "./user-BRphWhLv.mjs";
9
- import { a as notifyUser, i as init_dispatcher } from "./dispatcher-us-cOlZZ.mjs";
10
- import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-BM9nkHZV.mjs";
9
+ import { a as notifyUser, i as init_dispatcher } from "./dispatcher-DdpodHtR.mjs";
10
+ import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-DLIMozEm.mjs";
11
11
  import { n as openDefaultCached, t as init_store } from "./store-BhCFm1Tb.mjs";
12
12
  import { a as writeReviewGate, d as init_spec_guard, n as init_review_gate, p as isSpecFilePath } from "./review-gate-PHUE_mEA.mjs";
13
13
  import { a as readStateJSON, d as writeStateJSON, f as writeStateText, i as parseWaveProgress, o as readStateText, p as writeWaveProgress, r as init_state, s as readWaveProgress, t as addWorkedSlug } from "./state-7-p9AqA6.mjs";
@@ -708,16 +708,6 @@ async function postToolUse(ev, signal) {
708
708
  updateTaskStatus(ev.cwd, slug, "in-progress", "auto:first-edit");
709
709
  } catch {}
710
710
  }
711
- if (filePath && !isSpecFilePath(ev.cwd, filePath)) {
712
- const sd = new SpecDir(ev.cwd, slug);
713
- try {
714
- const unchecked = (sd.readFile("tasks.md").match(/^- \[ \] /gm) ?? []).length;
715
- if (unchecked > 0) items.push({
716
- level: "CONTEXT",
717
- message: `${unchecked} unchecked task(s) in tasks.md. Mark completed tasks via \`dossier action=check task_id="T-X.Y"\`.`
718
- });
719
- } catch {}
720
- }
721
711
  } catch {}
722
712
  }
723
713
  if ([
@@ -4,7 +4,7 @@ import { c as readActive, d as reviewStatusFor, h as verifyReviewFile, l as read
4
4
  import { n as init_audit, t as appendAudit } from "./audit-tp3tpgzR.mjs";
5
5
  import { h as upsertKnowledge, u as init_knowledge } from "./knowledge-7gqtk8yz.mjs";
6
6
  import { n as init_project, s as resolveOrRegisterProject } from "./project-DKLV_Zw3.mjs";
7
- import { a as notifyUser, i as init_dispatcher } from "./dispatcher-us-cOlZZ.mjs";
7
+ import { a as notifyUser, i as init_dispatcher } from "./dispatcher-DdpodHtR.mjs";
8
8
  import { n as openDefaultCached, t as init_store } from "./store-BhCFm1Tb.mjs";
9
9
  import { readFileSync, writeFileSync } from "node:fs";
10
10
  import { join } from "node:path";
@@ -2631,6 +2631,72 @@ function createApp(projectPath, store, _emb, version) {
2631
2631
  project_name: proj.name
2632
2632
  });
2633
2633
  });
2634
+ app.get("/api/briefing", (c) => {
2635
+ const filterProjectId = getProjectFilter(c.req.query("project"));
2636
+ try {
2637
+ const activeProjects = filterProjectId ? [getProject(store, filterProjectId)].filter(Boolean) : listActiveProjects(store);
2638
+ const activeSpecs = [];
2639
+ const recentCompletions = [];
2640
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2641
+ for (const p of activeProjects) {
2642
+ if (!p || !existsSync(p.path)) continue;
2643
+ const result = collectProjectTasks(p.path, p.name, p.id);
2644
+ for (const t of result.tasks) {
2645
+ const status = t.status;
2646
+ const waves = t.waves;
2647
+ if (status === "completed" || status === "done") {
2648
+ const completedAt = t.completed_at;
2649
+ if (completedAt && completedAt.slice(0, 10) === today) recentCompletions.push({
2650
+ slug: t.slug,
2651
+ completedAt
2652
+ });
2653
+ continue;
2654
+ }
2655
+ if (status === "cancelled" || status === "deferred") continue;
2656
+ if (waves && waves.length > 0) {
2657
+ const nonClosing = waves.filter((w) => w.key !== "closing");
2658
+ const currentIdx = nonClosing.findIndex((w) => w.isCurrent);
2659
+ const currentWave = currentIdx >= 0 ? currentIdx + 1 : nonClosing.length;
2660
+ const totalWaves = nonClosing.length;
2661
+ const totalAll = waves.reduce((s, w) => s + w.total, 0);
2662
+ const totalChecked = waves.reduce((s, w) => s + w.checked, 0);
2663
+ activeSpecs.push({
2664
+ slug: t.slug,
2665
+ currentWave,
2666
+ totalWaves,
2667
+ remainingTasks: totalAll - totalChecked
2668
+ });
2669
+ } else activeSpecs.push({
2670
+ slug: t.slug,
2671
+ currentWave: 1,
2672
+ totalWaves: 1,
2673
+ remainingTasks: (t.total ?? 0) - (t.completed ?? 0)
2674
+ });
2675
+ }
2676
+ }
2677
+ const knowledgeTotal = getKnowledgeStats(store, filterProjectId).total;
2678
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2679
+ const projectFilter = filterProjectId ? "AND ki.project_id = ?" : "";
2680
+ const overdueParams = [now];
2681
+ if (filterProjectId) overdueParams.push(filterProjectId);
2682
+ const overdueVerifications = store.db.prepare(`SELECT COUNT(*) as cnt FROM knowledge_index ki WHERE ki.enabled = 1 AND ki.verification_due IS NOT NULL AND ki.verification_due < ? ${projectFilter}`).get(...overdueParams)?.cnt ?? 0;
2683
+ return c.json({
2684
+ activeSpecs,
2685
+ completedToday: recentCompletions.length,
2686
+ knowledgeTotal,
2687
+ overdueVerifications,
2688
+ recentCompletions
2689
+ });
2690
+ } catch {
2691
+ return c.json({
2692
+ activeSpecs: [],
2693
+ completedToday: 0,
2694
+ knowledgeTotal: 0,
2695
+ overdueVerifications: 0,
2696
+ recentCompletions: []
2697
+ });
2698
+ }
2699
+ });
2634
2700
  app.get("/api/tasks/:slug/specs/:file", (c) => {
2635
2701
  const slug = c.req.param("slug");
2636
2702
  const file = c.req.param("file");
@@ -2920,6 +2986,21 @@ function createApp(projectPath, store, _emb, version) {
2920
2986
  cycleTimeBreakdown
2921
2987
  });
2922
2988
  });
2989
+ app.get("/api/analytics/heatmap", (c) => {
2990
+ const filterProjectId = getProjectFilter(c.req.query("project")) || void 0;
2991
+ const weeks = Math.min(Math.max(Math.floor(Number(c.req.query("weeks"))) || 16, 1), 52);
2992
+ const since = /* @__PURE__ */ new Date();
2993
+ since.setDate(since.getDate() - weeks * 7);
2994
+ const sinceStr = since.toISOString();
2995
+ const projectFilter = filterProjectId ? "AND project_id = ?" : "";
2996
+ const params = [sinceStr];
2997
+ if (filterProjectId) params.push(filterProjectId);
2998
+ const rows = store.db.prepare(`SELECT date(timestamp) as date, COUNT(*) as count FROM audit_log WHERE timestamp >= ? ${projectFilter} GROUP BY date(timestamp) ORDER BY date ASC`).all(...params);
2999
+ return c.json({
3000
+ data: rows,
3001
+ weeks
3002
+ });
3003
+ });
2923
3004
  app.get("/api/specs/:slug/similar", async (c) => {
2924
3005
  const { findSimilarSpecs } = await import("./vectors-BVQ0dz9J.mjs").then((n) => (n.t(), n.i));
2925
3006
  const slug = c.req.param("slug");
@@ -6,10 +6,10 @@ import { a as getKnowledgeByIDs, u as init_knowledge } from "./knowledge-7gqtk8y
6
6
  import { r as vectorSearchKnowledge, t as init_vectors } from "./vectors-BVQ0dz9J.mjs";
7
7
  import { a as subTypeBoost, r as searchKnowledgeFTS, t as init_fts } from "./fts-CG3NjtDr.mjs";
8
8
  import { n as init_user, t as getGitUserName } from "./user-BRphWhLv.mjs";
9
- import "./dispatcher-us-cOlZZ.mjs";
9
+ import "./dispatcher-DdpodHtR.mjs";
10
10
  import { n as shouldAutoAppend, t as init_lang_filter } from "./lang-filter--xQlqF9A.mjs";
11
- import { o as truncate, r as init_helpers } from "./directives-BM9nkHZV.mjs";
12
- import { c as updateTaskStatus, l as handleLedger, n as init_post_tool, o as post_tool_exports, s as init_status, u as init_ledger } from "./post-tool-CPUtuUxb.mjs";
11
+ import { o as truncate, r as init_helpers } from "./directives-DLIMozEm.mjs";
12
+ import { c as updateTaskStatus, l as handleLedger, n as init_post_tool, o as post_tool_exports, s as init_status, u as init_ledger } from "./post-tool-CX9gx971.mjs";
13
13
  import "./store-BhCFm1Tb.mjs";
14
14
  import { a as writeReviewGate, i as readReviewGate, n as init_review_gate, t as clearReviewGate } from "./review-gate-PHUE_mEA.mjs";
15
15
  import { d as writeStateJSON, n as ensureStateDir, p as writeWaveProgress, r as init_state, s as readWaveProgress, u as stateDir } from "./state-7-p9AqA6.mjs";
@@ -3,8 +3,8 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import { c as readActive, l as readActiveState, s as init_types, t as SpecDir } from "./types-BucChDqv.mjs";
4
4
  import { c as getRecentDecisions, h as upsertKnowledge, n as countKnowledge, r as deleteOrphanKnowledge, u as init_knowledge } from "./knowledge-7gqtk8yz.mjs";
5
5
  import { n as init_project, s as resolveOrRegisterProject } from "./project-DKLV_Zw3.mjs";
6
- import { a as notifyUser, i as init_dispatcher, r as extractSection } from "./dispatcher-us-cOlZZ.mjs";
7
- import { n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-BM9nkHZV.mjs";
6
+ import { a as notifyUser, i as init_dispatcher, r as extractSection } from "./dispatcher-DdpodHtR.mjs";
7
+ import { n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-DLIMozEm.mjs";
8
8
  import { n as openDefaultCached, t as init_store } from "./store-BhCFm1Tb.mjs";
9
9
  import { d as writeStateJSON, l as resetWorkedSlugs, r as init_state } from "./state-7-p9AqA6.mjs";
10
10
  import { existsSync, readFileSync, readdirSync } from "node:fs";
@@ -3,8 +3,8 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import { l as readActiveState, s as init_types } from "./types-BucChDqv.mjs";
4
4
  import { a as subTypeBoost, t as init_fts } from "./fts-CG3NjtDr.mjs";
5
5
  import { Embedder, t as init_embedder } from "./embedder-9lsjLVC6.mjs";
6
- import "./dispatcher-us-cOlZZ.mjs";
7
- import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-BM9nkHZV.mjs";
6
+ import "./dispatcher-DdpodHtR.mjs";
7
+ import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-DLIMozEm.mjs";
8
8
  import { n as openDefaultCached, t as init_store } from "./store-BhCFm1Tb.mjs";
9
9
  import { a as readStateJSON, c as readWorkedSlugs, d as writeStateJSON, n as ensureStateDir, r as init_state } from "./state-7-p9AqA6.mjs";
10
10
  import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-alfred",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "alfred": "dist/cli.mjs"
@@ -0,0 +1 @@
1
+ import{Kt as e,at as t,i as n,n as r,st as i,t as a,vt as o,yt as s}from"./api-SvfW-eaA.js";import{t as c}from"./link-BUI8NSjI.js";import{i as l,n as u,t as d}from"./tooltip-x6PhARM5.js";import"./es2015-Ba4HP1JV.js";import{t as f}from"./detail-drawer-Do5HDzQb.js";var p=e(s()),m=o();function h({analytics:e}){let{t:n}=t(),r=e.reworkRates.filter(e=>!e.pending),i=r.length>0?r.reduce((e,t)=>e+t.reworkRate,0)/r.length:0,a=e.cycleTimeBreakdown.length>0?e.cycleTimeBreakdown.reduce((e,t)=>e+t.phases.total,0)/e.cycleTimeBreakdown.length:0,o=e.cycleTimeBreakdown.length;return(0,m.jsx)(`div`,{className:`grid gap-4 sm:grid-cols-3`,children:[{label:n(`activity.avgCycleTime`),value:`${a.toFixed(1)}`,unit:n(`activity.days`),color:`#628141`},{label:n(`activity.avgReworkRate`),value:`${(i*100).toFixed(0)}%`,unit:``,color:i>.15?`#c0392b`:`#2d8b7a`},{label:n(`activity.totalSpecs`),value:String(o),unit:``,color:`#40513b`}].map(e=>(0,m.jsxs)(`div`,{className:`rounded-organic border border-border/60 bg-card py-4 px-4`,children:[(0,m.jsx)(`p`,{className:`text-[11px] font-medium text-muted-foreground uppercase tracking-wider`,children:e.label}),(0,m.jsxs)(`p`,{className:`mt-1 text-2xl font-bold`,style:{fontFamily:`var(--font-display)`,color:e.color},children:[e.value,e.unit&&(0,m.jsx)(`span`,{className:`ml-1 text-sm font-normal text-muted-foreground`,children:e.unit})]})]},e.label))})}function g({analytics:e}){let{t:n}=t();if(e.reworkRates.length===0)return null;let r=Math.max(...e.reworkRates.map(e=>e.reworkRate),.01);return(0,m.jsxs)(`div`,{className:`rounded-organic border border-border/60 bg-card py-4 px-4`,children:[(0,m.jsx)(`h3`,{className:`text-sm font-semibold mb-3`,children:n(`activity.rework.title`)}),(0,m.jsx)(`div`,{className:`space-y-3`,children:e.reworkRates.map(e=>{let t=Math.round(e.reworkRate*100),n=Math.max(e.reworkRate/r*100,2);return(0,m.jsxs)(`div`,{children:[(0,m.jsxs)(`div`,{className:`flex items-baseline justify-between mb-1`,children:[(0,m.jsx)(`span`,{className:`text-[11px] font-mono text-foreground/80`,children:e.slug}),(0,m.jsxs)(`span`,{className:`text-[11px] font-mono text-muted-foreground`,children:[t,`%`]})]}),(0,m.jsx)(`div`,{className:`h-4 bg-muted/30 rounded overflow-hidden`,children:(0,m.jsx)(`div`,{className:`h-full rounded`,style:{width:`${n}%`,backgroundColor:e.pending?`#e67e22`:`#2d8b7a`,opacity:e.pending?.5:1}})})]},e.slug)})}),e.reworkRates.some(e=>e.pending)&&(0,m.jsx)(`p`,{className:`text-[10px] text-muted-foreground mt-2`,children:n(`activity.rework.pending`)})]})}var _={planning:`#628141`,approval:`#e67e22`,implementation:`#2d8b7a`};function v({analytics:e}){let{t:n}=t();if(e.cycleTimeBreakdown.length===0)return null;let r=Math.max(...e.cycleTimeBreakdown.map(e=>e.phases.total),.1);return(0,m.jsxs)(`div`,{className:`rounded-organic border border-border/60 bg-card py-4 px-4`,children:[(0,m.jsx)(`h3`,{className:`text-sm font-semibold mb-3`,children:n(`activity.cycleTime.title`)}),(0,m.jsx)(`div`,{className:`space-y-3`,children:e.cycleTimeBreakdown.map(e=>{let t=e.phases,i=(t.planning??0)/r*100,a=(t.approvalWait??0)/r*100,o=(t.implementation??0)/r*100;return(0,m.jsxs)(`div`,{children:[(0,m.jsxs)(`div`,{className:`flex items-baseline justify-between mb-1`,children:[(0,m.jsx)(`span`,{className:`text-[11px] font-mono text-foreground/80`,children:e.slug}),(0,m.jsxs)(`span`,{className:`text-[11px] font-mono text-muted-foreground`,children:[t.total.toFixed(1),`d`]})]}),(0,m.jsxs)(`div`,{className:`h-4 bg-muted/30 rounded overflow-hidden flex`,children:[i>0&&(0,m.jsx)(`div`,{className:`h-full`,style:{width:`${i}%`,backgroundColor:_.planning},title:`${n(`activity.cycleTime.planning`)}: ${t.planning?.toFixed(1)}d`}),a>0&&(0,m.jsx)(`div`,{className:`h-full`,style:{width:`${a}%`,backgroundColor:_.approval},title:`${n(`activity.cycleTime.approval`)}: ${t.approvalWait?.toFixed(1)}d`}),o>0&&(0,m.jsx)(`div`,{className:`h-full`,style:{width:`${o}%`,backgroundColor:_.implementation},title:`${n(`activity.cycleTime.implementation`)}: ${t.implementation?.toFixed(1)}d`})]})]},e.slug)})}),(0,m.jsx)(`div`,{className:`flex gap-4 mt-3`,children:[`planning`,`approval`,`implementation`].map(e=>(0,m.jsxs)(`span`,{className:`flex items-center gap-1 text-[10px] text-muted-foreground`,children:[(0,m.jsx)(`span`,{className:`size-2 rounded-sm`,style:{backgroundColor:_[e]}}),n(`activity.cycleTime.${e}`)]},e))})]})}var y=12,b=y+2,x=28,S=16,C=7,w=[`var(--color-card)`,`#c8c4b8`,`#a8c4a0`,`#628141`,`#40513b`];function T(e){return e===0?w[0]:e<=2?w[1]:e<=5?w[2]:e<=10?w[3]:w[4]}function E(e){let t=e.getDay(),n=e.getDate()-t+(t===0?-6:1);return new Date(e.getFullYear(),e.getMonth(),n)}function D({data:e,weeks:n=16}){let{t:r}=t(),i=new Map;for(let t of e)i.set(t.date,t.count);let a=new Date,o=E(new Date(a.getFullYear(),a.getMonth(),a.getDate()-(n-1)*7)),s=[],c=[],f=-1;for(let e=0;e<n;e++)for(let t=0;t<C;t++){let n=new Date(o);if(n.setDate(n.getDate()+e*7+t),n>a)continue;let r=n.toISOString().slice(0,10),l=i.get(r)??0;s.push({date:r,count:l,col:e,row:t}),t===0&&n.getMonth()!==f&&(f=n.getMonth(),c.push({label:n.toLocaleDateString(`en`,{month:`short`}),col:e}))}let p=x+n*b,h=S+C*b;return(0,m.jsxs)(`div`,{className:`rounded-organic border border-border/60 bg-card py-4 px-4`,children:[(0,m.jsx)(`h3`,{className:`text-sm font-semibold mb-3`,children:r(`heatmap.title`)}),(0,m.jsx)(`div`,{className:`overflow-x-auto`,children:(0,m.jsxs)(`svg`,{width:p,height:h,className:`block`,children:[c.map(e=>(0,m.jsx)(`text`,{x:x+e.col*b,y:S-4,className:`fill-muted-foreground`,fontSize:10,children:e.label},`month-${e.col}`)),[`Mon`,``,`Wed`,``,`Fri`,``,``].map((e,t)=>e?(0,m.jsx)(`text`,{x:0,y:S+t*b+y-2,className:`fill-muted-foreground`,fontSize:10,children:e},`day-${t}`):null),s.map(e=>(0,m.jsxs)(d,{children:[(0,m.jsx)(l,{asChild:!0,children:(0,m.jsx)(`rect`,{x:x+e.col*b,y:S+e.row*b,width:y,height:y,rx:2,fill:T(e.count),className:`outline-1 outline-border/20`,"aria-label":r(`heatmap.tooltip`,{date:e.date,count:e.count})})}),(0,m.jsx)(u,{children:r(`heatmap.tooltip`,{date:e.date,count:e.count})})]},e.date))]})}),(0,m.jsxs)(`div`,{className:`flex items-center gap-1.5 mt-2 justify-end`,children:[(0,m.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:r(`heatmap.less`)}),w.map((e,t)=>(0,m.jsx)(`span`,{className:`inline-block size-3 rounded-sm border border-border/20`,style:{backgroundColor:e}},t)),(0,m.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:r(`heatmap.more`)})]})]})}function O(){let{t:e}=t(),{data:o}=i(r()),{data:s}=i(n()),[l,u]=(0,p.useState)(0),{data:d}=i(a(l)),[_,y]=(0,p.useState)(null),b=o&&((o.reworkRates?.length??0)>0||(o.cycleTimeBreakdown?.length??0)>0);return(0,m.jsxs)(`div`,{className:`flex flex-col gap-6 h-[calc(100vh-8rem)]`,children:[(0,m.jsx)(`h1`,{className:`text-2xl font-bold tracking-tight shrink-0`,style:{fontFamily:`var(--font-display)`},children:e(`activity.title`)}),b?(0,m.jsxs)(`div`,{className:`shrink-0 space-y-6`,children:[(0,m.jsx)(h,{analytics:o}),(0,m.jsxs)(`div`,{className:`grid gap-6 lg:grid-cols-2`,children:[(0,m.jsx)(g,{analytics:o}),(0,m.jsx)(v,{analytics:o})]})]}):(0,m.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-12 text-center shrink-0`,children:[(0,m.jsx)(`p`,{className:`text-lg font-medium text-muted-foreground`,style:{fontFamily:`var(--font-display)`},children:e(`activity.empty.title`)}),(0,m.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground/70`,children:e(`activity.empty.description`)})]}),(0,m.jsx)(`div`,{className:`shrink-0`,children:(0,m.jsx)(D,{data:s?.data??[],weeks:s?.weeks??16})}),(0,m.jsx)(k,{entries:d?.entries??[],total:d?.total??0,page:l,onPageChange:u,onSelect:y}),(0,m.jsx)(f,{open:!!_,onClose:()=>y(null),title:_?_.target?`${_.action} — ${_.target}`:_.action:``,children:_&&(0,m.jsxs)(`div`,{className:`space-y-3 text-sm`,children:[(0,m.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,m.jsx)(j,{event:_.action})}),(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`p`,{className:`text-[11px] text-muted-foreground uppercase tracking-wide`,children:e(`activity.log.slug`)}),_.target?(0,m.jsx)(c,{to:`/tasks/$slug`,params:{slug:_.target},className:`font-mono text-sm hover:underline`,style:{color:`#40513b`},children:_.target}):(0,m.jsx)(`p`,{className:`text-muted-foreground`,children:`—`})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`p`,{className:`text-[11px] text-muted-foreground uppercase tracking-wide`,children:e(`activity.log.actor`)}),(0,m.jsx)(`p`,{children:_.actor||`—`})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`p`,{className:`text-[11px] text-muted-foreground uppercase tracking-wide`,children:e(`activity.log.time`)}),(0,m.jsx)(`p`,{className:`font-mono text-[11px]`,children:new Date(_.timestamp).toLocaleString()})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`p`,{className:`text-[11px] text-muted-foreground uppercase tracking-wide`,children:e(`activity.log.detail`)}),(0,m.jsx)(`p`,{className:`whitespace-pre-wrap break-all text-[12px] leading-relaxed`,children:_.detail||`—`})]})]})]})})]})}function k({entries:e,total:n,page:r,onPageChange:i,onSelect:a}){let{t:o}=t(),s=Math.ceil(n/50);return(0,m.jsxs)(`div`,{className:`rounded-organic border border-border/60 bg-card flex flex-col min-h-0 flex-1`,children:[(0,m.jsxs)(`div`,{className:`flex items-center justify-between py-3 px-4 border-b border-border/30 shrink-0`,children:[(0,m.jsx)(`h3`,{className:`text-sm font-semibold`,children:o(`activity.log.title`)}),s>1&&(0,m.jsxs)(`div`,{className:`flex items-center gap-2 text-[11px] text-muted-foreground`,children:[(0,m.jsxs)(`span`,{children:[n,` `,o(`activity.log.entries`)]}),(0,m.jsx)(`button`,{type:`button`,disabled:r===0,onClick:()=>i(r-1),className:`px-2 py-0.5 rounded border border-border/40 disabled:opacity-30`,children:o(`activity.log.prev`)}),(0,m.jsxs)(`span`,{children:[r+1,`/`,s]}),(0,m.jsx)(`button`,{type:`button`,disabled:r>=s-1,onClick:()=>i(r+1),className:`px-2 py-0.5 rounded border border-border/40 disabled:opacity-30`,children:o(`activity.log.next`)})]})]}),e.length===0?(0,m.jsx)(`p`,{className:`text-sm text-muted-foreground py-8 text-center`,children:o(`activity.noMetrics`)}):(0,m.jsx)(`div`,{className:`overflow-auto flex-1 min-h-0`,children:(0,m.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,m.jsx)(`thead`,{className:`sticky top-0 bg-card z-10`,children:(0,m.jsxs)(`tr`,{className:`border-b border-border/40 text-left text-[11px] text-muted-foreground uppercase tracking-wider`,children:[(0,m.jsx)(`th`,{className:`py-2 px-4 whitespace-nowrap`,children:o(`activity.log.time`)}),(0,m.jsx)(`th`,{className:`py-2 pr-3 whitespace-nowrap`,children:o(`activity.log.event`)}),(0,m.jsx)(`th`,{className:`py-2 pr-3 whitespace-nowrap`,children:o(`activity.log.slug`)}),(0,m.jsx)(`th`,{className:`py-2 pr-3 whitespace-nowrap`,children:o(`activity.log.actor`)}),(0,m.jsx)(`th`,{className:`py-2 pr-4`,children:o(`activity.log.detail`)})]})}),(0,m.jsx)(`tbody`,{children:e.map((e,t)=>(0,m.jsx)(M,{entry:e,onSelect:()=>a(e)},t))})]})})]})}var A={"spec.init":{bg:`#40513b20`,text:`#40513b`},"spec.complete":{bg:`#62814120`,text:`#628141`},"review.submit":{bg:`#2d8b7a20`,text:`#2d8b7a`},"gate.set":{bg:`#e67e2220`,text:`#e67e22`},"gate.clear":{bg:`#62814120`,text:`#628141`},"gate.fix":{bg:`#e67e2220`,text:`#e67e22`},first_commit:{bg:`#7b6b8d20`,text:`#7b6b8d`},"task.status_change":{bg:`#44403c15`,text:`#44403c`},"living-spec.update":{bg:`#2d8b7a15`,text:`#2d8b7a`},"rework.checked":{bg:`#c0392b20`,text:`#c0392b`}};function j({event:e}){let t=A[e]??{bg:`#44403c10`,text:`#44403c`};return(0,m.jsx)(`span`,{className:`inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium font-mono whitespace-nowrap`,style:{backgroundColor:t.bg,color:t.text},children:e})}function M({entry:e,onSelect:t}){return(0,m.jsx)(m.Fragment,{children:(0,m.jsxs)(`tr`,{className:`border-b border-border/10 last:border-0 hover:bg-muted/20 cursor-pointer`,onClick:t,children:[(0,m.jsx)(`td`,{className:`py-1.5 px-4 text-[11px] text-muted-foreground font-mono whitespace-nowrap`,children:N(e.timestamp)}),(0,m.jsx)(`td`,{className:`py-1.5 pr-3`,children:(0,m.jsx)(j,{event:e.action})}),(0,m.jsx)(`td`,{className:`py-1.5 pr-3 font-mono text-[11px]`,children:e.target}),(0,m.jsx)(`td`,{className:`py-1.5 pr-3 text-[11px] text-muted-foreground`,children:e.actor}),(0,m.jsx)(`td`,{className:`py-1.5 pr-4 text-[11px] text-muted-foreground`,children:(0,m.jsx)(`span`,{className:`truncate max-w-[300px] inline-block align-bottom`,children:e.detail})})]})})}function N(e){let t=new Date(e);return`${String(t.getMonth()+1).padStart(2,`0`)}/${String(t.getDate()).padStart(2,`0`)} ${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`}export{O as component};