@markjaquith/agency 2.28.1 → 2.30.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.
Files changed (42) hide show
  1. package/README.md +63 -12
  2. package/cli.ts +15 -0
  3. package/fixtures/protocol/skill-setup-commands.json +18 -0
  4. package/package.json +1 -1
  5. package/skills/agency/SKILL.md +25 -15
  6. package/skills/agency/references/commands.md +34 -17
  7. package/skills/agency/references/contracts.md +46 -19
  8. package/skills/agency/references/recipes.md +50 -12
  9. package/src/cli-parser.test.ts +9 -0
  10. package/src/cli-parser.ts +20 -3
  11. package/src/cli.test.ts +205 -3
  12. package/src/commands/pr.test.ts +20 -1
  13. package/src/commands/repo.test.ts +66 -1
  14. package/src/commands/repo.ts +35 -8
  15. package/src/commands/status.test.ts +22 -0
  16. package/src/commands/status.ts +1 -0
  17. package/src/commands/sync.ts +5 -3
  18. package/src/commands/workbase.ts +2 -1
  19. package/src/graph-schema.test.ts +52 -4
  20. package/src/protocol.test.ts +41 -8
  21. package/src/readiness.test.ts +75 -17
  22. package/src/services/DoctorService.ts +22 -13
  23. package/src/services/EpicService.ts +1 -1
  24. package/src/services/GraphMutationService.ts +3 -3
  25. package/src/services/GraphService.ts +13 -4
  26. package/src/services/PhaseService.ts +1 -1
  27. package/src/services/ReadinessService.test.ts +47 -0
  28. package/src/services/RepositoryService.test.ts +299 -5
  29. package/src/services/RepositoryService.ts +725 -98
  30. package/src/services/SyncService.test.ts +36 -0
  31. package/src/services/SyncService.ts +20 -1
  32. package/src/services/TaskService.ts +1 -1
  33. package/src/services/WorkbaseService.test.ts +32 -0
  34. package/src/services/WorkbaseService.ts +22 -14
  35. package/src/services/WorktreeLock.test.ts +122 -0
  36. package/src/services/WorktreeService.test.ts +17 -2
  37. package/src/services/WorktreeService.ts +3 -3
  38. package/src/utils/process.test.ts +4 -3
  39. package/src/workbase/AGENTS.md +5 -0
  40. package/src/workbase/dependency-graph.test.ts +50 -0
  41. package/src/workbase/schemas.test.ts +52 -0
  42. package/src/workbase/schemas.ts +19 -0
package/README.md CHANGED
@@ -44,8 +44,8 @@ workbase/
44
44
  AGENTS.md # managed workbase instructions
45
45
  .opencode/
46
46
  opencode.jsonc # managed task and epic references
47
- agency.json
48
- repos/
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/
@@ -82,8 +82,27 @@ external-directory access, so Agency does not add blanket permission rules that
82
82
  could hide missing tool permissions. References provide context and never expand
83
83
  the write authority reported by `agency context`.
84
84
 
85
- Repository metadata comes directly from Git under `repos/{alias}`. Workbase
86
- configuration may provide a custom writable-worktree creation command.
85
+ Repository aliases and canonical fetch remotes are declared in tracked
86
+ `agency.json`; local bare clones and symlinks remain ignored under
87
+ `repos/{alias}`. A declaration contains no local path, symlink target, checkout,
88
+ or credential:
89
+
90
+ ```json
91
+ {
92
+ "version": 2,
93
+ "repositories": {
94
+ "frontend": {
95
+ "remote": "git@example.com:team/frontend.git"
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Existing version 2 workbases without `repositories` remain valid. Run
102
+ `agency repo setup` to preview deterministic adoption of legacy local aliases;
103
+ `agency repo setup --apply` writes declarations only when a portable origin is
104
+ unambiguous. Workbase configuration may also provide a custom writable-worktree
105
+ creation command.
87
106
 
88
107
  ### Custom Worktree Command
89
108
 
@@ -284,7 +303,7 @@ owning `TASK.md`. Stable IDs do not encode ordering in directory names.
284
303
  ## Quick Start
285
304
 
286
305
  ```bash
287
- agency init ~/work
306
+ agency workbase init ~/work
288
307
  cd ~/work
289
308
 
290
309
  agency repo add frontend git@github.com:example/frontend.git
@@ -298,6 +317,15 @@ agency work tasks/refresh-copy
298
317
  agency pr create refresh-copy
299
318
  ```
300
319
 
320
+ After cloning an existing workbase on another machine, restore its declared
321
+ repositories before preparing work:
322
+
323
+ ```bash
324
+ agency repo setup --dry-run
325
+ agency repo setup --apply
326
+ agency validate
327
+ ```
328
+
301
329
  ## Commands
302
330
 
303
331
  ### Target Context
@@ -361,27 +389,33 @@ materializing or pushing. Blocked, done, and dropped targets are rejected unless
361
389
 
362
390
  ### Reconciliation
363
391
 
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
392
+ `agency sync` first compares portable repository declarations with local
393
+ materializations, then compares every execution declaration with local branch
394
+ and worktree registration, checkout dirtiness, resolved reference commits, claim
395
+ expiry, and pull request and merge state. It reports
367
396
  structured `changes`, `warnings`, `unresolved`, and per-execution evidence. The
368
397
  default and `--dry-run` modes are observational.
369
398
 
370
399
  `agency sync --apply` performs only these safe transitions:
371
400
 
401
+ - materialize declared but missing repositories from their canonical remotes;
402
+ - adopt legacy materializations only when they have an unambiguous portable origin;
372
403
  - materialize missing checkouts when no registration, branch, or path conflicts;
373
404
  - release an active claim only after its declared expiry has passed;
374
405
  - record a single PR whose head and base match the declaration; and
375
406
  - mark work done after its authoritative PR is merged and no active claim remains.
376
407
 
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.
408
+ Apply never overwrites linked or invalid repositories, repairs remote drift,
409
+ modifies dirty checkouts, moves worktrees, switches branches, resets reference
410
+ commits, chooses among conflicting remotes or PRs, or bypasses active claims.
411
+ Those conditions remain visible in `warnings` or `unresolved` with a suggested
412
+ action.
380
413
 
381
414
  ### Workbase and Repositories
382
415
 
383
416
  ```text
384
- agency init [path] [--json]
417
+ agency workbase init [path] [--json]
418
+ agency init [path] [--json] # Alias
385
419
  agency workbase add <path> [--name <name>] [--json]
386
420
  agency workbase list [--json]
387
421
  agency workbase show <id|name|path> [--json]
@@ -392,6 +426,7 @@ agency workbase prune [--json]
392
426
  agency workbase default [<id|name|path> | --clear] [--json]
393
427
  agency integration status [--json]
394
428
  agency integration sync [--json]
429
+ agency repo setup [--dry-run | --apply] [--json]
395
430
  agency repo add <alias> <remote> [--json]
396
431
  agency repo link <alias> <path> [--json]
397
432
  agency repo list [--json]
@@ -404,6 +439,22 @@ agency repo remote <alias> [remote] [--json]
404
439
  agency repo verify <alias> [--json]
405
440
  ```
406
441
 
442
+ Repository JSON output exposes state facets rather than hiding partial setup:
443
+ `declared`, `materialized`, `linked`, `missing`, `invalid`, and
444
+ `remote-drifted`. A normal bare clone is declared and materialized; a local
445
+ checkout is declared and linked; a fresh workbase clone is declared and missing
446
+ until setup is applied.
447
+
448
+ `repo add`, `link`, `remote`, `rename`, and `remove` update the portable
449
+ declaration transactionally with local state. `repo remove` removes both the
450
+ declaration and an unused local materialization. `repo unlink` removes only this
451
+ machine's symlink and retains the declaration, leaving an actionable missing
452
+ state. Linking a local checkout over an unused managed clone likewise retains the
453
+ portable remote for other machines. `repo remote` updates managed clones but
454
+ never mutates an external linked checkout; drift remains visible until that
455
+ checkout is updated explicitly. Credential-bearing URLs, file URLs, and local
456
+ paths are never accepted as declarations.
457
+
407
458
  Registered workbases are stored in
408
459
  `$XDG_CONFIG_HOME/agency/workbases.json` (or `~/.config/agency/workbases.json`).
409
460
  Each registration has a stable ID and may have a unique name. A default workbase
package/cli.ts CHANGED
@@ -358,6 +358,18 @@ const commands: Record<string, Command> = {
358
358
  console.log(workbaseHelp)
359
359
  return
360
360
  }
361
+ if (args[0] === "init") {
362
+ await runCommand(
363
+ init({
364
+ path: args[1],
365
+ json: options.json,
366
+ silent: options.silent,
367
+ verbose: options.verbose,
368
+ cwd: options.cwd,
369
+ }),
370
+ )
371
+ return
372
+ }
361
373
  await runCommand(
362
374
  workbase({
363
375
  subcommand: args[0],
@@ -402,6 +414,8 @@ const commands: Record<string, Command> = {
402
414
  silent: options.silent,
403
415
  verbose: options.verbose,
404
416
  json: options.json,
417
+ dryRun: options["dry-run"],
418
+ apply: options.apply,
405
419
  cwd: options.cwd,
406
420
  }),
407
421
  )
@@ -502,6 +516,7 @@ const commands: Record<string, Command> = {
502
516
  json: options.json,
503
517
  silent: options.silent,
504
518
  verbose: options.verbose,
519
+ cwd: options.cwd,
505
520
  }),
506
521
  )
507
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.28.1",
3
+ "version": "2.30.0",
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,11 @@ 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.
125
135
 
126
136
  An agent already running in an Agency checkout must not call `agency work` to
127
137
  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
@@ -27,13 +28,15 @@ applying filters. `doctor` discovers required tools, integrations, repositories,
27
28
  refs, worktrees, permissions, drift, and optional runner capabilities. `sync` is
28
29
  observational unless `--apply` is explicit.
29
30
 
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.
31
+ Where `[filters]` appears, use repeatable `--status <status>` and `--repository
32
+ <alias>`, plus `--ready` or `--blocked` and `--pr` or `--no-pr`. Each pair is
33
+ mutually exclusive.
32
34
 
33
35
  ## Workbase And Repositories
34
36
 
35
37
  ```text
36
- agency init [path] [--json]
38
+ agency workbase init [path] [--json]
39
+ agency init [path] [--json] # Alias
37
40
  agency workbase add <path> [--name <name>] [--json]
38
41
  agency workbase list [--json]
39
42
  agency workbase show <id|name|path> [--json]
@@ -41,6 +44,7 @@ agency workbase name <id|name|path> (<name> | --clear) [--json]
41
44
  agency workbase default [<id|name|path> | --clear] [--json]
42
45
  agency workbase remove <id|name|path> [--json]
43
46
  agency workbase prune [--json]
47
+ agency repo setup [--dry-run | --apply] [--json]
44
48
  agency repo add <alias> <remote> [--json]
45
49
  agency repo link <alias> <path> [--json]
46
50
  agency repo list [--json]
@@ -53,9 +57,15 @@ agency repo remove <alias> [--json]
53
57
  agency repo unlink <alias> [--json]
54
58
  ```
55
59
 
56
- `repo add` creates a bare clone; `repo link` creates a symlink to an existing
57
- repository. Removal, unlink, and rename refuse active references or linked
58
- worktree conflicts.
60
+ `repo setup` defaults to an observational dry-run. Apply clones declared missing
61
+ repositories and adopts legacy materializations only when their portable origin
62
+ is unambiguous. Invalid paths and remote drift remain unresolved.
63
+
64
+ `repo add` creates a declaration and bare clone. `repo link` creates a local
65
+ symlink while retaining or inferring a credential-free portable remote.
66
+ `repo remove` removes both the declaration and unused local materialization;
67
+ `repo unlink` removes only this machine's symlink and retains the declaration.
68
+ Removal and rename refuse active references or linked worktree conflicts.
59
69
 
60
70
  ## Epics, Tasks, And Phases
61
71
 
@@ -130,7 +140,8 @@ worktrees when needed, preserve branches, and retain lifecycle provenance.
130
140
  ## Worktrees, Launch, And Pull Requests
131
141
 
132
142
  ```text
133
- agency work [<directory> | --epic <id>] [--runner <name>] [--print-command]
143
+ agency work [<directory-or-task-id> | --epic <id> | --task <id> [--phase <id>]]
144
+ [--runner <name> | --opencode | --claude] [--print-command] [--force]
134
145
  agency work prepare [target] [--dry-run] [--json]
135
146
  agency worktree list [--json]
136
147
  agency worktree inspect <task-id> [phase-id] [--json]
@@ -141,17 +152,23 @@ agency worktree repair <task-id> [phase-id] [--dry-run] [--json]
141
152
  agency pr create <task-id> [phase-id] [--draft] [--force] [--json]
142
153
  ```
143
154
 
144
- `work` is a launch flow, not an active-agent step. `work prepare` materializes
145
- without launching or changing status. Destructive remove and rebuild operations
146
- refuse dirty or conflicting state. Conservative repair may correct registration
147
- while preserving dirty files, but never discards changes. `pr create` requires a
148
- clean writable checkout, pushes the declared branch, invokes the configured
149
- delivery provider or falls back to `gh pr create --fill`, and records the
150
- returned URL.
155
+ `work` is a launch flow, not an active-agent step. It synchronizes managed
156
+ integration files before launch. Execution targets are materialized and claimed;
157
+ epics and multi-phase tasks launch in orchestration context without those steps.
158
+ `--print-command` suppresses only the final launch, so execution targets are still
159
+ materialized and claimed before the command is printed. `work prepare`
160
+ materializes without launching or changing status. Destructive remove and
161
+ rebuild operations refuse dirty or conflicting state. Conservative repair may
162
+ correct registration while preserving dirty files, but never discards changes.
163
+ `pr create` materializes a missing workspace, requires the resulting writable
164
+ checkout to be clean, pushes the declared branch, invokes the configured delivery
165
+ provider or falls back to `gh pr create --fill`, and records the returned pull
166
+ request record.
151
167
 
152
168
  ## Noninteractive Selection
153
169
 
154
- Use global `--workbase <id|name|path>` outside a workbase, or `--cwd <path>` to
170
+ Use global `--workbase <id|name|path>` outside a workbase. A path may identify a
171
+ registered workbase or an existing workbase directly. Use `--cwd <path>` to
155
172
  perform cwd inference elsewhere. Targeted commands accept `--epic`, `--task`,
156
173
  and, with a task, `--phase`. `--json`, `--no-input`, or non-TTY execution disables
157
174
  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,9 @@ 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.
59
93
 
60
94
  ## Active Agent: Execute Assigned Work
61
95
 
@@ -63,8 +97,10 @@ runner.
63
97
  agency context . --json
64
98
  ```
65
99
 
66
- 1. Verify context reports the expected execution target, no blockers, valid
67
- structure, and the current checkout as `authority.writable.checkoutPath`.
100
+ 1. Verify context reports the expected execution target, valid structure, the
101
+ current checkout as `authority.writable.checkoutPath`, and a claim owned by
102
+ the current session. Reject dependency or validation blockers and conflicting
103
+ claims; the owned unit's `working` status blocker is expected.
68
104
  2. Read `TASK.md`, and `PHASE.md` for phase work.
69
105
  3. Implement only in the writable checkout; treat all reference checkouts as
70
106
  read-only.
@@ -160,11 +196,12 @@ agency validate
160
196
  agency pr create checkout ui --json
161
197
  ```
162
198
 
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.
199
+ Agency materializes a missing workspace, then requires the writable worktree to
200
+ be clean. It pushes the declared branch, invokes the configured delivery
201
+ provider's create command or falls back to `gh pr create --fill`, and records the
202
+ returned pull request record. Do not manually write a URL or record if creation
203
+ fails. A PR being open is not equivalent to completion when the assigned outcome
204
+ requires merge.
168
205
 
169
206
  Agency does not create commits, run tests, wait for checks, merge the PR, or
170
207
  verify completion. Those remain orchestrator responsibilities.
@@ -214,6 +251,7 @@ agency restore phase checkout ui --dry-run --json
214
251
  agency restore phase checkout ui
215
252
  ```
216
253
 
217
- Archive only terminal work and only with explicit intent. Agency preserves the
254
+ As an operating policy, archive only terminal work and only with explicit intent;
255
+ the CLI also permits safe archival of nonterminal work. Agency preserves the
218
256
  branch and lifecycle provenance while enforcing graph, worktree, and destination
219
257
  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(
@@ -139,6 +146,7 @@ describe("strict CLI parsing", () => {
139
146
  ["repo", "remote", "agency", "https://example.com/repo.git"],
140
147
  ["repo", "verify", "agency"],
141
148
  ["workbase", "show", "primary", "--json"],
149
+ ["workbase", "init", "new-workbase", "--json"],
142
150
  ["workbase", "name", "primary", "renamed"],
143
151
  ["workbase", "name", "primary", "--clear"],
144
152
  ]) {
@@ -164,6 +172,7 @@ describe("strict CLI parsing", () => {
164
172
  test("enforces exact maximum positional arity for every leaf command", () => {
165
173
  for (const [args, usage] of [
166
174
  [["init", "one", "two"], "agency init"],
175
+ [["workbase", "init", "one", "two"], "agency workbase init"],
167
176
  [["workbase", "add", "one", "two"], "agency workbase add"],
168
177
  [["workbase", "list", "extra"], "agency workbase list"],
169
178
  [["integration", "status", "extra"], "agency integration status"],