@graphit/cli 0.2.348 → 0.2.351
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/bin/graphit +1 -1
- package/bin/graphit.ps1 +1 -1
- package/dist/commands/connector.js +27 -18
- package/dist/commands/connector.js.map +1 -1
- package/dist/commands/kb-repo.js +63 -17
- package/dist/commands/kb-repo.js.map +1 -1
- package/dist/commands/kb.js +44 -2
- package/dist/commands/kb.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-commands-doc.mjs +46 -24
- package/scripts/generate-tool-manifest.mjs +23 -5
- package/scripts/verb-policy-source.json +27 -3
- package/skills/graphit/SKILL.md +16 -12
- package/skills/graphit/VERSION.json +1 -1
- package/skills/graphit/references/governance.md +1 -1
- package/skills/graphit/references/kb-actions.md +2 -0
- package/skills/graphit/references/kb-discovery.md +11 -11
- package/skills/graphit/references/kb-traversal.md +2 -2
- package/skills/graphit/references/operations.md +2 -2
- package/skills/graphit/references/repo-kb.md +25 -22
- package/skills/graphit/references/repo-preparation.md +117 -0
- package/skills/graphit/references/semantic-authoring.md +17 -2
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
//
|
|
10
10
|
// Requires a prior `npm run build` (it imports the compiled registrars from dist/).
|
|
11
11
|
|
|
12
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, writeSync } from "node:fs";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import {
|
|
15
15
|
buildProgram,
|
|
@@ -28,6 +28,23 @@ const skillPath = join(cliRoot, "skills", "graphit", "SKILL.md");
|
|
|
28
28
|
const START = "<!-- COMMANDS:START -->";
|
|
29
29
|
const END = "<!-- COMMANDS:END -->";
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Feature #814, mirroring `writeStderr` in cli/src/stderr.ts.
|
|
33
|
+
*
|
|
34
|
+
* `console.error` is asynchronous when stderr is a pipe - which is how CI and
|
|
35
|
+
* every agent runs this generator - so a `process.exit()` in the same tick
|
|
36
|
+
* discards the buffered line. The remediation banner below is the whole value of
|
|
37
|
+
* a failing check run, so it is written synchronously; the guard in
|
|
38
|
+
* cli/test/lint-write-before-exit.test.mjs covers cli/src, not cli/scripts.
|
|
39
|
+
*/
|
|
40
|
+
function writeStderr(message) {
|
|
41
|
+
try {
|
|
42
|
+
writeSync(2, message.endsWith("\n") ? message : `${message}\n`);
|
|
43
|
+
} catch {
|
|
44
|
+
// stderr closed or busy - a lost log line is never worth failing a build.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
function esc(text) {
|
|
32
49
|
return String(text ?? "").replace(/\r?\n/g, " ").replace(/\|/g, "\\|").trim();
|
|
33
50
|
}
|
|
@@ -51,14 +68,23 @@ function renderBlock(program) {
|
|
|
51
68
|
flags: formatFlags(verb.options),
|
|
52
69
|
});
|
|
53
70
|
}
|
|
71
|
+
// The prose above the markers in SKILL.md already says the table is generated
|
|
72
|
+
// and to check `--help` for flags; this line only marks the block as generated.
|
|
54
73
|
const lines = [
|
|
55
74
|
"",
|
|
56
|
-
"_Generated
|
|
75
|
+
"_Generated by `npm run gen:commands`; do not hand-edit between the markers._",
|
|
57
76
|
"",
|
|
58
77
|
];
|
|
59
78
|
for (const name of groups.keys()) {
|
|
60
79
|
const { description, rows } = groups.get(name);
|
|
61
|
-
|
|
80
|
+
// A self-invocable group (`status`, `query`, `setup`) is its own single row,
|
|
81
|
+
// and Commander gives the group and the row the same description. Print it
|
|
82
|
+
// once, on the row - the row is what the tests pin and what an agent reads.
|
|
83
|
+
// SKILL.md is always-loaded and sits on a hard size ceiling, so a repeated
|
|
84
|
+
// description is paid for on every turn.
|
|
85
|
+
const groupDescription =
|
|
86
|
+
rows.length === 1 && rows[0].description === description ? "" : description;
|
|
87
|
+
lines.push(`**${name}**${groupDescription ? ` - ${esc(groupDescription)}` : ""}`);
|
|
62
88
|
for (const row of rows) {
|
|
63
89
|
const parts = [`- \`${row.command}\``];
|
|
64
90
|
if (row.description) parts.push(esc(row.description));
|
|
@@ -90,27 +116,23 @@ const program = await buildProgram();
|
|
|
90
116
|
const block = renderBlock(program);
|
|
91
117
|
|
|
92
118
|
if (toStdout) {
|
|
119
|
+
// No process.exit() after this write: on a pipe, exiting before stdout drains
|
|
120
|
+
// truncates the block, and callers diff it whole.
|
|
93
121
|
process.stdout.write(block);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
: "";
|
|
101
|
-
const next = injectBetweenMarkers(current, block);
|
|
122
|
+
} else {
|
|
123
|
+
// Normalize CRLF before compare so Windows checkouts don't report perpetual drift.
|
|
124
|
+
const current = existsSync(skillPath)
|
|
125
|
+
? readFileSync(skillPath, "utf-8").replace(/\r\n/g, "\n")
|
|
126
|
+
: "";
|
|
127
|
+
const next = injectBetweenMarkers(current, block);
|
|
102
128
|
|
|
103
|
-
if (current === next) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
process.exit(1);
|
|
129
|
+
if (current === next) {
|
|
130
|
+
writeStderr("Command table in SKILL.md is in sync.");
|
|
131
|
+
} else if (checkOnly) {
|
|
132
|
+
writeStderr("SKILL.md command table is stale - run: npm run gen:commands");
|
|
133
|
+
process.exitCode = 1;
|
|
134
|
+
} else {
|
|
135
|
+
writeFileSync(skillPath, next, "utf-8");
|
|
136
|
+
writeStderr(`Updated command table in ${skillPath}`);
|
|
137
|
+
}
|
|
113
138
|
}
|
|
114
|
-
|
|
115
|
-
writeFileSync(skillPath, next, "utf-8");
|
|
116
|
-
console.error(`Updated command table in ${skillPath}`);
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// - it never emits an org/user identity parameter. Tenancy is bound from the
|
|
19
19
|
// authenticated session at construction, never from a model-supplied value.
|
|
20
20
|
|
|
21
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync, writeSync } from "node:fs";
|
|
22
22
|
import { join } from "node:path";
|
|
23
23
|
import { buildProgram, cliRoot, collectVerbs } from "./commander-walk.mjs";
|
|
24
24
|
|
|
@@ -81,11 +81,29 @@ const APP_PARAM_TYPES = new Set(["string", "integer", "boolean"]);
|
|
|
81
81
|
const errors = [];
|
|
82
82
|
const fail = (msg) => errors.push(msg);
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Feature #814, mirroring `writeStderr` in cli/src/stderr.ts.
|
|
86
|
+
*
|
|
87
|
+
* `console.error` is asynchronous when stderr is a pipe - which is how CI and
|
|
88
|
+
* every agent runs this generator - so a `process.exit()` in the same tick
|
|
89
|
+
* discards the buffered lines. The gate failures below are the whole value of a
|
|
90
|
+
* failing run, so they are written synchronously; the guard in
|
|
91
|
+
* cli/test/lint-write-before-exit.test.mjs covers cli/src, not cli/scripts.
|
|
92
|
+
*/
|
|
93
|
+
function writeStderr(message) {
|
|
94
|
+
try {
|
|
95
|
+
writeSync(2, message.endsWith("\n") ? message : `${message}\n`);
|
|
96
|
+
} catch {
|
|
97
|
+
// stderr closed or busy - a lost log line is never worth failing a build.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
84
101
|
/** Nothing is written while a single gate is unsatisfied. */
|
|
85
102
|
function exitOnErrors() {
|
|
86
103
|
if (!errors.length) return;
|
|
87
|
-
|
|
88
|
-
|
|
104
|
+
writeStderr(
|
|
105
|
+
["Tool manifest generation failed:", ...errors.map((e) => ` - ${e}`)].join("\n"),
|
|
106
|
+
);
|
|
89
107
|
process.exit(1);
|
|
90
108
|
}
|
|
91
109
|
|
|
@@ -599,10 +617,10 @@ if (toStdout) {
|
|
|
599
617
|
if (current.manifest === nextManifest && current.policy === nextPolicy) {
|
|
600
618
|
console.error("Tool manifest and verb policy are in sync.");
|
|
601
619
|
} else if (checkOnly) {
|
|
602
|
-
|
|
620
|
+
writeStderr(
|
|
603
621
|
"Generated tool manifest / verb policy is stale - run: npm --prefix cli run gen:commands",
|
|
604
622
|
);
|
|
605
|
-
process.
|
|
623
|
+
process.exitCode = 1;
|
|
606
624
|
} else {
|
|
607
625
|
writeFileSync(manifestPath, nextManifest, "utf-8");
|
|
608
626
|
writeFileSync(policyOutPath, nextPolicy, "utf-8");
|
|
@@ -67,6 +67,14 @@
|
|
|
67
67
|
"requires_approval": false,
|
|
68
68
|
"silent_retry_exempt": false
|
|
69
69
|
},
|
|
70
|
+
"kb source": {
|
|
71
|
+
"surface": "both",
|
|
72
|
+
"noun": "kb_read",
|
|
73
|
+
"is_read_only": true,
|
|
74
|
+
"mutation_class": "none",
|
|
75
|
+
"requires_approval": false,
|
|
76
|
+
"silent_retry_exempt": false
|
|
77
|
+
},
|
|
70
78
|
"kb get": {
|
|
71
79
|
"surface": "both",
|
|
72
80
|
"noun": "kb_read",
|
|
@@ -137,7 +145,7 @@
|
|
|
137
145
|
"mutation_class": "none",
|
|
138
146
|
"requires_approval": false,
|
|
139
147
|
"silent_retry_exempt": true,
|
|
140
|
-
"reason": "A CI/shell verb: --path walks a local checkout the app has no filesystem for,
|
|
148
|
+
"reason": "A CI/shell verb: --path walks a local checkout the app has no filesystem for, --sha is the pipeline's job on a pull request, and with neither flag it plans the head of the bound branch - the admin's pre-merge check from a shell. An in-app turn reads the synced KB through the kb_read noun; it has no commit to verify, and the app's own read-only scan of the branch head is the Settings panel's, not an agent's."
|
|
141
149
|
},
|
|
142
150
|
"kb repo apply": {
|
|
143
151
|
"surface": "cli_only",
|
|
@@ -147,6 +155,22 @@
|
|
|
147
155
|
"silent_retry_exempt": true,
|
|
148
156
|
"reason": "The merge job's verb: it applies a provider-verified commit to the shared KB under the repository binding's apply lease. Shared-KB authorship in a repository-owned org happens through a pull request, never an in-app turn, so the app must not advertise it."
|
|
149
157
|
},
|
|
158
|
+
"kb repo status": {
|
|
159
|
+
"surface": "cli_only",
|
|
160
|
+
"is_read_only": true,
|
|
161
|
+
"mutation_class": "none",
|
|
162
|
+
"requires_approval": false,
|
|
163
|
+
"silent_retry_exempt": true,
|
|
164
|
+
"reason": "Reads the durable operation created by the CLI-only verify/apply workflow. The caller supplies its operation id from a shell or CI job; in-app turns do not create those operations."
|
|
165
|
+
},
|
|
166
|
+
"kb repo cancel": {
|
|
167
|
+
"surface": "cli_only",
|
|
168
|
+
"is_read_only": false,
|
|
169
|
+
"mutation_class": "kb",
|
|
170
|
+
"requires_approval": true,
|
|
171
|
+
"silent_retry_exempt": true,
|
|
172
|
+
"reason": "An org admin explicitly stops a saved repository apply task from a shell. This changes the CLI-only apply workflow and is not an in-app shared-KB authoring action."
|
|
173
|
+
},
|
|
150
174
|
"kb repo show": {
|
|
151
175
|
"surface": "cli_only",
|
|
152
176
|
"is_read_only": true,
|
|
@@ -177,7 +201,7 @@
|
|
|
177
201
|
"mutation_class": "kb_config",
|
|
178
202
|
"requires_approval": true,
|
|
179
203
|
"silent_retry_exempt": true,
|
|
180
|
-
"reason": "Binds a provider connection and repository to the org (org admin). The
|
|
204
|
+
"reason": "Binds a provider connection and repository to the org (org admin): the one-time configuration step that decides who owns the shared KB. The admin does it deliberately from a shell alongside the repository checkout they are about to hand the org, and the app's surface for it is the Settings panel's binding form, never an agent turn. Reviewed 2026-09-06 (Issue #921): the earlier reason claimed the connection ids came from the admin's own tooling. They did not - no verb produced one on any surface, which is the gap `connector list` now closes."
|
|
181
205
|
},
|
|
182
206
|
"kb repo identities": {
|
|
183
207
|
"surface": "cli_only",
|
|
@@ -572,7 +596,7 @@
|
|
|
572
596
|
"mutation_class": "none",
|
|
573
597
|
"requires_approval": false,
|
|
574
598
|
"silent_retry_exempt": false,
|
|
575
|
-
"reason": "Connection lifecycle remains CLI-only,
|
|
599
|
+
"reason": "Connection lifecycle remains CLI-only, and warehouse enumeration already exists in-app through the gated `list_warehouse_metadata` overlay tool. A ninth generated noun would duplicate that read surface and spend tool-window budget, so the Commander verb stays excluded while the platform replacement remains available. Reviewed 2026-09-06 (Issue #921): the verb now also lists Slack and repository connections, which the overlay does not - that is deliberate. Those ids are consumed only by verbs that are themselves cli_only (`kb repo bind`, the Slack setup done in the web app), so an in-app turn has nothing to spend them on."
|
|
576
600
|
},
|
|
577
601
|
"connector add snowflake-keypair": {
|
|
578
602
|
"surface": "cli_only",
|
package/skills/graphit/SKILL.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
name: graphit
|
|
3
3
|
description: >-
|
|
4
4
|
Use Graphit for ANY question about the user's business or product data: metrics, KPIs, revenue, retention, spend, users, cohorts, funnels, trends, comparisons, "why did X change", "how are we doing on Y", analysis, reports, or dashboards. Activate even when the user does not say "Graphit" or name any tool: if someone wants to understand their numbers, this is the tool. Graphit answers through a governed semantic layer (computed the team's way, reusable and safe to share) and delivers the answer as a fast cached-data query or a hand-authored interactive HTML dashboard, and can create the metrics, dimensions, and rules an answer needs. Prefer Graphit over hand-rolled one-off analysis whenever the data is, or could be, the user's business data. Skip only for pure software tasks (code, logs, config, infra) or data with nothing to do with the user's business.
|
|
5
|
-
skill_version: "0.2.
|
|
5
|
+
skill_version: "0.2.351"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
<!-- SIZE EXEMPTION (SKILL.md):
|
|
8
|
+
<!-- SIZE EXEMPTION (SKILL.md): hard limit 12,288 chars, exempted ceiling 32,000. Reviewed 2026-09-06. Always-loaded: the collaboration/pace spine, hard constraints + scope gate, the loop, and the generated command table (COMMANDS markers; cli/scripts/generate-commands-doc.mjs) - needed every turn, not deferrable. Marker sits after the frontmatter so the loader and sync-plugin-version.mjs parse it. Raises pay only for command-table growth; each is recorded in docs/knowledge/prompt-engineering/sizing/SIZING.md, prose changes in docs/workflow/prompt-changes/INDEX.md. -->
|
|
9
9
|
|
|
10
10
|
# Graphit CLI
|
|
11
11
|
|
|
@@ -92,7 +92,7 @@ Soft narration is what "just build it" drops. These hard stops hold even then: c
|
|
|
92
92
|
### Handoffs, failure, truthful reporting
|
|
93
93
|
|
|
94
94
|
- Name the handoffs. Some actions live on the platform, not the CLI: visiting a data source's verification link, deleting a source from the Sources Hub. Say when a step hands control back to the user, and move between building the dashboard and building the knowledge base through the gate.
|
|
95
|
-
- Keep
|
|
95
|
+
- Keep scratch files together. In repository-owned workflows, `.graphit/` holds durable KB definitions: never ignore or delete it as scratch. Read repo-preparation.md before authoring those files; other local artifacts follow operations.md.
|
|
96
96
|
- On failure: retry once if it looks transient (timeout, rate limit); on a real error (missing column, permission, validation) stop, say what failed and the next step, never a bare "something went wrong".
|
|
97
97
|
- Report truthfully: what worked, what did not, what you are unsure of. If only part succeeded, say which part and why the rest did not. Done means the answer is delivered and every dashboard element resolves on real data with no entity_sql_warnings.
|
|
98
98
|
|
|
@@ -142,6 +142,7 @@ Load only the relevant reference. Check `graphit <command> --help` for flags.
|
|
|
142
142
|
|
|
143
143
|
| Situation | Read |
|
|
144
144
|
|---|---|
|
|
145
|
+
| preparing a repository-owned KB from repository docs | repo-preparation.md |
|
|
145
146
|
| a brand-new or empty workspace, nothing connected yet | onboarding.md |
|
|
146
147
|
| scoping to a domain, data source, and assets | kb-discovery.md, kb-traversal.md, data-sources.md |
|
|
147
148
|
| a repository-owned (`manual`) org: verify, CI tokens, Data Sources via PR | references/repo-kb.md |
|
|
@@ -162,30 +163,32 @@ Load only the relevant reference. Check `graphit <command> --help` for flags.
|
|
|
162
163
|
|
|
163
164
|
## Commands
|
|
164
165
|
|
|
165
|
-
Claude Code supplies the `graphit` wrapper. On Codex, Cursor, terminals and CI, use `npx -y @graphit/cli@0.2.
|
|
166
|
+
Claude Code supplies the `graphit` wrapper. On Codex, Cursor, terminals and CI, use `npx -y @graphit/cli@0.2.351 <command>`; pin a version for reproducibility. The table is generated from the CLI; check command help for exact flags.
|
|
166
167
|
|
|
167
168
|
<!-- COMMANDS:START -->
|
|
168
169
|
|
|
169
|
-
_Generated
|
|
170
|
+
_Generated by `npm run gen:commands`; do not hand-edit between the markers._
|
|
170
171
|
|
|
171
172
|
**auth** - Authentication commands
|
|
172
173
|
- `auth login` - Log in to Graphit via browser
|
|
173
174
|
- `auth status` - Show current authentication status
|
|
174
175
|
- `auth logout` - Log out and clear stored credentials
|
|
175
176
|
|
|
176
|
-
**status**
|
|
177
|
+
**status**
|
|
177
178
|
- `status` - Show your effective permissions per domain (advisory; the server re-authorizes every operation)
|
|
178
179
|
|
|
179
180
|
**kb** - dbt-native Knowledge Base - semantic models with nested components, concrete metrics/families, groups, and retained rules
|
|
180
|
-
- `kb repo verify` -
|
|
181
|
+
- `kb repo verify` - Plan a .graphit/ tree: identity + access, semantic layer via provenance, validity + completeness, KB/DS/dashboard actions. Any refusal exits 2 (CI fails). --sha pulls that commit from the bound provider (CI); --path uploads a checkout for a local-only plan that can never be applied; neither plans the bound branch head - `--sha --pr --path --allow-dirty --kind --token --poll-interval-ms --timeout-ms`
|
|
181
182
|
- `kb repo show` - Show the repository binding: ownership mode, bound repository, branch, connection, last applied commit
|
|
182
183
|
- `kb repo mode <mode>` - Set KB ownership (org admin): managed = direct writes; manual = the repository owns shared KB assets and Data Source definitions (changes via pull request). A non-empty managed KB refuses manual
|
|
183
|
-
- `kb repo bind` - Bind the owning repository
|
|
184
|
+
- `kb repo bind` - Bind the owning repository (org admin); --repo resolves the provider connection naming it unless several healthy ones match - `--connection --repo --branch --approved-sha`
|
|
184
185
|
- `kb repo identities` - List git identities (org admin): linked, unlinked, and accounts the last plans could not link
|
|
185
186
|
- `kb repo link-identity <provider> <account> <member-email>` - Link a provider account (login or account id) to the member with that email (org admin)
|
|
186
187
|
- `kb repo unlink-identity <provider> <account>` - Unlink a provider account from its member (org admin); leaves a tombstone the silent email match cannot cross
|
|
187
188
|
- `kb repo export-datasources` - Write the live Data Source definitions as datasources/<name>.ds.yml + <name>.sql (org admin): the mirror an org commits before entering manual mode; byte-identical when nothing differs - `--out`
|
|
188
189
|
- `kb repo apply` - Apply a plan (org admin). --plan applies a saved plan id; --sha re-verifies the commit and applies the fresh plan in one call (the merge job). Refuses a stale plan, a changed tree, a failing verdict or a local-only plan; a concurrent apply on the same repository waits - `--plan --sha --pr --kind --token --poll-interval-ms --timeout-ms`
|
|
190
|
+
- `kb repo status <operation-id>` - Read a repository operation once by id; accepts the login or GRAPHIT_TOKEN
|
|
191
|
+
- `kb repo cancel` - Request cancellation of a saved plan (org admin login); already applied changes remain - `--plan`
|
|
189
192
|
- `kb repo token mint` - Mint a display-once CI machine token (org admin); scope kb:verify or kb:apply - `--scope`
|
|
190
193
|
- `kb repo token list` - List CI machine tokens: metadata only, never the secret
|
|
191
194
|
- `kb repo token revoke <token-id>` - Revoke a CI machine token (org admin)
|
|
@@ -200,8 +203,9 @@ _Generated from the CLI by `npm run gen:commands` - do not hand-edit between the
|
|
|
200
203
|
- `kb create rule` - Create a retained Graphit governance rule from JSON. Targets use model:, entity:, dimension:, metric: or group: identities - `--file --json`
|
|
201
204
|
- `kb update <noun> <name>` - Update an asset with a JSON patch. On semantic-model, a provided entities/dimensions/measures list replaces the stored list whole; explicit meta replaces author metadata whole - `--file --json`
|
|
202
205
|
- `kb delete <noun> <name>` - Delete an asset (requires --yes). Checks known definition dependencies; inspect usage separately for canvas impact - `--yes`
|
|
206
|
+
- `kb source <noun> <name>` - Read recorded definition files at the applied repository commit, with numbered lines and drift evidence - `--document --context`
|
|
203
207
|
- `kb get <noun> <name>` - Fetch one asset. Metrics include their family and sibling variants
|
|
204
|
-
- `kb list <noun>` - List
|
|
208
|
+
- `kb list <noun>` - List visible full definitions; opt into paged metric summaries for discovery - `--summary --limit --cursor`
|
|
205
209
|
- `kb tree` - The whole visible semantic layer: group -> semantic model -> assets, metric families collapsed to one card each
|
|
206
210
|
- `kb search <query>` - Search semantic models, metrics, groups and nested components - `--limit`
|
|
207
211
|
- `kb entity <name>` - One entity across every visible semantic model that declares it
|
|
@@ -211,7 +215,7 @@ _Generated from the CLI by `npm run gen:commands` - do not hand-edit between the
|
|
|
211
215
|
- `kb verify <noun> <name>` - Verify a Knowledge Base asset
|
|
212
216
|
- `kb unverify <noun> <name>` - Unverify a Knowledge Base asset
|
|
213
217
|
|
|
214
|
-
**query**
|
|
218
|
+
**query**
|
|
215
219
|
- `query <sql>` - Run SQL against a cached data source or a live warehouse (Snowflake / BigQuery). Check truncated before concluding - `--ds --warehouse --connection --limit --override-rules --verbose --adhoc-reason --apply-conditional --skip-conditional --timeout`
|
|
216
220
|
|
|
217
221
|
**metadata** - Warehouse metadata (Snowflake schemas / BigQuery datasets)
|
|
@@ -247,7 +251,7 @@ _Generated from the CLI by `npm run gen:commands` - do not hand-edit between the
|
|
|
247
251
|
- `dashboard delete <id>` - Delete a custom dashboard (requires --yes) - `--yes`
|
|
248
252
|
|
|
249
253
|
**connector** - Connection management. OAuth and GitHub connections are set up in the Graphit web app.
|
|
250
|
-
- `connector list` - List
|
|
254
|
+
- `connector list` - List connections (Snowflake, BigQuery, Slack, GitHub/Bitbucket)
|
|
251
255
|
- `connector add snowflake-keypair` - Add Snowflake via keypair auth - `--account --user --key --name --warehouse --role --database`
|
|
252
256
|
- `connector add bigquery-serviceaccount` - Add BigQuery via a service-account key (org admin only) - `--key-file --project --dataset --location --name --max-bytes-billed`
|
|
253
257
|
- `connector test <id>` - Test a connection
|
|
@@ -263,7 +267,7 @@ _Generated from the CLI by `npm run gen:commands` - do not hand-edit between the
|
|
|
263
267
|
**plugin** - Inspect Graphit assistant plugin status
|
|
264
268
|
- `plugin status` - Check plugin/package/skill version health - `--json --quiet --skip-network --repair`
|
|
265
269
|
|
|
266
|
-
**setup**
|
|
270
|
+
**setup**
|
|
267
271
|
- `setup` - Install legacy copied Graphit assistant files for Cursor or fallback setups - `--editor --project --update --legacy-copy --remove-legacy-copies --dry-run`
|
|
268
272
|
|
|
269
273
|
<!-- COMMANDS:END -->
|
|
@@ -8,7 +8,7 @@ Load when writing a governed query, explaining a refusal, or reporting provenanc
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| `{{ Metric('revenue') }}` | Reusable metric |
|
|
10
10
|
| `{{ Dimension('order__channel') }}` | Qualified grouping/filter field |
|
|
11
|
-
| `{{ Measure('order_total') }}` | Graphit's model-owned measure extension |
|
|
11
|
+
| `{{ Measure('order_total') }}` / `{{ Measure('order__order_total') }}` | Graphit's model-owned measure extension; the bare form resolves only when the name is unique across shared models, the `entity__name` form pins the owning model like a Dimension path |
|
|
12
12
|
|
|
13
13
|
Legacy token grammar is refused. Keep references inside complete executable SQL and canvas `data-graphit-sql`.
|
|
14
14
|
|
|
@@ -26,6 +26,8 @@ Read `semantic-authoring.md` for model/metric shapes and `metric-families.md` fo
|
|
|
26
26
|
|
|
27
27
|
Rules remain Graphit objects. Create them from JSON with body/constraints plus `apply_on` targets. Final targets are model, entity, dimension, metric, or group identities. A rule without targets is refused.
|
|
28
28
|
|
|
29
|
+
Target grammar, live and in a repository tree alike: `model:`, `entity:` and `group:` names are lowercase snake; `metric:` and `dimension:` names are UPPER (`metric:REVENUE_USD`). In a `.graphit/rules/*.rule.yml` file every target must name something the tree declares, including assets the same sync creates; a bare model name or the model's fully qualified `DATABASE.SCHEMA.TABLE` relation also resolves. `table:` targets are retired - target the semantic model. A rule's dbt-style `groups:` key is not imported; placement comes from `apply_on`.
|
|
30
|
+
|
|
29
31
|
Constraints keep their five semantics: required predicate, forbidden column, required filter, required aggregation, and value restriction. Use declared semantic identities and typed values.
|
|
30
32
|
|
|
31
33
|
## Update
|
|
@@ -4,12 +4,12 @@ Load before querying, authoring, or building a dashboard.
|
|
|
4
4
|
|
|
5
5
|
## Group-first discovery
|
|
6
6
|
|
|
7
|
-
1. Read visible groups and effective status.
|
|
8
|
-
2.
|
|
9
|
-
3.
|
|
10
|
-
4.
|
|
11
|
-
5.
|
|
12
|
-
6.
|
|
7
|
+
1. Read visible groups and effective status. Present the groups related to the question and agree on the starting group and audience with the user; carry forward a choice they already made.
|
|
8
|
+
2. Investigate that group in stages. First inventory its relevant models, metrics, dimensions, measures, entities, families and rules; then read the definitions needed to understand what already exists. Use bounded discovery and continuation rather than loading every full definition at once.
|
|
9
|
+
3. Alongside that focused investigation, run semantic search for the question and related concepts across other accessible groups. A related definition may live elsewhere. Inspect promising matches in full and explain their group and relevance; finding a match does not silently change the agreed data or authoring scope.
|
|
10
|
+
4. Look for existing dashboards using dashboard listing and metric usage. Inspect the relevant accessible dashboards before proposing a duplicate. KB search does not search dashboards or retained rules; use their own reads.
|
|
11
|
+
5. After each meaningful research stage, show what you found and recommend the next step. Let the user choose at real forks; do not silently research everything, build the result and leave them behind.
|
|
12
|
+
6. Before authoring, bring back the existing definitions and dashboards that answer the question, any reusable pieces, and the specific remaining gap. Recommend reuse, extension or new work and agree on that choice with the user before creating anything. Do not repeat a decision or approval they already supplied.
|
|
13
13
|
|
|
14
14
|
The lowercase group name is the semantic label. Use the server-provided uppercase `domain_keys`/status key for data-source `--domain`.
|
|
15
15
|
|
|
@@ -30,21 +30,21 @@ Entities replace relationship assets. Topics are metadata, not roots. Synonyms a
|
|
|
30
30
|
|
|
31
31
|
## Read roles
|
|
32
32
|
|
|
33
|
-
- `list` inventories a root noun.
|
|
33
|
+
- `list` inventories a root noun. For metric candidates, enable `summary`; set `limit` for the page size and pass `next_cursor` as `cursor` to continue. The CLI flags are `--summary`, `--limit`, and `--cursor`.
|
|
34
34
|
- `tree` shows the collapsed hierarchy.
|
|
35
35
|
- `search` covers models, metrics, groups, and nested components; not retained rules.
|
|
36
|
-
- `get` reads one exact root.
|
|
36
|
+
- `get` reads one exact root in full. Inspect candidate metrics and their owning models before deciding that inputs are equivalent; summaries cannot establish reuse.
|
|
37
37
|
- `entity` reads one entity across visible declaring models.
|
|
38
38
|
- `family` expands/resolves concrete members.
|
|
39
39
|
- `explore` accepts semantic-model, metric, or group.
|
|
40
40
|
- `usage` answers dashboard placement and rule impact.
|
|
41
41
|
|
|
42
|
-
A capped or empty search is not proof of absence.
|
|
42
|
+
A capped or empty search is not proof of absence. A summary page is also incomplete while `truncated` is true: follow `next_cursor` before declaring a gap. Report returned items against `total`; totals describe visible scope. If `migration_incomplete` is true, report an incomplete catalog instead of proposing missing assets. Summary descriptions are excerpts; full definitions remain available through `get`.
|
|
43
43
|
|
|
44
44
|
## Governed references
|
|
45
45
|
|
|
46
|
-
Use `{{ Metric('revenue') }}`, `{{ Dimension('order__channel') }}`, and `{{ Measure('order_total') }}` only for Graphit's measure extension. Legacy token grammar is refused.
|
|
46
|
+
Use `{{ Metric('revenue') }}`, `{{ Dimension('order__channel') }}`, and `{{ Measure('order_total') }}` only for Graphit's measure extension. A bare `Measure('name')` must be unique across shared models; write `Measure('entity__name')` to pin the owner. Legacy token grammar is refused.
|
|
47
47
|
|
|
48
48
|
## Gap decision
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Research first, then recommend. Show which existing definitions or dashboards already cover the request, what can be reused or extended, and what is still missing. Propose authoring only for that agreed gap, with formula, grain, binding, group, rule impact and verification. Ask when a choice is unresolved; do not treat a request to investigate as permission to build.
|
|
@@ -6,7 +6,7 @@ Load when investigating semantic reach or presenting KB results.
|
|
|
6
6
|
|
|
7
7
|
| Need | Read |
|
|
8
8
|
|---|---|
|
|
9
|
-
| Inventory roots | list semantic-model, metric, group, or rule |
|
|
9
|
+
| Inventory roots | list semantic-model, metric, group, or rule; enable `summary` for metric candidates |
|
|
10
10
|
| Full root definition | get |
|
|
11
11
|
| Collapsed hierarchy | tree |
|
|
12
12
|
| Ranked discovery | search |
|
|
@@ -15,7 +15,7 @@ Load when investigating semantic reach or presenting KB results.
|
|
|
15
15
|
| Semantic neighborhood | explore semantic-model, metric, or group |
|
|
16
16
|
| Dashboard/rule impact | usage |
|
|
17
17
|
|
|
18
|
-
`list metric` is flat. Families collapse in tree/search/family views.
|
|
18
|
+
`list metric` is flat. Families collapse in tree/search/family views. Metric summaries are candidates, not full definitions: use `get` for semantics and model/source binding before reuse. Continue with `next_cursor` while `truncated` is true; a partial page does not establish absence. Omitting `summary` preserves the existing full-definition listing.
|
|
19
19
|
|
|
20
20
|
## Investigations
|
|
21
21
|
|
|
@@ -58,6 +58,6 @@ Commands write only the result payload to stdout; all decoration (progress, tabl
|
|
|
58
58
|
|
|
59
59
|
## Working artifacts
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
For ordinary dashboard work, keep scratch HTML, exports and throwaway SQL together in `./.graphit/` (distinct from `~/.graphit/` credentials). Exception: in a repository-owned KB workflow that directory is durable, committed source. Load repo-preparation.md and keep scratch exports elsewhere; never make the definition tree self-ignoring.
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
Dashboard scratch is ephemeral and can be regenerated through the CLI. Offer cleanup only for artifacts known to be scratch. Never offer to remove a repository-owned `.graphit/` tree or an existing directory whose contents you have not classified.
|
|
@@ -21,9 +21,11 @@ Run `graphit kb repo show` first.
|
|
|
21
21
|
- `manual` with no binding: initialize. Scaffold `.graphit/` per `repo-preparation.md`,
|
|
22
22
|
run `graphit kb repo verify --path . --allow-dirty` (a `local_only` plan, never
|
|
23
23
|
applyable; an uncommitted `.graphit/` is refused without the flag), fix findings until
|
|
24
|
-
the verdict passes, commit on a branch, open the PR with the user's own tooling. Then tell an org admin to bind (`graphit kb repo bind --
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
the verdict passes, commit on a branch, open the PR with the user's own tooling. Then tell an org admin to bind (`graphit kb repo bind --repo <owner/name> --branch main`;
|
|
25
|
+
the connection resolves from the repository; on `connection_ambiguous` pass
|
|
26
|
+
`--connection <id>` from `graphit connector list`'s `id` column, never the card's token
|
|
27
|
+
fingerprint), link reviewers (`kb repo link-identity`) and mint the CI tokens
|
|
28
|
+
(below). Those are admin actions you never run yourself.
|
|
27
29
|
|
|
28
30
|
## A Data Source through a PR
|
|
29
31
|
|
|
@@ -34,9 +36,10 @@ Run `graphit kb repo show` first.
|
|
|
34
36
|
3. Branch, commit, open the PR with the user's tooling and report the PR link. CI verifies
|
|
35
37
|
the PR head and applies the merged commit; you never merge or apply.
|
|
36
38
|
|
|
37
|
-
A `.sql` change through a PR rebuilds the source with the same `ds_id
|
|
38
|
-
tombstones it;
|
|
39
|
-
|
|
39
|
+
A `.sql` change through a PR rebuilds the source with the same `ds_id`. A deleted file
|
|
40
|
+
tombstones it from the second apply on; the first apply keeps the source as `noop` with
|
|
41
|
+
the warning `ds_first_apply_retained` naming the file to commit. Removing a source
|
|
42
|
+
something still references refuses at plan time (`removal_referenced`).
|
|
40
43
|
|
|
41
44
|
## Both sides
|
|
42
45
|
|
|
@@ -63,11 +66,15 @@ Typed `{code, message}`; read the code, never the prose.
|
|
|
63
66
|
| `binding_incomplete`, `local_only`, `config_revision_moved` | bind first; apply reads the provider, not an upload; reload the binding and verify again |
|
|
64
67
|
| `plan_stale`, `tree_mismatch`, `action_digest_mismatch`, `plan_not_found`, `verdict_failed` | the plan no longer matches the org or the tree: verify again and apply the fresh plan |
|
|
65
68
|
| `apply_in_progress`, `migration_in_progress` | an apply or a migration holds the lease: wait, never cancel |
|
|
66
|
-
| `not_on_base_branch`, `not_descendant_of_last_import`, `pr_head_mismatch`, `
|
|
67
|
-
| `
|
|
69
|
+
| `not_on_base_branch`, `not_descendant_of_last_import`, `pr_head_mismatch`, `pull_request_not_merged`, `merged_commit_mismatch`, `pr_base_branch_mismatch` | verify the PR head; apply only its merged commit on the bound branch |
|
|
70
|
+
| `pull_request_not_found`, `pull_request_list_unavailable` | no PR resolved for that commit, or the index is still warming: pass `--pr <id>` naming the merged PR; if unavailable, retry later |
|
|
71
|
+
| `approvals_unavailable`, `no_head_bound_approvals`, `approval_head_binding_unprovable`, `identity_unlinked`, `identity_unverified`, `member_removed`, `approver_closure_uncovered`, `write_closure_uncovered` | check native PR approval, reviewer linkage and current Graphit permissions; incomplete or moved provider evidence refuses. Fix the cause, then verify again |
|
|
68
72
|
| `certificate_not_applyable`, `migration_requires_plan`, `migration_requires_commit`, `migration_mode_invalid`, `approved_sha_missing`, `approved_sha_mismatch` | migration only: the pre-delete `--kind migration` verify is a certificate; after the delete a fresh `--kind migration` verify yields the plan for `apply --plan <id>`; the SHA must match `bind --approved-sha` |
|
|
69
73
|
| `token_invalid`, `token_revoked`, `token_scope`, `token_repo_mismatch` | CI token: mint a fresh one, use the right scope, mint for this repository |
|
|
70
74
|
|
|
75
|
+
Operation status `failed_retryable`: retry once, then report. `refused` or a `fail`
|
|
76
|
+
verdict: never retry unchanged or route around it.
|
|
77
|
+
|
|
71
78
|
## Refusals inside the app
|
|
72
79
|
|
|
73
80
|
In a manual org the in-app agent and UI refuse shared writes with "the Knowledge Base is
|
|
@@ -77,11 +84,6 @@ its SQL in", "change its refresh contract in" or "remove it by deleting"
|
|
|
77
84
|
`datasources/{name}.sql` "and open a pull request". Private sandboxes and operational verbs
|
|
78
85
|
(refresh, rebuild, pause) stay direct. The fix is the file and a PR, never a workaround.
|
|
79
86
|
|
|
80
|
-
## Failures
|
|
81
|
-
|
|
82
|
-
Operation status `failed_retryable`: retry once, then report. `refused` or a `fail`
|
|
83
|
-
verdict: never retry; report the finding and its next step. Never route around a refusal.
|
|
84
|
-
|
|
85
87
|
## Truthful receipts
|
|
86
88
|
|
|
87
89
|
Report drafted, verified (local-only or provider), PR opened, merged and applied as
|
|
@@ -90,12 +92,13 @@ quote the operation id, the plan id and the verdict. Queued or timed out is not
|
|
|
90
92
|
|
|
91
93
|
## CI in one paragraph
|
|
92
94
|
|
|
93
|
-
Two jobs, two tokens, one pinned CLI version.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
95
|
+
Two jobs, two tokens, one pinned CLI version. Export `GRAPHIT_TOKEN` in the job
|
|
96
|
+
environment, never as `--token` in argv or shell traces. The required PR check uses
|
|
97
|
+
`kb:verify`: `graphit kb repo verify --sha $HEAD --pr $PR` (verify/status only).
|
|
98
|
+
After the customer merges, the protected `kb:apply` job runs
|
|
99
|
+
`graphit kb repo apply --sha $MERGED_SHA`. Both check native reviewers' current
|
|
100
|
+
Graphit permissions; the merger is audit context. Apply revalidates the actual
|
|
101
|
+
merged commit, including squash merges. CI always passes `--sha`; flagless
|
|
102
|
+
interactive verify resolves and reports the bound branch head. Admin commands:
|
|
103
|
+
`graphit kb repo token mint --scope kb:verify|kb:apply` (shown once, `gkb.` prefix),
|
|
104
|
+
`token list`, `token revoke <id>`. Tokens authorize calls, never replace reviewers.
|