swipium 1.1.0 → 1.3.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 (109) hide show
  1. package/README.md +14 -9
  2. package/THREAT_MODEL.md +59 -0
  3. package/dist/appMap/diff.js +60 -0
  4. package/dist/appMap/diff.js.map +1 -0
  5. package/dist/appMap/featureIndex.js +183 -0
  6. package/dist/appMap/featureIndex.js.map +1 -0
  7. package/dist/automation/capabilities.js +167 -0
  8. package/dist/automation/capabilities.js.map +1 -0
  9. package/dist/automation/gestures.js +94 -0
  10. package/dist/automation/gestures.js.map +1 -0
  11. package/dist/automation/maestroIr.js +282 -0
  12. package/dist/automation/maestroIr.js.map +1 -0
  13. package/dist/automation/plan.js +268 -0
  14. package/dist/automation/plan.js.map +1 -0
  15. package/dist/automation/report.js +83 -0
  16. package/dist/automation/report.js.map +1 -0
  17. package/dist/automation/selectors.js +201 -0
  18. package/dist/automation/selectors.js.map +1 -0
  19. package/dist/automation/types.js +13 -0
  20. package/dist/automation/types.js.map +1 -0
  21. package/dist/automation/waits.js +91 -0
  22. package/dist/automation/waits.js.map +1 -0
  23. package/dist/automation/webview.js +81 -0
  24. package/dist/automation/webview.js.map +1 -0
  25. package/dist/featureTesting/executionBootstrap.js +14 -10
  26. package/dist/featureTesting/executionBootstrap.js.map +1 -1
  27. package/dist/featureTesting/featureMap.js +53 -0
  28. package/dist/featureTesting/featureMap.js.map +1 -0
  29. package/dist/featureTesting/featureScope.js +354 -0
  30. package/dist/featureTesting/featureScope.js.map +1 -0
  31. package/dist/featureTesting/mapFeatureScope.js +143 -0
  32. package/dist/featureTesting/mapFeatureScope.js.map +1 -0
  33. package/dist/featureTesting/objectiveModel.js +129 -0
  34. package/dist/featureTesting/objectiveModel.js.map +1 -0
  35. package/dist/featureTesting/resultMerge.js +112 -0
  36. package/dist/featureTesting/resultMerge.js.map +1 -0
  37. package/dist/featureTesting/sources.js +96 -0
  38. package/dist/featureTesting/sources.js.map +1 -0
  39. package/dist/featureTesting/suiteBridge.js +51 -0
  40. package/dist/featureTesting/suiteBridge.js.map +1 -0
  41. package/dist/featureTesting/synonyms.js +73 -0
  42. package/dist/featureTesting/synonyms.js.map +1 -0
  43. package/dist/featureTesting/testCaseFactory.js +107 -0
  44. package/dist/featureTesting/testCaseFactory.js.map +1 -0
  45. package/dist/featureTesting/testPlan.js +50 -0
  46. package/dist/featureTesting/testPlan.js.map +1 -0
  47. package/dist/flows/repair.js +363 -0
  48. package/dist/flows/repair.js.map +1 -0
  49. package/dist/interop/maestro.js +151 -0
  50. package/dist/interop/maestro.js.map +1 -0
  51. package/dist/mobileAudit/checks.js +251 -0
  52. package/dist/mobileAudit/checks.js.map +1 -0
  53. package/dist/mobileAudit/evidence.js +49 -0
  54. package/dist/mobileAudit/evidence.js.map +1 -0
  55. package/dist/mobileAudit/profiles.js +73 -0
  56. package/dist/mobileAudit/profiles.js.map +1 -0
  57. package/dist/mobileAudit/results.js +41 -0
  58. package/dist/mobileAudit/results.js.map +1 -0
  59. package/dist/mobileAudit/runner.js +229 -0
  60. package/dist/mobileAudit/runner.js.map +1 -0
  61. package/dist/oracle/locator.js +177 -0
  62. package/dist/oracle/locator.js.map +1 -0
  63. package/dist/server.js +31 -0
  64. package/dist/server.js.map +1 -1
  65. package/dist/testSuite/exporter.js +70 -0
  66. package/dist/testSuite/exporter.js.map +1 -0
  67. package/dist/testSuite/lint.js +53 -0
  68. package/dist/testSuite/lint.js.map +1 -0
  69. package/dist/tools/build.js +172 -0
  70. package/dist/tools/build.js.map +1 -0
  71. package/dist/tools/bundletool.js +145 -0
  72. package/dist/tools/bundletool.js.map +1 -0
  73. package/dist/tools/capabilities.js +66 -4
  74. package/dist/tools/capabilities.js.map +1 -1
  75. package/dist/tools/featureTesting.js +344 -0
  76. package/dist/tools/featureTesting.js.map +1 -0
  77. package/dist/tools/flow.js +67 -1
  78. package/dist/tools/flow.js.map +1 -1
  79. package/dist/tools/flowRepair.js +66 -0
  80. package/dist/tools/flowRepair.js.map +1 -0
  81. package/dist/tools/idling.js +104 -0
  82. package/dist/tools/idling.js.map +1 -0
  83. package/dist/tools/inputCapabilities.js +30 -0
  84. package/dist/tools/inputCapabilities.js.map +1 -0
  85. package/dist/tools/issues.js +218 -0
  86. package/dist/tools/issues.js.map +1 -0
  87. package/dist/tools/jobs.js +12 -1
  88. package/dist/tools/jobs.js.map +1 -1
  89. package/dist/tools/locator.js +57 -0
  90. package/dist/tools/locator.js.map +1 -0
  91. package/dist/tools/maestro.js +78 -0
  92. package/dist/tools/maestro.js.map +1 -0
  93. package/dist/tools/mobileAudit.js +115 -0
  94. package/dist/tools/mobileAudit.js.map +1 -0
  95. package/dist/tools/resolveArtifact.js +80 -0
  96. package/dist/tools/resolveArtifact.js.map +1 -0
  97. package/dist/tools/resolveTarget.js +67 -0
  98. package/dist/tools/resolveTarget.js.map +1 -0
  99. package/dist/tools/suite.js +49 -1
  100. package/dist/tools/suite.js.map +1 -1
  101. package/dist/tools/testSuite.js +233 -0
  102. package/dist/tools/testSuite.js.map +1 -0
  103. package/dist/tools/wait.js +58 -0
  104. package/dist/tools/wait.js.map +1 -0
  105. package/dist/version.js +41 -2
  106. package/dist/version.js.map +1 -1
  107. package/docs/mcp-server.md +1 -1
  108. package/docs/tools.md +86 -3
  109. package/package.json +3 -2
@@ -0,0 +1,70 @@
1
+ // Exporters for the persistent suite (SWIPIUM-REQ-06 "qa_test_suite_export"). PURE: serialize the
2
+ // canonical suite to Markdown (review-ready), a per-functionality YAML directory, JSON, and a
3
+ // JUnit-like results doc. TestRail CSV / Jira-Xray are explicitly deferred (Non-Goals) — the shapes
4
+ // here are the v1 surface other tools can build on.
5
+ import { stringify } from 'yaml';
6
+ import { functionalitySlug } from './schema.js';
7
+ function groupByFunctionality(cases) {
8
+ const groups = new Map();
9
+ for (const c of cases) {
10
+ const key = c.functionality;
11
+ (groups.get(key) ?? groups.set(key, []).get(key)).push(c);
12
+ }
13
+ return groups;
14
+ }
15
+ function xmlEscape(s) {
16
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
17
+ }
18
+ export function exportMarkdown(suite) {
19
+ const out = ['# QA Test Suite', '', `Updated: ${suite.updatedAt}`, `Cases: ${suite.cases.length}`, ''];
20
+ for (const [functionality, cases] of groupByFunctionality(suite.cases)) {
21
+ out.push(`## ${functionality}`, '');
22
+ for (const c of cases) {
23
+ out.push(`### ${c.id}: ${c.title}`, '', `- **Priority:** ${c.priority} **Type:** ${c.type} **Creativity:** ${c.creativityLevel} **Status:** ${c.status}`, `- **Platforms:** ${c.platforms.join(', ')} **Automation:** ${c.automation.status} (locators ${c.automation.locatorReadiness}, replay ${c.automation.replayStatus})`, `- **Objective:** ${c.objective}`, '', '**Preconditions:**', ...(c.preconditions.length ? c.preconditions.map((p) => `- ${p}`) : ['- _none_']), '', '**Steps:**', ...(c.steps.length ? c.steps.map((s) => `${s.index}. ${s.action}${s.target ? ` → ${s.target}` : ''}${s.data ? ` [${s.data}]` : ''}`) : ['- _none_']), '', '**Expected:**', ...c.expectedResult.map((e) => `- ${e}`), '', `**Actual:** ${c.actualResult.status} — ${c.actualResult.summary}`, ...(c.evidence.length ? ['', `**Evidence:** ${c.evidence.map((e) => e.uri).join(', ')}`] : []), ...(c.ticketRefs.length ? [`**Tickets:** ${c.ticketRefs.join(', ')}`] : []), ...(c.requirementRefs.length ? [`**Requirements:** ${c.requirementRefs.join(', ')}`] : []), ...(c.issueRefs?.length ? [`**Linked issues:** ${c.issueRefs.map((r) => `${r.issueId} (${r.relationship}, ${r.lastIssueState})`).join(', ')}`] : []), ...(c.risk.length ? ['', '**Risks:**', ...c.risk.map((r) => `- ${r}`)] : []), `- **History:** ${c.history.length} run(s)`, '');
24
+ }
25
+ }
26
+ return out.join('\n');
27
+ }
28
+ export function exportYamlFiles(suite) {
29
+ return suite.cases.map((c) => ({
30
+ path: `${functionalitySlug(c.functionality)}/${c.id}.yaml`,
31
+ content: stringify(c),
32
+ }));
33
+ }
34
+ export function exportJunit(suite) {
35
+ const groups = groupByFunctionality(suite.cases);
36
+ const lines = ['<?xml version="1.0" encoding="UTF-8"?>', '<testsuites name="swipium-test-suite">'];
37
+ for (const [functionality, cases] of groups) {
38
+ const failures = cases.filter((c) => c.actualResult.status === 'fail').length;
39
+ const skipped = cases.filter((c) => c.actualResult.status === 'skipped' || c.actualResult.status === 'not_run' || c.actualResult.status === 'blocked').length;
40
+ lines.push(` <testsuite name="${xmlEscape(functionality)}" tests="${cases.length}" failures="${failures}" skipped="${skipped}">`);
41
+ for (const c of cases) {
42
+ lines.push(` <testcase classname="${xmlEscape(functionality)}" name="${xmlEscape(`${c.id}: ${c.title}`)}">`);
43
+ if (c.actualResult.status === 'fail') {
44
+ lines.push(` <failure message="${xmlEscape(c.actualResult.summary)}"${c.actualResult.failureCode ? ` type="${xmlEscape(c.actualResult.failureCode)}"` : ''}/>`);
45
+ }
46
+ else if (c.actualResult.status === 'skipped' || c.actualResult.status === 'not_run' || c.actualResult.status === 'blocked') {
47
+ lines.push(` <skipped message="${xmlEscape(c.actualResult.status)}: ${xmlEscape(c.actualResult.summary)}"/>`);
48
+ }
49
+ lines.push(' </testcase>');
50
+ }
51
+ lines.push(' </testsuite>');
52
+ }
53
+ lines.push('</testsuites>');
54
+ return lines.join('\n');
55
+ }
56
+ export function exportSuite(suite, format) {
57
+ switch (format) {
58
+ case 'json':
59
+ return { format, content: JSON.stringify(suite, null, 2), summary: `Exported ${suite.cases.length} case(s) as JSON.` };
60
+ case 'markdown':
61
+ return { format, content: exportMarkdown(suite), summary: `Exported ${suite.cases.length} case(s) as Markdown.` };
62
+ case 'junit':
63
+ return { format, content: exportJunit(suite), summary: `Exported ${suite.cases.length} case(s) as JUnit XML.` };
64
+ case 'yaml': {
65
+ const files = exportYamlFiles(suite);
66
+ return { format, files, summary: `Exported ${files.length} case file(s) as YAML.` };
67
+ }
68
+ }
69
+ }
70
+ //# sourceMappingURL=exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../src/testSuite/exporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ // Linter for the persistent suite (SWIPIUM-REQ-06 "qa_test_suite_lint"). PURE. Catches the failure
2
+ // modes that make a maintained suite untrustworthy: missing expected/actual results, unlinked or
3
+ // stale map links, duplicate ids, brittle automation above threshold, and — most importantly —
4
+ // `adversarial` cases that lack the safety metadata Swipium requires before it will ever run them.
5
+ /** A case may run adversarially only with explicit disposable-state / consent metadata. */
6
+ function hasAdversarialSafety(c) {
7
+ const tagged = c.tags.some((t) => /disposable|consent|sandbox/i.test(t));
8
+ const precondition = c.preconditions.some((p) => /disposable|sandbox|throwaway|test account/i.test(p));
9
+ const fixtureNote = c.fixtures.some((f) => /disposable|sandbox/i.test(f));
10
+ return tagged || precondition || fixtureNote;
11
+ }
12
+ export function lintSuite(suite, opts = {}) {
13
+ const findings = [];
14
+ const add = (severity, rule, message, id) => findings.push({ id, rule, severity, message });
15
+ const brittleGrades = opts.brittleThreshold === 'C' ? ['C', 'D'] : ['D'];
16
+ const seen = new Set();
17
+ const live = opts.liveFeatureIds ? new Set(opts.liveFeatureIds) : null;
18
+ for (const c of suite.cases) {
19
+ if (seen.has(c.id))
20
+ add('error', 'duplicate_id', `Duplicate case id ${c.id}`, c.id);
21
+ seen.add(c.id);
22
+ if (c.status === 'deprecated')
23
+ continue; // deprecated cases are exempt from content rules
24
+ if (!c.expectedResult.length || c.expectedResult.every((e) => !e.trim())) {
25
+ add('error', 'missing_expected', 'Case has no expected result', c.id);
26
+ }
27
+ // An executed case (has run history) that never recorded an actual result.
28
+ if (c.history.length > 0 && c.actualResult.status === 'not_run') {
29
+ add('error', 'missing_actual', 'Case has run history but actualResult is still not_run', c.id);
30
+ }
31
+ if (!c.mapLinks.length && c.status !== 'manual_only' && c.status !== 'draft') {
32
+ add('warn', 'unlinked_feature', 'Case is not linked to any app-map feature/screen', c.id);
33
+ }
34
+ if (live) {
35
+ const stale = c.mapLinks.filter((l) => l.kind === 'feature' && !live.has(l.id));
36
+ if (stale.length)
37
+ add('warn', 'stale_map_link', `Case links to feature(s) no longer in the app map: ${stale.map((l) => l.id).join(', ')}`, c.id);
38
+ }
39
+ if (c.automation.status === 'automated' && brittleGrades.includes(c.automation.locatorReadiness)) {
40
+ add('warn', 'brittle_automation', `Automated case has brittle locators (grade ${c.automation.locatorReadiness})`, c.id);
41
+ }
42
+ if (c.automation.status === 'automated' && (c.automation.replayStatus === 'failed' || c.automation.replayStatus === 'blocked')) {
43
+ add('warn', 'unreplayable_automation', `Automated case has replayStatus ${c.automation.replayStatus} — not release-gate proof`, c.id);
44
+ }
45
+ if (c.creativityLevel === 'adversarial' && !hasAdversarialSafety(c)) {
46
+ add('error', 'unsafe_adversarial', 'Adversarial case lacks disposable-state/consent safety metadata — Swipium will refuse to run it', c.id);
47
+ }
48
+ }
49
+ const errorCount = findings.filter((f) => f.severity === 'error').length;
50
+ const warnCount = findings.length - errorCount;
51
+ return { findings, errorCount, warnCount, ok: errorCount === 0 };
52
+ }
53
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/testSuite/lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ // qa_build_plan + qa_build (roadmap §4.5).
2
+ //
3
+ // qa_build_plan: side-effect-free. Proposes the exact prerequisite + build commands and the
4
+ // artifact globs the build will produce. An agent shows this and asks before compiling.
5
+ //
6
+ // qa_build: consent-gated. Runs the planned prerequisites + build as a JOB (returns a jobId;
7
+ // poll with qa_job_status), captures a combined build log artifact, and classifies a failure
8
+ // (GRADLE_FAILED / XCODEBUILD_FAILED / FLUTTER_BUILD_FAILED / BUILD_TIMED_OUT). On success it
9
+ // re-resolves the produced artifact so the next step (qa_prepare_target / qa_test_this) has it.
10
+ import { z } from 'zod';
11
+ import { qaOk, qaError } from '../lib/result.js';
12
+ import { qaFail } from '../oracle/failures.js';
13
+ import { requireConsent, consumeConsent } from '../consent/consent.js';
14
+ import { resolveProjectRoot } from '../context/projectRoot.js';
15
+ import { buildPlan } from '../build/plan.js';
16
+ import { executeBuild } from '../services/build.js';
17
+ const DEFAULT_BUILD_TIMEOUT_MS = 20 * 60_000; // 20 min — native builds are slow
18
+ async function rootFrom(server, sessions, sessionId, projectRoot) {
19
+ if (sessionId) {
20
+ const r = sessions.get(sessionId)?.root;
21
+ if (r)
22
+ return r;
23
+ }
24
+ const resolved = await resolveProjectRoot(server, projectRoot);
25
+ if (!resolved.root)
26
+ return { error: qaError({ what: 'Could not resolve a project root', changedState: false, retrySafe: true, nextSteps: ['Pass projectRoot or call qa_start_session.'], clientHint: resolved.hint }) };
27
+ return resolved.root;
28
+ }
29
+ function planSummary(plan) {
30
+ const pre = plan.prerequisites.map((s) => ` - ${s.label}: ${s.command}`).join('\n');
31
+ return (`Build plan: ${plan.framework} / ${plan.platform} / ${plan.variant}\n` +
32
+ (plan.prerequisites.length ? `prerequisites:\n${pre}\n` : '') +
33
+ `build: ${plan.build ? plan.build.command + ` (cwd: ${plan.build.cwd})` : '(none)'}\n` +
34
+ `expects: ${plan.expectedArtifactGlobs.join(', ')}\n` +
35
+ `toolchain: ${plan.toolchainOk ? 'ok' : 'MISSING ' + plan.missingToolchain.join(', ')}` +
36
+ (plan.notes.length ? `\nnotes:\n - ${plan.notes.join('\n - ')}` : ''));
37
+ }
38
+ export function registerBuild(server, sessions) {
39
+ server.registerTool('qa_build_plan', {
40
+ title: 'Plan a build from source',
41
+ description: 'Propose the exact prerequisite + build commands to produce an installable artifact for a platform, per framework (Expo/RN/native/Flutter). Side-effect free. Returns prerequisites (deps install, Expo prebuild, pod install), the main build command + cwd, expected artifact globs, and toolchain status. Typed blockers: UNSUPPORTED_FRAMEWORK, BUILD_COMMAND_UNAVAILABLE. Run qa_build to actually execute.',
42
+ inputSchema: {
43
+ sessionId: z.string().optional(),
44
+ projectRoot: z.string().optional(),
45
+ platform: z.enum(['android', 'ios']),
46
+ variant: z.enum(['debug', 'release']).optional(),
47
+ },
48
+ }, async ({ sessionId, projectRoot, platform, variant }) => {
49
+ const root = await rootFrom(server, sessions, sessionId, projectRoot);
50
+ if (typeof root !== 'string')
51
+ return root.error;
52
+ const plan = await buildPlan({ projectRoot: root, platform: platform, variant });
53
+ if (plan.failureCode) {
54
+ return qaFail(plan.failureCode, { what: plan.notes[0] ?? `Cannot plan a ${platform} build for ${plan.framework}`, extra: { plan } });
55
+ }
56
+ return qaOk({ plan }, planSummary(plan));
57
+ });
58
+ server.registerTool('qa_build', {
59
+ title: 'Build the app from source',
60
+ description: 'Run the planned prerequisites + build (consent-gated) as a background job. Captures a combined build log artifact and, on success, re-resolves the produced artifact (path/appId/installability). On failure returns a typed blocker (GRADLE_FAILED/XCODEBUILD_FAILED/FLUTTER_BUILD_FAILED/BUILD_TIMED_OUT/DEPENDENCY_INSTALL_REQUIRED) with the log — a build failure is NOT a test failure. Returns a jobId; poll qa_job_status. Requires a session (for artifacts/log storage).',
61
+ inputSchema: {
62
+ sessionId: z.string().describe('A session from qa_start_session (build log is stored as a session artifact).'),
63
+ platform: z.enum(['android', 'ios']),
64
+ variant: z.enum(['debug', 'release']).optional(),
65
+ timeoutMs: z.number().optional().describe(`Per-step timeout (default ${DEFAULT_BUILD_TIMEOUT_MS}).`),
66
+ consentId: z.string().optional(),
67
+ approve: z.boolean().optional(),
68
+ },
69
+ }, async ({ sessionId, platform, variant, timeoutMs, consentId, approve }) => {
70
+ const session = sessions.get(sessionId);
71
+ if (!session)
72
+ return qaError({ what: `Unknown sessionId "${sessionId}"`, changedState: false, retrySafe: true, nextSteps: ['Call qa_start_session first.'] });
73
+ const plan = await buildPlan({ projectRoot: session.root, platform: platform, variant });
74
+ if (plan.failureCode)
75
+ return qaFail(plan.failureCode, { what: plan.notes[0] ?? 'Cannot build', extra: { plan } });
76
+ if (!plan.toolchainOk)
77
+ return qaFail('BUILD_COMMAND_UNAVAILABLE', { what: `Missing toolchain: ${plan.missingToolchain.join(', ')}`, extra: { plan } });
78
+ if (!plan.build)
79
+ return qaFail('BUILD_COMMAND_UNAVAILABLE', { extra: { plan } });
80
+ // Consent: building from source spends minutes + writes into the project tree.
81
+ const steps = [...plan.prerequisites, plan.build];
82
+ const affects = { commands: steps.map((s) => s.command), cwd: plan.build.cwd };
83
+ const gate = consumeConsent(consentId, approve, { action: 'build_from_source', affects });
84
+ if (!gate.approved) {
85
+ sessions.recordMutation(session, {
86
+ tool: 'qa_build',
87
+ action: 'build_from_source',
88
+ risk: 'medium',
89
+ target: affects,
90
+ consent: { required: true, approved: false },
91
+ status: 'requested',
92
+ });
93
+ return requireConsent({
94
+ action: 'build_from_source',
95
+ risk: 'medium',
96
+ exactCommand: steps.map((s) => `(${s.cwd}) ${s.command}`).join('\n'),
97
+ affects,
98
+ explain: `Build ${plan.framework}/${platform}/${plan.variant} from source. This runs:\n${steps.map((s) => `• ${s.label}: ${s.command}`).join('\n')}`,
99
+ });
100
+ }
101
+ sessions.recordMutation(session, {
102
+ tool: 'qa_build',
103
+ action: 'build_from_source',
104
+ risk: 'medium',
105
+ target: affects,
106
+ consent: { required: true, consentId, approved: true },
107
+ status: 'approved',
108
+ });
109
+ const job = sessions.createJob(session, `build:${platform}`);
110
+ void runBuild(sessions, session, job, plan, timeoutMs ?? DEFAULT_BUILD_TIMEOUT_MS, { affects, consentId });
111
+ return qaOk({ jobId: job.jobId, status: 'running', kind: job.kind, plan }, `Started ${plan.framework}/${platform} build as job ${job.jobId}. Poll qa_job_status { sessionId:"${session.id}", jobId:"${job.jobId}" }.`);
112
+ });
113
+ }
114
+ async function runBuild(sessions, session, job, plan, timeoutMs, mutation) {
115
+ const signal = sessions.abortSignal(session, job.jobId);
116
+ const upd = (patch) => sessions.updateJobIfRunning(session, job, patch);
117
+ const res = await executeBuild(sessions, session, plan, { signal, timeoutMs, onProgress: (p) => upd({ progress: p }) });
118
+ if (res.aborted)
119
+ return;
120
+ if (!res.ok) {
121
+ const info = res.failureCode ? qaFail(res.failureCode) : undefined;
122
+ if (mutation) {
123
+ sessions.recordMutation(session, {
124
+ tool: 'qa_build',
125
+ action: 'build_from_source',
126
+ risk: 'medium',
127
+ target: mutation.affects,
128
+ consent: { required: true, consentId: mutation.consentId, approved: true },
129
+ status: 'blocked',
130
+ ledgerUri: res.logUri,
131
+ detail: `${res.failureCode}: ${res.error}`,
132
+ });
133
+ }
134
+ upd({
135
+ status: 'failed',
136
+ error: `${res.failureCode}: ${res.error}`,
137
+ result: { failureCode: res.failureCode, step: res.step, logUri: res.logUri, tail: res.tail, nextSteps: info?.structuredContent.nextSteps },
138
+ resultText: `❌ ${res.failureCode} during "${res.step}". Build failure ≠ test failure. Log: ${res.logUri}`,
139
+ endedAt: Date.now(),
140
+ });
141
+ return;
142
+ }
143
+ if (!res.artifact) {
144
+ if (mutation) {
145
+ sessions.recordMutation(session, {
146
+ tool: 'qa_build',
147
+ action: 'build_from_source',
148
+ risk: 'medium',
149
+ target: mutation.affects,
150
+ consent: { required: true, consentId: mutation.consentId, approved: true },
151
+ status: 'blocked',
152
+ ledgerUri: res.logUri,
153
+ detail: res.warning ?? 'build finished but no artifact was located',
154
+ });
155
+ }
156
+ upd({ status: 'done', progress: 'done', result: { built: true, artifact: null, logUri: res.logUri, warning: res.warning, searchedLocations: res.searchedLocations }, resultText: `⚠️ Build finished but Swipium could not locate the artifact. Log: ${res.logUri}`, endedAt: Date.now() });
157
+ return;
158
+ }
159
+ if (mutation) {
160
+ sessions.recordMutation(session, {
161
+ tool: 'qa_build',
162
+ action: 'build_from_source',
163
+ risk: 'medium',
164
+ target: { ...mutation.affects, artifact: res.artifact.path },
165
+ consent: { required: true, consentId: mutation.consentId, approved: true },
166
+ status: 'executed',
167
+ ledgerUri: res.logUri,
168
+ });
169
+ }
170
+ upd({ status: 'done', progress: 'done', result: { built: true, artifact: res.artifact, logUri: res.logUri }, resultText: `✅ Built ${res.artifact.type.toUpperCase()} at ${res.artifact.path}${res.artifact.appId ? ` (appId ${res.artifact.appId})` : ''}. Next: qa_prepare_target.`, endedAt: Date.now() });
171
+ }
172
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/tools/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ // qa_bundletool (hardening P0.2) — convert an .aab to an installable universal .apk via bundletool,
2
+ // cached under .swipium/artifacts/. Runs as a job (conversion can take a minute). Returns a typed
3
+ // AAB_NEEDS_BUNDLETOOL / AAB_BUILD_APKS_FAILED blocker when it cannot, never a generic error.
4
+ import { z } from 'zod';
5
+ import { qaOk, qaError } from '../lib/result.js';
6
+ import { qaFail } from '../oracle/failures.js';
7
+ import { requireConsent, consumeConsent } from '../consent/consent.js';
8
+ import { resolveArtifact } from '../artifacts/resolve.js';
9
+ import { convertAabToApk, findBundletool, buildAndInstallApkSet } from '../artifacts/bundletool.js';
10
+ import { startProgress } from '../session/progress.js';
11
+ import { log } from '../lib/logger.js';
12
+ export function registerBundletool(server, sessions) {
13
+ server.registerTool('qa_bundletool', {
14
+ title: 'Convert .aab → installable .apk',
15
+ description: 'Convert an Android App Bundle (.aab) into an installable APK set using bundletool, cached under .swipium/artifacts/. An .aab is NOT directly installable — this is the conversion step before qa_prepare_target. Default mode builds a UNIVERSAL .apk (works on any device). Pass connectedDevice:true to build a DEVICE-SPECIFIC APK set (--connected-device) and install:true to push it via bundletool install-apks. Uses the debug keystore by default (emulator/dev OK). Returns typed blockers (BUNDLETOOL_MISSING/AAB_NEEDS_BUNDLETOOL, AAB_BUILD_APKS_FAILED, AAB_DEVICE_SPEC_FAILED, AAB_INSTALL_FAILED, ANDROID_SIGNING_FAILED). Runs as a job; poll qa_job_status.',
16
+ inputSchema: {
17
+ sessionId: z.string(),
18
+ aab: z.string().optional().describe('Path to the .aab (default: the best .aab resolved under the project).'),
19
+ force: z.boolean().optional().describe('Rebuild even if a cached APK/APK set exists.'),
20
+ connectedDevice: z.boolean().optional().describe('Build a device-specific APK set for a connected device (bundletool --connected-device) instead of a universal APK.'),
21
+ install: z.boolean().optional().describe('With connectedDevice, also install the APK set on the device (bundletool install-apks). Requires an online adb device. Consent-gated (installs app code on a real device/emulator).'),
22
+ deviceId: z.string().optional().describe('adb serial to target for connectedDevice build/install (defaults to the only connected device).'),
23
+ consentId: z.string().optional(),
24
+ approve: z.boolean().optional(),
25
+ },
26
+ }, async ({ sessionId, aab, force, connectedDevice, install, deviceId, consentId, approve }) => {
27
+ const session = sessions.get(sessionId);
28
+ if (!session)
29
+ return qaError({ what: `Unknown sessionId "${sessionId}"`, changedState: false, retrySafe: true, nextSteps: ['Call qa_start_session first.'] });
30
+ // Resolve the .aab if not given.
31
+ let aabPath = aab;
32
+ if (!aabPath) {
33
+ const r = await resolveArtifact({ projectRoot: session.root, platform: 'android' }, false);
34
+ const found = [r.best, ...r.candidates].find((c) => c?.type === 'aab');
35
+ if (!found)
36
+ return qaFail('NO_BUILD_ARTIFACT', { what: 'No .aab found to convert', nextSteps: ['Pass aab=, or build an APK directly with qa_build.'] });
37
+ aabPath = found.path;
38
+ }
39
+ // Installing an APK set runs app code on a real device/emulator → consent-gated (build-only
40
+ // is safe and ungated). Confirm intent BEFORE any work, regardless of whether bundletool is
41
+ // installed. Mirrors qa_prepare_target / qa_prepare_ios_real_target.
42
+ let mutationConsent;
43
+ if (connectedDevice && install) {
44
+ const affects = { aab: aabPath, device: deviceId ?? '(only connected device)' };
45
+ const gate = consumeConsent(consentId, approve, { action: 'install_app', affects });
46
+ if (!gate.approved) {
47
+ sessions.recordMutation(session, { tool: 'qa_bundletool', action: 'install_app', risk: 'medium', target: affects, consent: { required: true, approved: false }, status: 'requested' });
48
+ return requireConsent({
49
+ action: 'install_app', risk: 'medium',
50
+ exactCommand: `bundletool build-apks --connected-device${deviceId ? ` --device-id ${deviceId}` : ''} --bundle ${aabPath} && bundletool install-apks --apks <set>`,
51
+ affects,
52
+ explain: `Build a device-specific APK set from ${aabPath} and INSTALL it on ${deviceId ?? 'the connected device'}? It pushes app code to the device.`,
53
+ });
54
+ }
55
+ mutationConsent = { required: true, consentId, approved: true };
56
+ }
57
+ // Fail fast + honestly when bundletool is unavailable (no job needed).
58
+ const launcher = await findBundletool();
59
+ if (!launcher) {
60
+ return qaFail('AAB_NEEDS_BUNDLETOOL', {
61
+ what: `bundletool is not installed — cannot convert ${aabPath}`,
62
+ nextSteps: [
63
+ 'Install bundletool (brew install bundletool) or set $BUNDLETOOL_JAR to bundletool.jar.',
64
+ 'Or build an APK directly: qa_build { platform: "android", variant: "debug" } (./gradlew assembleDebug).',
65
+ ],
66
+ extra: { aab: aabPath },
67
+ });
68
+ }
69
+ const job = sessions.createJob(session, 'bundletool:convert');
70
+ if (connectedDevice) {
71
+ void runDeviceApkSet(sessions, session, job, aabPath, { install: !!install, deviceId, force: !!force, mutationConsent });
72
+ return qaOk({ jobId: job.jobId, status: 'running', kind: job.kind, aab: aabPath, mode: 'connected-device', install: !!install, bundletool: launcher.describe }, `Building${install ? ' + installing' : ''} a device-specific APK set from ${aabPath} as job ${job.jobId} (${launcher.describe}). Poll qa_job_status.`);
73
+ }
74
+ void runConvert(sessions, session, job, aabPath, !!force);
75
+ return qaOk({ jobId: job.jobId, status: 'running', kind: job.kind, aab: aabPath, mode: 'universal', bundletool: launcher.describe }, `Converting ${aabPath} → universal APK as job ${job.jobId} (${launcher.describe}). Poll qa_job_status.`);
76
+ });
77
+ }
78
+ async function runDeviceApkSet(sessions, session, job, aabPath, opts) {
79
+ const signal = sessions.abortSignal(session, job.jobId);
80
+ const upd = (patch) => sessions.updateJobIfRunning(session, job, patch);
81
+ const prog = startProgress(sessions, session, job, 'building_apk_set', { statusText: 'Building a device-specific APK set with bundletool --connected-device.', nextExpected: opts.install ? 'Install the APK set on the device.' : 'Cache the APK set.' });
82
+ try {
83
+ const result = await buildAndInstallApkSet(aabPath, session.root, { deviceId: opts.deviceId, install: opts.install, signal, force: opts.force });
84
+ if (signal?.aborted)
85
+ return;
86
+ const logUri = result.logText ? sessions.saveArtifact(session, 'logs', `bundletool-apks-${job.jobId}.log`, result.logText, 'text/plain', 'bundletool device APK set log') : undefined;
87
+ if (!result.ok) {
88
+ if (opts.install) {
89
+ sessions.recordMutation(session, { tool: 'qa_bundletool', action: 'install_app', risk: 'medium', target: { aab: aabPath, device: opts.deviceId ?? null, apksPath: result.apksPath ?? null }, consent: opts.mutationConsent ?? { required: true, approved: true }, status: 'blocked', detail: `${result.failureCode}: ${result.error}` });
90
+ }
91
+ upd({ status: 'failed', error: `${result.failureCode}: ${result.error}`, result: { failureCode: result.failureCode, apksPath: result.apksPath ?? null, command: result.buildCommand ?? null, logUri, aab: aabPath }, resultText: `❌ ${result.failureCode}: ${result.error}`, endedAt: Date.now() });
92
+ return;
93
+ }
94
+ if (result.installed) {
95
+ sessions.addEnvChange(session, `installed APK set from ${aabPath} on ${opts.deviceId ?? 'connected device'}`);
96
+ sessions.recordMutation(session, { tool: 'qa_bundletool', action: 'install_app', risk: 'medium', target: { aab: aabPath, device: opts.deviceId ?? null, apksPath: result.apksPath ?? null }, consent: opts.mutationConsent ?? { required: true, approved: true }, status: 'executed' });
97
+ }
98
+ prog.done(result.installed ? 'Device APK set built + installed.' : 'Device APK set built.');
99
+ sessions.addWorkaround(session, `built device-specific APK set via bundletool${result.installed ? ' + installed' : ''}`);
100
+ upd({
101
+ status: 'done', progress: 'done',
102
+ result: { converted: true, mode: 'connected-device', installed: !!result.installed, originalArtifact: aabPath, apksPath: result.apksPath ?? null, buildCommand: result.buildCommand ?? null, installCommand: result.installCommand ?? null, logUri },
103
+ resultText: result.installed
104
+ ? `✅ Device-specific APK set installed from ${aabPath}. The app is on the device; continue with qa_prepare_target { bindOnly: true } or qa_smoke.`
105
+ : `✅ Device-specific APK set: ${result.apksPath}. Install it with qa_bundletool { connectedDevice: true, install: true } or bundletool install-apks.`,
106
+ endedAt: Date.now(),
107
+ });
108
+ }
109
+ catch (e) {
110
+ if (signal?.aborted)
111
+ return;
112
+ log('error', 'bundletool device APK set job failed', { jobId: job.jobId, err: String(e) });
113
+ upd({ status: 'failed', error: String(e), result: { failureCode: 'AAB_DEVICE_SPEC_FAILED' }, resultText: `❌ bundletool error: ${String(e)}`, endedAt: Date.now() });
114
+ }
115
+ }
116
+ async function runConvert(sessions, session, job, aabPath, force) {
117
+ const signal = sessions.abortSignal(session, job.jobId);
118
+ const upd = (patch) => sessions.updateJobIfRunning(session, job, patch);
119
+ const prog = startProgress(sessions, session, job, 'converting_aab', { statusText: 'Building a universal APK from the .aab with bundletool.', nextExpected: 'Extract universal.apk and cache it.' });
120
+ try {
121
+ const result = await convertAabToApk(aabPath, session.root, { signal, force });
122
+ if (signal?.aborted)
123
+ return;
124
+ if (!result.ok) {
125
+ const logUri = result.error ? sessions.saveArtifact(session, 'logs', `bundletool-${Date.now()}.log`, `${result.command ?? ''}\n${result.error}`, 'text/plain', 'bundletool conversion log') : undefined;
126
+ upd({ status: 'failed', error: `${result.failureCode}: ${result.error}`, result: { failureCode: result.failureCode, command: result.command, logUri, aab: aabPath }, resultText: `❌ ${result.failureCode}: ${result.error}`, endedAt: Date.now() });
127
+ return;
128
+ }
129
+ prog.done('Universal APK ready.');
130
+ sessions.addWorkaround(session, `converted .aab → universal .apk via bundletool (${result.fromCache ? 'cached' : 'built'})`);
131
+ upd({
132
+ status: 'done', progress: 'done',
133
+ result: { converted: true, fromCache: !!result.fromCache, originalArtifact: aabPath, generatedApk: result.apkPath, apksPath: result.apksPath ?? null, command: result.command ?? null },
134
+ resultText: `✅ ${result.fromCache ? 'Using cached' : 'Built'} universal APK: ${result.apkPath}. Next: qa_prepare_target { apk: "${result.apkPath}" }.`,
135
+ endedAt: Date.now(),
136
+ });
137
+ }
138
+ catch (e) {
139
+ if (signal?.aborted)
140
+ return;
141
+ log('error', 'bundletool job failed', { jobId: job.jobId, err: String(e) });
142
+ upd({ status: 'failed', error: String(e), result: { failureCode: 'AAB_BUILD_APKS_FAILED' }, resultText: `❌ bundletool error: ${String(e)}`, endedAt: Date.now() });
143
+ }
144
+ }
145
+ //# sourceMappingURL=bundletool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundletool.js","sourceRoot":"","sources":["../../src/tools/bundletool.ts"],"names":[],"mappings":"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"}