@osovv/grace-cli 3.4.0 → 3.6.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
@@ -10,13 +10,13 @@ This repository packages GRACE as reusable skills for coding agents. The current
10
10
  - knowledge-graph synchronization
11
11
  - controller-managed sequential or multi-agent implementation
12
12
 
13
- Current packaged version: `3.4.0`
13
+ Current packaged version: `3.6.0`
14
14
 
15
15
  ## What Changed In This Version
16
16
 
17
- - Added a rich Python adapter without `pyright` for `grace lint`.
18
- - Kept TypeScript/JavaScript on the TypeScript compiler API for exact export analysis.
19
- - Made adapter failures non-fatal so linting can continue with structural checks and warnings.
17
+ - Added `grace module find`, `grace module show`, and `grace file show` so the CLI can act as a GRACE-aware read/query layer over shared XML artifacts and file-local markup.
18
+ - Clarified across the shipped skills when to use `grace lint`, `grace module show`, and `grace file show` to move between public shared-doc context and private file-local context.
19
+ - Kept `grace lint` as the fast integrity gate while expanding the CLI into context navigation for agents and humans.
20
20
 
21
21
  ## Repository Layout
22
22
 
@@ -189,6 +189,22 @@ bun install
189
189
  bun run grace lint --path /path/to/grace-project
190
190
  ```
191
191
 
192
+ Query GRACE artifacts from the CLI:
193
+
194
+ ```bash
195
+ # Search modules across shared docs and linked file-local markup
196
+ bun run grace module find auth --path /path/to/grace-project
197
+ bun run grace module find src/provider/config-repo.ts --path /path/to/grace-project --json
198
+
199
+ # Show the shared/public module record
200
+ bun run grace module show M-AUTH --path /path/to/grace-project
201
+ bun run grace module show M-AUTH --path /path/to/grace-project --with verification
202
+
203
+ # Show file-local/private markup
204
+ bun run grace file show src/provider/config-repo.ts --path /path/to/grace-project
205
+ bun run grace file show src/provider/config-repo.ts --path /path/to/grace-project --contracts --blocks
206
+ ```
207
+
192
208
  The lint command is role-aware and adapter-aware:
193
209
 
194
210
  - structural checks stay language-agnostic
@@ -206,6 +222,12 @@ Current adapter behavior:
206
222
  - Python export analysis is exact when `__all__` is explicit, otherwise heuristic
207
223
  - other languages still benefit from structural GRACE checks even when rich export analysis is not available yet
208
224
 
225
+ The query commands follow the GRACE public/private split:
226
+
227
+ - `grace module show` reads shared/public module contracts, interfaces, dependencies, steps, and verification excerpts from the XML artifacts.
228
+ - `grace file show` reads file-local/private `MODULE_CONTRACT`, `MODULE_MAP`, `CHANGE_SUMMARY`, scoped contracts, and semantic blocks.
229
+ - `grace module find` searches both planes, including shared docs and linked file-local paths via `LINKS`.
230
+
209
231
  Optional `MODULE_CONTRACT` fields for linting:
210
232
 
211
233
  ```text
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@osovv/grace-cli",
3
- "version": "3.4.0",
4
- "description": "GRACE CLI for linting semantic markup, contracts, and GRACE XML artifacts with a Bun-powered grace binary.",
3
+ "version": "3.6.0",
4
+ "description": "GRACE CLI for linting semantic markup, contracts, and querying GRACE artifacts with a Bun-powered grace binary.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/osovv/grace-marketplace#readme",
7
7
  "repository": {
@@ -25,9 +25,12 @@
25
25
  "access": "public"
26
26
  },
27
27
  "files": [
28
+ "src/grace-file.ts",
28
29
  "src/grace.ts",
29
30
  "src/grace-lint.ts",
31
+ "src/grace-module.ts",
30
32
  "src/lint",
33
+ "src/query",
31
34
  "README.md",
32
35
  "LICENSE"
33
36
  ],
@@ -0,0 +1,78 @@
1
+ import { defineCommand } from "citty";
2
+
3
+ import { loadGraceArtifactIndex, resolveGovernedFile } from "./query/core";
4
+ import { formatFileText } from "./query/render";
5
+
6
+ function resolveFormat(format: unknown, json: unknown) {
7
+ const resolved = Boolean(json) ? "json" : String(format ?? "text");
8
+ if (resolved !== "text" && resolved !== "json") {
9
+ throw new Error(`Unsupported format \`${resolved}\`. Use \`text\` or \`json\`.`);
10
+ }
11
+
12
+ return resolved;
13
+ }
14
+
15
+ export const fileCommand = defineCommand({
16
+ meta: {
17
+ name: "file",
18
+ description: "Query file-local GRACE markup and private implementation context.",
19
+ },
20
+ subCommands: {
21
+ show: defineCommand({
22
+ meta: {
23
+ name: "show",
24
+ description: "Show file-local MODULE_CONTRACT, MODULE_MAP, CHANGE_SUMMARY, contracts, and blocks.",
25
+ },
26
+ args: {
27
+ target: {
28
+ type: "positional",
29
+ description: "Governed file path",
30
+ },
31
+ path: {
32
+ type: "string",
33
+ alias: "p",
34
+ description: "Project root to inspect",
35
+ default: ".",
36
+ },
37
+ contracts: {
38
+ type: "boolean",
39
+ description: "Include function/type/file-local contract details",
40
+ default: false,
41
+ },
42
+ blocks: {
43
+ type: "boolean",
44
+ description: "Include semantic block list",
45
+ default: false,
46
+ },
47
+ format: {
48
+ type: "string",
49
+ alias: "f",
50
+ description: "Output format: text or json",
51
+ default: "text",
52
+ },
53
+ json: {
54
+ type: "boolean",
55
+ description: "Shortcut for --format json",
56
+ default: false,
57
+ },
58
+ },
59
+ async run(context) {
60
+ const format = resolveFormat(context.args.format, context.args.json);
61
+ const index = loadGraceArtifactIndex(String(context.args.path ?? "."));
62
+ const fileRecord = resolveGovernedFile(index, String(context.args.target));
63
+
64
+ if (format === "json") {
65
+ process.stdout.write(`${JSON.stringify(fileRecord, null, 2)}\n`);
66
+ return;
67
+ }
68
+
69
+ process.stdout.write(
70
+ `${formatFileText(fileRecord, {
71
+ includeContracts: Boolean(context.args.contracts),
72
+ includeBlocks: Boolean(context.args.blocks),
73
+ })}\n`,
74
+ );
75
+ },
76
+ }),
77
+ },
78
+ });
@@ -0,0 +1,126 @@
1
+ import { defineCommand } from "citty";
2
+
3
+ import { findModules, loadGraceArtifactIndex, resolveModule } from "./query/core";
4
+ import { formatModuleFindTable, formatModuleText } from "./query/render";
5
+
6
+ function resolveFormat(format: unknown, json: unknown, allowed: string[], defaultFormat: string) {
7
+ const resolved = Boolean(json) ? "json" : String(format ?? defaultFormat);
8
+ if (!allowed.includes(resolved)) {
9
+ throw new Error(`Unsupported format \`${resolved}\`. Use ${allowed.map((value) => `\`${value}\``).join(" or ")}.`);
10
+ }
11
+
12
+ return resolved;
13
+ }
14
+
15
+ export const moduleCommand = defineCommand({
16
+ meta: {
17
+ name: "module",
18
+ description: "Query shared GRACE module artifacts.",
19
+ },
20
+ subCommands: {
21
+ find: defineCommand({
22
+ meta: {
23
+ name: "find",
24
+ description: "Find GRACE modules by id, name, path, purpose, annotations, verification, or dependencies.",
25
+ },
26
+ args: {
27
+ query: {
28
+ type: "positional",
29
+ required: false,
30
+ description: "Search query or path",
31
+ },
32
+ path: {
33
+ type: "string",
34
+ alias: "p",
35
+ description: "Project root to inspect",
36
+ default: ".",
37
+ },
38
+ type: {
39
+ type: "string",
40
+ description: "Filter by module type",
41
+ },
42
+ dependsOn: {
43
+ type: "string",
44
+ description: "Filter by dependency id",
45
+ },
46
+ format: {
47
+ type: "string",
48
+ alias: "f",
49
+ description: "Output format: table or json",
50
+ default: "table",
51
+ },
52
+ json: {
53
+ type: "boolean",
54
+ description: "Shortcut for --format json",
55
+ default: false,
56
+ },
57
+ },
58
+ async run(context) {
59
+ const format = resolveFormat(context.args.format, context.args.json, ["table", "json"], "table");
60
+ const index = loadGraceArtifactIndex(String(context.args.path ?? "."));
61
+ const matches = findModules(index, {
62
+ query: context.args.query ? String(context.args.query) : undefined,
63
+ type: context.args.type ? String(context.args.type) : undefined,
64
+ dependsOn: context.args.dependsOn ? String(context.args.dependsOn) : undefined,
65
+ });
66
+
67
+ if (format === "json") {
68
+ process.stdout.write(`${JSON.stringify(matches, null, 2)}\n`);
69
+ return;
70
+ }
71
+
72
+ process.stdout.write(`${formatModuleFindTable(matches)}\n`);
73
+ },
74
+ }),
75
+ show: defineCommand({
76
+ meta: {
77
+ name: "show",
78
+ description: "Show the shared/public GRACE record for a module id or path.",
79
+ },
80
+ args: {
81
+ target: {
82
+ type: "positional",
83
+ description: "Module id or file/path target",
84
+ },
85
+ path: {
86
+ type: "string",
87
+ alias: "p",
88
+ description: "Project root to inspect",
89
+ default: ".",
90
+ },
91
+ with: {
92
+ type: "string",
93
+ description: "Optional extras, currently supports: verification",
94
+ default: "",
95
+ },
96
+ format: {
97
+ type: "string",
98
+ alias: "f",
99
+ description: "Output format: text or json",
100
+ default: "text",
101
+ },
102
+ json: {
103
+ type: "boolean",
104
+ description: "Shortcut for --format json",
105
+ default: false,
106
+ },
107
+ },
108
+ async run(context) {
109
+ const format = resolveFormat(context.args.format, context.args.json, ["text", "json"], "text");
110
+ const index = loadGraceArtifactIndex(String(context.args.path ?? "."));
111
+ const moduleRecord = resolveModule(index, String(context.args.target));
112
+ const includeVerification = String(context.args.with ?? "")
113
+ .split(",")
114
+ .map((value) => value.trim().toLowerCase())
115
+ .includes("verification");
116
+
117
+ if (format === "json") {
118
+ process.stdout.write(`${JSON.stringify(moduleRecord, null, 2)}\n`);
119
+ return;
120
+ }
121
+
122
+ process.stdout.write(`${formatModuleText(moduleRecord, { withVerification: includeVerification })}\n`);
123
+ },
124
+ }),
125
+ },
126
+ });
package/src/grace.ts CHANGED
@@ -2,16 +2,20 @@
2
2
 
3
3
  import { defineCommand, type CommandDef, runMain } from "citty";
4
4
 
5
+ import { fileCommand } from "./grace-file";
5
6
  import { lintCommand } from "./grace-lint";
7
+ import { moduleCommand } from "./grace-module";
6
8
 
7
9
  const main = defineCommand({
8
10
  meta: {
9
11
  name: "grace",
10
- version: "3.4.0",
11
- description: "GRACE CLI for linting semantic markup and GRACE project artifacts.",
12
+ version: "3.6.0",
13
+ description: "GRACE CLI for linting semantic markup and querying GRACE project artifacts.",
12
14
  },
13
15
  subCommands: {
16
+ file: fileCommand,
14
17
  lint: lintCommand,
18
+ module: moduleCommand,
15
19
  },
16
20
  });
17
21