@gate-forge/pack-playwright 0.1.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/LICENSE +202 -0
- package/bin/gateforge-witness.js +40 -0
- package/dist/attestation/proxy.d.ts +40 -0
- package/dist/attestation/proxy.d.ts.map +1 -0
- package/dist/attestation/proxy.js +78 -0
- package/dist/attestation/proxy.js.map +1 -0
- package/dist/constants.d.ts +130 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +138 -0
- package/dist/constants.js.map +1 -0
- package/dist/discovery/adapters.d.ts +167 -0
- package/dist/discovery/adapters.d.ts.map +1 -0
- package/dist/discovery/adapters.js +276 -0
- package/dist/discovery/adapters.js.map +1 -0
- package/dist/discovery/discover.d.ts +57 -0
- package/dist/discovery/discover.d.ts.map +1 -0
- package/dist/discovery/discover.js +544 -0
- package/dist/discovery/discover.js.map +1 -0
- package/dist/discovery/index.d.ts +15 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +15 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/inference.d.ts +63 -0
- package/dist/discovery/inference.d.ts.map +1 -0
- package/dist/discovery/inference.js +173 -0
- package/dist/discovery/inference.js.map +1 -0
- package/dist/discovery/pytest-adapter.d.ts +205 -0
- package/dist/discovery/pytest-adapter.d.ts.map +1 -0
- package/dist/discovery/pytest-adapter.js +548 -0
- package/dist/discovery/pytest-adapter.js.map +1 -0
- package/dist/discovery/reconcile.d.ts +106 -0
- package/dist/discovery/reconcile.d.ts.map +1 -0
- package/dist/discovery/reconcile.js +268 -0
- package/dist/discovery/reconcile.js.map +1 -0
- package/dist/discovery/runner-env.d.ts +80 -0
- package/dist/discovery/runner-env.d.ts.map +1 -0
- package/dist/discovery/runner-env.js +139 -0
- package/dist/discovery/runner-env.js.map +1 -0
- package/dist/discovery/static-discovery.d.ts +121 -0
- package/dist/discovery/static-discovery.d.ts.map +1 -0
- package/dist/discovery/static-discovery.js +1028 -0
- package/dist/discovery/static-discovery.js.map +1 -0
- package/dist/discovery/supervised-run.d.ts +110 -0
- package/dist/discovery/supervised-run.d.ts.map +1 -0
- package/dist/discovery/supervised-run.js +328 -0
- package/dist/discovery/supervised-run.js.map +1 -0
- package/dist/discovery/trusted-config.d.ts +103 -0
- package/dist/discovery/trusted-config.d.ts.map +1 -0
- package/dist/discovery/trusted-config.js +117 -0
- package/dist/discovery/trusted-config.js.map +1 -0
- package/dist/fixture/evidence.d.ts +191 -0
- package/dist/fixture/evidence.d.ts.map +1 -0
- package/dist/fixture/evidence.js +366 -0
- package/dist/fixture/evidence.js.map +1 -0
- package/dist/fixture/fixture.d.ts +37 -0
- package/dist/fixture/fixture.d.ts.map +1 -0
- package/dist/fixture/fixture.js +38 -0
- package/dist/fixture/fixture.js.map +1 -0
- package/dist/fixture/witness-client.d.ts +164 -0
- package/dist/fixture/witness-client.d.ts.map +1 -0
- package/dist/fixture/witness-client.js +253 -0
- package/dist/fixture/witness-client.js.map +1 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +16 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +21 -0
- package/dist/json.js.map +1 -0
- package/dist/reporter/ledger.d.ts +105 -0
- package/dist/reporter/ledger.d.ts.map +1 -0
- package/dist/reporter/ledger.js +197 -0
- package/dist/reporter/ledger.js.map +1 -0
- package/dist/reporter/reporter.cjs +105 -0
- package/dist/reporter/reporter.cjs.map +1 -0
- package/dist/reporter/reporter.d.cts +35 -0
- package/dist/reporter/reporter.d.cts.map +1 -0
- package/dist/reporter/reporter.d.ts +167 -0
- package/dist/reporter/reporter.d.ts.map +1 -0
- package/dist/reporter/reporter.js +673 -0
- package/dist/reporter/reporter.js.map +1 -0
- package/dist/setup.d.ts +49 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +167 -0
- package/dist/setup.js.map +1 -0
- package/dist/supervisor/client.d.ts +73 -0
- package/dist/supervisor/client.d.ts.map +1 -0
- package/dist/supervisor/client.js +164 -0
- package/dist/supervisor/client.js.map +1 -0
- package/dist/supervisor/drain.d.ts +45 -0
- package/dist/supervisor/drain.d.ts.map +1 -0
- package/dist/supervisor/drain.js +235 -0
- package/dist/supervisor/drain.js.map +1 -0
- package/dist/supervisor/index.d.ts +16 -0
- package/dist/supervisor/index.d.ts.map +1 -0
- package/dist/supervisor/index.js +13 -0
- package/dist/supervisor/index.js.map +1 -0
- package/dist/supervisor/spool.d.ts +137 -0
- package/dist/supervisor/spool.d.ts.map +1 -0
- package/dist/supervisor/spool.js +263 -0
- package/dist/supervisor/spool.js.map +1 -0
- package/dist/surface.d.ts +134 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +139 -0
- package/dist/surface.js.map +1 -0
- package/dist/witness/adapter-registry.d.ts +38 -0
- package/dist/witness/adapter-registry.d.ts.map +1 -0
- package/dist/witness/adapter-registry.js +158 -0
- package/dist/witness/adapter-registry.js.map +1 -0
- package/dist/witness/bin.d.ts +21 -0
- package/dist/witness/bin.d.ts.map +1 -0
- package/dist/witness/bin.js +172 -0
- package/dist/witness/bin.js.map +1 -0
- package/dist/witness/browser.d.ts +173 -0
- package/dist/witness/browser.d.ts.map +1 -0
- package/dist/witness/browser.js +580 -0
- package/dist/witness/browser.js.map +1 -0
- package/dist/witness/classifications.d.ts +42 -0
- package/dist/witness/classifications.d.ts.map +1 -0
- package/dist/witness/classifications.js +87 -0
- package/dist/witness/classifications.js.map +1 -0
- package/dist/witness/env-attestation.d.ts +98 -0
- package/dist/witness/env-attestation.d.ts.map +1 -0
- package/dist/witness/env-attestation.js +202 -0
- package/dist/witness/env-attestation.js.map +1 -0
- package/dist/witness/loopback-pins.d.ts +79 -0
- package/dist/witness/loopback-pins.d.ts.map +1 -0
- package/dist/witness/loopback-pins.js +244 -0
- package/dist/witness/loopback-pins.js.map +1 -0
- package/dist/witness/server.d.ts +34 -0
- package/dist/witness/server.d.ts.map +1 -0
- package/dist/witness/server.js +2539 -0
- package/dist/witness/server.js.map +1 -0
- package/dist/witness/types.d.ts +643 -0
- package/dist/witness/types.d.ts.map +1 -0
- package/dist/witness/types.js +2 -0
- package/dist/witness/types.js.map +1 -0
- package/package.json +64 -0
- package/python/gateforge_persistence_intents.py +100 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kind/category inference rules (plan 2026-09-13 phase 2 item 5): pure
|
|
3
|
+
* functions over the facts a static scan collected. Every rule returns
|
|
4
|
+
* its id plus the source location that fired it — no opaque confidence
|
|
5
|
+
* scores, and no rule is allowed to silently become proof:
|
|
6
|
+
*
|
|
7
|
+
* - Strong kind rules (fixtures, request contexts, HTTP-client calls,
|
|
8
|
+
* network-less bodies) propose a {@link TestKind}.
|
|
9
|
+
* - Agreeing proposals decide the kind; conflicting or absent proposals
|
|
10
|
+
* resolve to `unknown` (visible, never promoted).
|
|
11
|
+
* - Title/folder keyword matches are WEAK signals only — recorded, but
|
|
12
|
+
* never kind-deciding (§3.2: "a unit test named 'creates account' is
|
|
13
|
+
* still a unit test").
|
|
14
|
+
* - Known mock patterns (`page.route`, `vi.mock`/`jest.mock`) become
|
|
15
|
+
* suppression signals; they can disqualify later proof but do not
|
|
16
|
+
* classify the test by themselves.
|
|
17
|
+
*/
|
|
18
|
+
import type { CategorySignal, KindSignal, RuleEvidence, SuppressionSignal, TestKind, WeakSignal } from '@gate-forge/core';
|
|
19
|
+
import type { StaticTestFacts } from './static-discovery.js';
|
|
20
|
+
/** Signature parameter names that prove a real API context is in play. */
|
|
21
|
+
export declare const API_FIXTURE_PARAMS: readonly string[];
|
|
22
|
+
/** The facts inference consumes (file-level facts shared by the scan). */
|
|
23
|
+
export interface InferenceFacts {
|
|
24
|
+
/** Repo-relative file (weak path hints). */
|
|
25
|
+
file: string;
|
|
26
|
+
/** Test title (weak title hints, category keywords). */
|
|
27
|
+
title: string;
|
|
28
|
+
/** Full title path (weak title hints). */
|
|
29
|
+
titlePath: readonly string[];
|
|
30
|
+
/** The static facts of the call: fixtures + body/file patterns. */
|
|
31
|
+
facts: StaticTestFacts;
|
|
32
|
+
}
|
|
33
|
+
/** What inference concluded for one test. */
|
|
34
|
+
export interface InferenceResult {
|
|
35
|
+
/** The concluded kind (`unknown` when nothing or a conflict). */
|
|
36
|
+
inferredKind: TestKind;
|
|
37
|
+
/** Strong kind rules that fired (kind + code evidence). */
|
|
38
|
+
kindSignals: KindSignal[];
|
|
39
|
+
/** Weak title/folder hints (never kind-deciding). */
|
|
40
|
+
weakSignals: WeakSignal[];
|
|
41
|
+
/** EVERY rule that fired, in stable rule-id order. */
|
|
42
|
+
rulesFired: RuleEvidence[];
|
|
43
|
+
/** Behavior-category hints (labels only). */
|
|
44
|
+
categorySignals: CategorySignal[];
|
|
45
|
+
/** Mock-pattern suppression signals observed for this test. */
|
|
46
|
+
mockSignals: SuppressionSignal[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Runs every rule over one test's facts and resolves the kind.
|
|
50
|
+
*
|
|
51
|
+
* Combination rule: distinct PROPOSED kinds are computed first — exactly
|
|
52
|
+
* one distinct kind decides; zero or more-than-one resolve to
|
|
53
|
+
* `unknown` (recorded, visible, never silently promoted).
|
|
54
|
+
*
|
|
55
|
+
* Args:
|
|
56
|
+
* input: the test's file/title/facts bundle.
|
|
57
|
+
*
|
|
58
|
+
* Returns:
|
|
59
|
+
* InferenceResult: kind, all fired rules with evidence locations,
|
|
60
|
+
* weak signals, category hints, and mock signals.
|
|
61
|
+
*/
|
|
62
|
+
export declare function inferTestKind(input: InferenceFacts): InferenceResult;
|
|
63
|
+
//# sourceMappingURL=inference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inference.d.ts","sourceRoot":"","sources":["../../src/discovery/inference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EAEV,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAAgB,CAAC;AAEjE,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,mEAAmE;IACnE,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,YAAY,EAAE,QAAQ,CAAC;IACvB,2DAA2D;IAC3D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,qDAAqD;IACrD,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,sDAAsD;IACtD,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,6CAA6C;IAC7C,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,+DAA+D;IAC/D,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AA+ED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAqEpE"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { BROWSER_FIXTURE_PARAMS } from './static-discovery.js';
|
|
2
|
+
/** Signature parameter names that prove a real API context is in play. */
|
|
3
|
+
export const API_FIXTURE_PARAMS = ['request'];
|
|
4
|
+
/** Rules that propose a kind, strongest-first, with their evidence. */
|
|
5
|
+
const KIND_RULES = [
|
|
6
|
+
{
|
|
7
|
+
ruleId: 'browser-fixture',
|
|
8
|
+
kind: 'browser-e2e',
|
|
9
|
+
applies: (input) => {
|
|
10
|
+
const browserParams = input.facts.signatureParams.filter((name) => BROWSER_FIXTURE_PARAMS.has(name));
|
|
11
|
+
if (browserParams.length === 0)
|
|
12
|
+
return null;
|
|
13
|
+
return {
|
|
14
|
+
evidence: `test signature declares browser fixture(s): ${browserParams.join(', ')}`,
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
ruleId: 'api-request-fixture',
|
|
20
|
+
kind: 'api-e2e',
|
|
21
|
+
applies: (input) => {
|
|
22
|
+
const apiParams = input.facts.signatureParams.filter((name) => API_FIXTURE_PARAMS.includes(name));
|
|
23
|
+
if (apiParams.length === 0)
|
|
24
|
+
return null;
|
|
25
|
+
return { evidence: `test signature declares API fixture(s): ${apiParams.join(', ')}` };
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
ruleId: 'http-client-call',
|
|
30
|
+
kind: 'api-e2e',
|
|
31
|
+
applies: (input) => {
|
|
32
|
+
const where = input.facts.httpClientCall ?? input.facts.fileHttpClientCall;
|
|
33
|
+
if (where === null)
|
|
34
|
+
return null;
|
|
35
|
+
return {
|
|
36
|
+
evidence: `HTTP client call at ${where.file}:${String(where.line)} reaches the application boundary`,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
// Network-less pure-function probe: no fixtures at all and no
|
|
42
|
+
// app-boundary (HTTP) call anywhere in the file → unit hint.
|
|
43
|
+
ruleId: 'networkless-unit',
|
|
44
|
+
kind: 'unit',
|
|
45
|
+
applies: (input) => {
|
|
46
|
+
if (input.facts.signatureParams.length > 0)
|
|
47
|
+
return null;
|
|
48
|
+
if (input.facts.pageRoute !== null)
|
|
49
|
+
return null;
|
|
50
|
+
if (input.facts.httpClientCall !== null || input.facts.fileHttpClientCall !== null)
|
|
51
|
+
return null;
|
|
52
|
+
return { evidence: 'no fixtures and no application-boundary call: a network-less function probe' };
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
/** Weak keyword hints per title/path token. Never kind-deciding. */
|
|
57
|
+
const TITLE_KEYWORD_RULES = [
|
|
58
|
+
{ token: 'e2e', hint: 'title mentions e2e (weak)' },
|
|
59
|
+
{ token: 'integration', hint: 'title mentions integration (weak)' },
|
|
60
|
+
{ token: 'unit', hint: 'title mentions unit (weak)' },
|
|
61
|
+
];
|
|
62
|
+
/** Path segments treated as weak hints. */
|
|
63
|
+
const PATH_KEYWORD_RULES = [
|
|
64
|
+
{ token: 'e2e', hint: 'path segment mentions e2e (weak)' },
|
|
65
|
+
{ token: 'integration', hint: 'path segment mentions integration (weak)' },
|
|
66
|
+
{ token: 'unit', hint: 'path segment mentions unit (weak)' },
|
|
67
|
+
];
|
|
68
|
+
/** Category keyword → dotted label (hints only, never proof). */
|
|
69
|
+
const CATEGORY_KEYWORDS = [
|
|
70
|
+
{ pattern: /\bcreat|\badd/i, label: 'persistence.create' },
|
|
71
|
+
{ pattern: /\bupdate|\bedit/i, label: 'persistence.update' },
|
|
72
|
+
{ pattern: /\bdelet|\bremov|\bdestroy/i, label: 'persistence.delete' },
|
|
73
|
+
{ pattern: /\bread|\bshow|\bview|\blist|\bdisplay/i, label: 'persistence.read' },
|
|
74
|
+
{ pattern: /\blogin|\blogout|\bauth|\bsign[ -]?(in|up)/i, label: 'authentication' },
|
|
75
|
+
{ pattern: /\bvalid|\binvalid/i, label: 'validation' },
|
|
76
|
+
{ pattern: /\bnavigat|\bredirect/i, label: 'navigation' },
|
|
77
|
+
{ pattern: /\bworkflow|\bjourney/i, label: 'workflow' },
|
|
78
|
+
];
|
|
79
|
+
/**
|
|
80
|
+
* Runs every rule over one test's facts and resolves the kind.
|
|
81
|
+
*
|
|
82
|
+
* Combination rule: distinct PROPOSED kinds are computed first — exactly
|
|
83
|
+
* one distinct kind decides; zero or more-than-one resolve to
|
|
84
|
+
* `unknown` (recorded, visible, never silently promoted).
|
|
85
|
+
*
|
|
86
|
+
* Args:
|
|
87
|
+
* input: the test's file/title/facts bundle.
|
|
88
|
+
*
|
|
89
|
+
* Returns:
|
|
90
|
+
* InferenceResult: kind, all fired rules with evidence locations,
|
|
91
|
+
* weak signals, category hints, and mock signals.
|
|
92
|
+
*/
|
|
93
|
+
export function inferTestKind(input) {
|
|
94
|
+
const kindSignals = [];
|
|
95
|
+
const rulesFired = [];
|
|
96
|
+
const weakSignals = [];
|
|
97
|
+
const categorySignals = [];
|
|
98
|
+
const mockSignals = [];
|
|
99
|
+
for (const rule of KIND_RULES) {
|
|
100
|
+
const outcome = rule.applies(input);
|
|
101
|
+
if (outcome === null)
|
|
102
|
+
continue;
|
|
103
|
+
// The evidence location: prefer the exact body location when the
|
|
104
|
+
// rule observed one, else the first fixture param is located at the
|
|
105
|
+
// call (unknown here) — inference callers pass call-level facts, so
|
|
106
|
+
// the evidence points at what the rule saw.
|
|
107
|
+
rulesFired.push({ ruleId: rule.ruleId, evidence: outcome.evidence, location: evidenceLocation(rule.ruleId, input) });
|
|
108
|
+
kindSignals.push({ ruleId: rule.ruleId, kind: rule.kind, evidence: outcome.evidence, location: evidenceLocation(rule.ruleId, input) });
|
|
109
|
+
}
|
|
110
|
+
for (const rule of TITLE_KEYWORD_RULES) {
|
|
111
|
+
const haystack = [...input.titlePath, input.title].join(' ').toLowerCase();
|
|
112
|
+
if (haystack.includes(rule.token)) {
|
|
113
|
+
weakSignals.push({ ruleId: 'title-keywords', evidence: rule.hint, location: weakLocation(input) });
|
|
114
|
+
rulesFired.push({ ruleId: 'title-keywords', evidence: rule.hint, location: weakLocation(input) });
|
|
115
|
+
break; // one title hint is enough; keep the trace small
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const rule of PATH_KEYWORD_RULES) {
|
|
119
|
+
const segments = input.file.toLowerCase().split('/');
|
|
120
|
+
if (segments.includes(rule.token)) {
|
|
121
|
+
weakSignals.push({ ruleId: 'path-keywords', evidence: rule.hint, location: weakLocation(input) });
|
|
122
|
+
rulesFired.push({ ruleId: 'path-keywords', evidence: rule.hint, location: weakLocation(input) });
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (input.facts.pageRoute !== null) {
|
|
127
|
+
mockSignals.push({
|
|
128
|
+
kind: 'mock',
|
|
129
|
+
detail: 'page.route interception inside the test body',
|
|
130
|
+
location: input.facts.pageRoute,
|
|
131
|
+
});
|
|
132
|
+
rulesFired.push({ ruleId: 'mock-page-route', evidence: 'page.route call intercepts network', location: input.facts.pageRoute });
|
|
133
|
+
}
|
|
134
|
+
if (input.facts.fileMockImport !== null) {
|
|
135
|
+
mockSignals.push({
|
|
136
|
+
kind: 'mock',
|
|
137
|
+
detail: 'vi.mock/jest.mock module mock in the test file',
|
|
138
|
+
location: input.facts.fileMockImport,
|
|
139
|
+
});
|
|
140
|
+
rulesFired.push({ ruleId: 'mock-module-import', evidence: 'module-level mock call', location: input.facts.fileMockImport });
|
|
141
|
+
}
|
|
142
|
+
for (const rule of CATEGORY_KEYWORDS) {
|
|
143
|
+
if (rule.pattern.test(input.title)) {
|
|
144
|
+
categorySignals.push({ label: rule.label, ruleId: 'category-keywords', location: weakLocation(input) });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const distinct = [...new Set(kindSignals.map((signal) => signal.kind))];
|
|
148
|
+
const inferredKind = distinct.length === 1 ? distinct[0] : 'unknown';
|
|
149
|
+
if (distinct.length > 1) {
|
|
150
|
+
rulesFired.push({
|
|
151
|
+
ruleId: 'kind-conflict',
|
|
152
|
+
evidence: `rules propose conflicting kinds (${distinct.sort().join(', ')}): resolved to unknown`,
|
|
153
|
+
location: weakLocation(input),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return { inferredKind, kindSignals, weakSignals, rulesFired, categorySignals, mockSignals };
|
|
157
|
+
}
|
|
158
|
+
/** The location a strong rule's evidence points at. */
|
|
159
|
+
function evidenceLocation(ruleId, input) {
|
|
160
|
+
if (ruleId === 'http-client-call') {
|
|
161
|
+
return input.facts.httpClientCall ?? input.facts.fileHttpClientCall ?? { file: input.file, line: 1, col: 0 };
|
|
162
|
+
}
|
|
163
|
+
if (ruleId === 'mock-page-route')
|
|
164
|
+
return input.facts.pageRoute ?? { file: input.file, line: 1, col: 0 };
|
|
165
|
+
// Fixture/unit rules have no sharper location than the file itself at
|
|
166
|
+
// line 1 — the catalog row carries the exact call location separately.
|
|
167
|
+
return { file: input.file, line: 1, col: 0 };
|
|
168
|
+
}
|
|
169
|
+
/** Stable placeholder location for file-level weak signals. */
|
|
170
|
+
function weakLocation(input) {
|
|
171
|
+
return { file: input.file, line: 1, col: 0 };
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=inference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inference.js","sourceRoot":"","sources":["../../src/discovery/inference.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import type { DiagnosticSuite } from '@gate-forge/core';
|
|
2
|
+
import { TestDiscoveryError } from './reconcile.js';
|
|
3
|
+
/** One collected pytest case, identity preserved (§3.5). */
|
|
4
|
+
export interface PytestCollectedCase {
|
|
5
|
+
/** The exact pytest node id, parameters included. */
|
|
6
|
+
nodeId: string;
|
|
7
|
+
/** File part of the node id (posix, suite-cwd-relative). */
|
|
8
|
+
file: string;
|
|
9
|
+
/** Class/test segments after the file part. */
|
|
10
|
+
titlePath: string[];
|
|
11
|
+
}
|
|
12
|
+
/** Outcome of one collection run. */
|
|
13
|
+
export interface PytestCollectionResult {
|
|
14
|
+
status: 'discovered' | 'unavailable';
|
|
15
|
+
/** Single-cause detail (errors verbatim, bounded). */
|
|
16
|
+
detail: string;
|
|
17
|
+
cases: PytestCollectedCase[];
|
|
18
|
+
/** Node ids pytest reported as collection errors, if any. */
|
|
19
|
+
collectionErrors: string[];
|
|
20
|
+
exitCode: number | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Composes the collection argv for a configured suite: the configured
|
|
24
|
+
* interpreter/args verbatim, then `--collect-only -q`, then the
|
|
25
|
+
* configured testPaths. Nothing else — no directory guessing, no extra
|
|
26
|
+
* commands beyond the configured argv + collection flags.
|
|
27
|
+
*
|
|
28
|
+
* Args:
|
|
29
|
+
* suite: the configured diagnostic suite.
|
|
30
|
+
*
|
|
31
|
+
* Returns:
|
|
32
|
+
* string[]: argv to spawn with cwd = repo root (the adapter passes the
|
|
33
|
+
* suite's own testPaths, which are repo-root-relative and resolved by
|
|
34
|
+
* the caller's cwd choice).
|
|
35
|
+
*/
|
|
36
|
+
export declare function pytestCollectArgv(suite: DiagnosticSuite): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Composes the Phase 4 diagnostic EXECUTION argv (junit XML into the
|
|
39
|
+
* EXCLUDED run-state dir). Exported now so the composition is tested;
|
|
40
|
+
* invoking it is Phase 4 work.
|
|
41
|
+
*
|
|
42
|
+
* Args:
|
|
43
|
+
* suite: the configured diagnostic suite.
|
|
44
|
+
* stateDir: absolute run-state directory (excluded from inputs).
|
|
45
|
+
*
|
|
46
|
+
* Returns:
|
|
47
|
+
* string[]: argv running the suite with a junitxml report at
|
|
48
|
+
* `<stateDir>/diagnostics/<suite.name>.xml`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function pytestExecutionArgv(suite: DiagnosticSuite, stateDir: string): string[];
|
|
51
|
+
/**
|
|
52
|
+
* Runs one bounded collection for a configured suite. The child runs as
|
|
53
|
+
* UNTRUSTED consumer code (all `GATEFORGE_*` env stripped — same trust
|
|
54
|
+
* boundary as playwright enumeration) with the suite's finite timeout.
|
|
55
|
+
*
|
|
56
|
+
* Args:
|
|
57
|
+
* suite: the configured suite (argv, testPaths, timeoutMs).
|
|
58
|
+
* cwd: absolute repo root the repo-relative testPaths resolve against.
|
|
59
|
+
*
|
|
60
|
+
* Returns:
|
|
61
|
+
* Promise<PytestCollectionResult>: collected node ids or an
|
|
62
|
+
* unavailable verdict — collection failure is data (§3.5: show
|
|
63
|
+
* incomplete status), never a fabricated empty success.
|
|
64
|
+
*/
|
|
65
|
+
export declare function collectPytestSuite(suite: DiagnosticSuite, cwd: string): Promise<PytestCollectionResult>;
|
|
66
|
+
/** One parsed junit-XML testcase (pytest diagnostics surface). */
|
|
67
|
+
export interface JunitTestCase {
|
|
68
|
+
/** Classname (module path as pytest emitted it). */
|
|
69
|
+
classname: string;
|
|
70
|
+
/** Test name incl. parameters, e.g. `test_x[param-2]`. */
|
|
71
|
+
name: string;
|
|
72
|
+
/** passed | failed | error | skipped. */
|
|
73
|
+
outcome: 'passed' | 'failed' | 'error' | 'skipped';
|
|
74
|
+
/** The skip/xfail type attribute when skipped, e.g. `pytest.xfail`. */
|
|
75
|
+
skipType?: string;
|
|
76
|
+
/** First line of failure/error/skip message, when present. */
|
|
77
|
+
message?: string;
|
|
78
|
+
/** The file attribute pytest emits when present (node-id reconstruction). */
|
|
79
|
+
file?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Parsed junit-XML document (one testsuite). */
|
|
82
|
+
export interface JunitDocument {
|
|
83
|
+
suiteName: string;
|
|
84
|
+
tests: number;
|
|
85
|
+
failures: number;
|
|
86
|
+
errors: number;
|
|
87
|
+
skipped: number;
|
|
88
|
+
cases: JunitTestCase[];
|
|
89
|
+
}
|
|
90
|
+
/** Typed parser failure for malformed junit XML (fail closed). */
|
|
91
|
+
export declare class JunitParseError extends Error {
|
|
92
|
+
constructor(message: string);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Parses a pytest junit-XML document into structured outcomes (plan
|
|
96
|
+
* phase 2 item 8: prefer structured results over parsing terminal
|
|
97
|
+
* colors). Bounded and strict: the parser understands the exact subset
|
|
98
|
+
* pytest emits (`<testsuite>` with `<testcase>` children carrying
|
|
99
|
+
* `<failure>`, `<error>`, or `<skipped type="...">` children) and THROWS
|
|
100
|
+
* (`JunitParseError`) on anything else — a malformed report is never
|
|
101
|
+
* silently read as a green run. xfail appears as `skipped` with
|
|
102
|
+
* `type="pytest.xfail"`; collection errors appear as testcases named
|
|
103
|
+
* `pytest_collection` with an `<error>` child.
|
|
104
|
+
*
|
|
105
|
+
* Args:
|
|
106
|
+
* xml: the junit-XML document text.
|
|
107
|
+
*
|
|
108
|
+
* Returns:
|
|
109
|
+
* JunitDocument: suite counters + one row per testcase.
|
|
110
|
+
*
|
|
111
|
+
* Throws:
|
|
112
|
+
* JunitParseError: on missing/malformed structure (fail closed).
|
|
113
|
+
*/
|
|
114
|
+
export declare function parseJunitXml(xml: string): JunitDocument;
|
|
115
|
+
/**
|
|
116
|
+
* Repo-relative form of `path` against `cwd` (absolute inputs only by
|
|
117
|
+
* contract; relative pass through normalized).
|
|
118
|
+
*/
|
|
119
|
+
export declare function repoRelative(cwd: string, path: string): string;
|
|
120
|
+
/** Honest status of one diagnostic suite run (§3.5 — never E2E proof). */
|
|
121
|
+
export type DiagnosticRunStatus =
|
|
122
|
+
/** Completed run, ≥1 passing test, no unexpected failures. */
|
|
123
|
+
'completed'
|
|
124
|
+
/** Completed run with ≥1 test failure. */
|
|
125
|
+
| 'failures'
|
|
126
|
+
/** Unavailable/incomplete: collection error, timeout, missing
|
|
127
|
+
* interpreter, interruption, zero tests, or only skipped/xfail. */
|
|
128
|
+
| 'incomplete';
|
|
129
|
+
/** Advisory diagnostic cause codes (plan §5.4 — report-only, never verdicts). */
|
|
130
|
+
export type DiagnosticCause = 'DIAGNOSTIC_TEST_FAILURE' | 'DIAGNOSTIC_RUN_INCOMPLETE';
|
|
131
|
+
/** One structured per-suite diagnostic result (plan §5.1 "Diagnostic result"). */
|
|
132
|
+
export interface DiagnosticRunResult {
|
|
133
|
+
/** The configured suite name. */
|
|
134
|
+
suite: string;
|
|
135
|
+
/** Honest status: completed | failures | incomplete. */
|
|
136
|
+
status: DiagnosticRunStatus;
|
|
137
|
+
/** Suite process exit code (pytest exit codes, null on spawn failure). */
|
|
138
|
+
exitCode: number | null;
|
|
139
|
+
/** True when the finite timeout expired and the child was killed. */
|
|
140
|
+
timedOut: boolean;
|
|
141
|
+
/** Spawn failure detail (e.g. missing interpreter), or null. */
|
|
142
|
+
spawnError: string | null;
|
|
143
|
+
/** Collection/setup errors observed (from stderr scan + junit). */
|
|
144
|
+
collectionErrors: string[];
|
|
145
|
+
/** The selected scope (the configured testPaths, verbatim). */
|
|
146
|
+
selectedScope: string[];
|
|
147
|
+
/** Node ids the report covered (file::name, parameters included). */
|
|
148
|
+
nodeIds: string[];
|
|
149
|
+
/** Per-case outcomes from the junit report. */
|
|
150
|
+
cases: Array<{
|
|
151
|
+
nodeId: string;
|
|
152
|
+
outcome: 'passed' | 'failed' | 'error' | 'skipped';
|
|
153
|
+
skipType?: string;
|
|
154
|
+
message?: string;
|
|
155
|
+
/** Failure phase: collection/setup surface as 'error', others 'call'. */
|
|
156
|
+
phase: 'collection' | 'setup' | 'call' | 'teardown' | 'unknown';
|
|
157
|
+
}>;
|
|
158
|
+
/** Explicit counters — skips/xfail never become passes or proof. */
|
|
159
|
+
counts: {
|
|
160
|
+
passed: number;
|
|
161
|
+
failed: number;
|
|
162
|
+
errors: number;
|
|
163
|
+
skipped: number;
|
|
164
|
+
xfailed: number;
|
|
165
|
+
};
|
|
166
|
+
/** True only when the run was bounded and its report parsed. */
|
|
167
|
+
complete: boolean;
|
|
168
|
+
/** Single-cause detail when incomplete. */
|
|
169
|
+
incompleteDetail: string | null;
|
|
170
|
+
/** Advisory causes for this suite (report-only). */
|
|
171
|
+
causes: DiagnosticCause[];
|
|
172
|
+
/** Absolute junit-XML report path (inside the excluded run-state dir). */
|
|
173
|
+
reportPath: string;
|
|
174
|
+
/** Whether the report file exists on disk. */
|
|
175
|
+
reportExists: boolean;
|
|
176
|
+
/** True when the junit report existed but could not be parsed (fail closed). */
|
|
177
|
+
reportUnparsable: boolean;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Executes one configured diagnostic suite ONCE (plan Phase 4 item 9, §3.5):
|
|
181
|
+
* an isolated process (every `GATEFORGE_*` variable stripped), the
|
|
182
|
+
* configured argv + a junit-XML report into the EXCLUDED run-state dir,
|
|
183
|
+
* and a finite timeout. The result is advisory diagnostic data — it is
|
|
184
|
+
* never witness evidence and never satisfies an E2E obligation.
|
|
185
|
+
*
|
|
186
|
+
* Exit semantics (plan §3.5 / pytest exit codes):
|
|
187
|
+
* - `completed`: run finished, ≥1 passed, no unexpected failures;
|
|
188
|
+
* - `failures`: the run finished with test failures;
|
|
189
|
+
* - `incomplete`: collection/setup error, timeout, missing interpreter,
|
|
190
|
+
* interruption, zero tests, or a run of ONLY skipped/xfail cases —
|
|
191
|
+
* never displayed as a passing diagnostic run.
|
|
192
|
+
*
|
|
193
|
+
* Args:
|
|
194
|
+
* suite: the configured suite (argv, testPaths, timeoutMs).
|
|
195
|
+
* repoRoot: absolute repo root (suite.cwd resolves against it).
|
|
196
|
+
* stateDir: absolute run-state directory (excluded from inputs); the
|
|
197
|
+
* junit report lands at `<stateDir>/diagnostics/<suite.name>.xml`.
|
|
198
|
+
*
|
|
199
|
+
* Returns:
|
|
200
|
+
* Promise<DiagnosticRunResult>: the structured diagnostic result.
|
|
201
|
+
*/
|
|
202
|
+
export declare function executePytestSuite(suite: DiagnosticSuite, repoRoot: string, stateDir: string): Promise<DiagnosticRunResult>;
|
|
203
|
+
/** Re-export so the adapter module is the single pytest surface. */
|
|
204
|
+
export { TestDiscoveryError };
|
|
205
|
+
//# sourceMappingURL=pytest-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pytest-adapter.d.ts","sourceRoot":"","sources":["../../src/discovery/pytest-adapter.ts"],"names":[],"mappings":"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"}
|