@towles/tool 0.0.62 → 0.0.64

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 (83) hide show
  1. package/package.json +50 -57
  2. package/src/commands/agentboard.ts +176 -0
  3. package/src/commands/{auto-claude.ts → auto-claude/index.ts} +18 -28
  4. package/src/commands/auto-claude/list.ts +114 -0
  5. package/src/commands/auto-claude/retry.test.ts +138 -0
  6. package/src/commands/auto-claude/retry.ts +139 -0
  7. package/src/commands/auto-claude/status.test.ts +147 -0
  8. package/src/commands/auto-claude/status.ts +123 -0
  9. package/src/commands/base.ts +7 -2
  10. package/src/commands/config.ts +5 -7
  11. package/src/commands/doctor.ts +111 -12
  12. package/src/commands/gh/branch.ts +4 -4
  13. package/src/commands/gh/pr.ts +1 -0
  14. package/src/commands/graph/index.ts +169 -0
  15. package/src/commands/graph.test.ts +1 -1
  16. package/src/commands/install.ts +40 -68
  17. package/src/commands/journal/daily-notes.ts +3 -3
  18. package/src/commands/journal/meeting.ts +3 -3
  19. package/src/commands/journal/note.ts +3 -3
  20. package/src/lib/auto-claude/claude-cli.ts +183 -0
  21. package/src/lib/auto-claude/config.test.ts +6 -8
  22. package/src/lib/auto-claude/config.ts +3 -4
  23. package/src/lib/auto-claude/index.ts +2 -3
  24. package/src/lib/auto-claude/labels.test.ts +85 -0
  25. package/src/lib/auto-claude/labels.ts +42 -0
  26. package/src/lib/auto-claude/pipeline-execution.test.ts +129 -33
  27. package/src/lib/auto-claude/pipeline.test.ts +2 -2
  28. package/src/lib/auto-claude/pipeline.ts +120 -36
  29. package/src/lib/auto-claude/prompt-templates/01_plan.prompt.md +68 -0
  30. package/src/lib/auto-claude/prompt-templates/{05_implement.prompt.md → 02_implement.prompt.md} +3 -2
  31. package/src/lib/auto-claude/prompt-templates/03_simplify.prompt.md +52 -0
  32. package/src/lib/auto-claude/prompt-templates/{06_review.prompt.md → 04_review.prompt.md} +29 -6
  33. package/src/lib/auto-claude/prompt-templates/index.test.ts +9 -42
  34. package/src/lib/auto-claude/prompt-templates/index.ts +13 -28
  35. package/src/lib/auto-claude/run-claude.test.ts +48 -68
  36. package/src/lib/auto-claude/shell.ts +6 -0
  37. package/src/lib/auto-claude/steps/create-pr.ts +89 -25
  38. package/src/lib/auto-claude/steps/fetch-issues.ts +4 -1
  39. package/src/lib/auto-claude/steps/implement.ts +9 -16
  40. package/src/lib/auto-claude/steps/simple-steps.ts +34 -0
  41. package/src/lib/auto-claude/steps/steps.test.ts +68 -63
  42. package/src/lib/auto-claude/templates.test.ts +91 -0
  43. package/src/lib/auto-claude/templates.ts +34 -0
  44. package/src/lib/auto-claude/test-helpers.ts +2 -1
  45. package/src/lib/auto-claude/utils-execution.test.ts +9 -57
  46. package/src/lib/auto-claude/utils.test.ts +5 -9
  47. package/src/lib/auto-claude/utils.ts +27 -253
  48. package/src/lib/graph/analyzer.test.ts +451 -0
  49. package/src/lib/graph/analyzer.ts +165 -0
  50. package/src/lib/graph/index.ts +24 -0
  51. package/src/lib/graph/labels.ts +87 -0
  52. package/src/lib/graph/parser.test.ts +150 -0
  53. package/src/lib/graph/parser.ts +65 -0
  54. package/src/lib/graph/render.ts +25 -0
  55. package/src/lib/graph/server.ts +70 -0
  56. package/src/lib/graph/sessions.ts +104 -0
  57. package/src/lib/graph/tools.ts +90 -0
  58. package/src/lib/graph/treemap.ts +211 -0
  59. package/src/lib/graph/types.ts +80 -0
  60. package/src/lib/install/claude-settings.ts +64 -0
  61. package/src/lib/journal/editor.ts +33 -0
  62. package/src/lib/journal/fs.ts +13 -0
  63. package/src/lib/journal/index.ts +11 -0
  64. package/src/lib/journal/paths.ts +106 -0
  65. package/src/lib/journal/{utils.ts → templates.ts} +3 -151
  66. package/src/utils/fs.ts +19 -0
  67. package/src/utils/git/exec.ts +18 -0
  68. package/src/utils/git/gh-cli-wrapper.test.ts +47 -8
  69. package/src/utils/git/gh-cli-wrapper.ts +31 -19
  70. package/src/utils/render.ts +3 -1
  71. package/src/commands/graph.ts +0 -970
  72. package/src/lib/auto-claude/prompt-templates/01_research.prompt.md +0 -21
  73. package/src/lib/auto-claude/prompt-templates/02_plan.prompt.md +0 -27
  74. package/src/lib/auto-claude/prompt-templates/03_plan-annotations.prompt.md +0 -15
  75. package/src/lib/auto-claude/prompt-templates/04_plan-implementation.prompt.md +0 -35
  76. package/src/lib/auto-claude/prompt-templates/07_refresh.prompt.md +0 -30
  77. package/src/lib/auto-claude/steps/plan-annotations.ts +0 -54
  78. package/src/lib/auto-claude/steps/plan-implementation.ts +0 -14
  79. package/src/lib/auto-claude/steps/plan.ts +0 -14
  80. package/src/lib/auto-claude/steps/refresh.ts +0 -114
  81. package/src/lib/auto-claude/steps/remove-label.ts +0 -22
  82. package/src/lib/auto-claude/steps/research.ts +0 -21
  83. package/src/lib/auto-claude/steps/review.ts +0 -14
@@ -1,21 +0,0 @@
1
- You are a senior developer researching a codebase to prepare for implementing a GitHub issue.
2
-
3
- Read the issue in @{{ISSUE_DIR}}/initial-ramblings.md and **research the codebase** to understand what implementing it involves.
4
-
5
- **CRITICAL:** Do **NOT** implement. Your **ONLY** deliverable is @{{ISSUE_DIR}}/research.md.
6
-
7
- If the issue is vague or trivial — research it anyway. Note what's ambiguous and list assumptions.
8
-
9
- ## Where to look
10
-
11
- Start at `{{SCOPE_PATH}}/`. Follow imports, check test files, trace types and schemas. Read every relevant file in full. Do not skim.
12
-
13
- ## What to write in @{{ISSUE_DIR}}/research.md
14
-
15
- 1. **Relevant files** — every file to read or modify, with brief descriptions
16
- 2. **Existing patterns** — how similar features are implemented in this codebase
17
- 3. **Dependencies** — libraries, utilities, shared code that are relevant
18
- 4. **Potential impact areas** — what else might break (tests, types, imports, configs)
19
- 5. **Existing test coverage** — which test files cover affected modules, what gaps exist. Run the project's test command to confirm the suite passes.
20
- 6. **Edge cases and constraints** — anything tricky
21
- 7. **Reference implementations** — similar features already built
@@ -1,27 +0,0 @@
1
- You are a senior developer planning the implementation for a GitHub issue.
2
-
3
- Read the issue in @{{ISSUE_DIR}}/initial-ramblings.md and the research in @{{ISSUE_DIR}}/research.md.
4
-
5
- **CRITICAL:** Do **NOT** implement. Your **ONLY** deliverable is @{{ISSUE_DIR}}/plan.md.
6
-
7
- Read actual source files before suggesting changes. If the issue is infeasible, explain why and propose the closest feasible alternative.
8
-
9
- The code lives primarily at `{{SCOPE_PATH}}/`.
10
-
11
- ## Write @{{ISSUE_DIR}}/plan.md
12
-
13
- 1. **Summary** — what we're building and why (1-2 paragraphs)
14
- 2. **Approach** — the high-level technical approach
15
- 3. **Architectural decisions** — significant choices and why
16
- 4. **Key code snippets** — concrete examples (function signatures, schemas, etc.)
17
- 5. **Scope boundaries** — what is explicitly out of scope
18
- 6. **Risks** — anything that needs special attention
19
- 7. **Test strategy** — use red/green TDD: for each testable behavior, write the test first (red), then implement to make it pass (green). List which test files to write/update and what each test asserts. Reference specific test files from the research. Prefer real implementations over mocks — only mock at external boundaries (network, filesystem, third-party APIs). Do not write tests for things the type system or compiler already enforces.
20
- 8. **Alternative approaches** — other valid solutions, why the chosen approach was preferred. For PR reviewers only.
21
-
22
- **Design principles:**
23
-
24
- - If the plan touches an area with a known bug, address it now.
25
- - Reuse existing abstractions — don't create parallel primitives.
26
-
27
- Keep under 500 lines. Focus on decisions, not repeating the research.
@@ -1,15 +0,0 @@
1
- You are a senior developer revising a plan based on reviewer feedback.
2
-
3
- Read the plan in @{{ISSUE_DIR}}/plan.md and annotations in @{{ISSUE_DIR}}/plan-annotations.md. The issue is in @{{ISSUE_DIR}}/initial-ramblings.md and research in @{{ISSUE_DIR}}/research.md.
4
-
5
- **CRITICAL:** Do **NOT** implement. Deliverables: (1) updated @{{ISSUE_DIR}}/plan.md, (2) @{{ISSUE_DIR}}/plan-annotations-addressed.md.
6
-
7
- The code lives primarily at `{{SCOPE_PATH}}/`.
8
-
9
- ## Instructions
10
-
11
- - Address every annotation — update the plan to incorporate feedback.
12
- - Questions → answer in the plan. Suggested approaches → evaluate and update. Missing info → add it.
13
- - If annotations contradict each other, choose the approach that best fits codebase patterns and document why.
14
- - Keep the same structure and formatting.
15
- - Write @{{ISSUE_DIR}}/plan-annotations-addressed.md listing each annotation and how it was addressed (one line per annotation).
@@ -1,35 +0,0 @@
1
- You are breaking down a plan into a detailed, ordered implementation checklist.
2
-
3
- Read the issue in @{{ISSUE_DIR}}/initial-ramblings.md, the research in @{{ISSUE_DIR}}/research.md, and the plan in @{{ISSUE_DIR}}/plan.md.
4
-
5
- **CRITICAL:** Do **NOT** implement. Your **ONLY** deliverable is @{{ISSUE_DIR}}/plan-implementation.md.
6
-
7
- The code lives primarily at `{{SCOPE_PATH}}/`.
8
-
9
- ## Write @{{ISSUE_DIR}}/plan-implementation.md
10
-
11
- - **Ordered markdown checkboxes** (`- [ ]` per task), small enough to implement in one focused session
12
- - Prefer real implementations over mocks — only mock at external boundaries (network, filesystem, third-party APIs)
13
- - Do not write tests for things the type system or compiler already enforces
14
- - Each task must follow **red/green TDD** structure:
15
- - **Files** — specific file paths to modify
16
- - **Changes** — concrete description (not vague like "update the component")
17
- - **Red** — write this test first, assert this behavior, run tests and confirm it **fails**
18
- - **Green** — implement the change, run tests and confirm it **passes**
19
- - **Acceptance** — how to verify the task is done
20
- - Order tasks so each builds on the previous (no forward dependencies)
21
- - Include setup tasks (new files, dependencies) as needed
22
- - Final task: "Run the project's type-check, test, and lint commands. Confirm zero errors."
23
-
24
- Example:
25
-
26
- ```
27
- - [ ] **Task 1: Add config schema**
28
- - Files: `src/lib/feature/config.ts`, `src/lib/feature/config.test.ts`
29
- - Changes: Define config schema with validation, export inferred type
30
- - Red: Write test asserting schema validates correct input and rejects invalid input — confirm it fails
31
- - Green: Implement the schema — confirm test passes
32
- - Acceptance: All tests pass, schema correctly validates/rejects
33
- ```
34
-
35
- Be specific enough that a developer can follow without re-reading the research or plan.
@@ -1,30 +0,0 @@
1
- You are updating an existing auto-claude branch to be compatible with the latest {{MAIN_BRANCH}}.
2
-
3
- ## Context
4
-
5
- - Original issue: @{{ISSUE_DIR}}/initial-ramblings.md
6
- - Checklist: @{{ISSUE_DIR}}/plan-implementation.md
7
- - What was implemented: @{{ISSUE_DIR}}/completed-summary.md
8
-
9
- The code lives primarily at `{{SCOPE_PATH}}/`.
10
-
11
- ## Your task
12
-
13
- 1. `git diff {{MAIN_BRANCH}}...HEAD` — what this PR changes
14
- 2. `git log {{MAIN_BRANCH}}..HEAD --oneline` — PR's commit history
15
- 3. `git diff HEAD...{{MAIN_BRANCH}}` — what {{MAIN_BRANCH}} changed since divergence
16
- 4. Check: do imports resolve? Do types/APIs still match? Conflicts with {{MAIN_BRANCH}}?
17
- 5. Fix issues directly. For merge conflicts, preserve PR intent while adopting {{MAIN_BRANCH}}'s patterns. Commit: `fix(scope): adapt to {{MAIN_BRANCH}} changes`
18
- 6. Run the project's type-check, test, and lint commands. Fix any errors.
19
-
20
- **CRITICAL:**
21
-
22
- - Do NOT re-implement. Only fix what broke due to {{MAIN_BRANCH}} changes.
23
- - If {{MAIN_BRANCH}} changed so fundamentally the PR's approach is no longer viable, report `NEEDS-ATTENTION`. Do NOT force a fix.
24
- - Do NOT push to remote. Do NOT modify plan or research files.
25
-
26
- ## Write @{{ISSUE_DIR}}/refresh-summary.md
27
-
28
- - **Status**: UP-TO-DATE, ADAPTED, or NEEDS-ATTENTION
29
- - **Changes made** — what broke and how you fixed it
30
- - **Risk areas** — anything a reviewer should double-check
@@ -1,54 +0,0 @@
1
- import { renameSync } from "node:fs";
2
- import { join } from "node:path";
3
-
4
- import consola from "consola";
5
-
6
- import { getConfig } from "../config.js";
7
- import { ARTIFACTS, STEP_LABELS, TEMPLATES } from "../prompt-templates/index.js";
8
- import {
9
- buildTokens,
10
- commitArtifacts,
11
- fileExists,
12
- log,
13
- logStep,
14
- resolveTemplate,
15
- runClaude,
16
- } from "../utils.js";
17
- import type { IssueContext } from "../utils.js";
18
-
19
- export async function stepPlanAnnotations(ctx: IssueContext): Promise<boolean> {
20
- const annotationsPath = join(ctx.issueDir, ARTIFACTS.planAnnotations);
21
- const addressedPath = join(ctx.issueDir, ARTIFACTS.planAnnotationsAddressed);
22
-
23
- if (!fileExists(annotationsPath)) {
24
- return true;
25
- }
26
-
27
- if (fileExists(addressedPath)) {
28
- logStep(STEP_LABELS.planAnnotations, ctx, true);
29
- return true;
30
- }
31
-
32
- logStep(STEP_LABELS.planAnnotations, ctx);
33
- log("Found plan-annotations.md — addressing reviewer notes");
34
-
35
- const tokens = buildTokens(ctx);
36
- const promptFile = resolveTemplate(TEMPLATES.planAnnotations, tokens, ctx.issueDir);
37
-
38
- const result = await runClaude({
39
- promptFile,
40
- permissionMode: "acceptEdits",
41
- maxTurns: getConfig().maxTurns,
42
- });
43
-
44
- if (result.is_error) {
45
- consola.error(`Plan-Annotations step failed: ${result.result}`);
46
- return false;
47
- }
48
-
49
- renameSync(annotationsPath, addressedPath);
50
- log("Annotations addressed — renamed to plan-annotations-addressed.md");
51
-
52
- await commitArtifacts(ctx, `chore(auto-claude): plan annotations for ${ctx.repo}#${ctx.number}`);
53
- return true;
54
- }
@@ -1,14 +0,0 @@
1
- import { join } from "node:path";
2
-
3
- import { ARTIFACTS, STEP_LABELS, TEMPLATES } from "../prompt-templates/index.js";
4
- import { runStepWithArtifact } from "../utils.js";
5
- import type { IssueContext } from "../utils.js";
6
-
7
- export async function stepPlanImplementation(ctx: IssueContext): Promise<boolean> {
8
- return runStepWithArtifact({
9
- stepName: STEP_LABELS.planImplementation,
10
- ctx,
11
- artifactPath: join(ctx.issueDir, ARTIFACTS.planImplementation),
12
- templateName: TEMPLATES.planImplementation,
13
- });
14
- }
@@ -1,14 +0,0 @@
1
- import { join } from "node:path";
2
-
3
- import { ARTIFACTS, STEP_LABELS, TEMPLATES } from "../prompt-templates/index.js";
4
- import { runStepWithArtifact } from "../utils.js";
5
- import type { IssueContext } from "../utils.js";
6
-
7
- export async function stepPlan(ctx: IssueContext): Promise<boolean> {
8
- return runStepWithArtifact({
9
- stepName: STEP_LABELS.plan,
10
- ctx,
11
- artifactPath: join(ctx.issueDir, ARTIFACTS.plan),
12
- templateName: TEMPLATES.plan,
13
- });
14
- }
@@ -1,114 +0,0 @@
1
- import { rmSync } from "node:fs";
2
- import { join } from "node:path";
3
-
4
- import consola from "consola";
5
-
6
- import { getConfig } from "../config.js";
7
- import { ARTIFACTS, STEP_LABELS, TEMPLATES } from "../prompt-templates/index.js";
8
- import {
9
- buildTokens,
10
- commitArtifacts,
11
- execSafe,
12
- fileExists,
13
- git,
14
- log,
15
- logStep,
16
- resolveTemplate,
17
- runClaude,
18
- } from "../utils.js";
19
- import type { IssueContext } from "../utils.js";
20
-
21
- export async function stepRefresh(ctx: IssueContext): Promise<boolean> {
22
- logStep(STEP_LABELS.refresh, ctx);
23
- const { mainBranch, remote } = getConfig();
24
-
25
- const branchList = await git(["branch", "--list", ctx.branch]);
26
- if (!branchList.includes(ctx.branch.split("/").pop()!)) {
27
- try {
28
- await git(["fetch", remote, ctx.branch]);
29
- await git(["checkout", ctx.branch]);
30
- } catch {
31
- log(`Branch ${ctx.branch} does not exist locally or remotely.`);
32
- return false;
33
- }
34
- }
35
-
36
- await git(["checkout", mainBranch]);
37
- await git(["pull", remote, mainBranch]);
38
- await git(["checkout", ctx.branch]);
39
-
40
- if (await isBranchUpToDate(mainBranch)) {
41
- log(`Branch is already up-to-date with ${mainBranch}.`);
42
- } else {
43
- await rebaseOrMerge(mainBranch);
44
- }
45
-
46
- const tokens = buildTokens(ctx);
47
- const promptFile = resolveTemplate(TEMPLATES.refresh, tokens, ctx.issueDir);
48
- const result = await runClaude({
49
- promptFile,
50
- permissionMode: "acceptEdits",
51
- maxTurns: getConfig().maxTurns,
52
- });
53
-
54
- if (result.is_error) {
55
- consola.error(`Refresh step failed: ${result.result}`);
56
- await git(["checkout", mainBranch]).catch(() => {});
57
- return false;
58
- }
59
-
60
- await commitArtifacts(ctx, `chore(auto-claude): refresh for ${ctx.repo}#${ctx.number}`);
61
- await invalidateStaleArtifacts(ctx);
62
-
63
- await git(["push", "--force-with-lease", "-u", remote, ctx.branch]);
64
- await git(["checkout", mainBranch]).catch(() => {});
65
-
66
- return true;
67
- }
68
-
69
- async function isBranchUpToDate(mainBranch: string): Promise<boolean> {
70
- try {
71
- await git(["merge-base", "--is-ancestor", mainBranch, "HEAD"]);
72
- return true;
73
- } catch {
74
- return false;
75
- }
76
- }
77
-
78
- async function rebaseOrMerge(mainBranch: string): Promise<void> {
79
- try {
80
- await git(["rebase", mainBranch]);
81
- } catch {
82
- await git(["rebase", "--abort"]).catch(() => {});
83
- try {
84
- await git(["merge", mainBranch, "--no-edit"]);
85
- } catch {
86
- const conflicts = await execSafe("git", ["diff", "--name-only", "--diff-filter=U"]);
87
- if (conflicts.stdout.length > 0) {
88
- await git(["merge", "--abort"]);
89
- throw new Error(`Merge conflicts detected in: ${conflicts.stdout}`);
90
- }
91
- await git(["add", "."]);
92
- await git(["commit", "--no-edit"]);
93
- }
94
- }
95
- }
96
-
97
- async function invalidateStaleArtifacts(ctx: IssueContext): Promise<void> {
98
- const paths = [
99
- join(ctx.issueDir, ARTIFACTS.review),
100
- join(ctx.issueDir, ARTIFACTS.completedSummary),
101
- ];
102
-
103
- const removed = paths.filter((p) => {
104
- if (fileExists(p)) {
105
- rmSync(p);
106
- return true;
107
- }
108
- return false;
109
- });
110
-
111
- if (removed.length > 0) {
112
- await commitArtifacts(ctx, "chore(auto-claude): invalidate stale artifacts after refresh");
113
- }
114
- }
@@ -1,22 +0,0 @@
1
- import { getConfig } from "../config.js";
2
- import { STEP_LABELS } from "../prompt-templates/index.js";
3
- import { ghRaw, log, logStep } from "../utils.js";
4
- import type { IssueContext } from "../utils.js";
5
-
6
- export async function stepRemoveLabel(ctx: IssueContext): Promise<boolean> {
7
- logStep(STEP_LABELS.removeLabel, ctx);
8
-
9
- const cfg = getConfig();
10
- await ghRaw([
11
- "issue",
12
- "edit",
13
- String(ctx.number),
14
- "--repo",
15
- ctx.repo,
16
- "--remove-label",
17
- cfg.triggerLabel,
18
- ]);
19
-
20
- log(`Removed "${cfg.triggerLabel}" label from ${ctx.repo}#${ctx.number}`);
21
- return true;
22
- }
@@ -1,21 +0,0 @@
1
- import { join } from "node:path";
2
-
3
- import { ARTIFACTS, STEP_LABELS, TEMPLATES } from "../prompt-templates/index.js";
4
- import { ensureBranch, fileExists, readFile, runStepWithArtifact } from "../utils.js";
5
- import type { IssueContext } from "../utils.js";
6
-
7
- function isValidResearch(path: string): boolean {
8
- return fileExists(path) && readFile(path).length > 200;
9
- }
10
-
11
- export async function stepResearch(ctx: IssueContext): Promise<boolean> {
12
- await ensureBranch(ctx.branch);
13
-
14
- return runStepWithArtifact({
15
- stepName: STEP_LABELS.research,
16
- ctx,
17
- artifactPath: join(ctx.issueDir, ARTIFACTS.research),
18
- templateName: TEMPLATES.research,
19
- artifactValidator: isValidResearch,
20
- });
21
- }
@@ -1,14 +0,0 @@
1
- import { join } from "node:path";
2
-
3
- import { ARTIFACTS, STEP_LABELS, TEMPLATES } from "../prompt-templates/index.js";
4
- import { runStepWithArtifact } from "../utils.js";
5
- import type { IssueContext } from "../utils.js";
6
-
7
- export async function stepReview(ctx: IssueContext): Promise<boolean> {
8
- return runStepWithArtifact({
9
- stepName: STEP_LABELS.review,
10
- ctx,
11
- artifactPath: join(ctx.issueDir, ARTIFACTS.review),
12
- templateName: TEMPLATES.review,
13
- });
14
- }