@markjaquith/agency 0.6.1 → 0.7.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 +2 -2
- package/src/commands/push.ts +25 -7
- package/src/commands/task-main.test.ts +43 -0
- package/src/commands/task.ts +46 -6
- package/templates/opencode.json +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markjaquith/agency",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Manages personal agents files",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Mark Jaquith",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"agency": "cli.ts"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"test": "bun test",
|
|
17
|
+
"test": "find src -name '*.test.ts' -print0 | xargs -0 -n 1 -P 4 bun test",
|
|
18
18
|
"format": "prettier --write .",
|
|
19
19
|
"format:check": "prettier --check .",
|
|
20
20
|
"knip": "knip --production",
|
package/src/commands/push.ts
CHANGED
|
@@ -278,23 +278,41 @@ const openGitHubPR = (
|
|
|
278
278
|
const { verbose = false } = options
|
|
279
279
|
|
|
280
280
|
// Run gh pr create --web with --head to specify the emit branch
|
|
281
|
-
|
|
281
|
+
// Set environment variables to ensure non-interactive mode in CI
|
|
282
|
+
// Add a 3 second timeout to prevent hanging in CI environments
|
|
283
|
+
const ghEffect = spawnProcess(
|
|
282
284
|
["gh", "pr", "create", "--web", "--head", branchName],
|
|
283
285
|
{
|
|
284
286
|
cwd: gitRoot,
|
|
285
287
|
stdout: verbose ? "inherit" : "pipe",
|
|
286
288
|
stderr: "pipe",
|
|
289
|
+
env: {
|
|
290
|
+
GH_PROMPT_DISABLED: "1",
|
|
291
|
+
NO_COLOR: "1",
|
|
292
|
+
},
|
|
287
293
|
},
|
|
288
294
|
).pipe(
|
|
289
|
-
Effect.
|
|
290
|
-
|
|
291
|
-
|
|
295
|
+
Effect.timeout("3 seconds"),
|
|
296
|
+
Effect.catchAll((error) => {
|
|
297
|
+
// Handle timeout or process errors
|
|
298
|
+
if (error._tag === "TimeoutException") {
|
|
299
|
+
return Effect.succeed({
|
|
300
|
+
exitCode: -1,
|
|
301
|
+
stdout: "",
|
|
302
|
+
stderr: "gh command timed out after 3 seconds",
|
|
303
|
+
})
|
|
304
|
+
}
|
|
305
|
+
// Handle ProcessError
|
|
306
|
+
return Effect.succeed({
|
|
307
|
+
exitCode: (error as any).exitCode ?? -1,
|
|
292
308
|
stdout: "",
|
|
293
|
-
stderr: error.stderr,
|
|
294
|
-
})
|
|
295
|
-
),
|
|
309
|
+
stderr: (error as any).stderr ?? String(error),
|
|
310
|
+
})
|
|
311
|
+
}),
|
|
296
312
|
)
|
|
297
313
|
|
|
314
|
+
const ghResult = yield* ghEffect
|
|
315
|
+
|
|
298
316
|
if (ghResult.exitCode !== 0) {
|
|
299
317
|
return yield* Effect.fail(
|
|
300
318
|
new Error(`gh CLI command failed: ${ghResult.stderr.trim()}`),
|
|
@@ -759,6 +759,49 @@ describe("task command", () => {
|
|
|
759
759
|
|
|
760
760
|
expect(await fileExists(join(tempDir, "AGENTS.md"))).toBe(true)
|
|
761
761
|
})
|
|
762
|
+
|
|
763
|
+
test("fails when on agency source branch without branch name in silent mode", async () => {
|
|
764
|
+
await initGitRepo(tempDir)
|
|
765
|
+
process.chdir(tempDir)
|
|
766
|
+
|
|
767
|
+
await initAgency(tempDir, "test")
|
|
768
|
+
|
|
769
|
+
// Create a task branch with agency files
|
|
770
|
+
await runTestEffect(task({ silent: true, emit: "original-feature" }))
|
|
771
|
+
|
|
772
|
+
// Verify we're on the source branch with agency.json
|
|
773
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
774
|
+
expect(currentBranch).toBe("agency/original-feature")
|
|
775
|
+
expect(await fileExists(join(tempDir, "agency.json"))).toBe(true)
|
|
776
|
+
|
|
777
|
+
// Try to run agency task again without providing a branch name
|
|
778
|
+
// This should fail because we're on an agency source branch
|
|
779
|
+
await expect(runTestEffect(task({ silent: true }))).rejects.toThrow(
|
|
780
|
+
"agency source branch",
|
|
781
|
+
)
|
|
782
|
+
})
|
|
783
|
+
|
|
784
|
+
test("prompts for branch name when on agency source branch", async () => {
|
|
785
|
+
await initGitRepo(tempDir)
|
|
786
|
+
process.chdir(tempDir)
|
|
787
|
+
|
|
788
|
+
await initAgency(tempDir, "test")
|
|
789
|
+
|
|
790
|
+
// Create a task branch with agency files
|
|
791
|
+
await runTestEffect(task({ silent: true, emit: "original-feature" }))
|
|
792
|
+
|
|
793
|
+
// Verify we're on the source branch with agency.json
|
|
794
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
795
|
+
expect(currentBranch).toBe("agency/original-feature")
|
|
796
|
+
expect(await fileExists(join(tempDir, "agency.json"))).toBe(true)
|
|
797
|
+
|
|
798
|
+
// With a branch name provided, it should work
|
|
799
|
+
await runTestEffect(task({ silent: true, emit: "new-feature" }))
|
|
800
|
+
|
|
801
|
+
// Verify we're now on the new branch
|
|
802
|
+
const newBranch = await getCurrentBranch(tempDir)
|
|
803
|
+
expect(newBranch).toBe("agency/new-feature")
|
|
804
|
+
})
|
|
762
805
|
})
|
|
763
806
|
|
|
764
807
|
describe("template-based source files", () => {
|
package/src/commands/task.ts
CHANGED
|
@@ -212,11 +212,21 @@ const taskContinue = (options: TaskOptions) =>
|
|
|
212
212
|
targetPath,
|
|
213
213
|
baseBranchToBranchFrom,
|
|
214
214
|
)
|
|
215
|
+
// Calculate the emit branch name for display
|
|
216
|
+
const cleanBranchForDisplay =
|
|
217
|
+
extractCleanBranch(sourceBranchName, config.sourceBranchPattern) ||
|
|
218
|
+
sourceBranchName
|
|
219
|
+
const emitBranchForDisplay = makeEmitBranchName(
|
|
220
|
+
cleanBranchForDisplay,
|
|
221
|
+
config.emitBranch,
|
|
222
|
+
)
|
|
223
|
+
|
|
215
224
|
log(
|
|
216
|
-
|
|
217
|
-
`
|
|
225
|
+
info(
|
|
226
|
+
`(${highlight.branch(baseBranchToBranchFrom)}) ${highlight.branch(sourceBranchName)} → ${highlight.branch(emitBranchForDisplay)}`,
|
|
218
227
|
),
|
|
219
228
|
)
|
|
229
|
+
log(done(`Created and switched to ${highlight.branch(sourceBranchName)}`))
|
|
220
230
|
|
|
221
231
|
// Calculate the new emit branch name
|
|
222
232
|
const newEmitBranchName = makeEmitBranchName(branchName, config.emitBranch)
|
|
@@ -367,6 +377,11 @@ export const task = (options: TaskOptions = {}) =>
|
|
|
367
377
|
const isFeature = yield* git.isFeatureBranch(currentBranch, targetPath)
|
|
368
378
|
verboseLog(`Is feature branch: ${isFeature}`)
|
|
369
379
|
|
|
380
|
+
// Check if we're on an agency source branch (has agency.json with backpacked files)
|
|
381
|
+
const agencyJsonPath = resolve(targetPath, "agency.json")
|
|
382
|
+
const hasAgencyJson = yield* fs.exists(agencyJsonPath)
|
|
383
|
+
verboseLog(`Has agency.json: ${hasAgencyJson}`)
|
|
384
|
+
|
|
370
385
|
// Determine base branch to branch from
|
|
371
386
|
let baseBranchToBranchFrom: string | undefined
|
|
372
387
|
|
|
@@ -458,8 +473,8 @@ export const task = (options: TaskOptions = {}) =>
|
|
|
458
473
|
// Determine branch name logic
|
|
459
474
|
let branchName = options.emit || options.branch
|
|
460
475
|
|
|
461
|
-
// If on main branch
|
|
462
|
-
if ((!isFeature || options.from) && !branchName) {
|
|
476
|
+
// If on main branch, using --from, or on an agency source branch without a branch name, prompt for it (unless in silent mode)
|
|
477
|
+
if ((!isFeature || options.from || hasAgencyJson) && !branchName) {
|
|
463
478
|
if (silent) {
|
|
464
479
|
if (options.from) {
|
|
465
480
|
return yield* Effect.fail(
|
|
@@ -469,6 +484,15 @@ export const task = (options: TaskOptions = {}) =>
|
|
|
469
484
|
),
|
|
470
485
|
)
|
|
471
486
|
}
|
|
487
|
+
if (hasAgencyJson) {
|
|
488
|
+
return yield* Effect.fail(
|
|
489
|
+
new Error(
|
|
490
|
+
`You're currently on ${highlight.branch(currentBranch)}, which is an agency source branch.\n` +
|
|
491
|
+
`Branch name is required when re-importing backpacked files.\n` +
|
|
492
|
+
`Use: 'agency task <branch-name>' or 'agency task --continue <branch-name>'`,
|
|
493
|
+
),
|
|
494
|
+
)
|
|
495
|
+
}
|
|
472
496
|
return yield* Effect.fail(
|
|
473
497
|
new Error(
|
|
474
498
|
`You're currently on ${highlight.branch(currentBranch)}, which appears to be your main branch.\n` +
|
|
@@ -823,11 +847,27 @@ const createFeatureBranchEffect = (
|
|
|
823
847
|
}
|
|
824
848
|
|
|
825
849
|
yield* git.createBranch(branchName, targetPath, baseBranch)
|
|
850
|
+
|
|
851
|
+
// Load config for emit pattern calculation
|
|
852
|
+
const configService = yield* ConfigService
|
|
853
|
+
const config = yield* configService.loadConfig()
|
|
854
|
+
|
|
855
|
+
// Calculate the emit branch name for display
|
|
856
|
+
const cleanBranchForDisplay =
|
|
857
|
+
extractCleanBranch(branchName, config.sourceBranchPattern) || branchName
|
|
858
|
+
const emitBranchForDisplay = makeEmitBranchName(
|
|
859
|
+
cleanBranchForDisplay,
|
|
860
|
+
config.emitBranch,
|
|
861
|
+
)
|
|
862
|
+
|
|
826
863
|
log(
|
|
827
|
-
|
|
828
|
-
|
|
864
|
+
info(
|
|
865
|
+
baseBranch
|
|
866
|
+
? `(${highlight.branch(baseBranch)}) ${highlight.branch(branchName)} → ${highlight.branch(emitBranchForDisplay)}`
|
|
867
|
+
: `${highlight.branch(branchName)} → ${highlight.branch(emitBranchForDisplay)}`,
|
|
829
868
|
),
|
|
830
869
|
)
|
|
870
|
+
log(done(`Created and switched to ${highlight.branch(branchName)}`))
|
|
831
871
|
})
|
|
832
872
|
|
|
833
873
|
// Helper: Discover template files
|
package/templates/opencode.json
CHANGED