specguard-mcp 0.1.33 → 0.1.35
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 +25 -8
- package/dist/src/support/specguard-api.d.ts +8 -8
- package/dist/src/support/specguard-api.js +30 -16
- package/dist/src/support/specguard-api.js.map +1 -1
- package/dist/src/tools/get-intent-schema.js +142 -31
- package/dist/src/tools/get-intent-schema.js.map +1 -1
- package/dist/src/tools/get-server-version.d.ts +5 -2
- package/dist/src/tools/get-server-version.js +11 -3
- package/dist/src/tools/get-server-version.js.map +1 -1
- package/dist/src/tools/lint-intent-annotations.js +10 -8
- package/dist/src/tools/lint-intent-annotations.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ Validates the `@intent:` annotations in a Ruby project's spec files against the
|
|
|
77
77
|
| argument | |
|
|
78
78
|
| --- | --- |
|
|
79
79
|
| `project_dir` | the project to lint; defaults to the server's working directory. A path that does not exist, or is not a directory, is refused by name — never reported as a missing linter |
|
|
80
|
-
| `paths` | specific spec files, relative to `project_dir`; omit to check
|
|
80
|
+
| `paths` | specific spec files, relative to `project_dir`; omit to check every spec file outside dependency/build directories. An empty list is an error rather than a synonym for "everything", because a run that selected nothing must not come back clean |
|
|
81
81
|
| `changed` | check what the branch changed since the merge base with the default branch — CI's mode; untracked spec files count too (no `git add` needed); `--exclude-standard` keeps `.gitignore`d paths out of the untracked leg alone, and a tracked file is never subject to `.gitignore`, so the dependency/build directory fence holds ignored tracked paths out |
|
|
82
82
|
| `base` | diff `changed` against this ref instead |
|
|
83
83
|
|
|
@@ -106,14 +106,28 @@ property can never appear in any refusal: `required` does not name it, and a clo
|
|
|
106
106
|
only ever reports the key you did send, so nothing you submit at any value causes the linter to
|
|
107
107
|
mention it. That part of the contract is reachable here and nowhere else in this toolset.
|
|
108
108
|
|
|
109
|
-
The answer carries the whole document in
|
|
110
|
-
cannot disagree:
|
|
109
|
+
The answer is an **envelope** that carries the whole document in both shapes, derived from one
|
|
110
|
+
fetched body so they cannot disagree — plus the enforcement identity beside it:
|
|
111
111
|
|
|
112
112
|
| field | |
|
|
113
113
|
| --- | --- |
|
|
114
|
-
| `structured` | the document **parsed** — the shape to read the field rules and any enumerated values off |
|
|
114
|
+
| `structured.schema` | the document **parsed** — the shape to read the field rules and any enumerated values off |
|
|
115
|
+
| `structured.enforced` | the identity the deployment itself serves from its `GET /version`: `schema_sha256`, the digest of the contract it actually enforces, and `schema_origin`, where those bytes come from on the server — or `null` when the deployment could not say |
|
|
115
116
|
| `text` | the served bytes **unchanged** — no re-encoding, no reformatting, so a digest taken over this text matches the canonical document's, which is the mirror's whole promise |
|
|
116
117
|
|
|
118
|
+
**The end-to-end check is derivable from this one tool.** Take a SHA-256 digest over `text` and
|
|
119
|
+
compare it with `enforced.schema_sha256`: a **match** means the reference you read is the contract
|
|
120
|
+
that will judge you; a **mismatch** means the bytes you received are *not* what the deployment
|
|
121
|
+
enforces — do not author annotations against them, and read `enforced.schema_origin` to see which
|
|
122
|
+
half of the disagreement is the server's. The tool serves both facts side by side and never
|
|
123
|
+
judges: a mismatch is never refused or warned here, because the judgment is yours.
|
|
124
|
+
|
|
125
|
+
**`enforced: null` means "this deployment could not say"** — its `/version` omits the identity
|
|
126
|
+
keys (a build predating the identity channel), answers non-2xx, or the identity fetch fails
|
|
127
|
+
entirely — and the document answer still stands in full. It is not the same null as a served
|
|
128
|
+
`schema_sha256: null` *inside* a present `enforced`: that is the deployment's own honest "I
|
|
129
|
+
enforce from this origin and cannot currently read it", passed through exactly as served.
|
|
130
|
+
|
|
117
131
|
Nothing in this bridge restates the schema's contents — not here, not in a tool description, not in
|
|
118
132
|
a test. The answer *is* the contract; any prose copy of it would be one release behind the document
|
|
119
133
|
this tool serves, and this repo deliberately vendors no copy of its own.
|
|
@@ -125,9 +139,9 @@ upgrading"*, not as a wrong URL. A **2xx** whose body will not parse is reported
|
|
|
125
139
|
mirror instead, naming the route rather than your configuration: the response arrived, so the
|
|
126
140
|
endpoint is not the thing to go and fix.
|
|
127
141
|
|
|
128
|
-
**Needs no API key of any kind** —
|
|
129
|
-
|
|
130
|
-
arguments.
|
|
142
|
+
**Needs no API key of any kind** — both routes it reads (the schema mirror and `GET /version`) are
|
|
143
|
+
unauthenticated by design, because a contract is not a secret — so it works with
|
|
144
|
+
`SPECGUARD_ENDPOINT` alone and sends no `Authorization` header. Takes no arguments.
|
|
131
145
|
|
|
132
146
|
### `get_repository_overview`
|
|
133
147
|
|
|
@@ -430,7 +444,10 @@ cancelled after two of four shards leaves a half-sized row in the history perman
|
|
|
430
444
|
|
|
431
445
|
Reports **which build of the SpecGuard deployment is answering**, read from the deployment's own
|
|
432
446
|
unauthenticated root-level `GET /version` — the figure the release bot's `VERSION` file carries,
|
|
433
|
-
served as
|
|
447
|
+
served as a JSON object and passed through verbatim. Since SPGD-1316 the body also carries the
|
|
448
|
+
enforced contract's identity beside the build (`schema_sha256` + `schema_origin`); this tool
|
|
449
|
+
passes the whole answer through without interpreting it — `get_intent_schema` is where the served
|
|
450
|
+
contract is read beside that identity and the two are compared.
|
|
434
451
|
|
|
435
452
|
**This is the server's build, not this bridge's.** The version in the initialize handshake's
|
|
436
453
|
`serverInfo` and the `specguard-mcp/<version>` User-Agent describe *this bridge* — a different
|
|
@@ -29,12 +29,12 @@ export declare function getJson(api: ApiConfig, path: string, query: Record<stri
|
|
|
29
29
|
* is for differs per caller, while the status check and the "reached and
|
|
30
30
|
* refused" hand-off to `describeFailure` do not.
|
|
31
31
|
*
|
|
32
|
-
* So this shares `
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
32
|
+
* So this shares through `requestText` — the one total deadline, the abort,
|
|
33
|
+
* the reached-and-stopped vs could-not-reach split, and every crafted status
|
|
34
|
+
* sentence — and differs from `getJson` in exactly one thing: it returns what
|
|
35
|
+
* came back instead of what it parsed. A caller that wants a parsed value
|
|
36
|
+
* parses it, and owns the diagnosis for its own body, which is the only place
|
|
37
|
+
* that diagnosis can be correct.
|
|
38
38
|
*/
|
|
39
39
|
export declare function getText(api: ApiConfig, path: string, fetchImpl: typeof globalThis.fetch): Promise<string>;
|
|
40
40
|
/**
|
|
@@ -79,8 +79,8 @@ export declare function patchJson(api: ApiConfig, path: string, body: Record<str
|
|
|
79
79
|
* "answered 204 but the body was not JSON" — the trap this verb specifically
|
|
80
80
|
* introduces, and the reason the DELETE path has its own success handling
|
|
81
81
|
* instead of sharing `requestJson`'s. The status check and the
|
|
82
|
-
* "reached and refused" hand-off to `describeFailure` are still shared
|
|
83
|
-
*
|
|
82
|
+
* "reached and refused" hand-off to `describeFailure` are still shared through
|
|
83
|
+
* `requestText`: only what happens to a SUCCESS body differs.
|
|
84
84
|
*/
|
|
85
85
|
export declare function deleteJson(api: ApiConfig, path: string, fetchImpl: typeof globalThis.fetch): Promise<string>;
|
|
86
86
|
/**
|
|
@@ -37,18 +37,15 @@ export async function getJson(api, path, query, fetchImpl) {
|
|
|
37
37
|
* is for differs per caller, while the status check and the "reached and
|
|
38
38
|
* refused" hand-off to `describeFailure` do not.
|
|
39
39
|
*
|
|
40
|
-
* So this shares `
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
40
|
+
* So this shares through `requestText` — the one total deadline, the abort,
|
|
41
|
+
* the reached-and-stopped vs could-not-reach split, and every crafted status
|
|
42
|
+
* sentence — and differs from `getJson` in exactly one thing: it returns what
|
|
43
|
+
* came back instead of what it parsed. A caller that wants a parsed value
|
|
44
|
+
* parses it, and owns the diagnosis for its own body, which is the only place
|
|
45
|
+
* that diagnosis can be correct.
|
|
46
46
|
*/
|
|
47
47
|
export async function getText(api, path, fetchImpl) {
|
|
48
|
-
|
|
49
|
-
if (!response.ok)
|
|
50
|
-
throw describeFailure(response.status, body, api);
|
|
51
|
-
return body;
|
|
48
|
+
return requestText(new URL(`${api.endpoint}${path}`), api, fetchImpl, { method: "GET" });
|
|
52
49
|
}
|
|
53
50
|
/**
|
|
54
51
|
* `POST` with a JSON body — the write half of the transport, and deliberately
|
|
@@ -102,14 +99,11 @@ export async function patchJson(api, path, body, fetchImpl) {
|
|
|
102
99
|
* "answered 204 but the body was not JSON" — the trap this verb specifically
|
|
103
100
|
* introduces, and the reason the DELETE path has its own success handling
|
|
104
101
|
* instead of sharing `requestJson`'s. The status check and the
|
|
105
|
-
* "reached and refused" hand-off to `describeFailure` are still shared
|
|
106
|
-
*
|
|
102
|
+
* "reached and refused" hand-off to `describeFailure` are still shared through
|
|
103
|
+
* `requestText`: only what happens to a SUCCESS body differs.
|
|
107
104
|
*/
|
|
108
105
|
export async function deleteJson(api, path, fetchImpl) {
|
|
109
|
-
|
|
110
|
-
if (!response.ok)
|
|
111
|
-
throw describeFailure(response.status, body, api);
|
|
112
|
-
return body;
|
|
106
|
+
return requestText(new URL(`${api.endpoint}${path}`), api, fetchImpl, { method: "DELETE" });
|
|
113
107
|
}
|
|
114
108
|
/**
|
|
115
109
|
* `DELETE` that answers with a JSON body — the destructive verb's one non-empty
|
|
@@ -179,6 +173,26 @@ async function requestJson(url, api, fetchImpl, request) {
|
|
|
179
173
|
"or login page.", response.status);
|
|
180
174
|
}
|
|
181
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* The raw-body verbs' half of the response handling `requestJson` owns, in one
|
|
178
|
+
* place.
|
|
179
|
+
*
|
|
180
|
+
* Extracted when `getText` needed a home beside the JSON verbs rather than
|
|
181
|
+
* copied into it: the status check and the "reached and refused" hand-off to
|
|
182
|
+
* `describeFailure` are identical for both raw-body verbs, and what a SUCCESS
|
|
183
|
+
* body is for — the thing that differs per caller — stays out of here. There
|
|
184
|
+
* is deliberately NO not-JSON branch: for a bytes-are-the-answer contract,
|
|
185
|
+
* `requestJson`'s "was not JSON" diagnosis is wrong even when a parse would
|
|
186
|
+
* fail, because it names a cause (misconfigured endpoint) the correct response
|
|
187
|
+
* in hand refutes. A caller that wants a parsed value parses its own body and
|
|
188
|
+
* owns that judgment.
|
|
189
|
+
*/
|
|
190
|
+
async function requestText(url, api, fetchImpl, request) {
|
|
191
|
+
const { response, body } = await fetchWithTimeout(url, api, fetchImpl, request);
|
|
192
|
+
if (!response.ok)
|
|
193
|
+
throw describeFailure(response.status, body, api);
|
|
194
|
+
return body;
|
|
195
|
+
}
|
|
182
196
|
/** The three-clause guard both `*JsonObject` narrowings share. */
|
|
183
197
|
function asJsonObject(body) {
|
|
184
198
|
if (typeof body !== "object" || body === null || Array.isArray(body)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specguard-api.js","sourceRoot":"","sources":["../../../src/support/specguard-api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,2BAA2B,GAI5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAc,EACd,IAAY,EACZ,KAAyC,EACzC,SAAkC;IAElC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,IAAI,EAAE,CAAC,CAAC;IAC9C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAc,EACd,IAAY,EACZ,SAAkC;IAElC,
|
|
1
|
+
{"version":3,"file":"specguard-api.js","sourceRoot":"","sources":["../../../src/support/specguard-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiError } from "../errors.js";
|
|
2
|
-
import { getText, requireEndpointApiConfig } from "../support/specguard-api.js";
|
|
2
|
+
import { getJsonObject, getText, requireEndpointApiConfig } from "../support/specguard-api.js";
|
|
3
3
|
/**
|
|
4
4
|
* The OpenTestIntent contract, READABLE — the reference this bridge was
|
|
5
5
|
* missing beside the judge it already had.
|
|
@@ -51,29 +51,85 @@ import { getText, requireEndpointApiConfig } from "../support/specguard-api.js";
|
|
|
51
51
|
* handling, exactly as `deleteJson` does for its empty `204`.
|
|
52
52
|
*
|
|
53
53
|
* The verbatim body is then served as the text view and PARSED ONCE for the
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
54
|
+
* document view, both derived from the one fetched value as `tools/types.ts`
|
|
55
|
+
* requires. The text half is what keeps the mirror's promise intact across
|
|
56
|
+
* this bridge: a consumer digesting what it received gets the same digest the
|
|
57
|
+
* platform's own spec asserts, which a re-encode or a pretty-print would
|
|
58
|
+
* destroy. The structured half is the shape an agent actually reads a
|
|
59
|
+
* contract from — and `application/schema+json` carries the `+json`
|
|
60
|
+
* structured-syntax suffix precisely so a client dispatching on "is this
|
|
61
|
+
* JSON" still parses it.
|
|
62
62
|
*
|
|
63
63
|
* A 2xx body that will not parse is a genuinely malformed mirror and is
|
|
64
64
|
* reported as THAT, naming the route rather than the endpoint variable: the
|
|
65
65
|
* response arrived, so the configuration is not the thing to go and fix.
|
|
66
66
|
*
|
|
67
|
+
* == The enforcement identity beside it: a SECOND body, whose disagreement IS
|
|
68
|
+
* the check
|
|
69
|
+
*
|
|
70
|
+
* Since SPGD-1316 the deployment also answers WHICH CONTRACT IT ENFORCES:
|
|
71
|
+
* `GET /version` carries `schema_sha256` — the digest of the vendored document
|
|
72
|
+
* this process validates every ingested annotation against — and
|
|
73
|
+
* `schema_origin`, the repo-relative path those bytes come from. The pairing
|
|
74
|
+
* the platform's own controller names is exact: the same bytes are fetchable,
|
|
75
|
+
* unauthenticated, from this same host at the mirror route above, so a client
|
|
76
|
+
* can digest them itself and check the served answer. This tool is where that
|
|
77
|
+
* loop closes. Until now the bridge carried those keys invisibly —
|
|
78
|
+
* `get_server_version` passed them through, but the tool whose question IS the
|
|
79
|
+
* contract named no comparison target, and `schema_sha256` appeared nowhere on
|
|
80
|
+
* this surface — so the question "is the reference I read the contract that
|
|
81
|
+
* will judge me?" was underivable from this toolset at all.
|
|
82
|
+
*
|
|
83
|
+
* `run()` now makes BOTH fetches and serves the two facts side by side. The
|
|
84
|
+
* identity fetch is the exact helper on the exact route `get_server_version`
|
|
85
|
+
* uses — `getJsonObject` against `/version` — so nothing new is invented: no
|
|
86
|
+
* second tool on that route, no new transport, no new credential kind, no new
|
|
87
|
+
* dependency. What is new is the shape of the answer: `structured` becomes an
|
|
88
|
+
* envelope, `{ schema, enforced }`, with the server's own key names preserved
|
|
89
|
+
* verbatim so the family cross-check is one vocabulary.
|
|
90
|
+
*
|
|
91
|
+
* The one-body doctrine above is RECONCILED here, not violated: `text` and
|
|
92
|
+
* `structured.schema` are two views of the ONE mirror body and must not
|
|
93
|
+
* disagree, while the whole point of `enforced` is that it CAN — a mismatch
|
|
94
|
+
* between a SHA-256 digest over `text` and `enforced.schema_sha256` IS the
|
|
95
|
+
* finding, and `enforced.schema_origin` is the fact that says which half of
|
|
96
|
+
* the disagreement is the server's. The tool serves both facts and never
|
|
97
|
+
* judges: refusing or warning on a mismatch would blind the agent in exactly
|
|
98
|
+
* the mangled-transport case where both facts matter most, and the judgment
|
|
99
|
+
* is the reader's.
|
|
100
|
+
*
|
|
101
|
+
* == The identity leg is best-effort by design
|
|
102
|
+
*
|
|
103
|
+
* Its failure must never fail the tool whose primary answer is the document.
|
|
104
|
+
* Any of — a deployment predating the identity channel (its `/version` omits
|
|
105
|
+
* the keys), a non-2xx answer, a network failure, a body that will not parse —
|
|
106
|
+
* yields `enforced: null` with the document answer still standing in full. No
|
|
107
|
+
* throw, no sentinel. `null` means "this deployment could not say", and the
|
|
108
|
+
* description says so in the reader's terms. This inherits the server's own
|
|
109
|
+
* nil doctrine in both directions: a current deployment whose vendored schema
|
|
110
|
+
* cannot be read answers `schema_sha256: null` at 200 — an honest null INSIDE
|
|
111
|
+
* a present envelope, passed through as served — while `enforced: null` is
|
|
112
|
+
* the envelope-level absence, the deployment having said nothing at all. The
|
|
113
|
+
* two nulls answer different questions and are kept apart.
|
|
114
|
+
*
|
|
67
115
|
* == No arguments, no credential
|
|
68
116
|
*
|
|
69
|
-
*
|
|
70
|
-
* advertises no argument and binds no key — the second consumer of
|
|
117
|
+
* Neither route takes parameters and neither authenticates anything, so the
|
|
118
|
+
* tool advertises no argument and binds no key — the second consumer of
|
|
71
119
|
* `requireEndpointApiConfig` after `get_server_version`, sending no
|
|
72
|
-
* `Authorization` header even when every key variable is set.
|
|
73
|
-
* not a secret, and presenting a key an endpoint does not read
|
|
74
|
-
* authentication, it is leakage.
|
|
120
|
+
* `Authorization` header on EITHER fetch even when every key variable is set.
|
|
121
|
+
* A contract is not a secret, and presenting a key an endpoint does not read
|
|
122
|
+
* is not authentication, it is leakage.
|
|
75
123
|
*/
|
|
76
124
|
const SCHEMA_PATH = "/schemas/open-test-intent.v1.json";
|
|
125
|
+
/**
|
|
126
|
+
* The identity route, beside the mirror route above — the exact path
|
|
127
|
+
* `get_server_version` reads, fetched here with the exact helper that tool
|
|
128
|
+
* uses. One route, one tool each: this is not a second tool on `/version`, it
|
|
129
|
+
* is the contract tool carrying the comparison target its own description
|
|
130
|
+
* invites the reader to compute.
|
|
131
|
+
*/
|
|
132
|
+
const VERSION_PATH = "/version";
|
|
77
133
|
const getIntentSchema = {
|
|
78
134
|
name: "get_intent_schema",
|
|
79
135
|
title: "OpenTestIntent schema",
|
|
@@ -85,17 +141,31 @@ const getIntentSchema = {
|
|
|
85
141
|
"also the ONLY way to learn parts of it: a refusal names the legal values of a field you got " +
|
|
86
142
|
"wrong but says nothing about a field you omitted, and an OPTIONAL property can never appear in " +
|
|
87
143
|
"any refusal at all — nothing you submit, at any value, causes the linter to mention it. The " +
|
|
88
|
-
"answer
|
|
89
|
-
"disagree: `structured` is it parsed, which is what to read the
|
|
90
|
-
"values off; `text` is the served bytes UNCHANGED, so a digest
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
144
|
+
"answer is an envelope carrying the whole document in both shapes, derived from one fetched " +
|
|
145
|
+
"body so they cannot disagree: `structured.schema` is it parsed, which is what to read the " +
|
|
146
|
+
"field rules and any enumerated values off; `text` is the served bytes UNCHANGED, so a digest " +
|
|
147
|
+
"taken over it matches the canonical document's. Beside the document, `structured.enforced` " +
|
|
148
|
+
"carries the enforcement identity the deployment itself serves from its `GET /version` — " +
|
|
149
|
+
"`schema_sha256`, the digest of the contract it actually enforces, and `schema_origin`, where " +
|
|
150
|
+
"those bytes come from on the server — which makes the end-to-end check derivable from this " +
|
|
151
|
+
"one tool: take a SHA-256 digest over `text` and compare it with `enforced.schema_sha256`. A " +
|
|
152
|
+
"match means the reference you read IS the contract that will judge you; a mismatch means the " +
|
|
153
|
+
"bytes you received are NOT what the deployment enforces, and you must not author annotations " +
|
|
154
|
+
"against them — `enforced.schema_origin` names which half of the disagreement is the " +
|
|
155
|
+
"server's. The tool serves both facts side by side and never judges: a mismatch is never " +
|
|
156
|
+
"refused or warned here, because the judgment is the reader's and a hard failure would blind " +
|
|
157
|
+
"you in exactly the mangled-transport case where both facts matter most. `enforced` is null " +
|
|
158
|
+
"when this deployment could not say — its `/version` omits the identity keys (a build " +
|
|
159
|
+
"predating the identity channel), answers non-2xx, or the identity fetch fails entirely — and " +
|
|
160
|
+
"the document answer still stands in full; null means 'this deployment could not say', never " +
|
|
161
|
+
"a sentinel. Nothing here restates the schema's contents — the answer is the contract, and " +
|
|
162
|
+
"any prose copy of it would be one release behind. A 404 means this deployment PREDATES the " +
|
|
163
|
+
"mirror route: the endpoint is right and the build is old. The error text names the endpoint " +
|
|
164
|
+
"as possibly misconfigured because a non-contract 404 body names no cause — when the other " +
|
|
165
|
+
"tools work against the same endpoint, read it as 'the deployment needs upgrading', not as a " +
|
|
166
|
+
"wrong URL. Needs NO API key of any kind — both routes it reads are unauthenticated by " +
|
|
167
|
+
"design, because a contract is not a secret — so it works with SPECGUARD_ENDPOINT alone and " +
|
|
168
|
+
"sends no Authorization header. Takes no arguments.",
|
|
99
169
|
inputSchema: {
|
|
100
170
|
type: "object",
|
|
101
171
|
// No properties, deliberately — a document has no ask to narrow. Still
|
|
@@ -108,11 +178,14 @@ const getIntentSchema = {
|
|
|
108
178
|
async run(_args, context) {
|
|
109
179
|
const api = requireEndpointApiConfig(context.config);
|
|
110
180
|
const document = await getText(api, SCHEMA_PATH, context.fetch);
|
|
181
|
+
const schema = parseSchemaDocument(document, api.endpoint);
|
|
111
182
|
return {
|
|
112
|
-
// The served bytes, unchanged — see this file's header.
|
|
113
|
-
// off this ONE value
|
|
183
|
+
// The served bytes, unchanged — see this file's header. The document's
|
|
184
|
+
// two views come off this ONE value; `enforced` is the deliberate SECOND
|
|
185
|
+
// body, whose possible disagreement with a digest over this text IS the
|
|
186
|
+
// check.
|
|
114
187
|
text: document,
|
|
115
|
-
structured:
|
|
188
|
+
structured: { schema, enforced: await enforcedIdentity(api, context.fetch) },
|
|
116
189
|
};
|
|
117
190
|
},
|
|
118
191
|
};
|
|
@@ -127,9 +200,9 @@ const getIntentSchema = {
|
|
|
127
200
|
* report has somewhere to go.
|
|
128
201
|
*
|
|
129
202
|
* The object narrowing is part of the same answer rather than a second failure
|
|
130
|
-
* mode bolted beside it:
|
|
131
|
-
*
|
|
132
|
-
*
|
|
203
|
+
* mode bolted beside it: a schema document's root is a JSON object, and a
|
|
204
|
+
* mirror serving an array or a bare scalar is malformed in exactly the way
|
|
205
|
+
* this sentence describes.
|
|
133
206
|
*/
|
|
134
207
|
function parseSchemaDocument(body, endpoint) {
|
|
135
208
|
let parsed;
|
|
@@ -149,5 +222,43 @@ function parseSchemaDocument(body, endpoint) {
|
|
|
149
222
|
}
|
|
150
223
|
return parsed;
|
|
151
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* The enforcement identity, fetched BEST-EFFORT — the `enforced` half of the
|
|
227
|
+
* envelope.
|
|
228
|
+
*
|
|
229
|
+
* Success is narrow and everything else is the same `null`. The narrow path: a
|
|
230
|
+
* 2xx JSON object carrying BOTH identity keys. A build predating the identity
|
|
231
|
+
* channel answers `{"version": …}` alone, and an envelope built over a missing
|
|
232
|
+
* key would be a fabricated half-answer rather than an honest absence, so the
|
|
233
|
+
* pair is required together — the same all-or-nothing choice the singular/
|
|
234
|
+
* plural branch in the transport makes. The values are copied through verbatim
|
|
235
|
+
* under the server's own key names, INCLUDING a null digest: a deployment that
|
|
236
|
+
* cannot currently read its vendored schema answers `schema_sha256: null` at
|
|
237
|
+
* 200 by its own doctrine, and that honesty is not this bridge's to improve —
|
|
238
|
+
* a present envelope saying "I enforce from this origin and cannot currently
|
|
239
|
+
* read it" is strictly more actionable than the envelope-level null below.
|
|
240
|
+
*
|
|
241
|
+
* Everything else — a non-2xx answer, an unreachable deployment, a timeout, a
|
|
242
|
+
* body that will not parse or is not an object, a `/version` that predates the
|
|
243
|
+
* route entirely — lands in the catch and returns `null`. That is deliberate:
|
|
244
|
+
* the identity leg is best-effort BY DESIGN, and its failure must never fail
|
|
245
|
+
* the tool whose primary answer is the document. `null` means "this deployment
|
|
246
|
+
* could not say", never a sentinel.
|
|
247
|
+
*/
|
|
248
|
+
async function enforcedIdentity(api, fetchImpl) {
|
|
249
|
+
try {
|
|
250
|
+
const version = await getJsonObject(api, VERSION_PATH, {}, fetchImpl);
|
|
251
|
+
if ("schema_sha256" in version && "schema_origin" in version) {
|
|
252
|
+
return {
|
|
253
|
+
schema_sha256: version["schema_sha256"],
|
|
254
|
+
schema_origin: version["schema_origin"],
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
152
263
|
export default getIntentSchema;
|
|
153
264
|
//# sourceMappingURL=get-intent-schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-intent-schema.js","sourceRoot":"","sources":["../../../src/tools/get-intent-schema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-intent-schema.js","sourceRoot":"","sources":["../../../src/tools/get-intent-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,8 +44,11 @@ import type { ToolDefinition } from "./types.js";
|
|
|
44
44
|
* the tool advertises no argument and requires no key: it is the first tool
|
|
45
45
|
* here served by `requireEndpointApiConfig`, and the transport sends no
|
|
46
46
|
* `Authorization` header for it. The body is passed through verbatim —
|
|
47
|
-
* reshaping
|
|
48
|
-
*
|
|
47
|
+
* reshaping it would be a second copy of the platform's own identity answer,
|
|
48
|
+
* one release behind it. Since SPGD-1316 that body also carries the enforced
|
|
49
|
+
* contract's identity (`schema_sha256` + `schema_origin`) beside the build;
|
|
50
|
+
* this tool does not interpret it — `get_intent_schema` serves the contract
|
|
51
|
+
* beside that identity, which is where the pair is compared.
|
|
49
52
|
*/
|
|
50
53
|
declare const getServerVersion: ToolDefinition;
|
|
51
54
|
export default getServerVersion;
|
|
@@ -44,15 +44,23 @@ import { getJsonObject, requireEndpointApiConfig } from "../support/specguard-ap
|
|
|
44
44
|
* the tool advertises no argument and requires no key: it is the first tool
|
|
45
45
|
* here served by `requireEndpointApiConfig`, and the transport sends no
|
|
46
46
|
* `Authorization` header for it. The body is passed through verbatim —
|
|
47
|
-
* reshaping
|
|
48
|
-
*
|
|
47
|
+
* reshaping it would be a second copy of the platform's own identity answer,
|
|
48
|
+
* one release behind it. Since SPGD-1316 that body also carries the enforced
|
|
49
|
+
* contract's identity (`schema_sha256` + `schema_origin`) beside the build;
|
|
50
|
+
* this tool does not interpret it — `get_intent_schema` serves the contract
|
|
51
|
+
* beside that identity, which is where the pair is compared.
|
|
49
52
|
*/
|
|
50
53
|
const getServerVersion = {
|
|
51
54
|
name: "get_server_version",
|
|
52
55
|
title: "Server version",
|
|
53
56
|
description: "Reports WHICH BUILD of the SpecGuard DEPLOYMENT is answering, read from the deployment's own " +
|
|
54
57
|
"unauthenticated root-level `GET /version` — the figure the release bot's VERSION file carries, " +
|
|
55
|
-
|
|
58
|
+
"served as a JSON object and passed through verbatim. Since SPGD-1316 that body also carries " +
|
|
59
|
+
"the enforced contract's identity beside the build — `schema_sha256`, the digest of the " +
|
|
60
|
+
"OpenTestIntent document this deployment validates annotations against, and `schema_origin`, " +
|
|
61
|
+
"where those bytes come from on the server — and the whole object is passed through without " +
|
|
62
|
+
"interpreting it; get_intent_schema is where the served contract is read beside that identity " +
|
|
63
|
+
"and the two are compared. " +
|
|
56
64
|
"This is the SERVER's build, NOT this bridge's: the version in the initialize handshake's " +
|
|
57
65
|
"`serverInfo` and the `specguard-mcp/<version>` User-Agent describe this bridge, a different " +
|
|
58
66
|
"component released on its own cadence, so never read one as the other. Pinning which build's " +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-server-version.js","sourceRoot":"","sources":["../../../src/tools/get-server-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAGtF
|
|
1
|
+
{"version":3,"file":"get-server-version.js","sourceRoot":"","sources":["../../../src/tools/get-server-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAGtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,gBAAgB,GAAmB;IACvC,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,gBAAgB;IACvB,WAAW,EACT,+FAA+F;QAC/F,iGAAiG;QACjG,8FAA8F;QAC9F,yFAAyF;QACzF,8FAA8F;QAC9F,6FAA6F;QAC7F,+FAA+F;QAC/F,4BAA4B;QAC5B,2FAA2F;QAC3F,8FAA8F;QAC9F,+FAA+F;QAC/F,iGAAiG;QACjG,0FAA0F;QAC1F,gGAAgG;QAChG,+FAA+F;QAC/F,8FAA8F;QAC9F,iGAAiG;QACjG,gGAAgG;QAChG,gGAAgG;QAChG,iGAAiG;QACjG,+FAA+F;QAC/F,uFAAuF;IACzF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,4EAA4E;QAC5E,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,mDAAmD;QACnD,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO;QACtB,MAAM,GAAG,GAAG,wBAAwB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAErD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAEvE,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACrC,UAAU,EAAE,MAAM;SACnB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -67,8 +67,8 @@ const lintIntentAnnotations = {
|
|
|
67
67
|
type: "array",
|
|
68
68
|
items: { type: "string" },
|
|
69
69
|
description: "Specific spec files to check, relative to project_dir. Omit to check every *_spec.rb " +
|
|
70
|
-
"under it. An empty list is an error, not a way
|
|
71
|
-
"Cannot be combined with `changed`.",
|
|
70
|
+
"under it outside dependency/build directories. An empty list is an error, not a way " +
|
|
71
|
+
"to say 'everything'. Cannot be combined with `changed`.",
|
|
72
72
|
},
|
|
73
73
|
changed: {
|
|
74
74
|
type: "boolean",
|
|
@@ -313,10 +313,11 @@ function truncate(value, limit = 2000) {
|
|
|
313
313
|
*
|
|
314
314
|
* `paths: []` is REFUSED rather than normalised. Both readings of it are bad and
|
|
315
315
|
* neither is what an agent meant: passed through, an empty list leaves the
|
|
316
|
-
* linter with no positional arguments and it audits
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
316
|
+
* linter with no positional arguments and it audits every spec file the default
|
|
317
|
+
* walk selects — every one outside the dependency/build directories — so "check
|
|
318
|
+
* nothing" comes back as a clean bill of health for the whole suite; silently
|
|
319
|
+
* treated as "not given", the same thing happens by a different route. A tool
|
|
320
|
+
* whose entire purpose is to stop a check that examined nothing
|
|
320
321
|
* from looking like a check that found nothing cannot itself answer an empty
|
|
321
322
|
* selection with "all clean". So it is an error, and the message says which of
|
|
322
323
|
* the two the caller probably wanted.
|
|
@@ -336,8 +337,9 @@ function optionalStringArray(value, field) {
|
|
|
336
337
|
const nonEmpty = entries.filter((entry) => entry !== "");
|
|
337
338
|
if (nonEmpty.length === 0) {
|
|
338
339
|
throw new CommandError(`\`${field}\` was given but names no file${entries.length === 0 ? "" : " (every entry was blank)"}, ` +
|
|
339
|
-
"which selects nothing to check. Omit `paths` to check every spec file in the project
|
|
340
|
-
"or list the files you want checked — an empty
|
|
340
|
+
"which selects nothing to check. Omit `paths` to check every spec file in the project " +
|
|
341
|
+
"outside dependency/build directories, or list the files you want checked — an empty " +
|
|
342
|
+
"selection is not treated as “everything”, " +
|
|
341
343
|
"because a run that checked nothing must never come back clean.");
|
|
342
344
|
}
|
|
343
345
|
// A leading `-` would be read by the linter's OptionParser as a flag rather
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint-intent-annotations.js","sourceRoot":"","sources":["../../../src/tools/lint-intent-annotations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAsB,MAAM,2BAA2B,CAAC;AACtG,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,qBAAqB,GAAmB;IAC5C,IAAI,EAAE,yBAAyB;IAE/B,KAAK,EAAE,0BAA0B;IAEjC,WAAW,EACT,kFAAkF;QAClF,4FAA4F;QAC5F,6FAA6F;QAC7F,mFAAmF;QACnF,+EAA+E;QAC/E,6FAA6F;QAC7F,4FAA4F;IAE9F,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,oFAAoF;oBACpF,8DAA8D;aACjE;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EACT,uFAAuF;oBACvF,
|
|
1
|
+
{"version":3,"file":"lint-intent-annotations.js","sourceRoot":"","sources":["../../../src/tools/lint-intent-annotations.ts"],"names":[],"mappings":"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"}
|