@markjaquith/agency 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -255,6 +255,32 @@ Complete output is the default. Pass `--compact` explicitly to omit document
255
255
  prose and low-level Git details while retaining identity, hashes, authority,
256
256
  paths, graph state, materialization state, and validation warnings.
257
257
 
258
+ ### Workbase Graph
259
+
260
+ `agency graph --json` exports the complete workbase as graph contract version 1.
261
+ Nodes use stable IDs (`epic:<id>`, `task:<id>`, `phase:<task>/<phase>`,
262
+ `repository:<alias>`, and `execution-unit:<kind>/<id>`). Typed edges are `owns`,
263
+ `depends_on`, `writes`, and `references`.
264
+
265
+ Every work node includes status, readiness, blockers, reverse dependents, and
266
+ aggregate progress. Only `done` satisfies a dependency. The graph summary counts
267
+ the statuses of all execution units, independent of filters.
268
+
269
+ ```text
270
+ agency graph [--json | --jsonl] [--ready | --blocked]
271
+ [--status <status>...] [--repository <alias>...] [--kind <kind>...]
272
+ [--include <bodies|workspace|git|pr>...]
273
+ ```
274
+
275
+ Filters are applied after graph state is computed. Returned edges always have
276
+ both endpoints in the filtered node set. Durable frontmatter and document hashes
277
+ are always present; prose, absolute workspace paths, Git inspection, and live PR
278
+ inspection are opt-in include layers.
279
+
280
+ `--jsonl` emits a versioned `meta` record, one record per node and edge, then an
281
+ `end` record with counts. Combining the metadata with the streamed node and edge
282
+ records reconstructs the same result as `--json`.
283
+
258
284
  ### Workbase and Repositories
259
285
 
260
286
  ```text
@@ -275,7 +301,7 @@ repository. Alias names are then used by all documents and commands.
275
301
 
276
302
  Commands that print Agency-owned results accept `--json`, including initialization,
277
303
  integration inspection/sync, repository mutations, entity creation/list/show,
278
- status, validation, and PR creation.
304
+ status, validation, graph export, and PR creation.
279
305
 
280
306
  ### Epics
281
307
 
@@ -477,14 +503,16 @@ recovery action. Version 1 defines these codes:
477
503
  | `ARCHIVE_ERROR` | Archive operation failed |
478
504
  | `WORKTREE_ERROR` | Worktree operation failed |
479
505
  | `PULL_REQUEST_ERROR` | Pull request operation failed |
506
+ | `GRAPH_ERROR` | Workbase graph construction failed |
480
507
  | `PROCESS_ERROR` | A child process failed and may be retried |
481
508
  | `PROTOCOL_OUTPUT_ERROR` | A command violated the machine output contract |
482
509
  | `COMMAND_FAILED` | An otherwise unclassified command failure |
483
510
 
484
511
  The Effect schemas are exported from `@markjaquith/agency` and
485
- `@markjaquith/agency/protocol`. The distributable JSON Schema is exported as
486
- `@markjaquith/agency/schemas/agency-envelope-v1.json`. Representative payloads
487
- are exported as `@markjaquith/agency/fixtures/protocol/success.json` and
512
+ `@markjaquith/agency/protocol`. The distributable JSON Schemas are exported as
513
+ `@markjaquith/agency/schemas/agency-envelope-v1.json` and
514
+ `@markjaquith/agency/schemas/agency-graph-v1.json`. Representative envelope
515
+ payloads are exported as `@markjaquith/agency/fixtures/protocol/success.json` and
488
516
  `@markjaquith/agency/fixtures/protocol/error.json`.
489
517
 
490
518
  ## Agent Skill
package/cli.ts CHANGED
@@ -9,6 +9,7 @@ import { work, help as workHelp } from "./src/commands/work"
9
9
  import { status, help as statusHelp } from "./src/commands/status"
10
10
  import { validate, help as validateHelp } from "./src/commands/validate"
11
11
  import { context, help as contextHelp } from "./src/commands/context"
12
+ import { graph, help as graphHelp } from "./src/commands/graph"
12
13
  import { repo, help as repoHelp } from "./src/commands/repo"
13
14
  import { epic, help as epicHelp } from "./src/commands/epic"
14
15
  import { phase, help as phaseHelp } from "./src/commands/phase"
@@ -30,6 +31,7 @@ import { PullRequestService } from "./src/services/PullRequestService"
30
31
  import { ArchiveService } from "./src/services/ArchiveService"
31
32
  import { IntegrationService } from "./src/services/IntegrationService"
32
33
  import { ContextService } from "./src/services/ContextService"
34
+ import { GraphService } from "./src/services/GraphService"
33
35
  import {
34
36
  collectCommandResult,
35
37
  errorEnvelope,
@@ -50,6 +52,7 @@ const CliLayer = Layer.mergeAll(
50
52
  ArchiveService.Default,
51
53
  IntegrationService.Default,
52
54
  ContextService.Default,
55
+ GraphService.Default,
53
56
  )
54
57
 
55
58
  /**
@@ -333,6 +336,28 @@ const commands: Record<string, Command> = {
333
336
  )
334
337
  },
335
338
  },
339
+ graph: {
340
+ run: async (_args: string[], options: Record<string, any>) => {
341
+ if (options.help) {
342
+ console.log(graphHelp)
343
+ return
344
+ }
345
+ await runCommand(
346
+ graph({
347
+ json: options.json,
348
+ jsonl: options.jsonl,
349
+ ready: options.ready,
350
+ blocked: options.blocked,
351
+ statuses: options.status,
352
+ repositories: options.repository,
353
+ kinds: options.kind,
354
+ include: options.include,
355
+ silent: options.silent,
356
+ verbose: options.verbose,
357
+ }),
358
+ )
359
+ },
360
+ },
336
361
  }
337
362
 
338
363
  function showMainHelp() {
@@ -355,6 +380,7 @@ Commands:
355
380
  status Show status for the current workbase
356
381
  validate [path] Validate a workbase
357
382
  context [target] Return complete target context
383
+ graph Export the complete workbase graph
358
384
 
359
385
  Global Options:
360
386
  -h, --help Show help for a command
@@ -373,7 +399,9 @@ For more information about a command, run:
373
399
  `)
374
400
  }
375
401
 
376
- const machineMode = process.argv.slice(2).includes("--json")
402
+ const machineMode = process.argv
403
+ .slice(2)
404
+ .some((argument) => argument === "--json" || argument === "--jsonl")
377
405
 
378
406
  try {
379
407
  const args = process.argv.slice(2)
@@ -401,11 +429,13 @@ try {
401
429
  !values.json &&
402
430
  !values["no-input"] &&
403
431
  Boolean(process.stdin.isTTY && process.stderr.isTTY)
404
- if (values.json) {
432
+ if (values.json || (values.jsonl && values.help)) {
405
433
  const result = await collectCommandResult(() =>
406
434
  command.run(commandArgs, { ...values, inputAllowed }),
407
435
  )
408
436
  writeEnvelope(successEnvelope(result))
437
+ } else if (values.jsonl) {
438
+ await command.run(commandArgs, { ...values, inputAllowed: false })
409
439
  } else {
410
440
  await command.run(commandArgs, { ...values, inputAllowed })
411
441
  }
package/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./src/workbase/schemas"
2
2
  export * from "./src/protocol"
3
+ export * from "./src/graph-schema"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -41,6 +41,9 @@
41
41
  "./schemas/agency-envelope-v1.json": {
42
42
  "default": "./schemas/agency-envelope-v1.schema.json"
43
43
  },
44
+ "./schemas/agency-graph-v1.json": {
45
+ "default": "./schemas/agency-graph-v1.schema.json"
46
+ },
44
47
  "./fixtures/protocol/success.json": {
45
48
  "default": "./fixtures/protocol/success.json"
46
49
  },