@markjaquith/agency 0.7.3 → 0.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "Manages personal agents files",
5
5
  "license": "MIT",
6
6
  "author": "Mark Jaquith",
@@ -8,7 +8,10 @@ import {
8
8
  initAgency,
9
9
  readFile,
10
10
  runTestEffect,
11
+ createFile,
12
+ runGitCommand,
11
13
  } from "../test-utils"
14
+ import { chmod } from "fs/promises"
12
15
 
13
16
  describe("edit command", () => {
14
17
  let tempDir: string
@@ -138,4 +141,95 @@ describe("edit command", () => {
138
141
  "Editor exited with code",
139
142
  )
140
143
  })
144
+
145
+ test("commits TASK.md with 'chore: agency edit' when file is modified", async () => {
146
+ await initGitRepo(tempDir)
147
+ process.chdir(tempDir)
148
+
149
+ // Initialize to create TASK.md
150
+ await initAgency(tempDir, "test-task")
151
+ await runTestEffect(task({ silent: true, emit: "test-feature" }))
152
+
153
+ // Get initial commit count
154
+ const result = Bun.spawnSync({
155
+ cmd: ["git", "rev-list", "--count", "HEAD"],
156
+ cwd: tempDir,
157
+ stdout: "pipe",
158
+ })
159
+ const initialCommits = new TextDecoder().decode(result.stdout).trim()
160
+
161
+ // Use a script that modifies TASK.md
162
+ const scriptPath = join(tempDir, "edit-script.sh")
163
+ await createFile(
164
+ tempDir,
165
+ "edit-script.sh",
166
+ '#!/bin/bash\necho "Updated task" >> "$1"\n',
167
+ )
168
+ await chmod(scriptPath, 0o755)
169
+ process.env.EDITOR = scriptPath
170
+
171
+ // Run edit command
172
+ await runTestEffect(taskEdit({ silent: true }))
173
+
174
+ // Check that a new commit was created
175
+ const finalResult = Bun.spawnSync({
176
+ cmd: ["git", "rev-list", "--count", "HEAD"],
177
+ cwd: tempDir,
178
+ stdout: "pipe",
179
+ })
180
+ const finalCommits = new TextDecoder().decode(finalResult.stdout).trim()
181
+ expect(Number.parseInt(finalCommits)).toBe(
182
+ Number.parseInt(initialCommits) + 1,
183
+ )
184
+
185
+ // Check the commit message
186
+ const msgResult = Bun.spawnSync({
187
+ cmd: ["git", "log", "-1", "--format=%s"],
188
+ cwd: tempDir,
189
+ stdout: "pipe",
190
+ })
191
+ const commitMessage = new TextDecoder().decode(msgResult.stdout).trim()
192
+ expect(commitMessage).toBe("chore: agency edit")
193
+
194
+ // Check that only TASK.md was committed
195
+ const filesResult = Bun.spawnSync({
196
+ cmd: ["git", "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD"],
197
+ cwd: tempDir,
198
+ stdout: "pipe",
199
+ })
200
+ const filesInCommit = new TextDecoder().decode(filesResult.stdout).trim()
201
+ expect(filesInCommit).toBe("TASK.md")
202
+ })
203
+
204
+ test("does not commit when TASK.md is not modified", async () => {
205
+ await initGitRepo(tempDir)
206
+ process.chdir(tempDir)
207
+
208
+ // Initialize to create TASK.md
209
+ await initAgency(tempDir, "test-task")
210
+ await runTestEffect(task({ silent: true, emit: "test-feature" }))
211
+
212
+ // Get initial commit count
213
+ const result = Bun.spawnSync({
214
+ cmd: ["git", "rev-list", "--count", "HEAD"],
215
+ cwd: tempDir,
216
+ stdout: "pipe",
217
+ })
218
+ const initialCommits = new TextDecoder().decode(result.stdout).trim()
219
+
220
+ // Use a mock editor that doesn't modify the file
221
+ process.env.EDITOR = "true"
222
+
223
+ // Run edit command
224
+ await runTestEffect(taskEdit({ silent: true }))
225
+
226
+ // Check that no new commit was created
227
+ const finalResult = Bun.spawnSync({
228
+ cmd: ["git", "rev-list", "--count", "HEAD"],
229
+ cwd: tempDir,
230
+ stdout: "pipe",
231
+ })
232
+ const finalCommits = new TextDecoder().decode(finalResult.stdout).trim()
233
+ expect(Number.parseInt(finalCommits)).toBe(Number.parseInt(initialCommits))
234
+ })
141
235
  })
@@ -910,6 +910,7 @@ const taskEditEffect = (options: TaskEditOptions = {}) =>
910
910
  const { log, verboseLog } = createLoggers(options)
911
911
 
912
912
  const fs = yield* FileSystemService
913
+ const git = yield* GitService
913
914
 
914
915
  const gitRoot = yield* ensureGitRepo()
915
916
 
@@ -943,6 +944,26 @@ const taskEditEffect = (options: TaskEditOptions = {}) =>
943
944
  }
944
945
 
945
946
  log(done("TASK.md edited"))
947
+
948
+ // Check if TASK.md has uncommitted changes
949
+ const hasChanges = yield* git.hasUncommittedChanges(gitRoot, "TASK.md")
950
+ verboseLog(`TASK.md has uncommitted changes: ${hasChanges}`)
951
+
952
+ if (hasChanges) {
953
+ // Commit the changes
954
+ yield* Effect.gen(function* () {
955
+ yield* git.gitAdd(["TASK.md"], gitRoot)
956
+ yield* git.gitCommit("chore: agency edit", gitRoot, {
957
+ noVerify: true,
958
+ })
959
+ log(done("Committed TASK.md changes"))
960
+ }).pipe(
961
+ Effect.catchAll((err) => {
962
+ verboseLog(`Failed to commit TASK.md: ${err}`)
963
+ return Effect.void
964
+ }),
965
+ )
966
+ }
946
967
  })
947
968
 
948
969
  export const editHelp = `
@@ -850,5 +850,21 @@ export class GitService extends Effect.Service<GitService>()("GitService", {
850
850
  Effect.map((result) => (result.exitCode === 0 ? result.stdout : null)),
851
851
  Effect.catchAll(() => Effect.succeed(null)),
852
852
  ),
853
+
854
+ /**
855
+ * Check if a file has uncommitted changes (staged or unstaged).
856
+ * Uses `git diff HEAD` to check for any changes to the file.
857
+ * @param gitRoot - The git repository root
858
+ * @param filePath - Path to the file relative to git root
859
+ * @returns true if the file has changes, false otherwise
860
+ */
861
+ hasUncommittedChanges: (gitRoot: string, filePath: string) =>
862
+ pipe(
863
+ runGitCommand(["git", "diff", "HEAD", "--", filePath], gitRoot),
864
+ Effect.map(
865
+ (result) => result.exitCode === 0 && result.stdout.length > 0,
866
+ ),
867
+ Effect.catchAll(() => Effect.succeed(false)),
868
+ ),
853
869
  }),
854
870
  }) {}