claude-alfred 0.3.13 → 0.3.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 (46) hide show
  1. package/README.ja.md +1 -1
  2. package/README.md +1 -1
  3. package/content/hooks/hooks.json +5 -0
  4. package/dist/cli.mjs +2 -2
  5. package/dist/{directives-D38Gs3Ld.mjs → directives-D9HvkIv-.mjs} +1 -1
  6. package/dist/{dispatcher-wn96mbEP.mjs → dispatcher-D6DBNmqa.mjs} +6 -6
  7. package/dist/{post-tool-sGk0fIBJ.mjs → post-tool-TwDkrOWU.mjs} +4 -4
  8. package/dist/{post-tool-CeSVspjd.mjs → post-tool-lPXibAhr.mjs} +5 -5
  9. package/dist/{pre-compact-BlQEQbZP.mjs → pre-compact-DZX1NMDH.mjs} +1 -1
  10. package/dist/pre-tool-DWsZykxS.mjs +66 -0
  11. package/dist/{review-gate-D6pA7CNB.mjs → review-gate-0cGEW7jx.mjs} +17 -2
  12. package/dist/{server-CgPMMrTO.mjs → server-1oPfR8EI.mjs} +6 -6
  13. package/dist/{session-start-tE5mAVMG.mjs → session-start-kperyKXR.mjs} +3 -3
  14. package/dist/{state-Bw1XMJxp.mjs → state-XSGGyez_.mjs} +2 -25
  15. package/dist/{stop-DItumrnH.mjs → stop-gh3SchT6.mjs} +2 -2
  16. package/dist/{user-prompt-DG6scjP0.mjs → user-prompt-BdEWX31N.mjs} +3 -5
  17. package/package.json +1 -1
  18. package/web/dist/assets/{activity-C1FTqhFl.js → activity-Cmg-bFZr.js} +1 -1
  19. package/web/dist/assets/{api-DUW_x4Qc.js → api-D53jbtlM.js} +1 -1
  20. package/web/dist/assets/{badge-CasOf-Iy.js → badge-DQlFqYx7.js} +1 -1
  21. package/web/dist/assets/{card-CHfuGvSw.js → card-Cl-Rp8LP.js} +1 -1
  22. package/web/dist/assets/circle-check-DS_prTp1.js +1 -0
  23. package/web/dist/assets/circle-dot-C_0NZ2Gc.js +1 -0
  24. package/web/dist/assets/{circle-x-BVT5qi-w.js → circle-x-Dn4UdyQZ.js} +1 -1
  25. package/web/dist/assets/{createLucideIcon-5rRvYiBC.js → createLucideIcon-DsqsOvzh.js} +1 -1
  26. package/web/dist/assets/dist-C1-OPfHP.js +1 -0
  27. package/web/dist/assets/{dist-YKGTWb04.js → dist-Cb-zpBQd.js} +1 -1
  28. package/web/dist/assets/{index-DGyD_f9j.js → index-CGpsnIcD.js} +3 -3
  29. package/web/dist/assets/{index-DF1Om0oI.css → index-Ck9cx0pQ.css} +1 -1
  30. package/web/dist/assets/{knowledge-C0koz_R_.js → knowledge-B2ykvT15.js} +1 -1
  31. package/web/dist/assets/{link-BBv-Zwrr.js → link-CuFcO5g4.js} +1 -1
  32. package/web/dist/assets/{pagination-0vUA_BUN.js → pagination-D0x3RW7K.js} +1 -1
  33. package/web/dist/assets/{progress-Q8H-LYzC.js → progress-1DCq6uTs.js} +1 -1
  34. package/web/dist/assets/{routes-j_NFYRTo.js → routes-Bfp-wxhw.js} +1 -1
  35. package/web/dist/assets/{scroll-area-WifYJqwD.js → scroll-area-oD1yU6lK.js} +1 -1
  36. package/web/dist/assets/separator-RTxNVL-d.js +1 -0
  37. package/web/dist/assets/{skeleton-W0NNrTUC.js → skeleton-DCX-0FSu.js} +1 -1
  38. package/web/dist/assets/{tasks-DuhUxMDe.js → tasks-DB3RlHvp.js} +1 -1
  39. package/web/dist/assets/{tasks._slug-BhDNz4kh.js → tasks._slug-DgpKHU_v.js} +3 -3
  40. package/web/dist/assets/{useParams-pNbbxrTn.js → useParams-CFR5Lw8_.js} +1 -1
  41. package/web/dist/index.html +6 -6
  42. package/dist/pre-tool-9mxFQxKH.mjs +0 -72
  43. package/web/dist/assets/circle-check-Cz0Ne7EA.js +0 -1
  44. package/web/dist/assets/circle-dot-ClhowmeB.js +0 -1
  45. package/web/dist/assets/dist-DqB2i2il.js +0 -1
  46. package/web/dist/assets/separator-BI3E_x2g.js +0 -1
package/README.ja.md CHANGED
@@ -123,7 +123,7 @@ JSON ファイルとして Git にコミットし、PR でレビューし、チ
123
123
  | サイズ | ファイル数 | 用途 |
124
124
  |--------|-----------|------|
125
125
  | **S** | 2 | バグ修正、設定変更 |
126
- | **M** | 4 | 新エンドポイント、リファクタ |
126
+ | **M** | 3-4 | 新エンドポイント、リファクタ |
127
127
  | **L/XL** | 5 | アーキテクチャ変更、新サブシステム |
128
128
  | **D** | 1 | 既存コードへの差分変更 |
129
129
 
package/README.md CHANGED
@@ -123,7 +123,7 @@ Search pipeline: Voyage AI vectors with reranking > FTS5 with fuzzy matching > k
123
123
  | Size | Files | Good for |
124
124
  |------|-------|----------|
125
125
  | **S** | 2 | Bug fix, config tweak |
126
- | **M** | 4 | New endpoint, moderate refactor |
126
+ | **M** | 3-4 | New endpoint, moderate refactor |
127
127
  | **L/XL** | 5 | Architecture change, new subsystem |
128
128
  | **D** | 1 | Brownfield delta change |
129
129
 
@@ -58,6 +58,11 @@
58
58
  "statusMessage": "alfred: checking spec approval...",
59
59
  "timeout": 5,
60
60
  "type": "command"
61
+ },
62
+ {
63
+ "type": "prompt",
64
+ "prompt": "You are a spec-driven development gatekeeper. An Edit/Write tool is being used WITHOUT an active spec. The command handler (alfred hook PreToolUse) already passed — meaning there is no review-gate or approval-gate blocking this edit. The only question is: does this change need a spec?\n\nEvaluate the conversation context and the file being edited. Respond with {\"ok\": true} if this is a TRIVIAL change that does NOT need a spec (examples: typo fix, documentation update, config tweak, comment edit, style fix, renaming, updating a version number). Respond with {\"ok\": false, \"reason\": \"This change requires a spec. Create one with: dossier action=init (use size=S for small changes, size=D for delta changes)\"} if this is SUBSTANTIAL work (new feature, bug fix requiring investigation, refactoring, architecture change, adding new functionality).\n\nWhen in doubt, allow it — false blocks are worse than missing specs.",
65
+ "timeout": 10
61
66
  }
62
67
  ]
63
68
  }
package/dist/cli.mjs CHANGED
@@ -371,7 +371,7 @@ const main = defineCommand({
371
371
  async run() {
372
372
  const { Store } = await import("./store-BffM-bi-.mjs").then((n) => (n.t(), n.r));
373
373
  const { Embedder } = await import("./embedder-D3hJoryD.mjs");
374
- const { serveMCP } = await import("./server-CgPMMrTO.mjs");
374
+ const { serveMCP } = await import("./server-1oPfR8EI.mjs");
375
375
  const store = Store.openDefault();
376
376
  let emb = null;
377
377
  try {
@@ -422,7 +422,7 @@ const main = defineCommand({
422
422
  description: "Event name"
423
423
  } },
424
424
  async run({ args }) {
425
- const { runHook } = await import("./dispatcher-wn96mbEP.mjs").then((n) => (n.i(), n.t));
425
+ const { runHook } = await import("./dispatcher-D6DBNmqa.mjs").then((n) => (n.i(), n.t));
426
426
  await runHook(args.event);
427
427
  }
428
428
  }),
@@ -3,7 +3,7 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import { c as incrementHitCount, f as searchKnowledgeKeyword, i as getKnowledgeByIDs, l as init_knowledge } from "./knowledge-C7rEfFSX.mjs";
4
4
  import { r as vectorSearchKnowledge, t as init_vectors } from "./vectors-DHZGQ096.mjs";
5
5
  import { a as subTypeBoost, i as searchKnowledgeFTS, o as subTypeHalfLife, r as init_fts } from "./fts-DICqcpG_.mjs";
6
- import { i as init_dispatcher, n as emitAdditionalContext } from "./dispatcher-wn96mbEP.mjs";
6
+ import { i as init_dispatcher, n as emitAdditionalContext } from "./dispatcher-D6DBNmqa.mjs";
7
7
  //#region src/mcp/helpers.ts
8
8
  function truncate(s, maxLen) {
9
9
  const runes = [...s];
@@ -89,27 +89,27 @@ async function runHook(event) {
89
89
  }
90
90
  }
91
91
  async function handleSessionStart(ev, signal) {
92
- const { sessionStart } = await import("./session-start-tE5mAVMG.mjs");
92
+ const { sessionStart } = await import("./session-start-kperyKXR.mjs");
93
93
  await sessionStart(ev, signal);
94
94
  }
95
95
  async function handlePreCompact(ev, signal) {
96
- const { preCompact } = await import("./pre-compact-BlQEQbZP.mjs");
96
+ const { preCompact } = await import("./pre-compact-DZX1NMDH.mjs");
97
97
  await preCompact(ev, signal);
98
98
  }
99
99
  async function handleUserPromptSubmit(ev, signal) {
100
- const { userPromptSubmit } = await import("./user-prompt-DG6scjP0.mjs");
100
+ const { userPromptSubmit } = await import("./user-prompt-BdEWX31N.mjs");
101
101
  await userPromptSubmit(ev, signal);
102
102
  }
103
103
  async function handlePostToolUse(ev, signal) {
104
- const { postToolUse } = await import("./post-tool-CeSVspjd.mjs");
104
+ const { postToolUse } = await import("./post-tool-lPXibAhr.mjs");
105
105
  await postToolUse(ev, signal);
106
106
  }
107
107
  async function handlePreToolUse(ev, _signal) {
108
- const { preToolUse } = await import("./pre-tool-9mxFQxKH.mjs");
108
+ const { preToolUse } = await import("./pre-tool-DWsZykxS.mjs");
109
109
  await preToolUse(ev);
110
110
  }
111
111
  async function handleStop(ev, _signal) {
112
- const { stop } = await import("./stop-DItumrnH.mjs");
112
+ const { stop } = await import("./stop-gh3SchT6.mjs");
113
113
  await stop(ev);
114
114
  }
115
115
  var init_dispatcher = __esmMin((() => {}));
@@ -5,11 +5,11 @@ import { n as init_audit, t as appendAudit } from "./audit-e13xK9Fr.mjs";
5
5
  import { a as getKnowledgeStats, d as promoteSubType, l as init_knowledge, m as upsertKnowledge, o as getPromotionCandidates, r as getKnowledgeByID } from "./knowledge-C7rEfFSX.mjs";
6
6
  import { i as searchKnowledgeFTS, r as init_fts, t as detectKnowledgeConflicts } from "./fts-DICqcpG_.mjs";
7
7
  import { n as init_project, t as detectProject } from "./project-DCKke4_Q.mjs";
8
- import { a as notifyUser, i as init_dispatcher } from "./dispatcher-wn96mbEP.mjs";
9
- import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-D38Gs3Ld.mjs";
8
+ import { a as notifyUser, i as init_dispatcher } from "./dispatcher-D6DBNmqa.mjs";
9
+ import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-D9HvkIv-.mjs";
10
10
  import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
11
- import { a as writeReviewGate, f as isSpecFilePath, n as init_review_gate, u as init_spec_guard } from "./review-gate-D6pA7CNB.mjs";
12
- import { c as readWaveProgress, i as parseWaveProgress, m as writeWaveProgress, n as addWorkedSlug, p as writeStateText, r as init_state, s as readStateText } from "./state-Bw1XMJxp.mjs";
11
+ import { a as writeReviewGate, d as init_spec_guard, n as init_review_gate, p as isSpecFilePath } from "./review-gate-0cGEW7jx.mjs";
12
+ import { a as readStateText, d as writeWaveProgress, n as init_state, o as readWaveProgress, r as parseWaveProgress, t as addWorkedSlug, u as writeStateText } from "./state-XSGGyez_.mjs";
13
13
  import { mkdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
14
14
  import { join } from "node:path";
15
15
  import { createHash } from "node:crypto";
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import "./types-K2jxpWyU.mjs";
3
3
  import "./audit-e13xK9Fr.mjs";
4
- import "./dispatcher-wn96mbEP.mjs";
5
- import "./directives-D38Gs3Ld.mjs";
6
- import { a as postToolUse, n as init_post_tool } from "./post-tool-sGk0fIBJ.mjs";
4
+ import "./dispatcher-D6DBNmqa.mjs";
5
+ import "./directives-D9HvkIv-.mjs";
6
+ import { a as postToolUse, n as init_post_tool } from "./post-tool-TwDkrOWU.mjs";
7
7
  import "./store-BffM-bi-.mjs";
8
- import "./review-gate-D6pA7CNB.mjs";
9
- import "./state-Bw1XMJxp.mjs";
8
+ import "./review-gate-0cGEW7jx.mjs";
9
+ import "./state-XSGGyez_.mjs";
10
10
  init_post_tool();
11
11
  export { postToolUse };
@@ -5,7 +5,7 @@ import { r as init_epic, s as syncTaskStatus } from "./epic-CfxJ13zy.mjs";
5
5
  import { n as init_audit, t as appendAudit } from "./audit-e13xK9Fr.mjs";
6
6
  import { l as init_knowledge, m as upsertKnowledge } from "./knowledge-C7rEfFSX.mjs";
7
7
  import { n as init_project, t as detectProject } from "./project-DCKke4_Q.mjs";
8
- import { a as notifyUser, i as init_dispatcher } from "./dispatcher-wn96mbEP.mjs";
8
+ import { a as notifyUser, i as init_dispatcher } from "./dispatcher-D6DBNmqa.mjs";
9
9
  import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
10
10
  import { readFileSync, writeFileSync } from "node:fs";
11
11
  import { join } from "node:path";
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
+ import { a as effectiveStatus, s as init_types } from "./types-K2jxpWyU.mjs";
4
+ import { d as init_spec_guard, f as isActiveSpecMalformed, l as denyTool, m as tryReadActiveSpec, n as init_review_gate, o as allowTool, p as isSpecFilePath, r as isGateActive } from "./review-gate-0cGEW7jx.mjs";
5
+ import "./state-XSGGyez_.mjs";
6
+ //#region src/hooks/pre-tool.ts
7
+ /**
8
+ * PreToolUse handler: block Edit/Write on review-gate or unapproved spec.
9
+ * Enforcement order: .alfred/ exempt → malformed check → review-gate → approval gate.
10
+ * Outputs explicit "allow" when spec exists and gates pass, so the subsequent
11
+ * prompt hook (spec-first LLM judge) is only evaluated when no spec is active.
12
+ */
13
+ async function preToolUse(ev) {
14
+ const toolName = ev.tool_name ?? "";
15
+ if (!BLOCKABLE_TOOLS.has(toolName)) return;
16
+ const toolInput = ev.tool_input ?? {};
17
+ const filePath = typeof toolInput.file_path === "string" ? toolInput.file_path : "";
18
+ if (filePath && isSpecFilePath(ev.cwd, filePath)) {
19
+ allowTool("Spec file edit");
20
+ return;
21
+ }
22
+ if (isActiveSpecMalformed(ev.cwd)) {
23
+ denyTool("Failed to read spec state (_active.md exists but could not be parsed). Fix or delete .alfred/specs/_active.md before editing source files.");
24
+ return;
25
+ }
26
+ const spec = tryReadActiveSpec(ev.cwd);
27
+ if (spec) {
28
+ const status = effectiveStatus(spec.status);
29
+ if (status === "deferred" || status === "cancelled") {
30
+ allowTool("Deferred/cancelled spec");
31
+ return;
32
+ }
33
+ }
34
+ const gate = isGateActive(ev.cwd);
35
+ if (gate) {
36
+ denyTool([
37
+ `${gate.gate === "wave-review" ? `Wave ${gate.wave ?? "?"} review` : "Spec self-review"} required for spec '${gate.slug}'. Complete review, then run: dossier action=gate sub_action=clear reason="<review summary>"`,
38
+ `- Gate reason: ${gate.reason}`,
39
+ "- \"I already reviewed mentally\" → Run actual review (3-agent or /alfred:inspect), then clear the gate"
40
+ ].join("\n"));
41
+ return;
42
+ }
43
+ if (!spec) return;
44
+ if ([
45
+ "M",
46
+ "L",
47
+ "XL"
48
+ ].includes(spec.size) && spec.reviewStatus !== "approved") {
49
+ denyTool([
50
+ `Spec '${spec.slug}' (size ${spec.size}) is not approved. Submit review via \`alfred dashboard\` or run self-review before implementation.`,
51
+ "- \"I'll get the review after implementation\" → The Stop hook will block you from finishing anyway",
52
+ "- \"This edit is trivial\" → All M/L/XL edits are gated. Use dossier init size=S for trivial changes"
53
+ ].join("\n"));
54
+ return;
55
+ }
56
+ allowTool("Spec exists, all gates passed");
57
+ }
58
+ var BLOCKABLE_TOOLS;
59
+ //#endregion
60
+ __esmMin((() => {
61
+ init_types();
62
+ init_review_gate();
63
+ init_spec_guard();
64
+ BLOCKABLE_TOOLS = new Set(["Edit", "Write"]);
65
+ }))();
66
+ export { preToolUse };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import { l as readActiveState, s as init_types } from "./types-K2jxpWyU.mjs";
4
- import { f as writeStateJSON, o as readStateJSON, r as init_state } from "./state-Bw1XMJxp.mjs";
4
+ import { i as readStateJSON, l as writeStateJSON, n as init_state } from "./state-XSGGyez_.mjs";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  import { join, resolve } from "node:path";
7
7
  //#region src/hooks/spec-guard.ts
@@ -20,11 +20,13 @@ function tryReadActiveSpec(cwd) {
20
20
  /**
21
21
  * Check if _active.md exists but cannot be parsed or has invalid enum values.
22
22
  * Used by PreToolUse to deny edits instead of silently allowing.
23
+ * Returns false when primary is empty (no active spec = valid state).
23
24
  */
24
25
  function isActiveSpecMalformed(cwd) {
25
26
  if (!cwd) return false;
26
27
  if (!existsSync(join(cwd, ".alfred", "specs", "_active.md"))) return false;
27
28
  try {
29
+ if (!readActiveState(cwd).primary) return false;
28
30
  return parseSpecState(cwd) === null;
29
31
  } catch {
30
32
  return true;
@@ -80,6 +82,19 @@ function hasUncheckedSelfReview(cwd, slug) {
80
82
  }
81
83
  }
82
84
  /**
85
+ * PreToolUse: explicitly allow tool via permissionDecision JSON (exit 0).
86
+ * Signals to Claude Code that this edit is permitted, so subsequent hooks
87
+ * (e.g. prompt-based spec-first judge) can be skipped.
88
+ */
89
+ function allowTool(reason) {
90
+ const out = { hookSpecificOutput: {
91
+ hookEventName: "PreToolUse",
92
+ permissionDecision: "allow",
93
+ permissionDecisionReason: reason
94
+ } };
95
+ process.stdout.write(`${JSON.stringify(out)}\n`);
96
+ }
97
+ /**
83
98
  * PreToolUse: deny tool via permissionDecision JSON (exit 0).
84
99
  */
85
100
  function denyTool(reason) {
@@ -167,4 +182,4 @@ var init_review_gate = __esmMin((() => {
167
182
  GATE_FILE = "review-gate.json";
168
183
  }));
169
184
  //#endregion
170
- export { writeReviewGate as a, denyTool as c, isActiveSpecMalformed as d, isSpecFilePath as f, readReviewGate as i, hasUncheckedSelfReview as l, init_review_gate as n, blockStop as o, tryReadActiveSpec as p, isGateActive as r, countUncheckedTasks as s, clearReviewGate as t, init_spec_guard as u };
185
+ export { writeReviewGate as a, countUncheckedTasks as c, init_spec_guard as d, isActiveSpecMalformed as f, readReviewGate as i, denyTool as l, tryReadActiveSpec as m, init_review_gate as n, allowTool as o, isSpecFilePath as p, isGateActive as r, blockStop as s, clearReviewGate as t, hasUncheckedSelfReview as u };
@@ -6,12 +6,12 @@ import { n as init_audit, t as appendAudit } from "./audit-e13xK9Fr.mjs";
6
6
  import { i as getKnowledgeByIDs, l as init_knowledge } from "./knowledge-C7rEfFSX.mjs";
7
7
  import { r as vectorSearchKnowledge, t as init_vectors } from "./vectors-DHZGQ096.mjs";
8
8
  import { a as subTypeBoost, i as searchKnowledgeFTS, r as init_fts } from "./fts-DICqcpG_.mjs";
9
- import "./dispatcher-wn96mbEP.mjs";
10
- import { o as truncate, r as init_helpers } from "./directives-D38Gs3Ld.mjs";
11
- 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-sGk0fIBJ.mjs";
9
+ import "./dispatcher-D6DBNmqa.mjs";
10
+ import { o as truncate, r as init_helpers } from "./directives-D9HvkIv-.mjs";
11
+ 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-TwDkrOWU.mjs";
12
12
  import "./store-BffM-bi-.mjs";
13
- import { a as writeReviewGate, i as readReviewGate, n as init_review_gate, t as clearReviewGate } from "./review-gate-D6pA7CNB.mjs";
14
- import { c as readWaveProgress, m as writeWaveProgress, r as init_state } from "./state-Bw1XMJxp.mjs";
13
+ import { a as writeReviewGate, i as readReviewGate, n as init_review_gate, t as clearReviewGate } from "./review-gate-0cGEW7jx.mjs";
14
+ import { d as writeWaveProgress, n as init_state, o as readWaveProgress } from "./state-XSGGyez_.mjs";
15
15
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
16
16
  import { join, resolve } from "node:path";
17
17
  import process$1 from "node:process";
@@ -19517,7 +19517,7 @@ function createMCPServer(store, emb, version) {
19517
19517
  Actions: status (read-only), init, update, switch, complete, delete (2-phase: preview then confirm=true), history, rollback, review, validate (read-only), gate (review gate management), check (mark task completed), defer (toggle deferred/resume), cancel.
19518
19518
 
19519
19519
  task_slug format: lowercase alphanumeric with hyphens (e.g. "my-feature", max 64 chars).
19520
- Size-based scaling: init accepts size (S/M/L/XL) and spec_type (feature/bugfix). S=3 files, M=4-5 files, L/XL=7 files.`, {
19520
+ Size-based scaling: init accepts size (S/M/L/XL) and spec_type (feature/bugfix). S=2 files, M=3-4 files, L/XL=5 files.`, {
19521
19521
  action: enumType([
19522
19522
  "init",
19523
19523
  "update",
@@ -3,10 +3,10 @@ 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-K2jxpWyU.mjs";
4
4
  import { l as init_knowledge, m as upsertKnowledge, n as deleteOrphanKnowledge, s as getRecentDecisions, t as countKnowledge } from "./knowledge-C7rEfFSX.mjs";
5
5
  import { n as init_project, t as detectProject } from "./project-DCKke4_Q.mjs";
6
- import { a as notifyUser, i as init_dispatcher, r as extractSection } from "./dispatcher-wn96mbEP.mjs";
7
- import { n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-D38Gs3Ld.mjs";
6
+ import { a as notifyUser, i as init_dispatcher, r as extractSection } from "./dispatcher-D6DBNmqa.mjs";
7
+ import { n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-D9HvkIv-.mjs";
8
8
  import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
9
- import { r as init_state, u as resetWorkedSlugs } from "./state-Bw1XMJxp.mjs";
9
+ import { c as resetWorkedSlugs, n as init_state } from "./state-XSGGyez_.mjs";
10
10
  import { existsSync, readFileSync, readdirSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  //#region src/hooks/session-start.ts
@@ -50,22 +50,6 @@ function writeStateText(cwd, name, data) {
50
50
  writeFileSync(join(stateDir(cwd), name), data);
51
51
  } catch {}
52
52
  }
53
- function writeLastIntent(cwd, intent) {
54
- if (!intent) {
55
- writeStateJSON(cwd, INTENT_FILE, null);
56
- return;
57
- }
58
- writeStateJSON(cwd, INTENT_FILE, {
59
- intent,
60
- timestamp: Date.now()
61
- });
62
- }
63
- function readLastIntent(cwd) {
64
- const data = readStateJSON(cwd, INTENT_FILE, null);
65
- if (!data || !data.intent || !data.timestamp) return null;
66
- if (Date.now() - data.timestamp > INTENT_EXPIRY_MS) return null;
67
- return data.intent;
68
- }
69
53
  /** Read the list of spec slugs worked on in this session. */
70
54
  function readWorkedSlugs(cwd) {
71
55
  const data = readStateJSON(cwd, WORKED_SLUGS_FILE, []);
@@ -138,17 +122,10 @@ function parseWaveProgress(tasksContent, slug) {
138
122
  waves
139
123
  };
140
124
  }
141
- var IMPLEMENT_INTENTS, INTENT_FILE, INTENT_EXPIRY_MS, WORKED_SLUGS_FILE, WAVE_PROGRESS_FILE;
125
+ var WORKED_SLUGS_FILE, WAVE_PROGRESS_FILE;
142
126
  var init_state = __esmMin((() => {
143
- IMPLEMENT_INTENTS = new Set([
144
- "implement",
145
- "bugfix",
146
- "tdd"
147
- ]);
148
- INTENT_FILE = "last-intent.json";
149
- INTENT_EXPIRY_MS = 1800 * 1e3;
150
127
  WORKED_SLUGS_FILE = "worked-slugs.json";
151
128
  WAVE_PROGRESS_FILE = "wave-progress.json";
152
129
  }));
153
130
  //#endregion
154
- export { readLastIntent as a, readWaveProgress as c, writeLastIntent as d, writeStateJSON as f, parseWaveProgress as i, readWorkedSlugs as l, writeWaveProgress as m, addWorkedSlug as n, readStateJSON as o, writeStateText as p, init_state as r, readStateText as s, IMPLEMENT_INTENTS as t, resetWorkedSlugs as u };
131
+ export { readStateText as a, resetWorkedSlugs as c, writeWaveProgress as d, readStateJSON as i, writeStateJSON as l, init_state as n, readWaveProgress as o, parseWaveProgress as r, readWorkedSlugs as s, addWorkedSlug as t, writeStateText as u };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import "./types-K2jxpWyU.mjs";
4
- import { l as hasUncheckedSelfReview, n as init_review_gate, o as blockStop, p as tryReadActiveSpec, r as isGateActive, s as countUncheckedTasks, u as init_spec_guard } from "./review-gate-D6pA7CNB.mjs";
5
- import { l as readWorkedSlugs, r as init_state } from "./state-Bw1XMJxp.mjs";
4
+ import { c as countUncheckedTasks, d as init_spec_guard, m as tryReadActiveSpec, n as init_review_gate, r as isGateActive, s as blockStop, u as hasUncheckedSelfReview } from "./review-gate-0cGEW7jx.mjs";
5
+ import { n as init_state, s as readWorkedSlugs } from "./state-XSGGyez_.mjs";
6
6
  //#region src/hooks/stop.ts
7
7
  /**
8
8
  * Stop handler:
@@ -3,10 +3,10 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
3
3
  import { l as readActiveState, s as init_types } from "./types-K2jxpWyU.mjs";
4
4
  import { a as subTypeBoost, r as init_fts } from "./fts-DICqcpG_.mjs";
5
5
  import { Embedder, t as init_embedder } from "./embedder-D3hJoryD.mjs";
6
- import "./dispatcher-wn96mbEP.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-D38Gs3Ld.mjs";
6
+ import "./dispatcher-D6DBNmqa.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-D9HvkIv-.mjs";
8
8
  import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
9
- import { d as writeLastIntent, f as writeStateJSON, l as readWorkedSlugs, o as readStateJSON, r as init_state, t as IMPLEMENT_INTENTS } from "./state-Bw1XMJxp.mjs";
9
+ import { i as readStateJSON, l as writeStateJSON, n as init_state, s as readWorkedSlugs } from "./state-XSGGyez_.mjs";
10
10
  import { existsSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  //#region src/hooks/user-prompt.ts
@@ -30,8 +30,6 @@ async function userPromptSubmit(ev, signal) {
30
30
  let intent = null;
31
31
  if (emb && promptVec) intent = await classifyIntentSemantic(emb, promptVec, signal);
32
32
  if (!intent) intent = classifyIntent(prompt);
33
- if (ev.cwd && existsSync(join(ev.cwd, ".alfred"))) if (intent && IMPLEMENT_INTENTS.has(intent)) writeLastIntent(ev.cwd, intent);
34
- else writeLastIntent(ev.cwd, null);
35
33
  const specDirective = checkSpecRequired(ev.cwd, intent);
36
34
  if (specDirective) {
37
35
  items.push(specDirective);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-alfred",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "alfred": "dist/cli.mjs"
@@ -1 +1 @@
1
- import{A as e,C as t,G as n,K as r,P as i,S as a,_t as o,i as s,j as c,t as l,y as u}from"./api-DUW_x4Qc.js";import{n as d,r as f,t as p}from"./dist-YKGTWb04.js";import{t as m}from"./dist-DqB2i2il.js";import{t as h}from"./progress-Q8H-LYzC.js";import{c as g,f as _,l as v,u as y}from"./index-DGyD_f9j.js";import{n as b,t as x}from"./badge-CasOf-Iy.js";import{i as S,n as ee,r as C,t as w}from"./card-CHfuGvSw.js";import{t as T}from"./skeleton-W0NNrTUC.js";var E=o(r(),1),D=n(),O=`Tabs`,[k,te]=a(O,[f]),A=f(),[j,M]=k(O),N=E.forwardRef((e,n)=>{let{__scopeTabs:r,value:i,onValueChange:a,defaultValue:o,orientation:s=`horizontal`,dir:c,activationMode:l=`automatic`,...u}=e,d=m(c),[f,p]=y({prop:i,onChange:a,defaultProp:o??``,caller:O});return(0,D.jsx)(j,{scope:r,baseId:g(),value:f,onValueChange:p,orientation:s,dir:d,activationMode:l,children:(0,D.jsx)(t.div,{dir:d,"data-orientation":s,...u,ref:n})})});N.displayName=O;var P=`TabsList`,F=E.forwardRef((e,n)=>{let{__scopeTabs:r,loop:i=!0,...a}=e,o=M(P,r),s=A(r);return(0,D.jsx)(d,{asChild:!0,...s,orientation:o.orientation,dir:o.dir,loop:i,children:(0,D.jsx)(t.div,{role:`tablist`,"aria-orientation":o.orientation,...a,ref:n})})});F.displayName=P;var I=`TabsTrigger`,L=E.forwardRef((e,n)=>{let{__scopeTabs:r,value:i,disabled:a=!1,...o}=e,s=M(I,r),c=A(r),l=B(s.baseId,i),u=V(s.baseId,i),d=i===s.value;return(0,D.jsx)(p,{asChild:!0,...c,focusable:!a,active:d,children:(0,D.jsx)(t.button,{type:`button`,role:`tab`,"aria-selected":d,"aria-controls":u,"data-state":d?`active`:`inactive`,"data-disabled":a?``:void 0,disabled:a,id:l,...o,ref:n,onMouseDown:_(e.onMouseDown,e=>{!a&&e.button===0&&e.ctrlKey===!1?s.onValueChange(i):e.preventDefault()}),onKeyDown:_(e.onKeyDown,e=>{[` `,`Enter`].includes(e.key)&&s.onValueChange(i)}),onFocus:_(e.onFocus,()=>{let e=s.activationMode!==`manual`;!d&&!a&&e&&s.onValueChange(i)})})})});L.displayName=I;var R=`TabsContent`,z=E.forwardRef((e,n)=>{let{__scopeTabs:r,value:i,forceMount:a,children:o,...s}=e,c=M(R,r),l=B(c.baseId,i),u=V(c.baseId,i),d=i===c.value,f=E.useRef(d);return E.useEffect(()=>{let e=requestAnimationFrame(()=>f.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,D.jsx)(v,{present:a||d,children:({present:r})=>(0,D.jsx)(t.div,{"data-state":d?`active`:`inactive`,"data-orientation":c.orientation,role:`tabpanel`,"aria-labelledby":l,hidden:!r,id:u,tabIndex:0,...s,ref:n,style:{...e.style,animationDuration:f.current?`0s`:void 0},children:r&&o})})});z.displayName=R;function B(e,t){return`${e}-trigger-${t}`}function V(e,t){return`${e}-content-${t}`}var H=N,U=F,W=L;function G({className:e,...t}){return(0,D.jsx)(`div`,{"data-slot":`table-container`,className:`relative w-full overflow-x-auto`,children:(0,D.jsx)(`table`,{"data-slot":`table`,className:u(`w-full caption-bottom text-sm`,e),...t})})}function K({className:e,...t}){return(0,D.jsx)(`thead`,{"data-slot":`table-header`,className:u(`[&_tr]:border-b`,e),...t})}function q({className:e,...t}){return(0,D.jsx)(`tbody`,{"data-slot":`table-body`,className:u(`[&_tr:last-child]:border-0`,e),...t})}function J({className:e,...t}){return(0,D.jsx)(`tr`,{"data-slot":`table-row`,className:u(`border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted`,e),...t})}function Y({className:e,...t}){return(0,D.jsx)(`th`,{"data-slot":`table-head`,className:u(`h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]`,e),...t})}function X({className:e,...t}){return(0,D.jsx)(`td`,{"data-slot":`table-cell`,className:u(`p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]`,e),...t})}function Z({className:e,orientation:t=`horizontal`,...n}){return(0,D.jsx)(H,{"data-slot":`tabs`,"data-orientation":t,orientation:t,className:u(`group/tabs flex gap-2 data-[orientation=horizontal]:flex-col`,e),...n})}var Q=b(`group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-8 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none`,{variants:{variant:{default:`bg-muted`,line:`gap-1 bg-transparent`}},defaultVariants:{variant:`default`}});function ne({className:e,variant:t=`default`,...n}){return(0,D.jsx)(U,{"data-slot":`tabs-list`,"data-variant":t,className:u(Q({variant:t}),e),...n})}function re({className:e,...t}){return(0,D.jsx)(W,{"data-slot":`tabs-trigger`,className:u(`relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-lg border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-colors group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,`group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent`,`data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground`,`after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100`,e),...t})}var ie=[`all`,`spec.init`,`spec.complete`,`review.submit`];function $(){let{t:e}=c(),[t,n]=(0,E.useState)(`all`),{data:r,isLoading:a}=i(l(100,t===`all`?void 0:t)),{data:o}=i(s()),u=r?.entries??[],d=(o?.epics??[]).filter(e=>e.status!==`completed`&&e.status!==`done`);return(0,D.jsxs)(`div`,{className:`space-y-6`,children:[(0,D.jsx)(Z,{value:t,onValueChange:n,children:(0,D.jsx)(ne,{children:ie.map(t=>(0,D.jsx)(re,{value:t,className:`text-xs`,children:t===`all`?e(`activity.all`):t},t))})}),a?(0,D.jsx)(`div`,{className:`space-y-2`,children:Array.from({length:5}).map((e,t)=>(0,D.jsx)(T,{className:`h-10 w-full`},`skel-${t}`))}):(0,D.jsx)(ae,{entries:u}),d.length>0&&(0,D.jsx)(ce,{epics:d})]})}function ae({entries:e}){let{t,locale:n}=c(),[r,i]=(0,E.useState)(null);return(0,D.jsxs)(G,{children:[(0,D.jsx)(K,{children:(0,D.jsxs)(J,{children:[(0,D.jsx)(Y,{className:`w-44`,children:t(`activity.timestamp`)}),(0,D.jsx)(Y,{className:`w-32`,children:t(`activity.action`)}),(0,D.jsx)(Y,{children:t(`activity.target`)}),(0,D.jsx)(Y,{children:t(`activity.detail`)})]})}),(0,D.jsxs)(q,{children:[e.map((e,t)=>{let a=r===t,o=!!e.detail&&e.detail.length>40;return(0,D.jsxs)(J,{className:o?`cursor-pointer hover:bg-accent/50`:``,onClick:()=>o&&i(a?null:t),children:[(0,D.jsx)(X,{className:`text-xs text-muted-foreground font-mono align-top`,children:le(e.timestamp,n)}),(0,D.jsx)(X,{className:`align-top`,children:(0,D.jsx)(se,{action:e.action})}),(0,D.jsx)(X,{className:`text-sm align-top`,children:e.target}),(0,D.jsx)(X,{className:`text-xs text-muted-foreground`,children:a?(0,D.jsx)(`div`,{className:`whitespace-pre-wrap break-words max-w-lg`,children:e.detail}):(0,D.jsx)(`div`,{className:`max-w-xs truncate`,children:e.detail})})]},`${e.timestamp}-${t}`)}),e.length===0&&(0,D.jsx)(J,{children:(0,D.jsx)(X,{colSpan:4,className:`text-center text-sm text-muted-foreground`,children:t(`activity.noActivity`)})})]})]})}var oe={"spec.init":`#40513b`,"spec.complete":`#2d8b7a`,"spec.delete":`#c0392b`,"review.submit":`#628141`,"living-spec.update":`#7b6b8d`};function se({action:e}){let t=oe[e]??`#6b7280`;return(0,D.jsx)(x,{variant:`outline`,className:`text-xs`,style:{borderColor:`${t}40`,color:t},children:e})}function ce({epics:e}){let{t}=c();return(0,D.jsxs)(`div`,{className:`space-y-3`,children:[(0,D.jsx)(`h3`,{className:`text-sm font-medium text-foreground`,children:t(`activity.epics`)}),(0,D.jsx)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:e.map(e=>{let t=e.total>0?e.completed/e.total*100:0;return(0,D.jsxs)(w,{children:[(0,D.jsx)(C,{className:`pb-2`,children:(0,D.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,D.jsx)(S,{className:`text-sm`,children:e.name}),(0,D.jsx)(x,{variant:`outline`,className:`text-xs`,children:e.status})]})}),(0,D.jsxs)(ee,{className:`space-y-2`,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(h,{value:t,className:`flex-1`}),(0,D.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[e.completed,`/`,e.total]})]}),e.tasks&&e.tasks.length>0&&(0,D.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:e.tasks.map(e=>(0,D.jsx)(x,{variant:`outline`,className:`text-[10px]`,style:{borderColor:e.status===`completed`||e.status===`done`?`rgba(45,139,122,0.3)`:`rgba(107,114,128,0.3)`,color:e.status===`completed`||e.status===`done`?`#2d8b7a`:`#6b7280`},children:e.slug},e.slug))})]})]},e.slug)})})]})}function le(t,n=`en`){try{return new Date(t).toLocaleString(e(n),{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`})}catch{return t}}export{$ as component};
1
+ import{A as e,C as t,G as n,K as r,P as i,S as a,_t as o,i as s,j as c,t as l,y as u}from"./api-D53jbtlM.js";import{n as d,r as f,t as p}from"./dist-Cb-zpBQd.js";import{t as m}from"./dist-C1-OPfHP.js";import{t as h}from"./progress-1DCq6uTs.js";import{c as g,f as _,l as v,u as y}from"./index-CGpsnIcD.js";import{n as b,t as x}from"./badge-DQlFqYx7.js";import{i as S,n as ee,r as C,t as w}from"./card-Cl-Rp8LP.js";import{t as T}from"./skeleton-DCX-0FSu.js";var E=o(r(),1),D=n(),O=`Tabs`,[k,te]=a(O,[f]),A=f(),[j,M]=k(O),N=E.forwardRef((e,n)=>{let{__scopeTabs:r,value:i,onValueChange:a,defaultValue:o,orientation:s=`horizontal`,dir:c,activationMode:l=`automatic`,...u}=e,d=m(c),[f,p]=y({prop:i,onChange:a,defaultProp:o??``,caller:O});return(0,D.jsx)(j,{scope:r,baseId:g(),value:f,onValueChange:p,orientation:s,dir:d,activationMode:l,children:(0,D.jsx)(t.div,{dir:d,"data-orientation":s,...u,ref:n})})});N.displayName=O;var P=`TabsList`,F=E.forwardRef((e,n)=>{let{__scopeTabs:r,loop:i=!0,...a}=e,o=M(P,r),s=A(r);return(0,D.jsx)(d,{asChild:!0,...s,orientation:o.orientation,dir:o.dir,loop:i,children:(0,D.jsx)(t.div,{role:`tablist`,"aria-orientation":o.orientation,...a,ref:n})})});F.displayName=P;var I=`TabsTrigger`,L=E.forwardRef((e,n)=>{let{__scopeTabs:r,value:i,disabled:a=!1,...o}=e,s=M(I,r),c=A(r),l=B(s.baseId,i),u=V(s.baseId,i),d=i===s.value;return(0,D.jsx)(p,{asChild:!0,...c,focusable:!a,active:d,children:(0,D.jsx)(t.button,{type:`button`,role:`tab`,"aria-selected":d,"aria-controls":u,"data-state":d?`active`:`inactive`,"data-disabled":a?``:void 0,disabled:a,id:l,...o,ref:n,onMouseDown:_(e.onMouseDown,e=>{!a&&e.button===0&&e.ctrlKey===!1?s.onValueChange(i):e.preventDefault()}),onKeyDown:_(e.onKeyDown,e=>{[` `,`Enter`].includes(e.key)&&s.onValueChange(i)}),onFocus:_(e.onFocus,()=>{let e=s.activationMode!==`manual`;!d&&!a&&e&&s.onValueChange(i)})})})});L.displayName=I;var R=`TabsContent`,z=E.forwardRef((e,n)=>{let{__scopeTabs:r,value:i,forceMount:a,children:o,...s}=e,c=M(R,r),l=B(c.baseId,i),u=V(c.baseId,i),d=i===c.value,f=E.useRef(d);return E.useEffect(()=>{let e=requestAnimationFrame(()=>f.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,D.jsx)(v,{present:a||d,children:({present:r})=>(0,D.jsx)(t.div,{"data-state":d?`active`:`inactive`,"data-orientation":c.orientation,role:`tabpanel`,"aria-labelledby":l,hidden:!r,id:u,tabIndex:0,...s,ref:n,style:{...e.style,animationDuration:f.current?`0s`:void 0},children:r&&o})})});z.displayName=R;function B(e,t){return`${e}-trigger-${t}`}function V(e,t){return`${e}-content-${t}`}var H=N,U=F,W=L;function G({className:e,...t}){return(0,D.jsx)(`div`,{"data-slot":`table-container`,className:`relative w-full overflow-x-auto`,children:(0,D.jsx)(`table`,{"data-slot":`table`,className:u(`w-full caption-bottom text-sm`,e),...t})})}function K({className:e,...t}){return(0,D.jsx)(`thead`,{"data-slot":`table-header`,className:u(`[&_tr]:border-b`,e),...t})}function q({className:e,...t}){return(0,D.jsx)(`tbody`,{"data-slot":`table-body`,className:u(`[&_tr:last-child]:border-0`,e),...t})}function J({className:e,...t}){return(0,D.jsx)(`tr`,{"data-slot":`table-row`,className:u(`border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted`,e),...t})}function Y({className:e,...t}){return(0,D.jsx)(`th`,{"data-slot":`table-head`,className:u(`h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]`,e),...t})}function X({className:e,...t}){return(0,D.jsx)(`td`,{"data-slot":`table-cell`,className:u(`p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]`,e),...t})}function Z({className:e,orientation:t=`horizontal`,...n}){return(0,D.jsx)(H,{"data-slot":`tabs`,"data-orientation":t,orientation:t,className:u(`group/tabs flex gap-2 data-[orientation=horizontal]:flex-col`,e),...n})}var Q=b(`group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-8 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none`,{variants:{variant:{default:`bg-muted`,line:`gap-1 bg-transparent`}},defaultVariants:{variant:`default`}});function ne({className:e,variant:t=`default`,...n}){return(0,D.jsx)(U,{"data-slot":`tabs-list`,"data-variant":t,className:u(Q({variant:t}),e),...n})}function re({className:e,...t}){return(0,D.jsx)(W,{"data-slot":`tabs-trigger`,className:u(`relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-lg border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-colors group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,`group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent`,`data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground`,`after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100`,e),...t})}var ie=[`all`,`spec.init`,`spec.complete`,`review.submit`];function $(){let{t:e}=c(),[t,n]=(0,E.useState)(`all`),{data:r,isLoading:a}=i(l(100,t===`all`?void 0:t)),{data:o}=i(s()),u=r?.entries??[],d=(o?.epics??[]).filter(e=>e.status!==`completed`&&e.status!==`done`);return(0,D.jsxs)(`div`,{className:`space-y-6`,children:[(0,D.jsx)(Z,{value:t,onValueChange:n,children:(0,D.jsx)(ne,{children:ie.map(t=>(0,D.jsx)(re,{value:t,className:`text-xs`,children:t===`all`?e(`activity.all`):t},t))})}),a?(0,D.jsx)(`div`,{className:`space-y-2`,children:Array.from({length:5}).map((e,t)=>(0,D.jsx)(T,{className:`h-10 w-full`},`skel-${t}`))}):(0,D.jsx)(ae,{entries:u}),d.length>0&&(0,D.jsx)(ce,{epics:d})]})}function ae({entries:e}){let{t,locale:n}=c(),[r,i]=(0,E.useState)(null);return(0,D.jsxs)(G,{children:[(0,D.jsx)(K,{children:(0,D.jsxs)(J,{children:[(0,D.jsx)(Y,{className:`w-44`,children:t(`activity.timestamp`)}),(0,D.jsx)(Y,{className:`w-32`,children:t(`activity.action`)}),(0,D.jsx)(Y,{children:t(`activity.target`)}),(0,D.jsx)(Y,{children:t(`activity.detail`)})]})}),(0,D.jsxs)(q,{children:[e.map((e,t)=>{let a=r===t,o=!!e.detail&&e.detail.length>40;return(0,D.jsxs)(J,{className:o?`cursor-pointer hover:bg-accent/50`:``,onClick:()=>o&&i(a?null:t),children:[(0,D.jsx)(X,{className:`text-xs text-muted-foreground font-mono align-top`,children:le(e.timestamp,n)}),(0,D.jsx)(X,{className:`align-top`,children:(0,D.jsx)(se,{action:e.action})}),(0,D.jsx)(X,{className:`text-sm align-top`,children:e.target}),(0,D.jsx)(X,{className:`text-xs text-muted-foreground`,children:a?(0,D.jsx)(`div`,{className:`whitespace-pre-wrap break-words max-w-lg`,children:e.detail}):(0,D.jsx)(`div`,{className:`max-w-xs truncate`,children:e.detail})})]},`${e.timestamp}-${t}`)}),e.length===0&&(0,D.jsx)(J,{children:(0,D.jsx)(X,{colSpan:4,className:`text-center text-sm text-muted-foreground`,children:t(`activity.noActivity`)})})]})]})}var oe={"spec.init":`#40513b`,"spec.complete":`#2d8b7a`,"spec.delete":`#c0392b`,"review.submit":`#628141`,"living-spec.update":`#7b6b8d`};function se({action:e}){let t=oe[e]??`#6b7280`;return(0,D.jsx)(x,{variant:`outline`,className:`text-xs`,style:{borderColor:`${t}40`,color:t},children:e})}function ce({epics:e}){let{t}=c();return(0,D.jsxs)(`div`,{className:`space-y-3`,children:[(0,D.jsx)(`h3`,{className:`text-sm font-medium text-foreground`,children:t(`activity.epics`)}),(0,D.jsx)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:e.map(e=>{let t=e.total>0?e.completed/e.total*100:0;return(0,D.jsxs)(w,{children:[(0,D.jsx)(C,{className:`pb-2`,children:(0,D.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,D.jsx)(S,{className:`text-sm`,children:e.name}),(0,D.jsx)(x,{variant:`outline`,className:`text-xs`,children:e.status})]})}),(0,D.jsxs)(ee,{className:`space-y-2`,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(h,{value:t,className:`flex-1`}),(0,D.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[e.completed,`/`,e.total]})]}),e.tasks&&e.tasks.length>0&&(0,D.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:e.tasks.map(e=>(0,D.jsx)(x,{variant:`outline`,className:`text-[10px]`,style:{borderColor:e.status===`completed`||e.status===`done`?`rgba(45,139,122,0.3)`:`rgba(107,114,128,0.3)`,color:e.status===`completed`||e.status===`done`?`#2d8b7a`:`#6b7280`},children:e.slug},e.slug))})]})]},e.slug)})})]})}function le(t,n=`en`){try{return new Date(t).toLocaleString(e(n),{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`})}catch{return t}}export{$ as component};