intent-log 0.1.0

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 (71) hide show
  1. package/README.md +64 -0
  2. package/dist/adapter/__tests__/claude-code-log-reader.test.d.ts +1 -0
  3. package/dist/adapter/__tests__/claude-code-log-reader.test.js +197 -0
  4. package/dist/adapter/__tests__/claude-code-log-reader.test.js.map +1 -0
  5. package/dist/adapter/__tests__/filesystem-repository.test.d.ts +1 -0
  6. package/dist/adapter/__tests__/filesystem-repository.test.js +152 -0
  7. package/dist/adapter/__tests__/filesystem-repository.test.js.map +1 -0
  8. package/dist/adapter/__tests__/privacy-filter.test.d.ts +1 -0
  9. package/dist/adapter/__tests__/privacy-filter.test.js +61 -0
  10. package/dist/adapter/__tests__/privacy-filter.test.js.map +1 -0
  11. package/dist/adapter/claude-code-log-reader.d.ts +11 -0
  12. package/dist/adapter/claude-code-log-reader.js +133 -0
  13. package/dist/adapter/claude-code-log-reader.js.map +1 -0
  14. package/dist/adapter/claude-code-summarizer.d.ts +6 -0
  15. package/dist/adapter/claude-code-summarizer.js +93 -0
  16. package/dist/adapter/claude-code-summarizer.js.map +1 -0
  17. package/dist/adapter/filesystem-repository.d.ts +39 -0
  18. package/dist/adapter/filesystem-repository.js +98 -0
  19. package/dist/adapter/filesystem-repository.js.map +1 -0
  20. package/dist/adapter/privacy-filter.d.ts +8 -0
  21. package/dist/adapter/privacy-filter.js +58 -0
  22. package/dist/adapter/privacy-filter.js.map +1 -0
  23. package/dist/cli/collect.d.ts +1 -0
  24. package/dist/cli/collect.js +19 -0
  25. package/dist/cli/collect.js.map +1 -0
  26. package/dist/cli/init.d.ts +1 -0
  27. package/dist/cli/init.js +39 -0
  28. package/dist/cli/init.js.map +1 -0
  29. package/dist/cli/log.d.ts +1 -0
  30. package/dist/cli/log.js +15 -0
  31. package/dist/cli/log.js.map +1 -0
  32. package/dist/cli/reset.d.ts +1 -0
  33. package/dist/cli/reset.js +7 -0
  34. package/dist/cli/reset.js.map +1 -0
  35. package/dist/cli/rm.d.ts +1 -0
  36. package/dist/cli/rm.js +7 -0
  37. package/dist/cli/rm.js.map +1 -0
  38. package/dist/cli/show.d.ts +1 -0
  39. package/dist/cli/show.js +21 -0
  40. package/dist/cli/show.js.map +1 -0
  41. package/dist/domain/__tests__/session.test.d.ts +1 -0
  42. package/dist/domain/__tests__/session.test.js +80 -0
  43. package/dist/domain/__tests__/session.test.js.map +1 -0
  44. package/dist/domain/__tests__/step.test.d.ts +1 -0
  45. package/dist/domain/__tests__/step.test.js +65 -0
  46. package/dist/domain/__tests__/step.test.js.map +1 -0
  47. package/dist/domain/session.d.ts +51 -0
  48. package/dist/domain/session.js +49 -0
  49. package/dist/domain/session.js.map +1 -0
  50. package/dist/domain/step.d.ts +13 -0
  51. package/dist/domain/step.js +98 -0
  52. package/dist/domain/step.js.map +1 -0
  53. package/dist/index.d.ts +2 -0
  54. package/dist/index.js +106 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/port/agent-log-reader.d.ts +6 -0
  57. package/dist/port/agent-log-reader.js +2 -0
  58. package/dist/port/agent-log-reader.js.map +1 -0
  59. package/dist/port/step-repository.d.ts +7 -0
  60. package/dist/port/step-repository.js +2 -0
  61. package/dist/port/step-repository.js.map +1 -0
  62. package/dist/port/summarizer.d.ts +13 -0
  63. package/dist/port/summarizer.js +2 -0
  64. package/dist/port/summarizer.js.map +1 -0
  65. package/dist/usecase/__tests__/collect.test.d.ts +1 -0
  66. package/dist/usecase/__tests__/collect.test.js +135 -0
  67. package/dist/usecase/__tests__/collect.test.js.map +1 -0
  68. package/dist/usecase/collect.d.ts +16 -0
  69. package/dist/usecase/collect.js +190 -0
  70. package/dist/usecase/collect.js.map +1 -0
  71. package/package.json +41 -0
@@ -0,0 +1,65 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { toMarkdown, fromMarkdown } from "../step.js";
3
+ const baseStep = {
4
+ number: 1,
5
+ title: "テスト機能追加",
6
+ session: "abc-123",
7
+ timestamp: new Date("2025-01-15T10:30:00Z"),
8
+ tags: ["feature", "test"],
9
+ prompt: "テスト機能を追加してください",
10
+ reasoning: "品質向上のため",
11
+ outcome: "テストが追加された",
12
+ friction: "型エラーが発生した",
13
+ };
14
+ describe("toMarkdown", () => {
15
+ it("全フィールドを正常に出力する", () => {
16
+ const md = toMarkdown(baseStep);
17
+ expect(md).toContain("step: 1");
18
+ expect(md).toContain('title: "テスト機能追加"');
19
+ expect(md).toContain('session: "abc-123"');
20
+ expect(md).toContain("timestamp: 2025-01-15T10:30:00Z");
21
+ expect(md).toContain("tags: [feature, test]");
22
+ expect(md).toContain("## prompt\n\nテスト機能を追加してください");
23
+ expect(md).toContain("## reasoning\n\n品質向上のため");
24
+ expect(md).toContain("## outcome\n\nテストが追加された");
25
+ expect(md).toContain("## friction\n\n型エラーが発生した");
26
+ });
27
+ it("frictionが空なら省略する", () => {
28
+ const step = { ...baseStep, friction: "" };
29
+ const md = toMarkdown(step);
30
+ expect(md).not.toContain("## friction");
31
+ });
32
+ it("tagsが空なら[]を出力する", () => {
33
+ const step = { ...baseStep, tags: [] };
34
+ const md = toMarkdown(step);
35
+ expect(md).toContain("tags: []");
36
+ });
37
+ });
38
+ describe("fromMarkdown", () => {
39
+ it("正常にパースできる", () => {
40
+ const md = toMarkdown(baseStep);
41
+ const parsed = fromMarkdown(md);
42
+ expect(parsed.number).toBe(1);
43
+ expect(parsed.title).toBe("テスト機能追加");
44
+ expect(parsed.session).toBe("abc-123");
45
+ expect(parsed.timestamp.toISOString()).toBe("2025-01-15T10:30:00.000Z");
46
+ expect(parsed.tags).toEqual(["feature", "test"]);
47
+ expect(parsed.prompt).toBe("テスト機能を追加してください");
48
+ expect(parsed.reasoning).toBe("品質向上のため");
49
+ expect(parsed.outcome).toBe("テストが追加された");
50
+ expect(parsed.friction).toBe("型エラーが発生した");
51
+ });
52
+ it("frontmatterがなければエラー", () => {
53
+ expect(() => fromMarkdown("no frontmatter")).toThrow("frontmatterが見つかりません");
54
+ });
55
+ it("frontmatter終了がなければエラー", () => {
56
+ expect(() => fromMarkdown("---\nstep: 1\n")).toThrow("frontmatterの終了が見つかりません");
57
+ });
58
+ it("toMarkdown → fromMarkdown のラウンドトリップ", () => {
59
+ const md = toMarkdown(baseStep);
60
+ const parsed = fromMarkdown(md);
61
+ const md2 = toMarkdown(parsed);
62
+ expect(md).toBe(md2);
63
+ });
64
+ });
65
+ //# sourceMappingURL=step.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.test.js","sourceRoot":"","sources":["../../../src/domain/__tests__/step.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod/v4";
2
+ declare const ContentBlock: z.ZodUnion<readonly [z.ZodObject<{
3
+ type: z.ZodLiteral<"text">;
4
+ text: z.ZodString;
5
+ }, z.core.$strip>, z.ZodObject<{
6
+ type: z.ZodLiteral<"thinking">;
7
+ thinking: z.ZodString;
8
+ }, z.core.$strip>, z.ZodObject<{
9
+ type: z.ZodLiteral<"tool_use">;
10
+ name: z.ZodString;
11
+ input: z.ZodUnknown;
12
+ }, z.core.$strip>, z.ZodObject<{
13
+ type: z.ZodLiteral<"tool_result">;
14
+ content: z.ZodOptional<z.ZodUnknown>;
15
+ }, z.core.$strip>, z.ZodObject<{
16
+ type: z.ZodString;
17
+ }, z.core.$strip>]>;
18
+ export declare const SessionEntry: z.ZodObject<{
19
+ type: z.ZodString;
20
+ isSidechain: z.ZodOptional<z.ZodBoolean>;
21
+ message: z.ZodOptional<z.ZodObject<{
22
+ role: z.ZodString;
23
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
24
+ type: z.ZodLiteral<"text">;
25
+ text: z.ZodString;
26
+ }, z.core.$strip>, z.ZodObject<{
27
+ type: z.ZodLiteral<"thinking">;
28
+ thinking: z.ZodString;
29
+ }, z.core.$strip>, z.ZodObject<{
30
+ type: z.ZodLiteral<"tool_use">;
31
+ name: z.ZodString;
32
+ input: z.ZodUnknown;
33
+ }, z.core.$strip>, z.ZodObject<{
34
+ type: z.ZodLiteral<"tool_result">;
35
+ content: z.ZodOptional<z.ZodUnknown>;
36
+ }, z.core.$strip>, z.ZodObject<{
37
+ type: z.ZodString;
38
+ }, z.core.$strip>]>>]>;
39
+ }, z.core.$strip>>;
40
+ }, z.core.$strip>;
41
+ export type SessionEntry = z.infer<typeof SessionEntry>;
42
+ export type ContentBlock = z.infer<typeof ContentBlock>;
43
+ export interface ConversationTurn {
44
+ userPrompt: string;
45
+ assistantThinking: string[];
46
+ assistantText: string[];
47
+ toolUses: string[];
48
+ skills: string[];
49
+ }
50
+ export declare function summaryContext(turn: ConversationTurn): string;
51
+ export {};
@@ -0,0 +1,49 @@
1
+ import { z } from "zod/v4";
2
+ const ContentBlockText = z.object({
3
+ type: z.literal("text"),
4
+ text: z.string(),
5
+ });
6
+ const ContentBlockThinking = z.object({
7
+ type: z.literal("thinking"),
8
+ thinking: z.string(),
9
+ });
10
+ const ContentBlockToolUse = z.object({
11
+ type: z.literal("tool_use"),
12
+ name: z.string(),
13
+ input: z.unknown(),
14
+ });
15
+ const ContentBlockToolResult = z.object({
16
+ type: z.literal("tool_result"),
17
+ content: z.unknown().optional(),
18
+ });
19
+ const ContentBlock = z.union([
20
+ ContentBlockText,
21
+ ContentBlockThinking,
22
+ ContentBlockToolUse,
23
+ ContentBlockToolResult,
24
+ z.object({ type: z.string() }), // Other
25
+ ]);
26
+ const MessageContent = z.union([z.string(), z.array(ContentBlock)]);
27
+ const Message = z.object({
28
+ role: z.string(),
29
+ content: MessageContent,
30
+ });
31
+ export const SessionEntry = z.object({
32
+ type: z.string(),
33
+ isSidechain: z.boolean().optional(),
34
+ message: Message.optional(),
35
+ });
36
+ export function summaryContext(turn) {
37
+ let ctx = `## ユーザーの指示\n${turn.userPrompt}\n`;
38
+ if (turn.assistantThinking.length > 0) {
39
+ ctx += `\n## AIの思考\n${turn.assistantThinking.join("\n")}\n`;
40
+ }
41
+ if (turn.assistantText.length > 0) {
42
+ ctx += `\n## AIの応答\n${turn.assistantText.join("\n")}\n`;
43
+ }
44
+ if (turn.toolUses.length > 0) {
45
+ ctx += `\n## 使用ツール\n${turn.toolUses.join(", ")}\n`;
46
+ }
47
+ return ctx;
48
+ }
49
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/domain/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;CACnB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,gBAAgB;IAChB,oBAAoB;IACpB,mBAAmB;IACnB,sBAAsB;IACtB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ;CACzC,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAEpE,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,cAAc;CACxB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAaH,MAAM,UAAU,cAAc,CAAC,IAAsB;IACnD,IAAI,GAAG,GAAG,eAAe,IAAI,CAAC,UAAU,IAAI,CAAC;IAC7C,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,GAAG,IAAI,eAAe,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC9D,CAAC;IACD,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,GAAG,IAAI,eAAe,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1D,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,GAAG,IAAI,eAAe,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACrD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface Step {
2
+ number: number;
3
+ title: string;
4
+ session: string;
5
+ timestamp: Date;
6
+ tags: string[];
7
+ prompt: string;
8
+ reasoning: string;
9
+ outcome: string;
10
+ friction: string;
11
+ }
12
+ export declare function toMarkdown(step: Step): string;
13
+ export declare function fromMarkdown(content: string): Step;
@@ -0,0 +1,98 @@
1
+ export function toMarkdown(step) {
2
+ const tagsStr = step.tags.length === 0 ? "[]" : `[${step.tags.join(", ")}]`;
3
+ const ts = step.timestamp.toISOString().replace(/\.\d{3}Z$/, "Z");
4
+ let md = `---
5
+ step: ${step.number}
6
+ title: "${step.title}"
7
+ session: "${step.session}"
8
+ timestamp: ${ts}
9
+ tags: ${tagsStr}
10
+ ---
11
+
12
+ ## prompt
13
+
14
+ ${step.prompt}
15
+
16
+ ## reasoning
17
+
18
+ ${step.reasoning}
19
+
20
+ ## outcome
21
+
22
+ ${step.outcome}`;
23
+ if (step.friction) {
24
+ md += `\n\n## friction\n\n${step.friction}`;
25
+ }
26
+ md += "\n";
27
+ return md;
28
+ }
29
+ export function fromMarkdown(content) {
30
+ const trimmed = content.trimStart();
31
+ if (!trimmed.startsWith("---")) {
32
+ throw new Error("frontmatterが見つかりません");
33
+ }
34
+ const rest = trimmed.slice(3);
35
+ const endIdx = rest.indexOf("---");
36
+ if (endIdx === -1) {
37
+ throw new Error("frontmatterの終了が見つかりません");
38
+ }
39
+ const frontmatter = rest.slice(0, endIdx).trim();
40
+ const body = rest.slice(endIdx + 3).trim();
41
+ const number = parseInt(extractField(frontmatter, "step"), 10);
42
+ if (isNaN(number))
43
+ throw new Error("step番号のパースに失敗");
44
+ const title = extractField(frontmatter, "title");
45
+ const session = extractField(frontmatter, "session");
46
+ const timestampStr = extractField(frontmatter, "timestamp");
47
+ const timestamp = new Date(timestampStr);
48
+ if (isNaN(timestamp.getTime())) {
49
+ throw new Error(`timestampのパースに失敗: ${timestampStr}`);
50
+ }
51
+ const tagsStr = extractFieldOptional(frontmatter, "tags") ?? "[]";
52
+ const tags = parseTags(tagsStr);
53
+ return {
54
+ number,
55
+ title,
56
+ session,
57
+ timestamp,
58
+ tags,
59
+ prompt: extractSection(body, "prompt"),
60
+ reasoning: extractSection(body, "reasoning"),
61
+ outcome: extractSection(body, "outcome"),
62
+ friction: extractSection(body, "friction"),
63
+ };
64
+ }
65
+ function extractField(frontmatter, key) {
66
+ for (const line of frontmatter.split("\n")) {
67
+ if (line.startsWith(`${key}:`)) {
68
+ const val = line.slice(key.length + 1).trim();
69
+ return val.replace(/^"|"$/g, "");
70
+ }
71
+ }
72
+ throw new Error(`フィールド '${key}' が見つかりません`);
73
+ }
74
+ function extractFieldOptional(frontmatter, key) {
75
+ try {
76
+ return extractField(frontmatter, key);
77
+ }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ }
82
+ function parseTags(s) {
83
+ const inner = s.trim().replace(/^\[/, "").replace(/\]$/, "");
84
+ if (!inner)
85
+ return [];
86
+ return inner.split(",").map((t) => t.trim());
87
+ }
88
+ function extractSection(body, section) {
89
+ const header = `## ${section}`;
90
+ const start = body.indexOf(header);
91
+ if (start === -1)
92
+ return "";
93
+ const afterHeader = body.slice(start + header.length);
94
+ const end = afterHeader.indexOf("\n## ");
95
+ const content = end === -1 ? afterHeader : afterHeader.slice(0, end);
96
+ return content.trim();
97
+ }
98
+ //# sourceMappingURL=step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.js","sourceRoot":"","sources":["../../src/domain/step.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { initCommand } from "./cli/init.js";
4
+ import { collectCommand } from "./cli/collect.js";
5
+ import { logCommand } from "./cli/log.js";
6
+ import { showCommand } from "./cli/show.js";
7
+ import { resetCommand } from "./cli/reset.js";
8
+ import { rmCommand } from "./cli/rm.js";
9
+ const program = new Command();
10
+ program
11
+ .name("intent")
12
+ .description("意図のバージョン管理CLI — AIとの対話ログから意図の進化過程を抽出・構造化")
13
+ .version("0.1.0");
14
+ program
15
+ .command("init")
16
+ .description(".intent/ を初期化")
17
+ .action(async () => {
18
+ try {
19
+ await initCommand();
20
+ }
21
+ catch (e) {
22
+ console.error(`エラー: ${e instanceof Error ? e.message : e}`);
23
+ process.exit(1);
24
+ }
25
+ });
26
+ program
27
+ .command("collect")
28
+ .description("ログから意図を収集")
29
+ .option("--session <id>", "特定セッションだけ収集")
30
+ .action(async (opts) => {
31
+ try {
32
+ await collectCommand(opts.session);
33
+ }
34
+ catch (e) {
35
+ console.error(`エラー: ${e instanceof Error ? e.message : e}`);
36
+ process.exit(1);
37
+ }
38
+ });
39
+ program
40
+ .command("log")
41
+ .description("ステップ一覧を表示")
42
+ .action(async () => {
43
+ try {
44
+ await logCommand();
45
+ }
46
+ catch (e) {
47
+ console.error(`エラー: ${e instanceof Error ? e.message : e}`);
48
+ process.exit(1);
49
+ }
50
+ });
51
+ program
52
+ .command("show")
53
+ .description("特定ステップの詳細表示")
54
+ .argument("<step>", "ステップ番号")
55
+ .action(async (step) => {
56
+ try {
57
+ await showCommand(parseInt(step, 10));
58
+ }
59
+ catch (e) {
60
+ console.error(`エラー: ${e instanceof Error ? e.message : e}`);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ program
65
+ .command("reset")
66
+ .description("すべてのステップとセッション履歴をリセット")
67
+ .option("--yes", "確認プロンプトをスキップ")
68
+ .action(async (opts) => {
69
+ try {
70
+ if (!opts.yes) {
71
+ const { createInterface } = await import("node:readline");
72
+ const rl = createInterface({
73
+ input: process.stdin,
74
+ output: process.stdout,
75
+ });
76
+ const answer = await new Promise((resolve) => {
77
+ rl.question("すべてのステップとセッション履歴を削除します。よろしいですか? (y/N) ", resolve);
78
+ });
79
+ rl.close();
80
+ if (answer.toLowerCase() !== "y") {
81
+ console.log("キャンセルしました。");
82
+ return;
83
+ }
84
+ }
85
+ await resetCommand();
86
+ }
87
+ catch (e) {
88
+ console.error(`エラー: ${e instanceof Error ? e.message : e}`);
89
+ process.exit(1);
90
+ }
91
+ });
92
+ program
93
+ .command("rm")
94
+ .description("特定のステップを削除")
95
+ .argument("<step>", "ステップ番号")
96
+ .action(async (step) => {
97
+ try {
98
+ await rmCommand(parseInt(step, 10));
99
+ }
100
+ catch (e) {
101
+ console.error(`エラー: ${e instanceof Error ? e.message : e}`);
102
+ process.exit(1);
103
+ }
104
+ });
105
+ program.parse();
106
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ConversationTurn } from "../domain/session.js";
2
+ export interface AgentLogReader {
3
+ listSessions(): Promise<string[]>;
4
+ readSession(sessionId: string): Promise<ConversationTurn[]>;
5
+ getSessionTimestamp(sessionId: string): Promise<Date>;
6
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-log-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-log-reader.js","sourceRoot":"","sources":["../../src/port/agent-log-reader.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { Step } from "../domain/step.js";
2
+ export interface StepRepository {
3
+ listSteps(): Promise<Step[]>;
4
+ getStep(number: number): Promise<Step>;
5
+ saveStep(step: Step): Promise<void>;
6
+ nextStepNumber(): Promise<number>;
7
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=step-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-repository.js","sourceRoot":"","sources":["../../src/port/step-repository.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import type { ConversationTurn } from "../domain/session.js";
2
+ import type { Step } from "../domain/step.js";
3
+ export interface StepDraft {
4
+ title: string;
5
+ prompt: string;
6
+ reasoning: string;
7
+ outcome: string;
8
+ tags?: string[];
9
+ skip?: boolean;
10
+ }
11
+ export interface Summarizer {
12
+ summarize(turns: ConversationTurn[], previousSteps: Step[]): Promise<StepDraft | null>;
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=summarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../src/port/summarizer.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,135 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { parsePlanText, parseSkillSession } from "../collect.js";
3
+ function makeTurn(prompt, skills = [], toolUses = []) {
4
+ return {
5
+ userPrompt: prompt,
6
+ assistantThinking: [],
7
+ assistantText: [],
8
+ toolUses,
9
+ skills,
10
+ };
11
+ }
12
+ const planPrompt = `Implement the following plan:
13
+
14
+ # プラン実行セッションからの意図抽出
15
+
16
+ ## Context
17
+
18
+ \`intent collect\` で claude-panes プロジェクトを収集すると、22セッション中 3つしか収集されない。調査の結果、17セッションが \`Implement the following plan:\` で始まるプラン実行セッションで、一律スキップされていた。
19
+
20
+ ## 変更
21
+
22
+ ### 1. \`src/usecase/collect.ts\` — プラン実行セッションの処理
23
+
24
+ parsePlanText() ヘルパーを追加。
25
+
26
+ ### 2. \`src/adapter/claude-code-summarizer.ts\` — プロンプト修正
27
+
28
+ skip 指示を削除。
29
+
30
+ ### 3. テスト追加
31
+
32
+ テストを新規作成。
33
+
34
+ ## 検証
35
+
36
+ npm run build && npm test
37
+ `;
38
+ describe("parsePlanText", () => {
39
+ it("タイトルと Context を正しく抽出する", () => {
40
+ const draft = parsePlanText(planPrompt);
41
+ expect(draft).not.toBeNull();
42
+ expect(draft.title).toBe("プラン実行セッションからの意図抽出");
43
+ expect(draft.prompt).toContain("intent collect");
44
+ expect(draft.prompt).toContain("一律スキップされていた");
45
+ expect(draft.tags).toEqual(["plan"]);
46
+ expect(draft.outcome).toContain("実装完了");
47
+ });
48
+ it("変更セクションからファイル一覧を reasoning に含める", () => {
49
+ const draft = parsePlanText(planPrompt);
50
+ expect(draft).not.toBeNull();
51
+ expect(draft.reasoning).toContain("src/usecase/collect.ts");
52
+ expect(draft.reasoning).toContain("src/adapter/claude-code-summarizer.ts");
53
+ });
54
+ it("Context なしのプランで null を返す", () => {
55
+ const noContext = `Implement the following plan:
56
+
57
+ # タイトルだけのプラン
58
+
59
+ ## 変更
60
+
61
+ 何かの変更
62
+ `;
63
+ const draft = parsePlanText(noContext);
64
+ expect(draft).toBeNull();
65
+ });
66
+ it("長いタイトルが30文字に切り詰められる", () => {
67
+ const longTitle = `Implement the following plan:
68
+
69
+ # これは非常に長いタイトルで30文字を超えるため切り詰めが必要になるはずです
70
+
71
+ ## Context
72
+
73
+ 何かのコンテキスト。
74
+ `;
75
+ const draft = parsePlanText(longTitle);
76
+ expect(draft).not.toBeNull();
77
+ expect(draft.title.length).toBeLessThanOrEqual(30);
78
+ });
79
+ it("プレフィックスのみで本文がない場合は null を返す", () => {
80
+ const draft = parsePlanText("Implement the following plan:");
81
+ expect(draft).toBeNull();
82
+ });
83
+ it("タイトルがない場合は null を返す", () => {
84
+ const noTitle = `Implement the following plan:
85
+
86
+ ## Context
87
+
88
+ 何かのコンテキスト。
89
+ `;
90
+ const draft = parsePlanText(noTitle);
91
+ expect(draft).toBeNull();
92
+ });
93
+ });
94
+ describe("parseSkillSession", () => {
95
+ it("Skill tool_use を含むセッションから StepDraft を生成する", () => {
96
+ const turns = [makeTurn("/commit", ["commit"], ["Skill"])];
97
+ const draft = parseSkillSession(turns);
98
+ expect(draft).not.toBeNull();
99
+ expect(draft.title).toBe("/commit スキル実行");
100
+ expect(draft.prompt).toBe("/commit");
101
+ expect(draft.tags).toEqual(["skill"]);
102
+ expect(draft.outcome).toContain("commit");
103
+ });
104
+ it("namespaced スキル名を正規化する", () => {
105
+ const turns = [
106
+ makeTurn("/commit", ["commit-commands:commit"], ["Skill"]),
107
+ ];
108
+ const draft = parseSkillSession(turns);
109
+ expect(draft).not.toBeNull();
110
+ expect(draft.title).toBe("/commit スキル実行");
111
+ });
112
+ it("skills が空のセッションでは null を返す", () => {
113
+ const turns = [makeTurn("通常の質問", [], ["Read", "Edit"])];
114
+ const draft = parseSkillSession(turns);
115
+ expect(draft).toBeNull();
116
+ });
117
+ it("複数ターンにまたがるスキルを集約する", () => {
118
+ const turns = [
119
+ makeTurn("/review-pr", ["code-review:code-review"], ["Skill"]),
120
+ makeTurn("修正して", ["commit-commands:commit"], ["Skill"]),
121
+ ];
122
+ const draft = parseSkillSession(turns);
123
+ expect(draft).not.toBeNull();
124
+ expect(draft.title).toBe("/code-review スキル実行");
125
+ expect(draft.reasoning).toContain("code-review");
126
+ expect(draft.reasoning).toContain("commit");
127
+ });
128
+ it("userPrompt が空でもスキル名をフォールバックに使う", () => {
129
+ const turns = [makeTurn("", ["commit"], ["Skill"])];
130
+ const draft = parseSkillSession(turns);
131
+ expect(draft).not.toBeNull();
132
+ expect(draft.prompt).toBe("/commit");
133
+ });
134
+ });
135
+ //# sourceMappingURL=collect.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.test.js","sourceRoot":"","sources":["../../../src/usecase/__tests__/collect.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { AgentLogReader } from "../port/agent-log-reader.js";
2
+ import type { Summarizer, StepDraft } from "../port/summarizer.js";
3
+ import type { PrivacyFilter } from "../adapter/privacy-filter.js";
4
+ import type { FileSystemRepository } from "../adapter/filesystem-repository.js";
5
+ import type { ConversationTurn } from "../domain/session.js";
6
+ export declare class CollectUseCase {
7
+ private reader;
8
+ private summarizer;
9
+ private filter;
10
+ private repository;
11
+ constructor(reader: AgentLogReader, summarizer: Summarizer, filter: PrivacyFilter, repository: FileSystemRepository);
12
+ collectAll(): Promise<void>;
13
+ collectSession(sessionId: string): Promise<boolean>;
14
+ }
15
+ export declare function parseSkillSession(turns: ConversationTurn[]): StepDraft | null;
16
+ export declare function parsePlanText(prompt: string): StepDraft | null;