hone-ai 0.5.0 → 0.10.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.
@@ -1,41 +1,41 @@
1
- import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
- import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs';
3
- import { join } from 'path';
4
- import { constructPrompt, type PromptPhase } from './prompt';
5
- import type { HoneConfig } from './config';
1
+ import { describe, expect, test, beforeEach, afterEach } from 'bun:test'
2
+ import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs'
3
+ import { join } from 'path'
4
+ import { constructPrompt, type PromptPhase } from './prompt'
5
+ import type { HoneConfig } from './config'
6
6
 
7
- const TEST_WORKSPACE = join(process.cwd(), '.test-prompt-workspace');
8
- const TEST_PLANS_DIR = join(TEST_WORKSPACE, '.plans');
7
+ const TEST_WORKSPACE = join(process.cwd(), '.test-prompt-workspace')
8
+ const TEST_PLANS_DIR = join(TEST_WORKSPACE, '.plans')
9
9
 
10
10
  beforeEach(() => {
11
11
  // Create isolated test workspace
12
12
  if (existsSync(TEST_WORKSPACE)) {
13
- rmSync(TEST_WORKSPACE, { recursive: true, force: true });
13
+ rmSync(TEST_WORKSPACE, { recursive: true, force: true })
14
14
  }
15
- mkdirSync(TEST_PLANS_DIR, { recursive: true });
16
-
15
+ mkdirSync(TEST_PLANS_DIR, { recursive: true })
16
+
17
17
  // Change to test workspace
18
- process.chdir(TEST_WORKSPACE);
19
- });
18
+ process.chdir(TEST_WORKSPACE)
19
+ })
20
20
 
21
21
  afterEach(() => {
22
22
  // Clean up and return to original directory
23
- const originalDir = join(TEST_WORKSPACE, '..');
24
- process.chdir(originalDir);
23
+ const originalDir = join(TEST_WORKSPACE, '..')
24
+ process.chdir(originalDir)
25
25
  if (existsSync(TEST_WORKSPACE)) {
26
- rmSync(TEST_WORKSPACE, { recursive: true, force: true });
26
+ rmSync(TEST_WORKSPACE, { recursive: true, force: true })
27
27
  }
28
- });
28
+ })
29
29
 
30
30
  const mockConfig: HoneConfig = {
31
31
  defaultAgent: 'claude',
32
32
  models: {
33
33
  opencode: 'claude-sonnet-4-20250514',
34
- claude: 'claude-sonnet-4-20250514'
34
+ claude: 'claude-sonnet-4-20250514',
35
35
  },
36
36
  feedbackInstructions: 'test: bun test',
37
- lintCommand: 'bun run lint'
38
- };
37
+ lintCommand: 'bun run lint',
38
+ }
39
39
 
40
40
  describe('constructPrompt', () => {
41
41
  test('includes phase header', () => {
@@ -43,239 +43,238 @@ describe('constructPrompt', () => {
43
43
  writeFileSync(
44
44
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
45
45
  'tasks:\n - id: task-001\n status: pending\n'
46
- );
47
-
46
+ )
47
+
48
48
  const prompt = constructPrompt({
49
49
  phase: 'implement',
50
50
  featureName: 'test',
51
- config: mockConfig
52
- });
53
-
54
- expect(prompt).toContain('# HONE: IMPLEMENT PHASE');
55
- });
56
-
51
+ config: mockConfig,
52
+ })
53
+
54
+ expect(prompt).toContain('# HONE: IMPLEMENT PHASE')
55
+ })
56
+
57
57
  test('includes AGENTS.md reference if exists', () => {
58
- writeFileSync(join(TEST_WORKSPACE, 'AGENTS.md'), '# Learning 1\nSome pattern');
58
+ writeFileSync(join(TEST_WORKSPACE, 'AGENTS.md'), '# Learning 1\nSome pattern')
59
59
  writeFileSync(
60
60
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
61
61
  'tasks:\n - id: task-001\n status: pending\n'
62
- );
63
-
62
+ )
63
+
64
64
  const prompt = constructPrompt({
65
65
  phase: 'implement',
66
66
  featureName: 'test',
67
- config: mockConfig
68
- });
69
-
70
- expect(prompt).toContain('# CONTEXT FILES');
71
- expect(prompt).toContain('@AGENTS.md');
72
- });
73
-
67
+ config: mockConfig,
68
+ })
69
+
70
+ expect(prompt).toContain('# CONTEXT FILES')
71
+ expect(prompt).toContain('@AGENTS.md')
72
+ })
73
+
74
74
  test('includes task file reference', () => {
75
75
  writeFileSync(
76
76
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
77
77
  'tasks:\n - id: task-001\n title: Test Task\n status: pending\n'
78
- );
79
-
78
+ )
79
+
80
80
  const prompt = constructPrompt({
81
81
  phase: 'implement',
82
82
  featureName: 'test',
83
- config: mockConfig
84
- });
85
-
86
- expect(prompt).toContain('# CONTEXT FILES');
87
- expect(prompt).toContain('@.plans/tasks-test.yml');
88
- });
89
-
83
+ config: mockConfig,
84
+ })
85
+
86
+ expect(prompt).toContain('# CONTEXT FILES')
87
+ expect(prompt).toContain('@.plans/tasks-test.yml')
88
+ })
89
+
90
90
  test('includes progress file reference if exists', () => {
91
91
  writeFileSync(
92
92
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
93
93
  'tasks:\n - id: task-001\n status: pending\n'
94
- );
95
- writeFileSync(
96
- join(TEST_PLANS_DIR, 'progress-test.txt'),
97
- 'Previous iteration completed'
98
- );
99
-
94
+ )
95
+ writeFileSync(join(TEST_PLANS_DIR, 'progress-test.txt'), 'Previous iteration completed')
96
+
100
97
  const prompt = constructPrompt({
101
98
  phase: 'implement',
102
99
  featureName: 'test',
103
- config: mockConfig
104
- });
105
-
106
- expect(prompt).toContain('# CONTEXT FILES');
107
- expect(prompt).toContain('@.plans/progress-test.txt');
108
- });
109
-
100
+ config: mockConfig,
101
+ })
102
+
103
+ expect(prompt).toContain('# CONTEXT FILES')
104
+ expect(prompt).toContain('@.plans/progress-test.txt')
105
+ })
106
+
110
107
  test('implement phase includes task selection instructions', () => {
111
108
  writeFileSync(
112
109
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
113
110
  'tasks:\n - id: task-001\n status: pending\n'
114
- );
115
-
111
+ )
112
+
116
113
  const prompt = constructPrompt({
117
114
  phase: 'implement',
118
115
  featureName: 'test',
119
- config: mockConfig
120
- });
121
-
122
- expect(prompt).toContain('# TASK SELECTION');
123
- expect(prompt).toContain('bun test');
124
- });
125
-
116
+ config: mockConfig,
117
+ })
118
+
119
+ expect(prompt).toContain('# TASK SELECTION')
120
+ expect(prompt).toContain('bun test')
121
+ })
122
+
126
123
  test('implement phase includes lint command if configured', () => {
127
124
  writeFileSync(
128
125
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
129
126
  'tasks:\n - id: task-001\n status: pending\n'
130
- );
131
-
127
+ )
128
+
132
129
  const prompt = constructPrompt({
133
130
  phase: 'implement',
134
131
  featureName: 'test',
135
- config: mockConfig
136
- });
137
-
138
- expect(prompt).toContain('bun run lint');
139
- });
140
-
132
+ config: mockConfig,
133
+ })
134
+
135
+ expect(prompt).toContain('bun run lint')
136
+ })
137
+
141
138
  test('review phase includes review checklist', () => {
142
139
  writeFileSync(
143
140
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
144
141
  'tasks:\n - id: task-001\n status: pending\n'
145
- );
146
-
142
+ )
143
+
147
144
  const prompt = constructPrompt({
148
145
  phase: 'review',
149
146
  featureName: 'test',
150
147
  config: mockConfig,
151
- taskId: 'task-001'
152
- });
153
-
154
- expect(prompt).toContain('# HONE: REVIEW PHASE');
155
- expect(prompt).toContain('# REVIEW CHECKLIST');
156
- expect(prompt).toContain('Correctness');
157
- expect(prompt).toContain('task-001');
158
- });
159
-
148
+ taskId: 'task-001',
149
+ })
150
+
151
+ expect(prompt).toContain('# HONE: REVIEW PHASE')
152
+ expect(prompt).toContain('# REVIEW CHECKLIST')
153
+ expect(prompt).toContain('Correctness')
154
+ expect(prompt).toContain('task-001')
155
+ })
156
+
160
157
  test('finalize phase includes review feedback', () => {
161
158
  writeFileSync(
162
159
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
163
160
  'tasks:\n - id: task-001\n status: pending\n'
164
- );
165
-
166
- const feedback = '**Issue**: Missing error handling\n**Suggestion**: Add try-catch';
161
+ )
162
+
163
+ const feedback = '**Issue**: Missing error handling\n**Suggestion**: Add try-catch'
167
164
  const prompt = constructPrompt({
168
165
  phase: 'finalize',
169
166
  featureName: 'test',
170
167
  config: mockConfig,
171
168
  taskId: 'task-001',
172
- reviewFeedback: feedback
173
- });
174
-
175
- expect(prompt).toContain('# HONE: FINALIZE PHASE');
176
- expect(prompt).toContain('# REVIEW FEEDBACK');
177
- expect(prompt).toContain('Missing error handling');
178
- });
179
-
169
+ reviewFeedback: feedback,
170
+ })
171
+
172
+ expect(prompt).toContain('# HONE: FINALIZE PHASE')
173
+ expect(prompt).toContain('# REVIEW FEEDBACK')
174
+ expect(prompt).toContain('Missing error handling')
175
+ })
176
+
180
177
  test('finalize phase without review feedback shows default message', () => {
181
178
  writeFileSync(
182
179
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
183
180
  'tasks:\n - id: task-001\n status: pending\n'
184
- );
185
-
181
+ )
182
+
186
183
  const prompt = constructPrompt({
187
184
  phase: 'finalize',
188
185
  featureName: 'test',
189
186
  config: mockConfig,
190
- taskId: 'task-001'
191
- });
192
-
193
- expect(prompt).toContain('No review feedback provided');
194
- });
195
-
187
+ taskId: 'task-001',
188
+ })
189
+
190
+ expect(prompt).toContain('No review feedback provided')
191
+ })
192
+
196
193
  test('handles missing AGENTS.md gracefully', () => {
197
194
  writeFileSync(
198
195
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
199
196
  'tasks:\n - id: task-001\n status: pending\n'
200
- );
201
-
197
+ )
198
+
202
199
  const prompt = constructPrompt({
203
200
  phase: 'implement',
204
201
  featureName: 'test',
205
- config: mockConfig
206
- });
207
-
208
- expect(prompt).not.toContain('@AGENTS.md');
209
- expect(prompt).toContain('# TASK SELECTION');
210
- });
211
-
202
+ config: mockConfig,
203
+ })
204
+
205
+ expect(prompt).not.toContain('@AGENTS.md')
206
+ expect(prompt).toContain('# TASK SELECTION')
207
+ })
208
+
212
209
  test('handles missing progress file gracefully', () => {
213
210
  writeFileSync(
214
211
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
215
212
  'tasks:\n - id: task-001\n status: pending\n'
216
- );
217
-
213
+ )
214
+
218
215
  const prompt = constructPrompt({
219
216
  phase: 'implement',
220
217
  featureName: 'test',
221
- config: mockConfig
222
- });
223
-
224
- expect(prompt).not.toContain('progress-test.txt');
225
- expect(prompt).toContain('# TASK SELECTION');
226
- });
227
-
218
+ config: mockConfig,
219
+ })
220
+
221
+ expect(prompt).not.toContain('progress-test.txt')
222
+ expect(prompt).toContain('# TASK SELECTION')
223
+ })
224
+
228
225
  test('uses default feedback instructions if not configured', () => {
229
226
  writeFileSync(
230
227
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
231
228
  'tasks:\n - id: task-001\n status: pending\n'
232
- );
233
-
229
+ )
230
+
234
231
  const configWithoutFeedback: HoneConfig = {
235
232
  ...mockConfig,
236
- feedbackInstructions: undefined
237
- };
238
-
233
+ feedbackInstructions: undefined,
234
+ }
235
+
239
236
  const prompt = constructPrompt({
240
237
  phase: 'implement',
241
238
  featureName: 'test',
242
- config: configWithoutFeedback
243
- });
244
-
245
- expect(prompt).toContain('test: bun test');
246
- });
247
-
239
+ config: configWithoutFeedback,
240
+ })
241
+
242
+ expect(prompt).toContain('test: bun test')
243
+ })
244
+
248
245
  test('implement phase includes failure handling instructions', () => {
249
246
  writeFileSync(
250
247
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
251
248
  'tasks:\n - id: task-001\n status: pending\n'
252
- );
253
-
249
+ )
250
+
254
251
  const prompt = constructPrompt({
255
252
  phase: 'implement',
256
253
  featureName: 'test',
257
- config: mockConfig
258
- });
259
-
260
- expect(prompt).toContain('If tests fail or there are errors you cannot fix');
261
- expect(prompt).toContain('DO NOT output TASK_COMPLETED');
262
- expect(prompt).toContain('task will remain pending');
263
- expect(prompt).toContain('Only output this marker if the task is fully complete');
264
- });
265
-
254
+ config: mockConfig,
255
+ })
256
+
257
+ expect(prompt).toContain('If tests fail or there are errors you cannot fix')
258
+ expect(prompt).toContain('DO NOT output TASK_COMPLETED')
259
+ expect(prompt).toContain('task will remain pending')
260
+ expect(prompt).toContain('Only output this marker if the task is fully complete')
261
+ })
262
+
266
263
  test('implement phase enforces task file isolation', () => {
267
264
  writeFileSync(
268
265
  join(TEST_PLANS_DIR, 'tasks-test.yml'),
269
266
  'tasks:\n - id: task-001\n status: pending\n'
270
- );
271
-
267
+ )
268
+
272
269
  const prompt = constructPrompt({
273
270
  phase: 'implement',
274
271
  featureName: 'test',
275
- config: mockConfig
276
- });
277
-
278
- expect(prompt).toContain('CRITICAL: You MUST only choose tasks from the task file referenced in CONTEXT FILES');
279
- expect(prompt).toContain('Do NOT select tasks from any other task file');
280
- });
281
- });
272
+ config: mockConfig,
273
+ })
274
+
275
+ expect(prompt).toContain(
276
+ 'CRITICAL: You MUST only choose tasks from the task file referenced in CONTEXT FILES'
277
+ )
278
+ expect(prompt).toContain('Do NOT select tasks from any other task file')
279
+ })
280
+ })
package/src/prompt.ts CHANGED
@@ -1,15 +1,15 @@
1
- import { existsSync } from 'fs';
2
- import { join, relative } from 'path';
3
- import { getPlansDir, type HoneConfig } from './config';
1
+ import { existsSync } from 'fs'
2
+ import { join, relative } from 'path'
3
+ import { getPlansDir, type HoneConfig } from './config'
4
4
 
5
- export type PromptPhase = 'implement' | 'review' | 'finalize';
5
+ export type PromptPhase = 'implement' | 'review' | 'finalize'
6
6
 
7
7
  export interface PromptOptions {
8
- phase: PromptPhase;
9
- featureName: string;
10
- config: HoneConfig;
11
- taskId?: string;
12
- reviewFeedback?: string;
8
+ phase: PromptPhase
9
+ featureName: string
10
+ config: HoneConfig
11
+ taskId?: string
12
+ reviewFeedback?: string
13
13
  }
14
14
 
15
15
  /**
@@ -17,49 +17,49 @@ export interface PromptOptions {
17
17
  * References files using @<path> syntax instead of embedding content.
18
18
  */
19
19
  export function constructPrompt(options: PromptOptions): string {
20
- const { phase, featureName, config, taskId, reviewFeedback } = options;
21
-
22
- const parts: string[] = [];
23
-
20
+ const { phase, featureName, config, taskId, reviewFeedback } = options
21
+
22
+ const parts: string[] = []
23
+
24
24
  // Build list of file references (relative to project root)
25
- const fileRefs: string[] = [];
26
- const cwd = process.cwd();
27
-
25
+ const fileRefs: string[] = []
26
+ const cwd = process.cwd()
27
+
28
28
  // Add task file reference (required)
29
- const taskPath = join(getPlansDir(), `tasks-${featureName}.yml`);
29
+ const taskPath = join(getPlansDir(), `tasks-${featureName}.yml`)
30
30
  if (existsSync(taskPath)) {
31
- const relPath = relative(cwd, taskPath);
32
- fileRefs.push(`@${relPath}`);
31
+ const relPath = relative(cwd, taskPath)
32
+ fileRefs.push(`@${relPath}`)
33
33
  }
34
-
34
+
35
35
  // Add progress file reference if exists
36
- const progressPath = join(getPlansDir(), `progress-${featureName}.txt`);
36
+ const progressPath = join(getPlansDir(), `progress-${featureName}.txt`)
37
37
  if (existsSync(progressPath)) {
38
- const relPath = relative(cwd, progressPath);
39
- fileRefs.push(`@${relPath}`);
38
+ const relPath = relative(cwd, progressPath)
39
+ fileRefs.push(`@${relPath}`)
40
40
  }
41
-
41
+
42
42
  // Add AGENTS.md reference if exists
43
- const agentsPath = join(cwd, 'AGENTS.md');
43
+ const agentsPath = join(cwd, 'AGENTS.md')
44
44
  if (existsSync(agentsPath)) {
45
- fileRefs.push(`@AGENTS.md`);
45
+ fileRefs.push(`@AGENTS.md`)
46
46
  }
47
-
47
+
48
48
  // Add phase-specific header with file references
49
- parts.push(getPhaseHeader(phase));
50
- parts.push('');
51
-
49
+ parts.push(getPhaseHeader(phase))
50
+ parts.push('')
51
+
52
52
  if (fileRefs.length > 0) {
53
- parts.push('# CONTEXT FILES');
54
- parts.push('');
55
- parts.push(fileRefs.join(' '));
56
- parts.push('');
53
+ parts.push('# CONTEXT FILES')
54
+ parts.push('')
55
+ parts.push(fileRefs.join(' '))
56
+ parts.push('')
57
57
  }
58
-
58
+
59
59
  // Add phase-specific instructions
60
- parts.push(getPhaseInstructions(phase, config, taskId, reviewFeedback));
61
-
62
- return parts.join('\n');
60
+ parts.push(getPhaseInstructions(phase, config, taskId, reviewFeedback))
61
+
62
+ return parts.join('\n')
63
63
  }
64
64
 
65
65
  /**
@@ -68,11 +68,11 @@ export function constructPrompt(options: PromptOptions): string {
68
68
  function getPhaseHeader(phase: PromptPhase): string {
69
69
  switch (phase) {
70
70
  case 'implement':
71
- return '# HONE: IMPLEMENT PHASE';
71
+ return '# HONE: IMPLEMENT PHASE'
72
72
  case 'review':
73
- return '# HONE: REVIEW PHASE';
73
+ return '# HONE: REVIEW PHASE'
74
74
  case 'finalize':
75
- return '# HONE: FINALIZE PHASE';
75
+ return '# HONE: FINALIZE PHASE'
76
76
  }
77
77
  }
78
78
 
@@ -85,16 +85,16 @@ function getPhaseInstructions(
85
85
  taskId?: string,
86
86
  reviewFeedback?: string
87
87
  ): string {
88
- const feedbackInstructions = config.feedbackInstructions || 'test: bun test';
89
- const lintCommand = config.lintCommand;
90
-
88
+ const feedbackInstructions = config.feedbackInstructions || 'test: bun test'
89
+ const lintCommand = config.lintCommand
90
+
91
91
  switch (phase) {
92
92
  case 'implement':
93
- return getImplementInstructions(feedbackInstructions, lintCommand);
93
+ return getImplementInstructions(feedbackInstructions, lintCommand)
94
94
  case 'review':
95
- return getReviewInstructions(taskId);
95
+ return getReviewInstructions(taskId)
96
96
  case 'finalize':
97
- return getFinalizeInstructions(feedbackInstructions, lintCommand, reviewFeedback);
97
+ return getFinalizeInstructions(feedbackInstructions, lintCommand, reviewFeedback)
98
98
  }
99
99
  }
100
100
 
@@ -137,12 +137,12 @@ Only run feedback loops AFTER you have fully completed implementing the task.
137
137
 
138
138
  Run feedback loops ONLY when the task implementation is complete:
139
139
 
140
- ${feedbackInstructions}`;
140
+ ${feedbackInstructions}`
141
141
 
142
142
  if (lintCommand) {
143
- instructions += `\n${lintCommand}`;
143
+ instructions += `\n${lintCommand}`
144
144
  }
145
-
145
+
146
146
  instructions += `
147
147
 
148
148
  If CLI or script, run them and verify output.
@@ -161,9 +161,9 @@ At the end, output on a single line:
161
161
  TASK_COMPLETED: <task-id>
162
162
 
163
163
  This allows hone to track which task you completed.
164
- Only output this marker if the task is fully complete and all feedback loops pass.`;
164
+ Only output this marker if the task is fully complete and all feedback loops pass.`
165
165
 
166
- return instructions;
166
+ return instructions
167
167
  }
168
168
 
169
169
  /**
@@ -198,7 +198,7 @@ Provide specific, actionable feedback. If everything looks good, say "LGTM" (Loo
198
198
  Structure your feedback as:
199
199
  - **Issue**: Description of the problem
200
200
  - **Suggestion**: How to fix it
201
- - **Priority**: critical | high | medium | low`;
201
+ - **Priority**: critical | high | medium | low`
202
202
  }
203
203
 
204
204
  /**
@@ -213,7 +213,7 @@ function getFinalizeInstructions(
213
213
 
214
214
  Finalize the task by applying review feedback and updating all tracking files.
215
215
 
216
- IMPORTANT: This is the ONLY phase where git commits are allowed. If you already committed in
216
+ IMPORTANT: This is the ONLY phase where git commits are allowed. If you already committed in
217
217
  the implement phase, you did it wrong - but continue with finalization anyway.
218
218
 
219
219
  # REVIEW FEEDBACK
@@ -227,10 +227,10 @@ ${reviewFeedback || 'No review feedback provided (review was skipped or approved
227
227
 
228
228
  2. **Run Final Feedback Loops** (if needed)
229
229
  - If you applied feedback or made any changes:
230
- ${feedbackInstructions}`;
230
+ ${feedbackInstructions}`
231
231
 
232
232
  if (lintCommand) {
233
- instructions += `\n ${lintCommand}`;
233
+ instructions += `\n ${lintCommand}`
234
234
  }
235
235
 
236
236
  instructions += `
@@ -247,23 +247,23 @@ ${reviewFeedback || 'No review feedback provided (review was skipped or approved
247
247
  TASK-XXX: <task-title>
248
248
  Date: <ISO-8601-datetime>
249
249
  ================================================================================
250
-
250
+
251
251
  Summary:
252
252
  <concise summary of what was done>
253
-
253
+
254
254
  Files Changed:
255
255
  - file1.ts (created/modified/deleted with brief description)
256
256
  - file2.ts (...)
257
-
257
+
258
258
  Key Decisions:
259
259
  - Decision 1
260
260
  - Decision 2
261
-
261
+
262
262
  Next Task: <next-task-id> or "All tasks complete"
263
263
  \`\`\`
264
264
 
265
265
  5. **Update AGENTS.md** (if learnings exist)
266
- - Add useful learnings and patterns under appropriate heading
266
+ - Add useful learnings and gotchas under appropriate heading
267
267
  - Be terse - only add truly useful info that future agents need
268
268
  - Don't duplicate existing info
269
269
 
@@ -287,9 +287,7 @@ If you cannot commit (e.g., no changes to commit), that indicates a problem - in
287
287
  At the end, output on a single line:
288
288
  FINALIZED: <task-id>
289
289
 
290
- Only output this marker AFTER you have successfully created the git commit.`;
290
+ Only output this marker AFTER you have successfully created the git commit.`
291
291
 
292
- return instructions;
292
+ return instructions
293
293
  }
294
-
295
-