mirai-graph 1.0.0 → 1.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.
Files changed (31) hide show
  1. package/.github/workflows/ci.yml +19 -0
  2. package/CHANGELOG.md +50 -0
  3. package/CITATION.cff +2 -1
  4. package/README.md +21 -2
  5. package/ROADMAP.md +11 -16
  6. package/docs/adoption/cli.md +16 -1
  7. package/examples/project-technology-context-traversal/README.md +17 -0
  8. package/examples/project-technology-context-traversal/graph/objects.json +78 -0
  9. package/examples/project-technology-context-traversal/graph/relations.json +47 -0
  10. package/examples/project-technology-context-traversal/graph.json +30 -0
  11. package/examples/project-technology-context-traversal/selection.example.json +29 -0
  12. package/examples/project-technology-context-traversal/sources/announcement.md +3 -0
  13. package/examples/project-technology-context-traversal/sources/release-guide.md +3 -0
  14. package/examples/project-technology-context-traversal/sources/release-smoke.md +3 -0
  15. package/examples/project-technology-context-traversal/sources/rollback-policy.md +3 -0
  16. package/package.json +4 -3
  17. package/packages/cli/project-technology.js +43 -3
  18. package/packages/cli/validate-context-traversal.js +292 -0
  19. package/packages/cli/validate-mirai-graph.js +21 -2
  20. package/packages/project-technology/context-traversal.js +668 -0
  21. package/packages/project-technology/index.js +23 -40
  22. package/releases/1.1.0.md +36 -0
  23. package/releases/1.1.1.md +25 -0
  24. package/releases/README.md +2 -0
  25. package/schemas/context-pack.schema.json +54 -1
  26. package/schemas/context-traversal-receipt.schema.json +64 -0
  27. package/standard/context-pack-generation.md +38 -1
  28. package/standard/object-model.md +11 -2
  29. package/standard/project-technology.md +37 -1
  30. package/standard/relation-model.md +11 -1
  31. package/standard/test-suite.md +5 -1
@@ -7,6 +7,25 @@ on:
7
7
  pull_request:
8
8
 
9
9
  jobs:
10
+ context-traversal:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ runs-on: ${{ matrix.os }}
16
+
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Setup Node
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: "20"
25
+
26
+ - name: Verify deterministic context traversal
27
+ run: node packages/cli/validate-context-traversal.js
28
+
10
29
  release-check:
11
30
  runs-on: ubuntu-latest
12
31
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,56 @@ All notable changes to Mirai Graph will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.1.1] - 2026-08-26
8
+
9
+ ### Fixed
10
+
11
+ - Sequential context traversal now reads the accepted legacy aliases used by
12
+ existing `graph.json` 2.0.0 repositories (`type`, `from`, `to`,
13
+ `relation_type` and `status`) without requiring a graph rewrite.
14
+ - Established structural and required relation names are projected onto the
15
+ public traversal vocabulary while preserving their direction and mandatory
16
+ closure semantics.
17
+ - Existing accepted Mirai readiness levels and revision-bound objects without
18
+ an explicit historical readiness field remain usable; draft, seed, gap,
19
+ blocked, stale and deprecated states still fail closed.
20
+
21
+ ### Compatibility
22
+
23
+ - This patch makes the 1.1.0 compatibility promise executable. It does not
24
+ change schema `2.0.0`, the Project Technology activation contract, provider
25
+ transport or write boundaries.
26
+
27
+ ## [1.1.0] - 2026-08-26
28
+
29
+ ### Added
30
+
31
+ - Model-independent `discover`, `expand`, `compile` and `verify` phases for
32
+ progressively navigating Project Technology context.
33
+ - Public JavaScript API and matching CLI for deterministic traversal,
34
+ mandatory dependency closure and usage verification.
35
+ - One bounded context-traversal receipt contract and direct context-pack fields
36
+ for selection, completeness, exact sources and a stable digest.
37
+ - Universal fixtures for software, research, organization, platform,
38
+ skill-like and multi-repository graphs, including macOS, Linux and Windows CI.
39
+
40
+ ### Safety Boundary
41
+
42
+ - All traversal phases are read-only and generated context never authorizes a
43
+ write.
44
+ - Required sources, processes and validators cannot be removed to meet a token
45
+ budget. Missing, stale, blocked, deprecated, conflicting, cyclic or tampered
46
+ context fails closed.
47
+ - Access data is limited to safe references and availability metadata; secret
48
+ values and private source content are not included.
49
+
50
+ ### Compatibility
51
+
52
+ - The public `graph.json` schema remains `2.0.0` and
53
+ `mirai.project_technology.contract_version` remains `1.0.0`.
54
+ - Existing graphs need no migration, the original context command remains
55
+ available, and provider/consumer behavior is unchanged.
56
+
7
57
  ## [1.0.0] - 2026-08-17
8
58
 
9
59
  ### Changed
package/CITATION.cff CHANGED
@@ -17,4 +17,5 @@ keywords:
17
17
  - complex systems
18
18
  - context engineering
19
19
  - systems engineering
20
- date-released: "2026-05-28"
20
+ version: "1.1.0"
21
+ date-released: "2026-08-26"
package/README.md CHANGED
@@ -10,7 +10,7 @@ Use it when a software project has useful knowledge spread across README files,
10
10
  docs, issues, chats, code comments and AI prompts, and you need a small
11
11
  machine-readable map that developers and AI assistants can validate and reuse.
12
12
 
13
- Status: stable public `1.0.0` release.
13
+ Status: stable public `1.1.0` release.
14
14
 
15
15
  ## What Problem Does It Solve?
16
16
 
@@ -42,7 +42,7 @@ Start with a normal repository and use Mirai Graph to:
42
42
 
43
43
  ## Current Installation Status
44
44
 
45
- The repository is ready as the stable `mirai-graph@1.0.0` package. To verify a
45
+ The repository is ready as the stable `mirai-graph@1.1.0` package. To verify a
46
46
  repository checkout directly, use:
47
47
 
48
48
  ```bash
@@ -111,6 +111,25 @@ mirai-graph technology context . --task "implement the approved feature"
111
111
  mirai-graph technology verify . --significant-work
112
112
  ```
113
113
 
114
+ For deeper graphs, the same `context` operation supports four read-only phases:
115
+
116
+ ```bash
117
+ mirai-graph technology context . --phase discover --task "implement the approved feature"
118
+ mirai-graph technology context . --phase expand --input receipt.json --select capability.delivery
119
+ mirai-graph technology context . --phase compile --input receipt.json --selection selection.json
120
+ mirai-graph technology context . --phase verify --packet context-pack.json --evidence usage-evidence.json
121
+ ```
122
+
123
+ `discover` returns a bounded top-level choice. `expand` follows only selected
124
+ branches. `compile` adds every required process, constraint and validator, and
125
+ returns an immutable context pack only when the selection is complete.
126
+ `verify` proves that required sources influenced a decision and a checked
127
+ outcome; merely loading a document is not enough.
128
+
129
+ The programmatic API exposes the same operations as `discoverContext`,
130
+ `expandContext`, `compileContext` and `verifyContext`. Mirai Graph does not call
131
+ or depend on a particular AI model.
132
+
114
133
  Changing operations return a preview unless `--apply` is explicit. See
115
134
  [Project Technology](standard/project-technology.md) for provider/consumer
116
135
  binding, local state and safety boundaries.
package/ROADMAP.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mirai Graph Roadmap
2
2
 
3
- Status: 1.0 release-candidate roadmap
3
+ Status: stable 1.1 roadmap
4
4
 
5
5
  ## Phase 0: Public Foundation
6
6
 
@@ -228,19 +228,14 @@ Planned artifacts:
228
228
  - release process;
229
229
  - public examples from approved external adopters.
230
230
 
231
- ## Near-Term Work After 1.0 RC
232
-
233
- 1. Execute the `1.0.0-rc.6` release: tag, GitHub Release and npm publication
234
- only after release-state checks are accepted.
235
- 2. Continue adopter workflow: import/export helper skeletons, richer report
236
- formatting and more adoption recipes when they directly support self-service
237
- adoption.
238
- 3. Add one or two external public-safe pilots maintained outside the original
239
- Mirai Graph authoring contour.
240
- 4. Expand organization-governance validation reports and adoption recipes.
241
- 5. Collect real multi-model Character Layer replay evidence before stronger
231
+ ## Near-Term Work After 1.1
232
+
233
+ 1. Validate sequential context traversal in independent adopter projects and
234
+ collect public-safe compatibility evidence.
235
+ 2. Continue adopter workflow with richer reports and domain-neutral recipes.
236
+ 3. Add external public-safe pilots maintained outside the original Mirai Graph
237
+ authoring contour.
238
+ 4. Collect real multi-model replay evidence before stronger effectiveness or
242
239
  portability claims.
243
- 6. Explore a local interactive playground only after deterministic report
244
- fixtures remain stable.
245
- 7. Turn evidence package v0.3 and the two article foundations into a
246
- publication-ready reproducibility bundle.
240
+ 5. Keep the deterministic CLI and public contracts stable while improving
241
+ ranking as a replaceable client-side concern.
@@ -1,6 +1,6 @@
1
1
  # Mirai Graph CLI
2
2
 
3
- Status: 1.0 release-candidate CLI guide
3
+ Status: 1.1 stable CLI guide
4
4
 
5
5
  Mirai Graph keeps the reference scripts for direct automation. The
6
6
  `mirai-graph` entrypoint is the primary command surface for common checks and
@@ -82,6 +82,19 @@ npx mirai-graph release state --markdown
82
82
  npm run validate:release-state
83
83
  ```
84
84
 
85
+ Discover and compile task context without writing files:
86
+
87
+ ```bash
88
+ npx mirai-graph technology context . --phase discover --task "prepare the release"
89
+ npx mirai-graph technology context . --phase expand --input receipt.json --select capability.release
90
+ npx mirai-graph technology context . --phase compile --input receipt.json --selection selection.json
91
+ npx mirai-graph technology context . --phase verify --packet context-pack.json --evidence usage-evidence.json
92
+ ```
93
+
94
+ Omitting `--phase` keeps the original bounded context-discovery behavior.
95
+ Receipt, selection, context-pack and usage-evidence files are caller-owned
96
+ inputs and outputs; the command never stores them itself.
97
+
85
98
  ## Output Boundary
86
99
 
87
100
  - JSON output is intended for tools and CI.
@@ -97,6 +110,8 @@ npm run validate:release-state
97
110
  and npm auth state, but it does not publish or authorize a release.
98
111
  - Generated context, evidence, feedback and proposals do not authorize
99
112
  canonical updates.
113
+ - Context traversal never reads secret values into its output. Access is
114
+ represented by a safe reference, availability and required permission.
100
115
 
101
116
  ## Command Aliases
102
117
 
@@ -0,0 +1,17 @@
1
+ # Project Technology Context Traversal
2
+
3
+ This synthetic example shows a domain-neutral release graph with a three-level
4
+ path, mandatory rollback and validation dependencies, and one optional branch.
5
+
6
+ Start with discovery:
7
+
8
+ ```bash
9
+ mirai-graph technology context . --phase discover --task "prepare and verify a release"
10
+ ```
11
+
12
+ Save the returned `traversal_receipt`, expand the selected capability and
13
+ process, then copy the returned task and graph digests into
14
+ `selection.example.json`. Compilation adds the rollback constraint and release
15
+ smoke even if the selector did not name them.
16
+
17
+ All operations are read-only. The example contains synthetic public data only.
@@ -0,0 +1,78 @@
1
+ [
2
+ {
3
+ "id": "capability.release_delivery",
4
+ "kind": "capability",
5
+ "title": "Release delivery",
6
+ "summary": "Prepare a bounded and verifiable software release.",
7
+ "owner": "role.release_owner",
8
+ "readiness": "accepted",
9
+ "authority": "contract",
10
+ "expansion_policy": "expandable",
11
+ "evidence": [],
12
+ "profile": "core"
13
+ },
14
+ {
15
+ "id": "process.release_verification",
16
+ "kind": "process",
17
+ "title": "Release verification",
18
+ "summary": "Run the accepted release checks before publication.",
19
+ "owner": "role.release_owner",
20
+ "readiness": "accepted",
21
+ "authority": "contract",
22
+ "expansion_policy": "expandable",
23
+ "evidence": [],
24
+ "profile": "core"
25
+ },
26
+ {
27
+ "id": "source.release_guide",
28
+ "kind": "source",
29
+ "title": "Release guide",
30
+ "summary": "The authoritative local guide for the synthetic release.",
31
+ "owner": "role.release_owner",
32
+ "readiness": "accepted",
33
+ "authority": "source",
34
+ "expansion_policy": "terminal",
35
+ "source_refs": ["sources/release-guide.md"],
36
+ "evidence": [],
37
+ "profile": "core"
38
+ },
39
+ {
40
+ "id": "constraint.rollback_required",
41
+ "kind": "constraint",
42
+ "title": "Rollback is required",
43
+ "summary": "Publication must retain a tested rollback path.",
44
+ "owner": "role.release_owner",
45
+ "readiness": "accepted",
46
+ "authority": "contract",
47
+ "expansion_policy": "terminal",
48
+ "source_refs": ["sources/rollback-policy.md"],
49
+ "evidence": [],
50
+ "profile": "core"
51
+ },
52
+ {
53
+ "id": "check.release_smoke",
54
+ "kind": "check",
55
+ "title": "Release smoke",
56
+ "summary": "Verify the installed release identity and core behavior.",
57
+ "owner": "role.release_quality",
58
+ "readiness": "accepted",
59
+ "authority": "validator",
60
+ "expansion_policy": "terminal",
61
+ "source_refs": ["sources/release-smoke.md"],
62
+ "evidence": [],
63
+ "profile": "core"
64
+ },
65
+ {
66
+ "id": "capability.optional_announcement",
67
+ "kind": "capability",
68
+ "title": "Optional announcement",
69
+ "summary": "Prepare a public announcement only when requested.",
70
+ "owner": "role.communication",
71
+ "readiness": "accepted",
72
+ "authority": "reference",
73
+ "expansion_policy": "terminal",
74
+ "source_refs": ["sources/announcement.md"],
75
+ "evidence": [],
76
+ "profile": "core"
77
+ }
78
+ ]
@@ -0,0 +1,47 @@
1
+ [
2
+ {
3
+ "id": "relation.capability.release_delivery.contains.process.release_verification",
4
+ "type": "contains",
5
+ "source": "capability.release_delivery",
6
+ "target": "process.release_verification",
7
+ "readiness": "accepted",
8
+ "evidence": [],
9
+ "profile": "core"
10
+ },
11
+ {
12
+ "id": "relation.process.release_verification.documented_by.source.release_guide",
13
+ "type": "documented_by",
14
+ "source": "process.release_verification",
15
+ "target": "source.release_guide",
16
+ "readiness": "accepted",
17
+ "evidence": [],
18
+ "profile": "core"
19
+ },
20
+ {
21
+ "id": "relation.process.release_verification.governed_by.constraint.rollback_required",
22
+ "type": "governed_by",
23
+ "source": "process.release_verification",
24
+ "target": "constraint.rollback_required",
25
+ "readiness": "accepted",
26
+ "evidence": [],
27
+ "profile": "core"
28
+ },
29
+ {
30
+ "id": "relation.process.release_verification.validated_by.check.release_smoke",
31
+ "type": "validated_by",
32
+ "source": "process.release_verification",
33
+ "target": "check.release_smoke",
34
+ "readiness": "accepted",
35
+ "evidence": [],
36
+ "profile": "core"
37
+ },
38
+ {
39
+ "id": "relation.capability.release_delivery.contains.capability.optional_announcement",
40
+ "type": "contains",
41
+ "source": "capability.release_delivery",
42
+ "target": "capability.optional_announcement",
43
+ "readiness": "accepted",
44
+ "evidence": [],
45
+ "profile": "core"
46
+ }
47
+ ]
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://mirai-graph.dev/schemas/graph-manifest.schema.json",
3
+ "format": "mirai-graph",
4
+ "schema_version": "2.0.0",
5
+ "id": "example.project_technology_context_traversal",
6
+ "aliases": [],
7
+ "title": "Project Technology Context Traversal Example",
8
+ "scope": "repository",
9
+ "kind": "project_graph",
10
+ "owner": "example.delivery_owner",
11
+ "profiles": [],
12
+ "graph": {
13
+ "root": "graph",
14
+ "source_of_truth": ["graph"],
15
+ "objects": ["graph/objects.json"],
16
+ "relations": ["graph/relations.json"],
17
+ "schemas": [],
18
+ "generated": [],
19
+ "raw_sources": ["sources"]
20
+ },
21
+ "imports": [],
22
+ "extensions": {
23
+ "mirai.project_technology": {
24
+ "contract_version": "1.0.0",
25
+ "enabled": true,
26
+ "context_policy": "task_scoped",
27
+ "source_boundary": "hybrid_sot"
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "selector": "human",
3
+ "task_digest": "replace-with-discover-task-digest",
4
+ "graph_digest": "replace-with-discover-graph-digest",
5
+ "result_owner_id": "role.release_owner",
6
+ "selected": [
7
+ {
8
+ "id": "capability.release_delivery",
9
+ "reason": "The requested outcome is a release.",
10
+ "confidence": 1
11
+ },
12
+ {
13
+ "id": "process.release_verification",
14
+ "reason": "The release must be verified before publication.",
15
+ "confidence": 1
16
+ },
17
+ {
18
+ "id": "source.release_guide",
19
+ "reason": "This is the accepted release source.",
20
+ "confidence": 1
21
+ }
22
+ ],
23
+ "rejected": [
24
+ {
25
+ "id": "capability.optional_announcement",
26
+ "reason": "An announcement was not requested."
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,3 @@
1
+ # Optional announcement
2
+
3
+ Publish an announcement only when it belongs to the accepted release scope.
@@ -0,0 +1,3 @@
1
+ # Release guide
2
+
3
+ Build once, verify the exact artifact, and publish only that artifact.
@@ -0,0 +1,3 @@
1
+ # Release smoke
2
+
3
+ Check the installed version, package checksum and one representative operation.
@@ -0,0 +1,3 @@
1
+ # Rollback policy
2
+
3
+ Keep the previous immutable version available until the new version is verified.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mirai-graph",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "private": false,
5
5
  "description": "An evolutionary graph operating model for managing the growth of complex systems.",
6
6
  "license": "MIT",
@@ -13,9 +13,10 @@
13
13
  "./project-technology": "./packages/project-technology/index.js"
14
14
  },
15
15
  "scripts": {
16
- "pretest": "npm run test:project-technology",
16
+ "pretest": "npm run test:project-technology && npm run test:context-traversal && npm run validate:project-technology-schemas",
17
17
  "test:project-technology": "node packages/cli/validate-project-technology.js",
18
- "validate:project-technology-schemas": "node -e \"JSON.parse(require('fs').readFileSync('schemas/project-technology-extension.schema.json')); JSON.parse(require('fs').readFileSync('schemas/project-technology-target-export.schema.json'))\"",
18
+ "test:context-traversal": "node packages/cli/validate-context-traversal.js",
19
+ "validate:project-technology-schemas": "node -e \"const fs=require('fs'); for (const file of ['project-technology-extension.schema.json','project-technology-target-export.schema.json','context-traversal-receipt.schema.json','context-pack.schema.json']) JSON.parse(fs.readFileSync('schemas/'+file))\"",
19
20
  "validate:graph-manifest": "node packages/cli/validate-graph-manifest-migration.js",
20
21
  "validate:minimal": "node packages/cli/validate-mirai-graph.js examples/minimal-graph",
21
22
  "validate:benchmark": "node packages/cli/validate-mirai-graph.js benchmarks/synthetic-context-reduction-v0",
@@ -2,6 +2,7 @@
2
2
 
3
3
  "use strict";
4
4
 
5
+ const fs = require("fs");
5
6
  const path = require("path");
6
7
  const { execute } = require("../project-technology");
7
8
 
@@ -12,6 +13,10 @@ function usage() {
12
13
  console.error("Options: --apply --task <text> --source <file> --target-id <id>");
13
14
  console.error(" --semantic-digest <sha256:...> --provider-revision <sha>");
14
15
  console.error(" --refresh-binding --significant-work --max-objects <count>");
16
+ console.error("Context: --phase discover --task <text>");
17
+ console.error(" --phase expand --input <receipt.json> --select <id> [--select <id>]");
18
+ console.error(" --phase compile --input <receipt.json> --selection <selection.json>");
19
+ console.error(" --phase verify --packet <context-pack.json> --evidence <usage-evidence.json>");
15
20
  }
16
21
 
17
22
  function parse(argv) {
@@ -20,31 +25,66 @@ function parse(argv) {
20
25
  let repository = ".";
21
26
  if (argv[0] && !argv[0].startsWith("--")) repository = argv.shift();
22
27
  const options = {};
23
- const values = new Set(["--task", "--source", "--target-id", "--semantic-digest", "--provider-revision", "--max-objects"]);
28
+ const values = new Set(["--task", "--source", "--target-id", "--semantic-digest", "--provider-revision", "--max-objects", "--phase", "--input", "--select", "--selection", "--packet", "--evidence", "--selector", "--reason", "--confidence", "--context-budget"]);
24
29
  const flags = new Set(["--apply", "--refresh-binding", "--significant-work"]);
25
30
  const names = {
26
31
  "--task": "task", "--source": "source", "--target-id": "targetId",
27
32
  "--semantic-digest": "semanticDigest", "--provider-revision": "providerRevision",
28
33
  "--max-objects": "maxObjects", "--apply": "apply",
29
34
  "--refresh-binding": "refreshBinding", "--significant-work": "significantWork",
35
+ "--phase": "phase", "--input": "input", "--select": "selectedIds",
36
+ "--selection": "selectionFile", "--packet": "packetFile", "--evidence": "evidenceFile",
37
+ "--selector": "selector", "--reason": "reason", "--confidence": "confidence",
38
+ "--context-budget": "contextBudget",
30
39
  };
31
40
  while (argv.length) {
32
41
  const token = argv.shift();
33
42
  if (flags.has(token)) options[names[token]] = true;
34
43
  else if (values.has(token)) {
35
44
  if (!argv.length) throw new Error(`missing value for ${token}`);
36
- options[names[token]] = argv.shift();
45
+ const value = argv.shift();
46
+ if (token === "--select") options.selectedIds = [...(options.selectedIds || []), value];
47
+ else options[names[token]] = value;
37
48
  } else throw new Error(`unsupported argument ${token}`);
38
49
  }
39
50
  return { operation, repository: path.resolve(repository), options };
40
51
  }
41
52
 
53
+ function readJsonFile(file) {
54
+ const absolute = path.resolve(file);
55
+ if (!fs.existsSync(absolute) || fs.lstatSync(absolute).isSymbolicLink()) throw new Error(`unsafe or missing JSON input ${file}`);
56
+ return JSON.parse(fs.readFileSync(absolute, "utf8").replace(/^\uFEFF/, ""));
57
+ }
58
+
59
+ function hydrateContextOptions(request) {
60
+ if (request.operation !== "context" || !request.options.phase) return;
61
+ const phase = request.options.phase;
62
+ if (!new Set(["discover", "expand", "compile", "verify"]).has(phase)) throw new Error(`unsupported context phase ${phase}`);
63
+ if (["expand", "compile"].includes(phase)) {
64
+ if (!request.options.input) throw new Error(`${phase} requires --input`);
65
+ const payload = readJsonFile(request.options.input);
66
+ request.options.traversalReceipt = payload.traversal_receipt || payload;
67
+ }
68
+ if (phase === "compile") {
69
+ if (!request.options.selectionFile) throw new Error("compile requires --selection");
70
+ request.options.selection = readJsonFile(request.options.selectionFile);
71
+ }
72
+ if (phase === "verify") {
73
+ if (!request.options.packetFile || !request.options.evidenceFile) throw new Error("verify requires --packet and --evidence");
74
+ const packet = readJsonFile(request.options.packetFile);
75
+ request.options.contextPack = packet.context_pack || packet;
76
+ request.options.usageEvidence = readJsonFile(request.options.evidenceFile);
77
+ }
78
+ }
79
+
42
80
  let request;
43
81
  try { request = parse(process.argv.slice(2)); }
44
82
  catch (error) {
45
83
  console.error(error.message); usage(); process.exit(1);
46
84
  }
47
85
  if (!request) { usage(); process.exit(1); }
86
+ try { hydrateContextOptions(request); }
87
+ catch (error) { console.error(error.message); usage(); process.exit(1); }
48
88
 
49
89
  let output;
50
90
  try { output = execute(request.operation, request.repository, request.options); }
@@ -61,4 +101,4 @@ catch (error) {
61
101
  };
62
102
  }
63
103
  process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
64
- process.exit(output.status === "fail" ? 1 : output.status === "blocked" ? 2 : 0);
104
+ process.exitCode = output.status === "fail" ? 1 : ["blocked", "needs_more_discovery", "needs_decision"].includes(output.status) ? 2 : 0;