@markjaquith/agency 2.29.0 → 2.30.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.
Files changed (50) hide show
  1. package/README.md +72 -16
  2. package/cli.ts +3 -0
  3. package/fixtures/protocol/skill-setup-commands.json +18 -0
  4. package/package.json +1 -1
  5. package/skills/agency/SKILL.md +30 -15
  6. package/skills/agency/references/commands.md +38 -17
  7. package/skills/agency/references/contracts.md +46 -19
  8. package/skills/agency/references/recipes.md +52 -12
  9. package/src/cli-parser.test.ts +7 -0
  10. package/src/cli-parser.ts +13 -2
  11. package/src/cli.test.ts +422 -3
  12. package/src/commands/doctor.test.ts +22 -0
  13. package/src/commands/init.test.ts +3 -2
  14. package/src/commands/integration.test.ts +21 -1
  15. package/src/commands/integration.ts +8 -4
  16. package/src/commands/pr.test.ts +20 -1
  17. package/src/commands/repo.test.ts +66 -1
  18. package/src/commands/repo.ts +35 -8
  19. package/src/commands/status.test.ts +22 -0
  20. package/src/commands/status.ts +1 -0
  21. package/src/commands/sync.ts +5 -3
  22. package/src/commands/work.test.ts +74 -1
  23. package/src/commands/work.ts +26 -3
  24. package/src/graph-schema.test.ts +52 -4
  25. package/src/protocol.test.ts +41 -8
  26. package/src/readiness.test.ts +75 -17
  27. package/src/services/DoctorService.ts +32 -18
  28. package/src/services/EpicService.ts +1 -1
  29. package/src/services/GraphMutationService.ts +3 -3
  30. package/src/services/GraphService.ts +13 -4
  31. package/src/services/IntegrationService.test.ts +37 -12
  32. package/src/services/IntegrationService.ts +70 -21
  33. package/src/services/PhaseService.ts +1 -1
  34. package/src/services/ReadinessService.test.ts +47 -0
  35. package/src/services/RepositoryService.test.ts +299 -5
  36. package/src/services/RepositoryService.ts +725 -98
  37. package/src/services/SyncService.test.ts +36 -0
  38. package/src/services/SyncService.ts +20 -1
  39. package/src/services/TaskService.ts +1 -1
  40. package/src/services/WorkbaseService.test.ts +32 -0
  41. package/src/services/WorkbaseService.ts +22 -14
  42. package/src/services/WorktreeLock.test.ts +122 -0
  43. package/src/services/WorktreeService.test.ts +17 -2
  44. package/src/services/WorktreeService.ts +3 -3
  45. package/src/utils/process.test.ts +4 -3
  46. package/src/workbase/AGENTS.md +9 -1
  47. package/src/workbase/dependency-graph.test.ts +50 -0
  48. package/src/workbase/opencode-file.ts +3 -13
  49. package/src/workbase/schemas.test.ts +52 -0
  50. package/src/workbase/schemas.ts +19 -0
package/README.md CHANGED
@@ -43,9 +43,9 @@ frontmatter; prose below it supplies human and agent context.
43
43
  workbase/
44
44
  AGENTS.md # managed workbase instructions
45
45
  .opencode/
46
- opencode.jsonc # managed task and epic references
47
- agency.json
48
- repos/
46
+ opencode.jsonc # managed whole-workbase reference
47
+ agency.json # tracked config and portable repository declarations
48
+ repos/ # ignored local materializations
49
49
  frontend/ # bare Git repository or symlink
50
50
  backend/
51
51
  epics/
@@ -76,14 +76,35 @@ Agency keeps discovery and other observational commands read-only. Run
76
76
  files or refresh checksum-safe managed files. Customized files are reported but
77
77
  never overwritten.
78
78
 
79
- The OpenCode config advertises only the task and epic directories as documented
80
- references. OpenCode automatically grants those references scoped
81
- external-directory access, so Agency does not add blanket permission rules that
82
- could hide missing tool permissions. References provide context and never expand
83
- the write authority reported by `agency context`.
79
+ The OpenCode config advertises the complete workbase as one portable relative
80
+ reference. `agency work` sets `OPENCODE_CONFIG` to the managed file and injects
81
+ runtime-only absolute rules that allow external access across the workbase while
82
+ denying edits outside the execution unit's writable checkout. This makes the
83
+ config effective from nested task and phase Git checkouts without persisting a
84
+ machine-specific path or granting access outside the workbase. Bash and Agency
85
+ operations must still follow the write authority reported by `agency context`.
84
86
 
85
- Repository metadata comes directly from Git under `repos/{alias}`. Workbase
86
- configuration may provide a custom writable-worktree creation command.
87
+ Repository aliases and canonical fetch remotes are declared in tracked
88
+ `agency.json`; local bare clones and symlinks remain ignored under
89
+ `repos/{alias}`. A declaration contains no local path, symlink target, checkout,
90
+ or credential:
91
+
92
+ ```json
93
+ {
94
+ "version": 2,
95
+ "repositories": {
96
+ "frontend": {
97
+ "remote": "git@example.com:team/frontend.git"
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
103
+ Existing version 2 workbases without `repositories` remain valid. Run
104
+ `agency repo setup` to preview deterministic adoption of legacy local aliases;
105
+ `agency repo setup --apply` writes declarations only when a portable origin is
106
+ unambiguous. Workbase configuration may also provide a custom writable-worktree
107
+ creation command.
87
108
 
88
109
  ### Custom Worktree Command
89
110
 
@@ -182,6 +203,10 @@ Every runner receives the same `AGENCY_RUNNER`, `AGENCY_CLAIMANT`,
182
203
  `AGENCY_SESSION_ID`, `AGENCY_CLAIM_REVISION`, `AGENCY_WORKBASE`, `AGENCY_TARGET`,
183
204
  `AGENCY_TASK_ID`, `AGENCY_PHASE_ID`, and `AGENCY_PROMPT` environment. Configured
184
205
  environment is added without overriding these normalized values.
206
+ The `opencode` runner additionally receives `OPENCODE_CONFIG` for the workbase's
207
+ managed integration and `OPENCODE_CONFIG_CONTENT` with runtime-only,
208
+ workbase-scoped access and edit rules. These values keep the Git-synced config
209
+ portable while providing whole-workbase read access at every launch location.
185
210
  `--print-command` prints the exact cwd and argv plus non-secret environment keys
186
211
  without launching the runner.
187
212
 
@@ -298,6 +323,15 @@ agency work tasks/refresh-copy
298
323
  agency pr create refresh-copy
299
324
  ```
300
325
 
326
+ After cloning an existing workbase on another machine, restore its declared
327
+ repositories before preparing work:
328
+
329
+ ```bash
330
+ agency repo setup --dry-run
331
+ agency repo setup --apply
332
+ agency validate
333
+ ```
334
+
301
335
  ## Commands
302
336
 
303
337
  ### Target Context
@@ -361,22 +395,27 @@ materializing or pushing. Blocked, done, and dropped targets are rejected unless
361
395
 
362
396
  ### Reconciliation
363
397
 
364
- `agency sync` compares every execution declaration with local branch and worktree
365
- registration, writable and reference checkout dirtiness, resolved reference
366
- commits, claim expiry, and GitHub pull request and merge state. It reports
398
+ `agency sync` first compares portable repository declarations with local
399
+ materializations, then compares every execution declaration with local branch
400
+ and worktree registration, checkout dirtiness, resolved reference commits, claim
401
+ expiry, and pull request and merge state. It reports
367
402
  structured `changes`, `warnings`, `unresolved`, and per-execution evidence. The
368
403
  default and `--dry-run` modes are observational.
369
404
 
370
405
  `agency sync --apply` performs only these safe transitions:
371
406
 
407
+ - materialize declared but missing repositories from their canonical remotes;
408
+ - adopt legacy materializations only when they have an unambiguous portable origin;
372
409
  - materialize missing checkouts when no registration, branch, or path conflicts;
373
410
  - release an active claim only after its declared expiry has passed;
374
411
  - record a single PR whose head and base match the declaration; and
375
412
  - mark work done after its authoritative PR is merged and no active claim remains.
376
413
 
377
- Apply never modifies dirty checkouts, moves worktrees, switches branches, resets
378
- reference commits, chooses among multiple PRs, or bypasses active claims. Those
379
- conditions remain visible in `warnings` or `unresolved` with a suggested action.
414
+ Apply never overwrites linked or invalid repositories, repairs remote drift,
415
+ modifies dirty checkouts, moves worktrees, switches branches, resets reference
416
+ commits, chooses among conflicting remotes or PRs, or bypasses active claims.
417
+ Those conditions remain visible in `warnings` or `unresolved` with a suggested
418
+ action.
380
419
 
381
420
  ### Workbase and Repositories
382
421
 
@@ -393,6 +432,7 @@ agency workbase prune [--json]
393
432
  agency workbase default [<id|name|path> | --clear] [--json]
394
433
  agency integration status [--json]
395
434
  agency integration sync [--json]
435
+ agency repo setup [--dry-run | --apply] [--json]
396
436
  agency repo add <alias> <remote> [--json]
397
437
  agency repo link <alias> <path> [--json]
398
438
  agency repo list [--json]
@@ -405,6 +445,22 @@ agency repo remote <alias> [remote] [--json]
405
445
  agency repo verify <alias> [--json]
406
446
  ```
407
447
 
448
+ Repository JSON output exposes state facets rather than hiding partial setup:
449
+ `declared`, `materialized`, `linked`, `missing`, `invalid`, and
450
+ `remote-drifted`. A normal bare clone is declared and materialized; a local
451
+ checkout is declared and linked; a fresh workbase clone is declared and missing
452
+ until setup is applied.
453
+
454
+ `repo add`, `link`, `remote`, `rename`, and `remove` update the portable
455
+ declaration transactionally with local state. `repo remove` removes both the
456
+ declaration and an unused local materialization. `repo unlink` removes only this
457
+ machine's symlink and retains the declaration, leaving an actionable missing
458
+ state. Linking a local checkout over an unused managed clone likewise retains the
459
+ portable remote for other machines. `repo remote` updates managed clones but
460
+ never mutates an external linked checkout; drift remains visible until that
461
+ checkout is updated explicitly. Credential-bearing URLs, file URLs, and local
462
+ paths are never accepted as declarations.
463
+
408
464
  Registered workbases are stored in
409
465
  `$XDG_CONFIG_HOME/agency/workbases.json` (or `~/.config/agency/workbases.json`).
410
466
  Each registration has a stable ID and may have a unique name. A default workbase
package/cli.ts CHANGED
@@ -414,6 +414,8 @@ const commands: Record<string, Command> = {
414
414
  silent: options.silent,
415
415
  verbose: options.verbose,
416
416
  json: options.json,
417
+ dryRun: options["dry-run"],
418
+ apply: options.apply,
417
419
  cwd: options.cwd,
418
420
  }),
419
421
  )
@@ -514,6 +516,7 @@ const commands: Record<string, Command> = {
514
516
  json: options.json,
515
517
  silent: options.silent,
516
518
  verbose: options.verbose,
519
+ cwd: options.cwd,
517
520
  }),
518
521
  )
519
522
  },
@@ -0,0 +1,18 @@
1
+ [
2
+ ["init", "/work/agency", "--json"],
3
+ ["workbase", "init", "/work/agency", "--json"],
4
+ ["repo", "add", "agency", "git@example.com:owner/agency.git", "--json"],
5
+ ["repo", "setup", "--dry-run", "--json"],
6
+ ["repo", "setup", "--apply", "--json"],
7
+ ["repo", "link", "agency", "/work/agency-repository", "--json"],
8
+ [
9
+ "--workbase",
10
+ "/work/agency",
11
+ "repo",
12
+ "link",
13
+ "agency",
14
+ "/work/agency-repository"
15
+ ],
16
+ ["validate", "/work/agency"],
17
+ ["--workbase", "/work/agency", "repo", "verify", "agency"]
18
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "2.29.0",
3
+ "version": "2.30.1",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -5,14 +5,15 @@ description: >
5
5
  and pull requests. Use when inspecting or changing Agency-managed work,
6
6
  coordinating dependencies, launching agents, or finishing an execution unit.
7
7
  license: MIT
8
- compatibility: Requires the agency CLI and Git. Agent launch requires a configured runner; GitHub pull requests require gh.
8
+ compatibility: Requires the agency CLI and Git. Agent launch requires OpenCode, Claude, or a configured runner; default GitHub delivery requires gh.
9
9
  ---
10
10
 
11
11
  # Agency
12
12
 
13
- Agency keeps plans and lifecycle state in durable Markdown documents. Git
14
- checkouts under `code/` are materialized local state. Treat the documents as the
15
- source of truth and Agency commands as the safe way to mutate their structure.
13
+ Agency keeps plans and lifecycle state in durable Markdown documents and keeps
14
+ portable repository aliases in `agency.json`. Bare repositories under `repos/`
15
+ and Git checkouts under `code/` are ignored local materializations. Treat tracked
16
+ workbase state as authoritative and Agency commands as the safe mutation path.
16
17
 
17
18
  ## Start With Context
18
19
 
@@ -27,8 +28,9 @@ readiness, write authority, checkout state, PR state, and validation warnings.
27
28
  Use its paths and IDs instead of inferring them from the process cwd.
28
29
 
29
30
  At the workbase root, context cannot infer one entity from `.`. Use
30
- `agency next --json` or `agency graph --json` to choose a target, then pass that
31
- target to `agency context <target> --json`.
31
+ `agency next --json` or `agency graph --json` to choose a target, then inspect it
32
+ with explicit `--epic`, `--task`, and `--phase` selectors or its returned document
33
+ path. Do not pass a graph node key as a positional context target.
32
34
 
33
35
  For broader orchestration, load the graph and discover available capabilities:
34
36
 
@@ -46,14 +48,17 @@ output or editing documents.
46
48
  ## Mental Model
47
49
 
48
50
  - A **workbase** contains durable epics, tasks, phases, and repository aliases.
51
+ - A repository declaration stores an alias and credential-free canonical fetch
52
+ remote; local bare clones and linked checkouts are replaceable machine state.
49
53
  - An **epic** coordinates tasks. It may inspect repositories but never writes code.
50
54
  - A **task** is one durable outcome. It is either an execution unit itself or a
51
55
  container for phases.
52
56
  - A **phase** is one execution unit within a multi-phase task, normally one PR.
53
57
  - An **execution unit** has exactly one writable `repo`, optional read-only
54
58
  `repos`, one branch, one base, and one recorded PR value.
55
- - `open` is available, `working` is actively owned, and `done` or `dropped` is
56
- terminal. Only `done` satisfies a dependency.
59
+ - `open` is eligible for readiness evaluation, `working` is actively owned, and
60
+ `done` or `dropped` is terminal. An open unit may still be blocked; only `done`
61
+ satisfies a dependency.
57
62
 
58
63
  The `authority` returned by context is decisive. Write only through
59
64
  `authority.writable.checkoutPath`. Every entry in `authority.references` is
@@ -65,6 +70,7 @@ Require explicit user intent before:
65
70
 
66
71
  - initializing a workbase;
67
72
  - adding, linking, renaming, or removing a repository alias;
73
+ - applying repository setup or sync changes;
68
74
  - launching another agent with `agency work` from an active agent session;
69
75
  - creating a pull request;
70
76
  - archiving, restoring, dropping, or reopening work; or
@@ -79,13 +85,14 @@ independently meaningful tasks need coordination.
79
85
  - Keep task-wide decisions in `TASK.md` and phase delivery details in `PHASE.md`.
80
86
  - Never write through plural `repos` references.
81
87
  - Never edit bare repositories or repository symlinks under `repos/`.
88
+ - Never persist local paths, symlink targets, worktrees, or credentials as
89
+ repository remotes.
82
90
  - Never manually create, move, or remove generated `code/` worktrees.
83
91
  - Never invent IDs, revisions, PR URLs, dependency completion, or checkout state.
84
92
  - Preserve parent backlinks and dependency declarations; use Agency mutations
85
93
  instead of hand-editing structural frontmatter.
86
94
  - Run `agency validate` before worktree or PR operations and after structural edits.
87
- - Do not bypass dirty-worktree, active-claim, revision, readiness, or failed-check
88
- protections.
95
+ - Do not bypass dirty-worktree, active-claim, revision, or readiness protections.
89
96
 
90
97
  ## Operating Protocol
91
98
 
@@ -94,8 +101,9 @@ independently meaningful tasks need coordination.
94
101
  1. Run `agency context . --json`.
95
102
  2. Confirm `target`, `graph.readiness`, `authority`, `workspace`, and `validation`.
96
103
  3. Read the returned task and phase document paths for prose requirements.
97
- 4. Stop on validation errors, blockers, an unexpected writable repository, or a
98
- conflicting active owner.
104
+ 4. Stop on validation errors, dependency blockers, an unexpected writable
105
+ repository, or a conflicting active owner. For an active agent, a `working`
106
+ status blocker is expected only when the current session owns the claim.
99
107
 
100
108
  ### Work
101
109
 
@@ -119,9 +127,16 @@ independently meaningful tasks need coordination.
119
127
 
120
128
  ## Human Launch vs Active Agent
121
129
 
122
- `agency work` is a human/orchestrator launch flow. It selects work, checks
123
- readiness, materializes managed checkouts, claims the execution unit, marks it
124
- working, and starts the configured runner.
130
+ `agency work` is a human/orchestrator launch flow. It first reconciles managed
131
+ integration files, then selects work and checks readiness. For an execution unit,
132
+ it materializes managed checkouts, claims the unit, marks it working, and starts
133
+ the selected built-in or configured runner. Epic and multi-phase task launches
134
+ start in orchestration context without materializing or claiming execution work.
135
+ OpenCode launches expose the managed config file and inject runtime-only access
136
+ rules scoped to the workbase. These grant visibility from orchestration
137
+ directories and nested execution checkouts while denying direct edits outside
138
+ the writable checkout. They do not make the Git-synced config machine-specific
139
+ or replace write authority from `agency context`.
125
140
 
126
141
  An agent already running in an Agency checkout must not call `agency work` to
127
142
  start itself again. It should inspect context, perform the assigned work, and
@@ -1,7 +1,8 @@
1
1
  # Agency Command Reference
2
2
 
3
- Use this reference after `agency context . --json` identifies the target. Run
4
- `agency <command> --help` for the exact options supported by the installed CLI.
3
+ Use this reference after `agency context . --json` identifies the target. The
4
+ forms below are exact for this Agency release. Run `agency <command> --help` when
5
+ using an option not shown here or when the installed CLI version differs.
5
6
  Commands that return Agency-owned data accept `--json` unless noted otherwise.
6
7
 
7
8
  ## Discovery And Health
@@ -25,10 +26,13 @@ checkout descendants, or a task ID. Complete output includes prose and Git
25
26
  details; `--compact` intentionally omits them. `graph` computes readiness before
26
27
  applying filters. `doctor` discovers required tools, integrations, repositories,
27
28
  refs, worktrees, permissions, drift, and optional runner capabilities. `sync` is
28
- observational unless `--apply` is explicit.
29
+ observational unless `--apply` is explicit. Integration status includes safe
30
+ remediation when customized OpenCode config prevents Agency from guaranteeing
31
+ whole-workbase access.
29
32
 
30
- `next` currently resolves only the process cwd. Although global `--cwd` and
31
- `--workbase` are accepted by the parser, run `next` from the intended workbase.
33
+ Where `[filters]` appears, use repeatable `--status <status>` and `--repository
34
+ <alias>`, plus `--ready` or `--blocked` and `--pr` or `--no-pr`. Each pair is
35
+ mutually exclusive.
32
36
 
33
37
  ## Workbase And Repositories
34
38
 
@@ -42,6 +46,7 @@ agency workbase name <id|name|path> (<name> | --clear) [--json]
42
46
  agency workbase default [<id|name|path> | --clear] [--json]
43
47
  agency workbase remove <id|name|path> [--json]
44
48
  agency workbase prune [--json]
49
+ agency repo setup [--dry-run | --apply] [--json]
45
50
  agency repo add <alias> <remote> [--json]
46
51
  agency repo link <alias> <path> [--json]
47
52
  agency repo list [--json]
@@ -54,9 +59,15 @@ agency repo remove <alias> [--json]
54
59
  agency repo unlink <alias> [--json]
55
60
  ```
56
61
 
57
- `repo add` creates a bare clone; `repo link` creates a symlink to an existing
58
- repository. Removal, unlink, and rename refuse active references or linked
59
- worktree conflicts.
62
+ `repo setup` defaults to an observational dry-run. Apply clones declared missing
63
+ repositories and adopts legacy materializations only when their portable origin
64
+ is unambiguous. Invalid paths and remote drift remain unresolved.
65
+
66
+ `repo add` creates a declaration and bare clone. `repo link` creates a local
67
+ symlink while retaining or inferring a credential-free portable remote.
68
+ `repo remove` removes both the declaration and unused local materialization;
69
+ `repo unlink` removes only this machine's symlink and retains the declaration.
70
+ Removal and rename refuse active references or linked worktree conflicts.
60
71
 
61
72
  ## Epics, Tasks, And Phases
62
73
 
@@ -131,7 +142,8 @@ worktrees when needed, preserve branches, and retain lifecycle provenance.
131
142
  ## Worktrees, Launch, And Pull Requests
132
143
 
133
144
  ```text
134
- agency work [<directory> | --epic <id>] [--runner <name>] [--print-command]
145
+ agency work [<directory-or-task-id> | --epic <id> | --task <id> [--phase <id>]]
146
+ [--runner <name> | --opencode | --claude] [--print-command] [--force]
135
147
  agency work prepare [target] [--dry-run] [--json]
136
148
  agency worktree list [--json]
137
149
  agency worktree inspect <task-id> [phase-id] [--json]
@@ -142,17 +154,26 @@ agency worktree repair <task-id> [phase-id] [--dry-run] [--json]
142
154
  agency pr create <task-id> [phase-id] [--draft] [--force] [--json]
143
155
  ```
144
156
 
145
- `work` is a launch flow, not an active-agent step. `work prepare` materializes
146
- without launching or changing status. Destructive remove and rebuild operations
147
- refuse dirty or conflicting state. Conservative repair may correct registration
148
- while preserving dirty files, but never discards changes. `pr create` requires a
149
- clean writable checkout, pushes the declared branch, invokes the configured
150
- delivery provider or falls back to `gh pr create --fill`, and records the
151
- returned URL.
157
+ `work` is a launch flow, not an active-agent step. It synchronizes managed
158
+ integration files before launch. Execution targets are materialized and claimed;
159
+ epics and multi-phase tasks launch in orchestration context without those steps.
160
+ The OpenCode runner receives a runtime managed-config path plus absolute access
161
+ and edit rules scoped to the workbase; none are persisted, and `context` still
162
+ defines write authority.
163
+ `--print-command` suppresses only the final launch, so execution targets are still
164
+ materialized and claimed before the command is printed. `work prepare`
165
+ materializes without launching or changing status. Destructive remove and
166
+ rebuild operations refuse dirty or conflicting state. Conservative repair may
167
+ correct registration while preserving dirty files, but never discards changes.
168
+ `pr create` materializes a missing workspace, requires the resulting writable
169
+ checkout to be clean, pushes the declared branch, invokes the configured delivery
170
+ provider or falls back to `gh pr create --fill`, and records the returned pull
171
+ request record.
152
172
 
153
173
  ## Noninteractive Selection
154
174
 
155
- Use global `--workbase <id|name|path>` outside a workbase, or `--cwd <path>` to
175
+ Use global `--workbase <id|name|path>` outside a workbase. A path may identify a
176
+ registered workbase or an existing workbase directly. Use `--cwd <path>` to
156
177
  perform cwd inference elsewhere. Targeted commands accept `--epic`, `--task`,
157
178
  and, with a task, `--phase`. `--json`, `--no-input`, or non-TTY execution disables
158
179
  prompts; provide all selectors and required inputs explicitly.
@@ -17,12 +17,36 @@ contains:
17
17
  and read-only references;
18
18
  - `workspace`: code path, materialization and registration state, commits, and
19
19
  inspection warnings;
20
- - `pr`: recorded URL and state; and
20
+ - `pr`: recorded provider-neutral pull request identity and state; and
21
21
  - `validation`: validity and issues.
22
22
 
23
23
  Compact context retains identity, revisions, authority, paths, graph state,
24
24
  materialization, and warnings while omitting prose and low-level Git details.
25
25
 
26
+ ## Repository Declarations
27
+
28
+ Tracked `agency.json` may contain portable repository declarations:
29
+
30
+ ```json
31
+ {
32
+ "version": 2,
33
+ "repositories": {
34
+ "frontend": { "remote": "git@example.com:team/frontend.git" }
35
+ }
36
+ }
37
+ ```
38
+
39
+ Remotes are provider-neutral network Git remotes. Local paths, file URLs, and
40
+ credential-bearing HTTP URLs are invalid. `repos/`, task and phase `code/`, and
41
+ symlink targets are local-only and never part of this contract.
42
+
43
+ Repository inspection returns `declaredRemote`, the actual local `remote`, and
44
+ orthogonal `states`: `declared`, `materialized`, `linked`, `missing`, `invalid`,
45
+ and `remote-drifted`. Setup JSON contains `mode`, `actions`, `unresolved`, and the
46
+ post-operation `repositories`. Actions are `materialize` or `adopt`, with
47
+ `planned` or `applied` status. Dry-run never mutates. Apply never overwrites a
48
+ link or path and never repairs drift without an explicit remote choice.
49
+
26
50
  ## Frontmatter Shapes
27
51
 
28
52
  ### Epic
@@ -98,9 +122,11 @@ status: open
98
122
  ```
99
123
 
100
124
  `ticketUrl` belongs to tasks and epics, not phases. `description` is optional but
101
- must be non-empty when present. `pr` is a GitHub PR URL or `null`. Status is
102
- `open`, `working`, `delegated`, `done`, or `dropped`; `delegated` is readable
103
- legacy state but cannot be newly assigned.
125
+ must be non-empty when present. `pr` is `null`, a legacy GitHub PR URL, or a
126
+ provider-neutral record containing `provider`, `repository`, `identifier`, `url`,
127
+ `state`, `draft`, and `merged`. New PR creation writes the structured record.
128
+ Status is `open`, `working`, `delegated`, `done`, or `dropped`; `delegated` is
129
+ readable legacy state but cannot be newly assigned.
104
130
 
105
131
  ## Structural Invariants
106
132
 
@@ -167,7 +193,7 @@ CLI subprocess output. The Effect schemas are exported by the package and by
167
193
 
168
194
  Only the envelope and graph result have published JSON Schemas. The envelope's
169
195
  `result` is intentionally unconstrained. Context, next, claim, prepare, sync,
170
- and PR result shapes are exercised by CLI tests but do not have independent
196
+ repository setup, and PR result shapes are exercised by CLI tests but do not have independent
171
197
  published schemas.
172
198
 
173
199
  ### Output And Exit Guarantees
@@ -244,18 +270,18 @@ mutations recheck every affected file while holding the graph mutation lock.
244
270
 
245
271
  ## Selectors And Projections
246
272
 
247
- `--workbase <id|name|path>` selects a registered workbase. `--cwd <path>` asks
248
- Agency to perform target inference as if invoked there. They are mutually
249
- exclusive. Targeted commands accept `--epic`, `--task`, and `--phase` where
250
- applicable; phase requires task, and entity selectors cannot be combined with a
251
- positional target ID. Non-target positional values, such as a status outcome,
252
- remain valid where the command syntax requires them.
273
+ `--workbase <id|name|path>` selects a registered workbase by ID, name, or path;
274
+ an existing path may also resolve an unregistered workbase directly. `--cwd
275
+ <path>` asks Agency to perform target inference as if invoked there. They are
276
+ mutually exclusive. Targeted commands accept `--epic`, `--task`, and `--phase`
277
+ where applicable; phase requires task, and entity selectors cannot be combined
278
+ with a positional target ID. Non-target positional values, such as a status
279
+ outcome, remain valid where the command syntax requires them.
253
280
 
254
281
  `--json`, `--no-input`, and non-TTY execution disable interactive prompts and
255
- selection. Supply every required value or explicit entity selector. The current
256
- `next` implementation uses the process cwd even when global `--cwd` or
257
- `--workbase` parses successfully; run `next --json` from the intended workbase
258
- until that routing gap is fixed.
282
+ selection. Supply every required value or explicit entity selector. Global
283
+ `--cwd` and `--workbase` selectors apply to `next` as they do to other discovery
284
+ commands.
259
285
 
260
286
  Context defaults to the `complete` projection. `--compact` omits prose and
261
287
  low-level Git details but retains identity, document hashes, authority, paths,
@@ -273,10 +299,11 @@ node set.
273
299
  and `claim` does not enforce dependency readiness. Inspect readiness, then
274
300
  claim with the observed revision and handle conflicts.
275
301
  - There is no `assign` command, remote queue, scheduler, heartbeat, claim renewal,
276
- runner monitor, or cancellation API. `work` can claim and launch one local
277
- configured runner, but it is a process-launching, non-JSON flow rather than a
278
- machine assignment API. External orchestrators claim with claimant and runner
279
- IDs, then manage their runner themselves.
302
+ runner monitor, or cancellation API. For an execution unit, `work` can claim
303
+ and launch one local built-in or configured runner, but it is a
304
+ process-launching, non-JSON flow rather than a machine assignment API. External
305
+ orchestrators claim with claimant and runner IDs, then manage their runner
306
+ themselves.
280
307
  - Agency does not edit code, create commits, run repository checks, wait for PR
281
308
  checks, merge PRs, or verify that a requested completion condition is true.
282
309
  `finish` records the caller's asserted outcome after ownership checks.
@@ -2,7 +2,9 @@
2
2
 
3
3
  For an entity target, run `agency context . --json` before selecting a recipe.
4
4
  At the workbase root, use `agency next --json` or `agency graph --json` to choose
5
- a target, then inspect that explicit target with `agency context <target> --json`.
5
+ a target, then inspect it with explicit `--epic`, `--task`, and `--phase`
6
+ selectors or its returned document path. Graph node keys such as `task/<id>` and
7
+ `phase/<task>/<phase>` are not positional context targets.
6
8
 
7
9
  The machine-orchestration forms in the inspect-through-recover recipes are
8
10
  captured in `fixtures/protocol/orchestration-recipes.json` and tested against the
@@ -10,6 +12,38 @@ real CLI parser. Their lifecycle behavior is covered by CLI and service fixtures
10
12
  Replace angle-bracket placeholders with values from context or a prior machine
11
13
  result; never scrape them from human output.
12
14
 
15
+ ## Initialize A Workbase
16
+
17
+ For an existing local checkout, initialize the workbase and link the repository:
18
+
19
+ ```bash
20
+ agency init <workbase-path>
21
+ agency --workbase <workbase-path> repo link <alias> <repository-path>
22
+ agency validate <workbase-path>
23
+ agency --workbase <workbase-path> repo verify <alias>
24
+ ```
25
+
26
+ Use `repo add <alias> <remote>` instead when Agency should create and manage a
27
+ bare clone from a remote. Initialization and repository registration require
28
+ explicit user intent.
29
+
30
+ ## Restore A Workbase On A New Machine
31
+
32
+ After cloning the tracked workbase, inspect repository setup before applying it:
33
+
34
+ ```bash
35
+ agency repo setup --dry-run --json
36
+ agency repo setup --apply --json
37
+ agency validate
38
+ agency doctor --json
39
+ ```
40
+
41
+ Apply clones only declared missing repositories. It does not overwrite linked
42
+ checkouts, repair invalid paths, or choose between drifted remotes. Resolve those
43
+ states explicitly, then rerun setup. A machine may replace an unused managed
44
+ clone with `repo link`; the portable declaration remains available to every
45
+ other machine.
46
+
13
47
  ## Inspect A Target
14
48
 
15
49
  ```bash
@@ -53,9 +87,11 @@ agency validate
53
87
  agency work tasks/checkout/phases/api
54
88
  ```
55
89
 
56
- `agency work` is intentionally last: it checks readiness, materializes
57
- worktrees, creates a claim, marks the execution unit working, and launches the
58
- runner.
90
+ `agency work` is intentionally last: it synchronizes managed integration files,
91
+ checks readiness, materializes worktrees, creates a claim, marks this execution
92
+ unit working, and launches the runner. OpenCode receives whole-workbase read
93
+ visibility through runtime-only config and permission values; this does not
94
+ expand the writable checkout reported by `agency context`.
59
95
 
60
96
  ## Active Agent: Execute Assigned Work
61
97
 
@@ -63,8 +99,10 @@ runner.
63
99
  agency context . --json
64
100
  ```
65
101
 
66
- 1. Verify context reports the expected execution target, no blockers, valid
67
- structure, and the current checkout as `authority.writable.checkoutPath`.
102
+ 1. Verify context reports the expected execution target, valid structure, the
103
+ current checkout as `authority.writable.checkoutPath`, and a claim owned by
104
+ the current session. Reject dependency or validation blockers and conflicting
105
+ claims; the owned unit's `working` status blocker is expected.
68
106
  2. Read `TASK.md`, and `PHASE.md` for phase work.
69
107
  3. Implement only in the writable checkout; treat all reference checkouts as
70
108
  read-only.
@@ -160,11 +198,12 @@ agency validate
160
198
  agency pr create checkout ui --json
161
199
  ```
162
200
 
163
- The writable worktree must be clean. Agency pushes the declared branch, invokes
164
- the configured delivery provider's create command or falls back to
165
- `gh pr create --fill`, and records the returned URL. Do not manually write a URL
166
- if creation fails. A PR being open is not equivalent to completion when the
167
- assigned outcome requires merge.
201
+ Agency materializes a missing workspace, then requires the writable worktree to
202
+ be clean. It pushes the declared branch, invokes the configured delivery
203
+ provider's create command or falls back to `gh pr create --fill`, and records the
204
+ returned pull request record. Do not manually write a URL or record if creation
205
+ fails. A PR being open is not equivalent to completion when the assigned outcome
206
+ requires merge.
168
207
 
169
208
  Agency does not create commits, run tests, wait for checks, merge the PR, or
170
209
  verify completion. Those remain orchestrator responsibilities.
@@ -214,6 +253,7 @@ agency restore phase checkout ui --dry-run --json
214
253
  agency restore phase checkout ui
215
254
  ```
216
255
 
217
- Archive only terminal work and only with explicit intent. Agency preserves the
256
+ As an operating policy, archive only terminal work and only with explicit intent;
257
+ the CLI also permits safe archival of nonterminal work. Agency preserves the
218
258
  branch and lifecycle provenance while enforcing graph, worktree, and destination
219
259
  safety. Never move archived directories by hand.
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test"
2
2
  import orchestrationRecipes from "../fixtures/protocol/orchestration-recipes.json"
3
+ import skillSetupCommands from "../fixtures/protocol/skill-setup-commands.json"
3
4
  import { parseCli } from "./cli-parser"
4
5
 
5
6
  const expectUsageError = (args: string[], usage: string) => {
@@ -13,6 +14,12 @@ describe("strict CLI parsing", () => {
13
14
  }
14
15
  })
15
16
 
17
+ test("accepts every documented skill setup command", () => {
18
+ for (const args of skillSetupCommands) {
19
+ expect(() => parseCli(args)).not.toThrow()
20
+ }
21
+ })
22
+
16
23
  test("rejects misspelled and command-inapplicable options", () => {
17
24
  expectUsageError(["task", "list", "--josn"], "agency task")
18
25
  expectUsageError(