swipium 1.2.0 → 1.4.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.
Files changed (50) hide show
  1. package/README.md +11 -11
  2. package/dist/appMap/featureIndex.js +183 -0
  3. package/dist/appMap/featureIndex.js.map +1 -0
  4. package/dist/featureTesting/executionBootstrap.js +14 -10
  5. package/dist/featureTesting/executionBootstrap.js.map +1 -1
  6. package/dist/featureTesting/featureMap.js +53 -0
  7. package/dist/featureTesting/featureMap.js.map +1 -0
  8. package/dist/featureTesting/featureScope.js +354 -0
  9. package/dist/featureTesting/featureScope.js.map +1 -0
  10. package/dist/featureTesting/mapFeatureScope.js +143 -0
  11. package/dist/featureTesting/mapFeatureScope.js.map +1 -0
  12. package/dist/featureTesting/objectiveModel.js +129 -0
  13. package/dist/featureTesting/objectiveModel.js.map +1 -0
  14. package/dist/featureTesting/resultMerge.js +112 -0
  15. package/dist/featureTesting/resultMerge.js.map +1 -0
  16. package/dist/featureTesting/sources.js +96 -0
  17. package/dist/featureTesting/sources.js.map +1 -0
  18. package/dist/featureTesting/suiteBridge.js +51 -0
  19. package/dist/featureTesting/suiteBridge.js.map +1 -0
  20. package/dist/featureTesting/synonyms.js +73 -0
  21. package/dist/featureTesting/synonyms.js.map +1 -0
  22. package/dist/featureTesting/testCaseFactory.js +107 -0
  23. package/dist/featureTesting/testCaseFactory.js.map +1 -0
  24. package/dist/featureTesting/testPlan.js +50 -0
  25. package/dist/featureTesting/testPlan.js.map +1 -0
  26. package/dist/server.js +11 -0
  27. package/dist/server.js.map +1 -1
  28. package/dist/tools/agent.js +12 -0
  29. package/dist/tools/agent.js.map +1 -1
  30. package/dist/tools/appMap.js +123 -1
  31. package/dist/tools/appMap.js.map +1 -1
  32. package/dist/tools/build.js +172 -0
  33. package/dist/tools/build.js.map +1 -0
  34. package/dist/tools/bundletool.js +145 -0
  35. package/dist/tools/bundletool.js.map +1 -0
  36. package/dist/tools/capabilities.js +24 -0
  37. package/dist/tools/capabilities.js.map +1 -1
  38. package/dist/tools/featureTesting.js +344 -0
  39. package/dist/tools/featureTesting.js.map +1 -0
  40. package/dist/tools/resolveArtifact.js +80 -0
  41. package/dist/tools/resolveArtifact.js.map +1 -0
  42. package/dist/tools/resolveTarget.js +67 -0
  43. package/dist/tools/resolveTarget.js.map +1 -0
  44. package/dist/tools/snapshot.js +41 -1
  45. package/dist/tools/snapshot.js.map +1 -1
  46. package/dist/version.js +16 -2
  47. package/dist/version.js.map +1 -1
  48. package/docs/mcp-server.md +1 -1
  49. package/docs/tools.md +52 -3
  50. package/package.json +1 -1
@@ -0,0 +1,354 @@
1
+ // Feature scope resolution (SWIPIUM-REQ-03 "Feature Scope Model" + "Query and Ranking"). PURE.
2
+ // Given a natural-language feature request and the available ground truth — the static code index,
3
+ // the runtime screen graph, and existing tests — rank every plausible code/runtime artifact, group
4
+ // them into feature candidates, and return the best-supported FeatureScope plus disambiguation when
5
+ // genuinely-different features tie. No device, no filesystem, no LLM: deterministic and unit-testable.
6
+ import { normalizeQuery, termsAreUnrelated } from './synonyms.js';
7
+ // ---- scoring weights ----------------------------------------------------------------------------
8
+ const CORE_W = 1.0;
9
+ const SYN_W = 0.4;
10
+ const KIND_WEIGHT = { symbol: 1.0, route: 1.0, runtime: 0.9, test: 0.6, file: 0.45 };
11
+ const SYMBOL_KIND_WEIGHT = {
12
+ screen: 1.0, service: 0.85, hook: 0.7, component: 0.7, function: 0.55, class: 0.6, constant: 0.5,
13
+ };
14
+ const EXACT_BONUS = 0.8; // an item whose tokens contain every core term
15
+ function hits(tokens, q) {
16
+ const present = new Set(tokens);
17
+ const matched = q.coreTerms.filter((t) => present.has(t));
18
+ const synMatched = q.expandedTerms.filter((t) => present.has(t) && !q.coreTerms.includes(t));
19
+ return { matched, synMatched };
20
+ }
21
+ function baseScore(h, q, tokens) {
22
+ if (!h.matched.length && !h.synMatched.length)
23
+ return 0;
24
+ let s = h.matched.length * CORE_W + h.synMatched.length * SYN_W;
25
+ // Exact feature-name match: the item carries every core term (highest-ranked per requirement).
26
+ if (q.coreTerms.length && q.coreTerms.every((t) => tokens.includes(t)))
27
+ s += EXACT_BONUS;
28
+ return s;
29
+ }
30
+ // ---- Union-Find over core terms (clustering) ----------------------------------------------------
31
+ class UF {
32
+ parent = new Map();
33
+ find(x) {
34
+ if (!this.parent.has(x))
35
+ this.parent.set(x, x);
36
+ let r = x;
37
+ while (this.parent.get(r) !== r)
38
+ r = this.parent.get(r);
39
+ this.parent.set(x, r);
40
+ return r;
41
+ }
42
+ union(a, b) {
43
+ const ra = this.find(a);
44
+ const rb = this.find(b);
45
+ if (ra !== rb)
46
+ this.parent.set(ra, rb);
47
+ }
48
+ root(x) {
49
+ return this.find(x);
50
+ }
51
+ }
52
+ function slug(terms) {
53
+ const base = terms.join('-').replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '');
54
+ return `feat-${base || 'unknown'}`.slice(0, 64);
55
+ }
56
+ function titleCase(terms) {
57
+ return terms.map((t) => t.charAt(0).toUpperCase() + t.slice(1)).join(' ');
58
+ }
59
+ // state-changing / risky vocab used for strategy + risk derivation
60
+ const STATEFUL_TERMS = new Set(['create', 'add', 'new', 'edit', 'update', 'save', 'checkout', 'pay', 'purchase', 'order', 'subscribe', 'submit', 'send', 'post', 'upload', 'book']);
61
+ const DESTRUCTIVE_TERMS = new Set(['delete', 'remove', 'destroy', 'clear', 'wipe', 'cancel', 'logout', 'deactivate']);
62
+ const PAYMENT_TERMS = new Set(['checkout', 'payment', 'pay', 'purchase', 'order', 'subscribe', 'billing']);
63
+ const AUTH_TERMS = new Set(['auth', 'login', 'signin', 'logon', 'authentication', 'credentials', 'password', 'account', 'register', 'signup']);
64
+ function collectMatches(input, q) {
65
+ const out = [];
66
+ const push = (m) => {
67
+ if (m.score > 0)
68
+ out.push(m);
69
+ };
70
+ for (const s of input.index.symbols) {
71
+ const h = hits(s.tokens, q);
72
+ const score = baseScore(h, q, s.tokens) * KIND_WEIGHT.symbol * SYMBOL_KIND_WEIGHT[s.kind];
73
+ push({ source: 'symbol', name: s.name, file: s.file, line: s.line, kind: s.kind, matchedTerms: [...h.matched, ...h.synMatched], score, tokens: s.tokens });
74
+ }
75
+ for (const r of input.index.routes) {
76
+ const h = hits(r.tokens, q);
77
+ const score = baseScore(h, q, r.tokens) * KIND_WEIGHT.route;
78
+ push({ source: 'route', name: r.route, file: r.file, line: r.line, matchedTerms: [...h.matched, ...h.synMatched], score, tokens: r.tokens });
79
+ }
80
+ for (const f of input.index.files) {
81
+ const h = hits(f.tokens, q);
82
+ const score = baseScore(h, q, f.tokens) * KIND_WEIGHT.file;
83
+ push({ source: 'file', name: f.base, file: f.file, matchedTerms: [...h.matched, ...h.synMatched], score, tokens: f.tokens });
84
+ }
85
+ for (const n of input.runtimeScreens ?? []) {
86
+ const tokens = [...tokenizeLoose(n.title), ...tokenizeLoose(n.route), ...tokenizeLoose(n.text)];
87
+ const h = hits(tokens, q);
88
+ const score = baseScore(h, q, tokens) * KIND_WEIGHT.runtime;
89
+ push({ source: 'runtime', name: n.title || n.route || n.id, file: undefined, kind: 'runtime_node', matchedTerms: [...h.matched, ...h.synMatched], score, tokens });
90
+ // carry the node id on `line`-less match via name; id kept for screen extraction below
91
+ if (score > 0)
92
+ out[out.length - 1].runtimeId = n.id;
93
+ }
94
+ for (const t of input.existingTests ?? []) {
95
+ const tokens = tokenizeLoose(`${t.title} ${t.id}`);
96
+ const h = hits(tokens, q);
97
+ const score = baseScore(h, q, tokens) * KIND_WEIGHT.test;
98
+ push({ source: 'test', name: t.title || t.id, matchedTerms: [...h.matched, ...h.synMatched], score, tokens });
99
+ if (score > 0)
100
+ out[out.length - 1].testRef = t;
101
+ }
102
+ return out;
103
+ }
104
+ function tokenizeLoose(s) {
105
+ if (!s)
106
+ return [];
107
+ return s
108
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
109
+ .toLowerCase()
110
+ .split(/[^a-z0-9]+/)
111
+ .filter((t) => t.length > 1);
112
+ }
113
+ /** Group matches into feature candidates by the core terms they share (union-find). */
114
+ function cluster(matches, q) {
115
+ const uf = new UF();
116
+ // Union all core terms that co-occur within any single match.
117
+ for (const m of matches) {
118
+ const core = m.matchedTerms.filter((t) => q.coreTerms.includes(t));
119
+ for (let i = 1; i < core.length; i++)
120
+ uf.union(core[0], core[i]);
121
+ }
122
+ const byRoot = new Map();
123
+ const rootFor = (m) => {
124
+ const core = m.matchedTerms.filter((t) => q.coreTerms.includes(t));
125
+ if (core.length)
126
+ return uf.root(core[0]);
127
+ // synonym-only match → attach to the synonym's owning core term if derivable, else its own bucket
128
+ return m.matchedTerms[0] ?? '∅';
129
+ };
130
+ for (const m of matches) {
131
+ const root = rootFor(m);
132
+ let c = byRoot.get(root);
133
+ if (!c) {
134
+ c = { terms: new Set(), matches: [], score: 0 };
135
+ byRoot.set(root, c);
136
+ }
137
+ for (const t of m.matchedTerms)
138
+ c.terms.add(t);
139
+ c.matches.push(m);
140
+ c.score += m.score;
141
+ }
142
+ return [...byRoot.values()].sort((a, b) => b.score - a.score);
143
+ }
144
+ function deriveRisks(terms) {
145
+ const risks = [];
146
+ const has = (set) => [...terms].some((t) => set.has(t));
147
+ if (has(DESTRUCTIVE_TERMS))
148
+ risks.push({ risk: 'destructive actions present', level: 'high', rationale: 'Feature vocabulary includes delete/remove/cancel — requires disposable state and explicit consent.' });
149
+ if (has(PAYMENT_TERMS))
150
+ risks.push({ risk: 'real-money / purchase path', level: 'high', rationale: 'Payment/checkout flows can charge real accounts — use a sandbox/test fixture.' });
151
+ if (has(AUTH_TERMS))
152
+ risks.push({ risk: 'authentication gate', level: 'medium', rationale: 'Likely blocked behind login — needs test credentials to exercise fully.' });
153
+ if (!risks.length)
154
+ risks.push({ risk: 'low-risk read/navigation', level: 'low', rationale: 'No destructive/payment/auth vocabulary detected in scope.' });
155
+ return risks;
156
+ }
157
+ function deriveStrategy(terms, hasRuntime, hasStatic, confidence) {
158
+ const has = (set) => [...terms].some((t) => set.has(t));
159
+ if (confidence < 0.15 || (!hasRuntime && !hasStatic))
160
+ return 'manual_blocked';
161
+ if (has(DESTRUCTIVE_TERMS) || has(PAYMENT_TERMS))
162
+ return 'manual_blocked';
163
+ if (has(STATEFUL_TERMS))
164
+ return 'stateful_e2e';
165
+ if (hasRuntime || hasStatic)
166
+ return 'targeted_explore';
167
+ return 'smoke';
168
+ }
169
+ function buildScope(c, q, input, maxScore) {
170
+ const limit = input.limit ?? 8;
171
+ const matches = [...c.matches].sort((a, b) => b.score - a.score);
172
+ const coreTerms = q.coreTerms.filter((t) => c.terms.has(t));
173
+ const displayTerms = coreTerms.length ? coreTerms : [...c.terms].slice(0, 3);
174
+ const featureId = slug(displayTerms.length ? displayTerms : q.coreTerms);
175
+ const title = titleCase(displayTerms.length ? displayTerms : q.coreTerms);
176
+ const staticScreens = [];
177
+ const runtimeScreens = [];
178
+ const entryPoints = [];
179
+ const functions = [];
180
+ const dataDependencies = [];
181
+ const existingTests = [];
182
+ const seenDep = new Set();
183
+ for (const m of matches) {
184
+ const conf = maxScore > 0 ? Math.min(1, m.score / maxScore) : 0;
185
+ if (m.source === 'symbol') {
186
+ if (m.kind === 'screen') {
187
+ staticScreens.push({ name: m.name, origin: 'static', file: m.file, confidence: conf });
188
+ entryPoints.push({ kind: 'screen_component', value: m.name, file: m.file, confidence: conf });
189
+ }
190
+ else if (m.kind === 'service' || m.kind === 'class') {
191
+ if (!seenDep.has(m.name)) {
192
+ seenDep.add(m.name);
193
+ dataDependencies.push({ name: m.name, kind: 'external', evidence: `${m.kind} ${m.file}:${m.line}` });
194
+ }
195
+ }
196
+ functions.push({ name: m.name, kind: m.kind ?? 'function', file: m.file, line: m.line ?? 0 });
197
+ }
198
+ else if (m.source === 'route') {
199
+ const isDeepLink = /:\/\//.test(m.name);
200
+ entryPoints.push({ kind: isDeepLink ? 'deep_link' : 'route', value: m.name, file: m.file, confidence: conf });
201
+ staticScreens.push({ name: m.name, origin: 'static', file: m.file, route: m.name, confidence: conf });
202
+ }
203
+ else if (m.source === 'runtime') {
204
+ const id = m.runtimeId;
205
+ runtimeScreens.push({ name: m.name, origin: 'runtime', id, route: undefined, confidence: conf });
206
+ if (id)
207
+ entryPoints.push({ kind: 'runtime_node', value: id, confidence: conf });
208
+ }
209
+ else if (m.source === 'test') {
210
+ const ref = m.testRef;
211
+ if (ref)
212
+ existingTests.push(ref);
213
+ }
214
+ }
215
+ // fixture/credential data dependencies inferred from feature vocabulary
216
+ if ([...c.terms].some((t) => AUTH_TERMS.has(t)))
217
+ dataDependencies.push({ name: 'test credentials', kind: 'fixture', evidence: 'auth vocabulary in scope' });
218
+ if ([...c.terms].some((t) => PAYMENT_TERMS.has(t)))
219
+ dataDependencies.push({ name: 'sandbox payment method', kind: 'fixture', evidence: 'payment vocabulary in scope' });
220
+ const confidence = maxScore > 0 ? Math.min(1, c.score / maxScore) : 0;
221
+ const risks = deriveRisks(c.terms);
222
+ const strategy = deriveStrategy(c.terms, runtimeScreens.length > 0, staticScreens.length > 0, confidence);
223
+ const coverageGaps = [];
224
+ if (!runtimeScreens.length)
225
+ coverageGaps.push({ area: 'runtime', reason: 'No runtime screen has been observed for this feature yet — run a focused exploration.' });
226
+ if (!staticScreens.length)
227
+ coverageGaps.push({ area: 'static', reason: 'No screen/route component matched in source — the static index may be incomplete or the feature is named differently.' });
228
+ if (!existingTests.length)
229
+ coverageGaps.push({ area: 'tests', reason: 'No existing test/flow covers this feature — generate cases.' });
230
+ const objective = `Validate the "${title}" feature${input.platform ? ` on ${input.platform}` : ''}: reach its entry point, exercise the primary path, and verify the expected outcome.`;
231
+ return {
232
+ featureId,
233
+ query: input.query,
234
+ title,
235
+ objective,
236
+ confidence: round(confidence),
237
+ sourceMatches: dedupeMatches(matches).slice(0, limit),
238
+ staticScreens: dedupeScreens(staticScreens).slice(0, limit),
239
+ runtimeScreens: dedupeScreens(runtimeScreens).slice(0, limit),
240
+ entryPoints: dedupeEntry(entryPoints).slice(0, limit),
241
+ functions: functions.slice(0, limit),
242
+ dataDependencies,
243
+ risks,
244
+ existingTests: dedupeTests(existingTests),
245
+ coverageGaps,
246
+ recommendedStrategy: strategy,
247
+ matchedTerms: [...c.terms],
248
+ };
249
+ }
250
+ function round(n) {
251
+ return Math.round(n * 100) / 100;
252
+ }
253
+ function dedupeMatches(m) {
254
+ const seen = new Set();
255
+ return m.filter((x) => {
256
+ const k = `${x.source}:${x.name}:${x.file ?? ''}:${x.line ?? ''}`;
257
+ if (seen.has(k))
258
+ return false;
259
+ seen.add(k);
260
+ return true;
261
+ });
262
+ }
263
+ function dedupeScreens(s) {
264
+ const seen = new Set();
265
+ return s.filter((x) => {
266
+ const k = `${x.origin}:${x.id ?? ''}:${x.name}:${x.file ?? ''}`;
267
+ if (seen.has(k))
268
+ return false;
269
+ seen.add(k);
270
+ return true;
271
+ });
272
+ }
273
+ function dedupeEntry(e) {
274
+ const seen = new Set();
275
+ return e.filter((x) => {
276
+ const k = `${x.kind}:${x.value}`;
277
+ if (seen.has(k))
278
+ return false;
279
+ seen.add(k);
280
+ return true;
281
+ });
282
+ }
283
+ function dedupeTests(t) {
284
+ const seen = new Set();
285
+ return t.filter((x) => {
286
+ if (seen.has(x.id))
287
+ return false;
288
+ seen.add(x.id);
289
+ return true;
290
+ });
291
+ }
292
+ /** Build the feature scope: rank, cluster, and pick the best candidate (asking only on a real tie). */
293
+ export function buildFeatureScope(input) {
294
+ const q = normalizeQuery(input.query);
295
+ const matches = collectMatches(input, q);
296
+ const searched = {
297
+ terms: q.expandedTerms,
298
+ files: input.index.files.length,
299
+ symbols: input.index.symbols.length,
300
+ routes: input.index.routes.length,
301
+ runtimeScreens: (input.runtimeScreens ?? []).length,
302
+ };
303
+ if (!matches.length) {
304
+ // No feature found — honest empty scope with searched terms (acceptance criterion).
305
+ const empty = {
306
+ featureId: slug(q.coreTerms),
307
+ query: input.query,
308
+ title: titleCase(q.coreTerms),
309
+ objective: `No code or runtime evidence found for "${input.query}".`,
310
+ confidence: 0,
311
+ sourceMatches: [],
312
+ staticScreens: [],
313
+ runtimeScreens: [],
314
+ entryPoints: [],
315
+ functions: [],
316
+ dataDependencies: [],
317
+ risks: [{ risk: 'feature not located', level: 'medium', rationale: 'No matching code symbols, routes, runtime screens, or tests.' }],
318
+ existingTests: [],
319
+ coverageGaps: [
320
+ { area: 'map', reason: 'Feature not present in the current map — run an initial qa_test_this/qa_explore to grow coverage, or refine the feature name.' },
321
+ ],
322
+ recommendedStrategy: 'manual_blocked',
323
+ matchedTerms: [],
324
+ };
325
+ return { primary: empty, candidates: [], searched, found: false };
326
+ }
327
+ const clusters = cluster(matches, q);
328
+ const maxScore = clusters[0].score;
329
+ const scopes = clusters.map((c) => buildScope(c, q, input, maxScore));
330
+ const primary = scopes[0];
331
+ const candidates = scopes.map((s) => ({
332
+ featureId: s.featureId,
333
+ title: s.title,
334
+ confidence: s.confidence,
335
+ matchedTerms: s.matchedTerms,
336
+ topMatches: s.sourceMatches.slice(0, 3).map((m) => `${m.source}:${m.name}`),
337
+ }));
338
+ // Disambiguation: ask ONE question only when the top two candidates are close AND about
339
+ // genuinely-different features (no shared core term).
340
+ let needsInput;
341
+ if (scopes.length >= 2) {
342
+ const a = scopes[0];
343
+ const b = scopes[1];
344
+ const close = b.confidence >= a.confidence * 0.75 && a.confidence > 0;
345
+ if (close && termsAreUnrelated(a.matchedTerms.filter((t) => q.coreTerms.includes(t)), b.matchedTerms.filter((t) => q.coreTerms.includes(t)))) {
346
+ needsInput = {
347
+ question: `"${input.query}" matched more than one distinct feature. Which one should Swipium test?`,
348
+ options: scopes.slice(0, 4).map((s) => `${s.title} (${Math.round(s.confidence * 100)}%)`),
349
+ };
350
+ }
351
+ }
352
+ return { primary, candidates, needsInput, searched, found: true };
353
+ }
354
+ //# sourceMappingURL=featureScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureScope.js","sourceRoot":"","sources":["../../src/featureTesting/featureScope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,143 @@
1
+ // Vision Gap Fix 3 — app-map-FIRST feature scoping. The product principle is "read the durable app
2
+ // map before deciding what to do". qa_feature_scope / qa_feature_test_plan / qa_test_feature must scope
3
+ // from `.swipium/app-map.json` (features, static + runtime topology, tickets, persistent suite) BEFORE
4
+ // falling back to a fresh code scan. This shared service builds an app-map-enriched FeatureScopeInput
5
+ // and reuses the deterministic ranker in featureScope.ts, then reconciles the result back to a known
6
+ // map feature id so scope ids stay compatible with qa_app_map_feature_scope.
7
+ import { buildFeatureIndex, tokenize } from '../appMap/featureIndex.js';
8
+ import { buildFeatureScope } from './featureScope.js';
9
+ import { loadAppMap } from '../appMap/store.js';
10
+ import { appMapResourceUri } from '../appMap/store.js';
11
+ import { loadSuite } from '../testSuite/store.js';
12
+ import { detectFramework } from '../context/detect.js';
13
+ function fallbackProject(root) {
14
+ const fw = detectFramework(root);
15
+ return { root, gitRemote: null, packageName: null, workspaceTarget: null, framework: fw, platforms: fw === 'native-android' ? ['android'] : fw === 'native-ios' ? ['ios'] : ['android', 'ios'] };
16
+ }
17
+ /** Synthesize index entries from the durable map so a feature that exists ONLY in the app map is found. */
18
+ function indexFromMap(map, base) {
19
+ const symbols = [...base.symbols];
20
+ const routes = [...base.routes];
21
+ const files = [...base.files];
22
+ const seenSym = new Set(symbols.map((s) => `${s.name}:${s.file}`));
23
+ // Map features → synthetic "screen" symbols carrying the feature's title/objective tokens, so the
24
+ // ranker locates a feature even when no source symbol survives a code rename/deletion.
25
+ for (const f of map.features) {
26
+ const name = f.title.replace(/[^A-Za-z0-9]+/g, '') || f.id;
27
+ const file = f.sourceFiles[0] ?? `app-map:${f.id}`;
28
+ const key = `${name}:${file}`;
29
+ const tokens = [...new Set([...tokenize(f.title), ...tokenize(f.objective ?? ''), ...tokenize(f.id)])];
30
+ if (!seenSym.has(key)) {
31
+ symbols.push({ name, kind: 'screen', file, line: 0, tokens });
32
+ seenSym.add(key);
33
+ }
34
+ }
35
+ // Static screens → synthetic routes/files so their names/routes participate in ranking.
36
+ for (const s of map.staticTopology.screens) {
37
+ const tokens = [...new Set([...tokenize(s.name), ...tokenize(s.route ?? '')])];
38
+ if (s.route)
39
+ routes.push({ route: s.route, file: s.sourceFiles[0] ?? `app-map:${s.id}`, line: 0, tokens });
40
+ files.push({ file: s.sourceFiles[0] ?? `app-map:${s.id}`, base: s.name, tokens });
41
+ }
42
+ return { ...base, symbols, routes, files };
43
+ }
44
+ /** Historical runtime screens recorded in the durable map (used when no live session graph exists). */
45
+ function runtimeScreensFromMap(map) {
46
+ return map.runtimeTopology.screens.map((r) => ({
47
+ id: r.id,
48
+ title: r.title,
49
+ route: r.route,
50
+ text: [...(r.textTokens ?? []), ...(r.locatorIds ?? [])].join(' ').trim() || undefined,
51
+ }));
52
+ }
53
+ /** Existing tests recorded in the durable map's suite index. */
54
+ function testsFromMap(map) {
55
+ return map.testSuite.cases.map((c) => ({ id: c.id, title: c.title, source: c.source ?? 'app-map' }));
56
+ }
57
+ /** Cases from the canonical persistent suite (.swipium/test-suite.json) — the growing QA context the
58
+ * vision requires feature scoping to read, not just the app-map's mirrored index. Each case also
59
+ * contributes a synthetic feature symbol so a suite-only functionality is locatable. */
60
+ function testsFromSuite(root) {
61
+ const tests = [];
62
+ const symbols = [];
63
+ try {
64
+ const suite = loadSuite(root);
65
+ for (const c of suite.cases) {
66
+ if (c.status === 'deprecated')
67
+ continue;
68
+ tests.push({ id: c.id, title: c.title, source: 'suite' });
69
+ const tokens = [...new Set([...tokenize(c.functionality), ...tokenize(c.title), ...tokenize(c.featureId), ...tokenize(c.objective ?? '')])];
70
+ symbols.push({ name: (c.functionality || c.title).replace(/[^A-Za-z0-9]+/g, '') || c.id, kind: 'screen', file: `suite:${c.id}`, line: 0, tokens });
71
+ }
72
+ }
73
+ catch {
74
+ /* best-effort */
75
+ }
76
+ return { tests, symbols };
77
+ }
78
+ /** Pick the map feature that best overlaps the scoped result's terms — to reconcile the scope id. */
79
+ function reconcileMapFeature(map, result) {
80
+ if (!result.found)
81
+ return {};
82
+ const scopeTerms = new Set(result.primary.matchedTerms.map((t) => t.toLowerCase()));
83
+ let best;
84
+ for (const f of map.features) {
85
+ const ft = new Set([...tokenize(f.title), ...tokenize(f.id), ...tokenize(f.objective ?? '')]);
86
+ let score = 0;
87
+ for (const t of ft)
88
+ if (scopeTerms.has(t))
89
+ score++;
90
+ if (score > 0 && (!best || score > best.score))
91
+ best = { id: f.id, title: f.title, score };
92
+ }
93
+ return best ? { id: best.id, title: best.title } : {};
94
+ }
95
+ /** Ticket ids whose trace scopes/touches this feature (so scope carries ticketRefs). */
96
+ function ticketRefsForFeature(map, featureId) {
97
+ if (!featureId)
98
+ return [];
99
+ return map.tickets.tickets.filter((t) => t.scopedFeatures.includes(featureId)).map((t) => t.id);
100
+ }
101
+ /**
102
+ * Resolve a feature scope using the durable app map as primary context, falling back to a fresh code
103
+ * scan only to fill gaps. Returns the same FeatureScopeResult shape (so callers are unchanged) plus the
104
+ * reconciled map feature id, ticket refs, runtime evidence source, and the app map resource uri.
105
+ */
106
+ export function buildMapFeatureScope(input) {
107
+ const at = new Date().toISOString();
108
+ const map = input.map ?? loadAppMap(input.root, fallbackProject(input.root), at).map;
109
+ const appMapUri = appMapResourceUri(input.root);
110
+ // Code index: provided, else fresh scan (still useful — but the map is layered on top as primary).
111
+ const baseIndex = input.index ?? buildFeatureIndex(input.root);
112
+ // The growing QA context (Fix #3): the persistent suite is durable feature knowledge too, so feed its
113
+ // cases into scoping as existing tests + synthetic feature symbols (a suite-only feature is findable).
114
+ const suite = testsFromSuite(input.root);
115
+ if (!map) {
116
+ // No durable map yet — still layer the persistent suite on top of the pure code-scan scope.
117
+ const idx = { ...baseIndex, symbols: [...baseIndex.symbols, ...suite.symbols] };
118
+ const res = buildFeatureScope({ query: input.query, index: idx, runtimeScreens: input.runtimeScreens, existingTests: [...(input.existingTests ?? []), ...suite.tests], platform: input.platform, limit: input.limit });
119
+ return { ...res, appMapUri, ticketRefs: [], runtimeSource: input.runtimeScreens?.length ? 'session' : 'none' };
120
+ }
121
+ const baseEnriched = indexFromMap(map, baseIndex);
122
+ const enrichedIndex = { ...baseEnriched, symbols: [...baseEnriched.symbols, ...suite.symbols] };
123
+ // Runtime evidence: prefer the live session graph; else fall back to historical map screens.
124
+ let runtimeScreens = input.runtimeScreens;
125
+ let runtimeSource = 'session';
126
+ if (!runtimeScreens || !runtimeScreens.length) {
127
+ runtimeScreens = runtimeScreensFromMap(map);
128
+ runtimeSource = runtimeScreens.length ? 'app_map' : 'none';
129
+ }
130
+ const existingTests = [...(input.existingTests ?? []), ...testsFromMap(map), ...suite.tests];
131
+ const scopeInput = { query: input.query, index: enrichedIndex, runtimeScreens, existingTests, platform: input.platform, limit: input.limit };
132
+ const result = buildFeatureScope(scopeInput);
133
+ // Reconcile to a known map feature so the scope id matches qa_app_map_feature_scope's id.
134
+ const reconciled = reconcileMapFeature(map, result);
135
+ if (reconciled.id && result.found) {
136
+ result.primary.featureId = reconciled.id;
137
+ if (reconciled.title)
138
+ result.primary.title = reconciled.title;
139
+ }
140
+ const ticketRefs = ticketRefsForFeature(map, reconciled.id);
141
+ return { ...result, appMapUri, mapFeatureId: reconciled.id, ticketRefs, runtimeSource };
142
+ }
143
+ //# sourceMappingURL=mapFeatureScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapFeatureScope.js","sourceRoot":"","sources":["../../src/featureTesting/mapFeatureScope.ts"],"names":[],"mappings":"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"}