@markjaquith/agency 3.1.0 → 3.1.1

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/README.md CHANGED
@@ -66,7 +66,7 @@ workbase/
66
66
  .agency/
67
67
  AGENTS.md # managed Agency instructions
68
68
  .opencode/
69
- opencode.jsonc # managed @agency subagent, instructions, and reference
69
+ opencode.jsonc # managed planning agent, instructions, and reference
70
70
  tui.jsonc # managed TUI plugin registration
71
71
  plugins/agency-repository-skills.ts # managed workbase access and checkout skills
72
72
  tui/agency-debug.ts # managed /agency-debug TUI diagnostic
@@ -116,17 +116,14 @@ Agency-managed root `AGENTS.md` to `.agency/AGENTS.md` once the OpenCode config
116
116
  can load the hidden file. A customized root file, including a symlink, is
117
117
  preserved as user-owned content.
118
118
 
119
- The OpenCode config defines an `@agency` subagent for delegated workbase
120
- orchestration, loads Agency's hidden instructions in addition to any user-owned
121
- root `AGENTS.md`, advertises the complete workbase as one portable reference,
122
- and replaces the built-in Plan agent with `agency-plan`. That planning agent can
123
- update `TASK.md`, `PHASE.md`, and `EPIC.md`, inspect the workbase through
124
- read-only Agency commands, and use explicit Agency CLI permissions to create or
125
- update planning structure. Its normal research tools and the complete Agency CLI
126
- remain available; managed Agency instructions and reported authority govern each
127
- operation.
128
- When the subagent launches work in another agent, it verifies that the agent
129
- started and returns without waiting for the task to finish.
119
+ The OpenCode config loads Agency's hidden instructions in addition to any
120
+ user-owned root `AGENTS.md`, advertises the complete workbase as one portable
121
+ reference, and replaces the built-in Plan agent with `agency-plan`. That
122
+ planning agent can update `TASK.md`, `PHASE.md`, and `EPIC.md`, inspect the
123
+ workbase through read-only Agency commands, and use explicit Agency CLI
124
+ permissions to create or update planning structure. Its normal research tools
125
+ and the complete Agency CLI remain available; managed Agency instructions and
126
+ reported authority govern each operation.
130
127
  The TUI-only `/agency-debug` command reports TUI companion initialization and
131
128
  whether the server plugin registered writable-checkout skills. It uses a native
132
129
  toast and does not submit a prompt to an LLM. When no writable checkout skill
package/cli-main.ts CHANGED
@@ -618,6 +618,7 @@ const commands: Record<string, Command> = {
618
618
  subcommand: args[0],
619
619
  args: args.slice(1),
620
620
  dryRun: options["dry-run"],
621
+ force: options.force,
621
622
  json: options.json,
622
623
  silent: options.silent,
623
624
  verbose: options.verbose,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -664,11 +664,17 @@ describe("strict CLI parsing", () => {
664
664
  "--phase",
665
665
  "verify",
666
666
  "--dry-run",
667
+ "--force",
667
668
  ]),
668
669
  ).toMatchObject({
669
670
  commandName: "worktree",
670
671
  args: ["rebuild", "example", "verify"],
671
- values: { task: "example", phase: "verify", "dry-run": true },
672
+ values: {
673
+ task: "example",
674
+ phase: "verify",
675
+ "dry-run": true,
676
+ force: true,
677
+ },
672
678
  })
673
679
  expectUsageError(
674
680
  ["worktree", "inspect", "example", "--dry-run"],
package/src/cli-parser.ts CHANGED
@@ -870,6 +870,7 @@ const commands = {
870
870
  ...outputOptions,
871
871
  ...entitySelectorOptions,
872
872
  "dry-run": { type: "boolean" },
873
+ force: { type: "boolean" },
873
874
  },
874
875
  subcommands: {
875
876
  list: {
@@ -886,31 +887,31 @@ const commands = {
886
887
  },
887
888
  prepare: {
888
889
  usage:
889
- "agency worktree prepare <task-id> [phase-id] [--dry-run] [--json]",
890
+ "agency worktree prepare <task-id> [phase-id] [--dry-run] [--force] [--json]",
890
891
  minArgs: 1,
891
892
  maxArgs: 2,
892
- options: ["dry-run", "json", "task", "phase"],
893
+ options: ["dry-run", "force", "json", "task", "phase"],
893
894
  },
894
895
  remove: {
895
896
  usage:
896
- "agency worktree remove <task-id> [phase-id] [--dry-run] [--json]",
897
+ "agency worktree remove <task-id> [phase-id] [--dry-run] [--force] [--json]",
897
898
  minArgs: 1,
898
899
  maxArgs: 2,
899
- options: ["dry-run", "json", "task", "phase"],
900
+ options: ["dry-run", "force", "json", "task", "phase"],
900
901
  },
901
902
  rebuild: {
902
903
  usage:
903
- "agency worktree rebuild <task-id> [phase-id] [--dry-run] [--json]",
904
+ "agency worktree rebuild <task-id> [phase-id] [--dry-run] [--force] [--json]",
904
905
  minArgs: 1,
905
906
  maxArgs: 2,
906
- options: ["dry-run", "json", "task", "phase"],
907
+ options: ["dry-run", "force", "json", "task", "phase"],
907
908
  },
908
909
  repair: {
909
910
  usage:
910
- "agency worktree repair <task-id> [phase-id] [--dry-run] [--json]",
911
+ "agency worktree repair <task-id> [phase-id] [--dry-run] [--force] [--json]",
911
912
  minArgs: 1,
912
913
  maxArgs: 2,
913
- options: ["dry-run", "json", "task", "phase"],
914
+ options: ["dry-run", "force", "json", "task", "phase"],
914
915
  },
915
916
  },
916
917
  },
package/src/cli.test.ts CHANGED
@@ -1373,12 +1373,7 @@ status: open
1373
1373
  }
1374
1374
  if (launch === launches[0]) {
1375
1375
  expect(effectiveConfig.instructions).toContain(".agency/AGENTS.md")
1376
- expect(effectiveConfig.agent.agency).toMatchObject({
1377
- description: expect.stringContaining(
1378
- "Agency workbase orchestration",
1379
- ),
1380
- mode: "subagent",
1381
- })
1376
+ expect(effectiveConfig.agent.agency).toBeUndefined()
1382
1377
  expect(effectiveConfig.references).toEqual({
1383
1378
  workbase: {
1384
1379
  path: "..",
@@ -1386,18 +1381,6 @@ status: open
1386
1381
  "Complete Agency workbase context; write authority still comes only from agency context",
1387
1382
  },
1388
1383
  })
1389
- const agencyProbe = Bun.spawnSync(
1390
- ["opencode", "debug", "agent", "agency"],
1391
- { cwd: contract.cwd, env: environment },
1392
- )
1393
- expect(agencyProbe.exitCode).toBe(0)
1394
- expect(JSON.parse(agencyProbe.stdout.toString())).toMatchObject({
1395
- name: "agency",
1396
- description: expect.stringContaining(
1397
- "Agency workbase orchestration",
1398
- ),
1399
- mode: "subagent",
1400
- })
1401
1384
  for (const document of documents) {
1402
1385
  const read = Bun.spawnSync(
1403
1386
  [
@@ -45,11 +45,7 @@ describe("init command", () => {
45
45
  ).text()
46
46
  const config = JSON.parse(opencode.slice(opencode.indexOf("\n\n") + 2))
47
47
  expect(config.instructions).toEqual([".agency/AGENTS.md"])
48
- expect(config.agent.agency).toMatchObject({
49
- description: expect.stringContaining("Agency workbase orchestration"),
50
- mode: "subagent",
51
- prompt: expect.stringContaining("agency context . --json"),
52
- })
48
+ expect(config.agent.agency).toBeUndefined()
53
49
  expect(config.agent.plan).toEqual({ disable: true })
54
50
  expect(config.agent["agency-plan"]).toMatchObject({
55
51
  mode: "primary",
@@ -6,6 +6,7 @@ import { WorktreeService } from "../services/WorktreeService"
6
6
  interface WorktreeOptions extends BaseCommandOptions {
7
7
  readonly subcommand?: string
8
8
  readonly args?: readonly string[]
9
+ readonly force?: boolean
9
10
  }
10
11
 
11
12
  const targetLabel = (owner: {
@@ -134,5 +135,6 @@ Options:
134
135
  --task <id> Select a task without positional IDs
135
136
  --phase <id> Select a phase with --task
136
137
  --dry-run Preflight and report changes without applying them
138
+ --force Override an existing worktree operation lock
137
139
  --json Print structured output
138
140
  `
@@ -186,9 +186,12 @@ describe("IntegrationService", () => {
186
186
  }
187
187
  expect(managedWorkbaseAgents).toContain("agency push --json")
188
188
  expect(managedWorkbaseAgents).toContain("agency-execution-v1")
189
- expect(managedWorkbaseAgents).toContain("agency context . --full --json")
189
+ expect(managedWorkbaseAgents).toContain("agency context . --json")
190
190
  expect(managedWorkbaseAgents).toContain(
191
- "Workers use full context here because they need the assigned document prose",
191
+ "Pass `--full` only when document prose or low-level VCS details are needed",
192
+ )
193
+ expect(managedWorkbaseAgents).not.toContain(
194
+ "agency context . --full --json",
192
195
  )
193
196
  expect(managedWorkbaseAgents).toContain(
194
197
  "Never pass `--work` or `--auto` to `agency task create`",
@@ -681,19 +684,11 @@ describe("IntegrationService", () => {
681
684
  )
682
685
  })
683
686
 
684
- test("configures Agency agents with complete workbase access", () => {
687
+ test("configures Agency planning with complete workbase access", () => {
685
688
  const config = JSON.parse(managedBody(managedWorkbaseOpencode))
686
689
 
687
690
  expect(config.instructions).toEqual([".agency/AGENTS.md"])
688
691
  expect(config.agent).toEqual({
689
- agency: {
690
- description:
691
- "Handles Agency workbase orchestration and workflow operations with the Agency CLI",
692
- mode: "subagent",
693
- prompt: expect.stringMatching(
694
- /agency context \. --json[\s\S]+agency work prepare[\s\S]+never pass `--work` or `--auto`/,
695
- ),
696
- },
697
692
  plan: {
698
693
  disable: true,
699
694
  },
@@ -716,19 +711,16 @@ describe("IntegrationService", () => {
716
711
  },
717
712
  },
718
713
  })
719
- expect(config.agent.agency.model).toBeUndefined()
720
- expect(config.agent.agency.permission).toBeUndefined()
721
714
  expect(config.agent["agency-plan"].prompt).toContain(
722
715
  "Explicit-new intent overrides reuse",
723
716
  )
724
- expect(config.agent.agency.hidden).toBeUndefined()
725
- expect(config.agent.agency.steps).toBeUndefined()
726
- expect(config.agent.agency.prompt).toContain(
727
- "Return the prepared execution contract to the caller",
728
- )
717
+ expect(config.agent.agency).toBeUndefined()
729
718
  expect(config.agent["agency-plan"].prompt).toContain(
730
719
  "Start with `agency context . --json`",
731
720
  )
721
+ expect(config.agent["agency-plan"].prompt).toContain(
722
+ "Pass `--full` only when document prose or low-level VCS details are needed",
723
+ )
732
724
  expect(config.agent["agency-plan"].prompt).toContain(
733
725
  "decompose it into independently deliverable tasks",
734
726
  )
@@ -1,6 +1,6 @@
1
1
  import { afterEach, describe, expect, test } from "bun:test"
2
2
  import { Effect } from "effect"
3
- import { mkdtemp, readdir, rm } from "node:fs/promises"
3
+ import { mkdtemp, readdir, rm, utimes } from "node:fs/promises"
4
4
  import { tmpdir } from "node:os"
5
5
  import { join } from "node:path"
6
6
  import { withWorktreeLocks } from "./WorktreeLock"
@@ -54,11 +54,90 @@ describe("withWorktreeLocks", () => {
54
54
  _tag: "Left",
55
55
  left: {
56
56
  _tag: "WorktreeLockError",
57
- message: `Another worktree operation is in progress for 'alpha'. If no operation is active, remove the stale sentinel with: rm '${lockPath}'`,
57
+ message: `Another worktree operation is in progress for 'alpha'. Retry with --force or remove the stale sentinel with: rm '${lockPath}'`,
58
58
  },
59
59
  })
60
60
  })
61
61
 
62
+ test("removes stale locks before acquiring them", async () => {
63
+ const root = await createTempDir()
64
+ tempDirs.push(root)
65
+ const lockPath = join(
66
+ root,
67
+ `.agency-worktree-${Buffer.from("alpha:task").toString("hex")}.lock`,
68
+ )
69
+ await Bun.write(lockPath, "")
70
+ const staleAt = new Date(Date.now() - 11 * 60 * 1000)
71
+ await utimes(lockPath, staleAt, staleAt)
72
+
73
+ await expect(
74
+ Effect.runPromise(
75
+ withWorktreeLocks(root, [{ taskId: "alpha" }], Effect.void),
76
+ ),
77
+ ).resolves.toBeUndefined()
78
+ })
79
+
80
+ test("force overrides an active lock", async () => {
81
+ const root = await createTempDir()
82
+ tempDirs.push(root)
83
+ let firstEntered!: () => void
84
+ let firstRelease!: () => void
85
+ const firstEnteredPromise = new Promise<void>((resolve) => {
86
+ firstEntered = resolve
87
+ })
88
+ const firstReleasePromise = new Promise<void>((resolve) => {
89
+ firstRelease = resolve
90
+ })
91
+ const first = Effect.runPromise(
92
+ withWorktreeLocks(
93
+ root,
94
+ [{ taskId: "alpha" }],
95
+ Effect.promise(async () => {
96
+ firstEntered()
97
+ await firstReleasePromise
98
+ }),
99
+ ),
100
+ )
101
+ await firstEnteredPromise
102
+
103
+ let forcedEntered!: () => void
104
+ let forcedRelease!: () => void
105
+ const forcedEnteredPromise = new Promise<void>((resolve) => {
106
+ forcedEntered = resolve
107
+ })
108
+ const forcedReleasePromise = new Promise<void>((resolve) => {
109
+ forcedRelease = resolve
110
+ })
111
+ const forced = Effect.runPromise(
112
+ withWorktreeLocks(
113
+ root,
114
+ [{ taskId: "alpha" }],
115
+ Effect.promise(async () => {
116
+ forcedEntered()
117
+ await forcedReleasePromise
118
+ }),
119
+ { force: true },
120
+ ),
121
+ )
122
+ await forcedEnteredPromise
123
+
124
+ firstRelease()
125
+ await first
126
+
127
+ const conflict = await Effect.runPromise(
128
+ Effect.either(
129
+ withWorktreeLocks(root, [{ taskId: "alpha" }], Effect.void),
130
+ ),
131
+ )
132
+ expect(conflict).toMatchObject({
133
+ _tag: "Left",
134
+ left: { _tag: "WorktreeLockError" },
135
+ })
136
+
137
+ forcedRelease()
138
+ await forced
139
+ })
140
+
62
141
  test("releases locks when the protected operation fails", async () => {
63
142
  const root = await createTempDir()
64
143
  tempDirs.push(root)
@@ -1,5 +1,5 @@
1
1
  import { Data, Effect } from "effect"
2
- import { open, rm } from "node:fs/promises"
2
+ import { open, rm, stat } from "node:fs/promises"
3
3
  import { join } from "node:path"
4
4
 
5
5
  class WorktreeLockError extends Data.TaggedError("WorktreeLockError")<{
@@ -12,10 +12,23 @@ export interface WorktreeLockTarget {
12
12
  readonly phaseId?: string
13
13
  }
14
14
 
15
+ export interface WorktreeLockOptions {
16
+ readonly force?: boolean
17
+ }
18
+
19
+ const lockTimeoutMs = 10 * 60 * 1000
20
+
21
+ const isErrorCode = (cause: unknown, code: string) =>
22
+ typeof cause === "object" &&
23
+ cause !== null &&
24
+ "code" in cause &&
25
+ cause.code === code
26
+
15
27
  const withWorktreeLock = <A, E, R>(
16
28
  root: string,
17
29
  target: WorktreeLockTarget,
18
30
  effect: Effect.Effect<A, E, R>,
31
+ options: WorktreeLockOptions,
19
32
  ): Effect.Effect<A, E | WorktreeLockError, R> => {
20
33
  const key = Buffer.from(
21
34
  `${target.taskId}:${target.phaseId ?? "task"}`,
@@ -24,18 +37,41 @@ const withWorktreeLock = <A, E, R>(
24
37
  const removalCommand = `rm '${lockPath.replaceAll("'", `'\\''`)}'`
25
38
  return Effect.acquireUseRelease(
26
39
  Effect.tryPromise({
27
- try: () => open(lockPath, "wx"),
40
+ try: async () => {
41
+ try {
42
+ return await open(lockPath, "wx")
43
+ } catch (cause) {
44
+ if (!isErrorCode(cause, "EEXIST")) throw cause
45
+ let stale = false
46
+ try {
47
+ stale = Date.now() - (await stat(lockPath)).mtimeMs >= lockTimeoutMs
48
+ } catch (statCause) {
49
+ if (!isErrorCode(statCause, "ENOENT")) throw statCause
50
+ }
51
+ if (!options.force && !stale) throw cause
52
+ await rm(lockPath, { force: true })
53
+ return open(lockPath, "wx")
54
+ }
55
+ },
28
56
  catch: (cause) =>
29
57
  new WorktreeLockError({
30
- message: `Another worktree operation is in progress for '${target.taskId}${target.phaseId ? `/${target.phaseId}` : ""}'. If no operation is active, remove the stale sentinel with: ${removalCommand}`,
58
+ message: `Another worktree operation is in progress for '${target.taskId}${target.phaseId ? `/${target.phaseId}` : ""}'. Retry with --force or remove the stale sentinel with: ${removalCommand}`,
31
59
  cause,
32
60
  }),
33
61
  }),
34
62
  () => effect,
35
63
  (lock) =>
36
64
  Effect.promise(async () => {
65
+ let ownsLock = false
66
+ try {
67
+ const [held, current] = await Promise.all([
68
+ lock.stat(),
69
+ stat(lockPath),
70
+ ])
71
+ ownsLock = held.dev === current.dev && held.ino === current.ino
72
+ } catch {}
37
73
  await lock.close().catch(() => undefined)
38
- await rm(lockPath, { force: true }).catch(() => undefined)
74
+ if (ownsLock) await rm(lockPath, { force: true }).catch(() => undefined)
39
75
  }),
40
76
  )
41
77
  }
@@ -44,6 +80,7 @@ export const withWorktreeLocks = <A, E, R>(
44
80
  root: string,
45
81
  targets: readonly WorktreeLockTarget[],
46
82
  effect: Effect.Effect<A, E, R>,
83
+ options: WorktreeLockOptions = {},
47
84
  ): Effect.Effect<A, E | WorktreeLockError, R> => {
48
85
  const unique = new Map(
49
86
  targets.map((target) => [
@@ -55,7 +92,7 @@ export const withWorktreeLocks = <A, E, R>(
55
92
  for (const [, target] of [...unique.entries()]
56
93
  .sort(([left], [right]) => left.localeCompare(right))
57
94
  .reverse()) {
58
- current = withWorktreeLock(root, target, current)
95
+ current = withWorktreeLock(root, target, current, options)
59
96
  }
60
97
  return current
61
98
  }
@@ -259,6 +259,7 @@ interface MaterializeOptions extends BaseCommandOptions {
259
259
  }
260
260
 
261
261
  interface RemoveOptions extends BaseCommandOptions {
262
+ readonly force?: boolean
262
263
  readonly snapshots?: WorktreeRemovalSnapshot[]
263
264
  readonly lockHeld?: boolean
264
265
  readonly allowReferenceDrift?: boolean
@@ -267,6 +268,7 @@ interface RemoveOptions extends BaseCommandOptions {
267
268
  }
268
269
 
269
270
  interface LifecycleOptions extends BaseCommandOptions {
271
+ readonly force?: boolean
270
272
  readonly lockHeld?: boolean
271
273
  }
272
274
 
@@ -1825,6 +1827,7 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
1825
1827
  root,
1826
1828
  [{ taskId, ...(phaseId ? { phaseId } : {}) }],
1827
1829
  materialization,
1830
+ { force: options.force },
1828
1831
  )
1829
1832
  }),
1830
1833
 
@@ -2148,6 +2151,7 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
2148
2151
  root,
2149
2152
  [{ taskId, ...(phaseId ? { phaseId } : {}) }],
2150
2153
  removal,
2154
+ { force: options.force },
2151
2155
  )
2152
2156
  }),
2153
2157
 
@@ -2170,6 +2174,7 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
2170
2174
  ...options,
2171
2175
  lockHeld: true,
2172
2176
  }),
2177
+ { force: options.force },
2173
2178
  )
2174
2179
  }
2175
2180
  const inspection = yield* inspectExecution(taskId, phaseId, root)
@@ -2316,6 +2321,7 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
2316
2321
  ...options,
2317
2322
  lockHeld: true,
2318
2323
  }),
2324
+ { force: options.force },
2319
2325
  )
2320
2326
  }
2321
2327
  const inspection = yield* inspectExecution(taskId, phaseId, root)
@@ -79,10 +79,10 @@ commands without prescribing an execution environment.
79
79
  Start every session with one read-only command:
80
80
 
81
81
  ```bash
82
- agency context . --full --json
82
+ agency context . --json
83
83
  ```
84
84
 
85
- Workers use full context here because they need the assigned document prose. Use
85
+ Pass `--full` only when document prose or low-level VCS details are needed. Use
86
86
  the returned target, document paths and revisions, dependency readiness,
87
87
  authority, checkout state, PR state, and validation result. Do not infer these
88
88
  from directory names or stale prose.
@@ -8,7 +8,7 @@ const checksum = (content: string) =>
8
8
 
9
9
  const agencyPlanPrompt = `You are in Agency Plan mode. Think, read, search, and delegate exploration to construct a well-formed plan for the user's goal. Keep the plan comprehensive but concise, and ask clarifying questions when important tradeoffs or intent are unclear.
10
10
 
11
- Start with \`agency context . --json\`. Use its document paths and revisions, then inspect the graph, related epics, tasks, phases, linked tickets, and repository declarations needed to understand the work. Use machine-readable Agency output when available instead of inferring structure from directory names.
11
+ Start with \`agency context . --json\`. Pass \`--full\` only when document prose or low-level VCS details are needed. Use its document paths and revisions, then inspect the graph, related epics, tasks, phases, linked tickets, and repository declarations needed to understand the work. Use machine-readable Agency output when available instead of inferring structure from directory names.
12
12
 
13
13
  When planning an epic, decompose it into independently deliverable tasks with explicit dependencies. Add phases only when one task genuinely requires multiple ordered delivery units. Reuse or update existing work instead of creating duplicate tasks or phases, except when the user explicitly requests a new, separate, or follow-up item. Explicit-new intent overrides reuse of active and archived work even when the subject or suggested ID matches.
14
14
 
@@ -20,24 +20,12 @@ const agencyPlanBashPermissions = {
20
20
  "agency *": "allow",
21
21
  }
22
22
 
23
- const agencyAgentPrompt = `You are the Agency workflow specialist. Use the Agency CLI to handle delegated workbase orchestration and workflow operations. Always start with \`agency context . --json\` and follow the managed Agency instructions and reported authority.
24
-
25
- When the intent and parameters are known, use the matching managed Command Fast Path exactly. The recipes cover creation, preparation, synchronization, phase conversion, archiving, review work, inspection, dropping, continuation, publication, pull requests, non-PR completion, multi-phase setup, investigation handoff, and review refresh. Preparation recipes call \`agency work prepare <task-or-document> --json\`. Do not probe help or list unrelated state, never pass \`--work\` or \`--auto\` to \`agency task create\`, and use \`--dry-run\` only where the recipe or caller requests it. Use CLI discovery only when no fast-path recipe matches or a prescribed command rejects known-current syntax.
26
-
27
- Return the prepared execution contract to the caller. Agency owns the target, validation, materialized workspace facts, and native commands; the caller owns presentation and process orchestration.`
28
-
29
23
  const body = () =>
30
24
  `${JSON.stringify(
31
25
  {
32
26
  $schema: "https://opencode.ai/config.json",
33
27
  instructions: [".agency/AGENTS.md"],
34
28
  agent: {
35
- agency: {
36
- description:
37
- "Handles Agency workbase orchestration and workflow operations with the Agency CLI",
38
- mode: "subagent",
39
- prompt: agencyAgentPrompt,
40
- },
41
29
  plan: {
42
30
  disable: true,
43
31
  },