swipium 1.0.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 +21 -0
- package/README.md +295 -0
- package/dist/appMap/automationLink.js +74 -0
- package/dist/appMap/automationLink.js.map +1 -0
- package/dist/appMap/build.js +193 -0
- package/dist/appMap/build.js.map +1 -0
- package/dist/appMap/codeIndex.js +73 -0
- package/dist/appMap/codeIndex.js.map +1 -0
- package/dist/appMap/featureModel.js +83 -0
- package/dist/appMap/featureModel.js.map +1 -0
- package/dist/appMap/firstRunApply.js +131 -0
- package/dist/appMap/firstRunApply.js.map +1 -0
- package/dist/appMap/fsWalk.js +75 -0
- package/dist/appMap/fsWalk.js.map +1 -0
- package/dist/appMap/issues.js +227 -0
- package/dist/appMap/issues.js.map +1 -0
- package/dist/appMap/migrations.js +87 -0
- package/dist/appMap/migrations.js.map +1 -0
- package/dist/appMap/prelaunch.js +66 -0
- package/dist/appMap/prelaunch.js.map +1 -0
- package/dist/appMap/projectRegistry.js +70 -0
- package/dist/appMap/projectRegistry.js.map +1 -0
- package/dist/appMap/provenance.js +52 -0
- package/dist/appMap/provenance.js.map +1 -0
- package/dist/appMap/query.js +118 -0
- package/dist/appMap/query.js.map +1 -0
- package/dist/appMap/runtimeMerge.js +207 -0
- package/dist/appMap/runtimeMerge.js.map +1 -0
- package/dist/appMap/schema.js +65 -0
- package/dist/appMap/schema.js.map +1 -0
- package/dist/appMap/screenMatch.js +75 -0
- package/dist/appMap/screenMatch.js.map +1 -0
- package/dist/appMap/staticScan.js +614 -0
- package/dist/appMap/staticScan.js.map +1 -0
- package/dist/appMap/store.js +173 -0
- package/dist/appMap/store.js.map +1 -0
- package/dist/appMap/tsAstScan.js +184 -0
- package/dist/appMap/tsAstScan.js.map +1 -0
- package/dist/artifacts/bundletool.js +199 -0
- package/dist/artifacts/bundletool.js.map +1 -0
- package/dist/artifacts/resolve.js +388 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/automationGen/appiumModel.js +129 -0
- package/dist/automationGen/appiumModel.js.map +1 -0
- package/dist/automationGen/ciEmitter.js +80 -0
- package/dist/automationGen/ciEmitter.js.map +1 -0
- package/dist/automationGen/jsEmitter.js +440 -0
- package/dist/automationGen/jsEmitter.js.map +1 -0
- package/dist/automationGen/packagePatch.js +56 -0
- package/dist/automationGen/packagePatch.js.map +1 -0
- package/dist/automationGen/projectProfile.js +317 -0
- package/dist/automationGen/projectProfile.js.map +1 -0
- package/dist/automationGen/pythonEmitter.js +386 -0
- package/dist/automationGen/pythonEmitter.js.map +1 -0
- package/dist/automationGen/readmeEmitter.js +66 -0
- package/dist/automationGen/readmeEmitter.js.map +1 -0
- package/dist/automationGen/suitePlan.js +94 -0
- package/dist/automationGen/suitePlan.js.map +1 -0
- package/dist/automationGen/validation.js +150 -0
- package/dist/automationGen/validation.js.map +1 -0
- package/dist/build/parseBuildLog.js +119 -0
- package/dist/build/parseBuildLog.js.map +1 -0
- package/dist/build/plan.js +150 -0
- package/dist/build/plan.js.map +1 -0
- package/dist/ci/preflight.js +85 -0
- package/dist/ci/preflight.js.map +1 -0
- package/dist/cli/init.js +105 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan.js +85 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/suite.js +85 -0
- package/dist/cli/suite.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/consent/consent.js +43 -0
- package/dist/consent/consent.js.map +1 -0
- package/dist/context/detect.js +156 -0
- package/dist/context/detect.js.map +1 -0
- package/dist/context/findApps.js +198 -0
- package/dist/context/findApps.js.map +1 -0
- package/dist/context/projectRoot.js +41 -0
- package/dist/context/projectRoot.js.map +1 -0
- package/dist/context/scan.js +167 -0
- package/dist/context/scan.js.map +1 -0
- package/dist/core/target.js +115 -0
- package/dist/core/target.js.map +1 -0
- package/dist/core/targetPlan.js +140 -0
- package/dist/core/targetPlan.js.map +1 -0
- package/dist/drivers/DirectDriver.js +228 -0
- package/dist/drivers/DirectDriver.js.map +1 -0
- package/dist/drivers/Driver.js +4 -0
- package/dist/drivers/Driver.js.map +1 -0
- package/dist/drivers/SimctlDriver.js +127 -0
- package/dist/drivers/SimctlDriver.js.map +1 -0
- package/dist/drivers/WdaDriver.js +250 -0
- package/dist/drivers/WdaDriver.js.map +1 -0
- package/dist/explore/candidates.js +93 -0
- package/dist/explore/candidates.js.map +1 -0
- package/dist/explore/graph.js +116 -0
- package/dist/explore/graph.js.map +1 -0
- package/dist/explore/memory.js +35 -0
- package/dist/explore/memory.js.map +1 -0
- package/dist/explore/planner.js +105 -0
- package/dist/explore/planner.js.map +1 -0
- package/dist/explore/policy.js +85 -0
- package/dist/explore/policy.js.map +1 -0
- package/dist/explore/runner.js +475 -0
- package/dist/explore/runner.js.map +1 -0
- package/dist/explore/signatures.js +35 -0
- package/dist/explore/signatures.js.map +1 -0
- package/dist/explore/suite.js +55 -0
- package/dist/explore/suite.js.map +1 -0
- package/dist/featureTesting/executionBootstrap.js +140 -0
- package/dist/featureTesting/executionBootstrap.js.map +1 -0
- package/dist/firstRun/authStateMachine.js +83 -0
- package/dist/firstRun/authStateMachine.js.map +1 -0
- package/dist/firstRun/classifyScreen.js +201 -0
- package/dist/firstRun/classifyScreen.js.map +1 -0
- package/dist/firstRun/firstRunPlanner.js +207 -0
- package/dist/firstRun/firstRunPlanner.js.map +1 -0
- package/dist/firstRun/firstRunRunner.js +331 -0
- package/dist/firstRun/firstRunRunner.js.map +1 -0
- package/dist/firstRun/generatedDataPolicy.js +215 -0
- package/dist/firstRun/generatedDataPolicy.js.map +1 -0
- package/dist/firstRun/inputPlanner.js +67 -0
- package/dist/firstRun/inputPlanner.js.map +1 -0
- package/dist/firstRun/onboardingStateMachine.js +46 -0
- package/dist/firstRun/onboardingStateMachine.js.map +1 -0
- package/dist/firstRun/paywallPolicy.js +54 -0
- package/dist/firstRun/paywallPolicy.js.map +1 -0
- package/dist/firstRun/types.js +7 -0
- package/dist/firstRun/types.js.map +1 -0
- package/dist/fixtures/catalog.js +131 -0
- package/dist/fixtures/catalog.js.map +1 -0
- package/dist/flows/discover.js +18 -0
- package/dist/flows/discover.js.map +1 -0
- package/dist/flows/generate.js +211 -0
- package/dist/flows/generate.js.map +1 -0
- package/dist/flows/lint.js +97 -0
- package/dist/flows/lint.js.map +1 -0
- package/dist/flows/pack.js +68 -0
- package/dist/flows/pack.js.map +1 -0
- package/dist/flows/run.js +738 -0
- package/dist/flows/run.js.map +1 -0
- package/dist/flows/schema.js +240 -0
- package/dist/flows/schema.js.map +1 -0
- package/dist/flows/seedExec.js +108 -0
- package/dist/flows/seedExec.js.map +1 -0
- package/dist/flows/templates.js +155 -0
- package/dist/flows/templates.js.map +1 -0
- package/dist/flows/waitGuards.js +12 -0
- package/dist/flows/waitGuards.js.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/ios/signing.js +182 -0
- package/dist/ios/signing.js.map +1 -0
- package/dist/issues/classify.js +186 -0
- package/dist/issues/classify.js.map +1 -0
- package/dist/issues/fingerprint.js +130 -0
- package/dist/issues/fingerprint.js.map +1 -0
- package/dist/issues/index.js +240 -0
- package/dist/issues/index.js.map +1 -0
- package/dist/issues/metrics.js +155 -0
- package/dist/issues/metrics.js.map +1 -0
- package/dist/issues/recurrence.js +193 -0
- package/dist/issues/recurrence.js.map +1 -0
- package/dist/issues/report.js +110 -0
- package/dist/issues/report.js.map +1 -0
- package/dist/issues/reportBridge.js +119 -0
- package/dist/issues/reportBridge.js.map +1 -0
- package/dist/issues/schema.js +90 -0
- package/dist/issues/schema.js.map +1 -0
- package/dist/issues/sourceRevision.js +108 -0
- package/dist/issues/sourceRevision.js.map +1 -0
- package/dist/issues/store.js +155 -0
- package/dist/issues/store.js.map +1 -0
- package/dist/lib/android.js +278 -0
- package/dist/lib/android.js.map +1 -0
- package/dist/lib/commandTemplate.js +55 -0
- package/dist/lib/commandTemplate.js.map +1 -0
- package/dist/lib/coordSpace.js +23 -0
- package/dist/lib/coordSpace.js.map +1 -0
- package/dist/lib/device.js +87 -0
- package/dist/lib/device.js.map +1 -0
- package/dist/lib/gitignore.js +22 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/image.js +97 -0
- package/dist/lib/image.js.map +1 -0
- package/dist/lib/logger.js +8 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/metroState.js +45 -0
- package/dist/lib/metroState.js.map +1 -0
- package/dist/lib/needsInput.js +201 -0
- package/dist/lib/needsInput.js.map +1 -0
- package/dist/lib/png.js +103 -0
- package/dist/lib/png.js.map +1 -0
- package/dist/lib/redact.js +21 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/result.js +87 -0
- package/dist/lib/result.js.map +1 -0
- package/dist/lib/schemaHash.js +65 -0
- package/dist/lib/schemaHash.js.map +1 -0
- package/dist/lib/sensitive.js +13 -0
- package/dist/lib/sensitive.js.map +1 -0
- package/dist/lib/simctl.js +149 -0
- package/dist/lib/simctl.js.map +1 -0
- package/dist/lib/spawn.js +144 -0
- package/dist/lib/spawn.js.map +1 -0
- package/dist/lib/wda.js +347 -0
- package/dist/lib/wda.js.map +1 -0
- package/dist/lib/wdaConfig.js +69 -0
- package/dist/lib/wdaConfig.js.map +1 -0
- package/dist/lib/wdaTune.js +58 -0
- package/dist/lib/wdaTune.js.map +1 -0
- package/dist/oracle/auth.js +22 -0
- package/dist/oracle/auth.js.map +1 -0
- package/dist/oracle/failures.js +193 -0
- package/dist/oracle/failures.js.map +1 -0
- package/dist/oracle/health.js +123 -0
- package/dist/oracle/health.js.map +1 -0
- package/dist/oracle/record.js +36 -0
- package/dist/oracle/record.js.map +1 -0
- package/dist/orchestration/envelope.js +52 -0
- package/dist/orchestration/envelope.js.map +1 -0
- package/dist/orchestration/goal.js +98 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/plan/plan.js +124 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/prompts/index.js +63 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/report/artifactManifest.js +44 -0
- package/dist/report/artifactManifest.js.map +1 -0
- package/dist/report/coverage.js +60 -0
- package/dist/report/coverage.js.map +1 -0
- package/dist/report/evidence.js +84 -0
- package/dist/report/evidence.js.map +1 -0
- package/dist/report/export.js +447 -0
- package/dist/report/export.js.map +1 -0
- package/dist/report/flake.js +61 -0
- package/dist/report/flake.js.map +1 -0
- package/dist/report/history.js +564 -0
- package/dist/report/history.js.map +1 -0
- package/dist/report/policy.js +98 -0
- package/dist/report/policy.js.map +1 -0
- package/dist/report/qaLevel.js +96 -0
- package/dist/report/qaLevel.js.map +1 -0
- package/dist/report/readiness.js +213 -0
- package/dist/report/readiness.js.map +1 -0
- package/dist/report/summary.js +42 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/testCatalog.js +93 -0
- package/dist/report/testCatalog.js.map +1 -0
- package/dist/report/timing.js +37 -0
- package/dist/report/timing.js.map +1 -0
- package/dist/server.js +180 -0
- package/dist/server.js.map +1 -0
- package/dist/services/automationGenerate.js +60 -0
- package/dist/services/automationGenerate.js.map +1 -0
- package/dist/services/build.js +66 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/preflight.js +51 -0
- package/dist/services/preflight.js.map +1 -0
- package/dist/services/prepareAndroid.js +183 -0
- package/dist/services/prepareAndroid.js.map +1 -0
- package/dist/services/prepareIos.js +162 -0
- package/dist/services/prepareIos.js.map +1 -0
- package/dist/services/report.js +537 -0
- package/dist/services/report.js.map +1 -0
- package/dist/services/smoke.js +120 -0
- package/dist/services/smoke.js.map +1 -0
- package/dist/services/suiteGenerate.js +123 -0
- package/dist/services/suiteGenerate.js.map +1 -0
- package/dist/services/testSuiteKnowledge.js +150 -0
- package/dist/services/testSuiteKnowledge.js.map +1 -0
- package/dist/session/attach.js +47 -0
- package/dist/session/attach.js.map +1 -0
- package/dist/session/progress.js +56 -0
- package/dist/session/progress.js.map +1 -0
- package/dist/session/store.js +329 -0
- package/dist/session/store.js.map +1 -0
- package/dist/snapshot/overlays.js +132 -0
- package/dist/snapshot/overlays.js.map +1 -0
- package/dist/snapshot/parse.js +204 -0
- package/dist/snapshot/parse.js.map +1 -0
- package/dist/snapshot/present.js +12 -0
- package/dist/snapshot/present.js.map +1 -0
- package/dist/snapshot/settle.js +36 -0
- package/dist/snapshot/settle.js.map +1 -0
- package/dist/state/profile.js +318 -0
- package/dist/state/profile.js.map +1 -0
- package/dist/suite/compile.js +176 -0
- package/dist/suite/compile.js.map +1 -0
- package/dist/suite/lint.js +45 -0
- package/dist/suite/lint.js.map +1 -0
- package/dist/suite/pom.js +285 -0
- package/dist/suite/pom.js.map +1 -0
- package/dist/suite/testcase.js +87 -0
- package/dist/suite/testcase.js.map +1 -0
- package/dist/testSuite/generator.js +222 -0
- package/dist/testSuite/generator.js.map +1 -0
- package/dist/testSuite/history.js +44 -0
- package/dist/testSuite/history.js.map +1 -0
- package/dist/testSuite/issueLinks.js +96 -0
- package/dist/testSuite/issueLinks.js.map +1 -0
- package/dist/testSuite/merge.js +190 -0
- package/dist/testSuite/merge.js.map +1 -0
- package/dist/testSuite/schema.js +86 -0
- package/dist/testSuite/schema.js.map +1 -0
- package/dist/testSuite/store.js +116 -0
- package/dist/testSuite/store.js.map +1 -0
- package/dist/testSuite/traceability.js +55 -0
- package/dist/testSuite/traceability.js.map +1 -0
- package/dist/tools/act.js +457 -0
- package/dist/tools/act.js.map +1 -0
- package/dist/tools/agent.js +225 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/appMap.js +317 -0
- package/dist/tools/appMap.js.map +1 -0
- package/dist/tools/assertVisual.js +74 -0
- package/dist/tools/assertVisual.js.map +1 -0
- package/dist/tools/automationGenerate.js +394 -0
- package/dist/tools/automationGenerate.js.map +1 -0
- package/dist/tools/capabilities.js +114 -0
- package/dist/tools/capabilities.js.map +1 -0
- package/dist/tools/clearOverlay.js +150 -0
- package/dist/tools/clearOverlay.js.map +1 -0
- package/dist/tools/detectContext.js +41 -0
- package/dist/tools/detectContext.js.map +1 -0
- package/dist/tools/doctor.js +116 -0
- package/dist/tools/doctor.js.map +1 -0
- package/dist/tools/explore.js +289 -0
- package/dist/tools/explore.js.map +1 -0
- package/dist/tools/firstRun.js +136 -0
- package/dist/tools/firstRun.js.map +1 -0
- package/dist/tools/flow.js +331 -0
- package/dist/tools/flow.js.map +1 -0
- package/dist/tools/flowGenerate.js +55 -0
- package/dist/tools/flowGenerate.js.map +1 -0
- package/dist/tools/getArtifact.js +39 -0
- package/dist/tools/getArtifact.js.map +1 -0
- package/dist/tools/health.js +41 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/ios.js +492 -0
- package/dist/tools/ios.js.map +1 -0
- package/dist/tools/jobs.js +20 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/network.js +50 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/note.js +69 -0
- package/dist/tools/note.js.map +1 -0
- package/dist/tools/plan.js +49 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/prepareIosTarget.js +99 -0
- package/dist/tools/prepareIosTarget.js.map +1 -0
- package/dist/tools/prepareTarget.js +257 -0
- package/dist/tools/prepareTarget.js.map +1 -0
- package/dist/tools/report.js +42 -0
- package/dist/tools/report.js.map +1 -0
- package/dist/tools/screenRecord.js +24 -0
- package/dist/tools/screenRecord.js.map +1 -0
- package/dist/tools/screenshot.js +63 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/smoke.js +39 -0
- package/dist/tools/smoke.js.map +1 -0
- package/dist/tools/snapshot.js +129 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/startSession.js +169 -0
- package/dist/tools/startSession.js.map +1 -0
- package/dist/tools/state.js +87 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/suite.js +412 -0
- package/dist/tools/suite.js.map +1 -0
- package/dist/tools/testThis.js +774 -0
- package/dist/tools/testThis.js.map +1 -0
- package/dist/tools/wda.js +477 -0
- package/dist/tools/wda.js.map +1 -0
- package/dist/version.js +62 -0
- package/dist/version.js.map +1 -0
- package/dist/visual/ocr.js +72 -0
- package/dist/visual/ocr.js.map +1 -0
- package/dist/visual/provider.js +75 -0
- package/dist/visual/provider.js.map +1 -0
- package/docs/README.md +19 -0
- package/docs/assets/swipium-lockup-ink-on-light.png +0 -0
- package/docs/mcp-server.md +135 -0
- package/docs/tools.md +130 -0
- package/package.json +70 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// qa_explore (Phase 3.3) ā bounded, safe-by-default guided exploration as a background job. Drives
|
|
2
|
+
// the runExplore service: observe ā rank safe candidates ā act ā health ā graph, writing a screen
|
|
3
|
+
// graph artifact (JSON + Markdown) and recording qa_note outcomes. Returns a running jobId; the
|
|
4
|
+
// terminal state + graphUri land in the job result (poll qa_job_status). Thin wrapper ā all logic
|
|
5
|
+
// is in src/explore/*.
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { qaOk, qaError } from '../lib/result.js';
|
|
8
|
+
import { requireConsent, consumeConsent } from '../consent/consent.js';
|
|
9
|
+
import { getDriver } from '../session/attach.js';
|
|
10
|
+
import { runExplore } from '../explore/runner.js';
|
|
11
|
+
import { appendExploreMemory } from '../explore/memory.js';
|
|
12
|
+
import { buildAppMap } from '../appMap/build.js';
|
|
13
|
+
import { mergeFromExploration } from '../services/testSuiteKnowledge.js';
|
|
14
|
+
import { hasDisposableState } from '../fixtures/catalog.js';
|
|
15
|
+
import { generateAndCompileSuite } from '../services/suiteGenerate.js';
|
|
16
|
+
import { startProgress } from '../session/progress.js';
|
|
17
|
+
import { log } from '../lib/logger.js';
|
|
18
|
+
const HIGH_IMPACT_CONFIRMATION_CLASSES = new Set([
|
|
19
|
+
'payment',
|
|
20
|
+
'message_send',
|
|
21
|
+
'external_invite',
|
|
22
|
+
'account_delete',
|
|
23
|
+
'bulk_delete',
|
|
24
|
+
'permission_change',
|
|
25
|
+
'data_export',
|
|
26
|
+
'generic_destructive',
|
|
27
|
+
]);
|
|
28
|
+
function needsHighImpactConfirmation(riskClass) {
|
|
29
|
+
return !!riskClass && HIGH_IMPACT_CONFIRMATION_CLASSES.has(riskClass);
|
|
30
|
+
}
|
|
31
|
+
function promotedActionsFor(session, graph, promotions) {
|
|
32
|
+
const promoted = promotions.find((p) => p.status === 'promote');
|
|
33
|
+
if (!promoted)
|
|
34
|
+
return [];
|
|
35
|
+
const edges = graph.allEdges();
|
|
36
|
+
const used = new Set();
|
|
37
|
+
const actions = [];
|
|
38
|
+
for (let i = 0; i < promoted.path.length - 1; i++) {
|
|
39
|
+
const from = promoted.path[i];
|
|
40
|
+
const to = promoted.path[i + 1];
|
|
41
|
+
const edge = edges.find((e) => e.from === from && e.to === to && e.outcome === 'changed_screen');
|
|
42
|
+
const locatorValue = edge?.action.locator?.value;
|
|
43
|
+
if (!edge || typeof locatorValue !== 'string')
|
|
44
|
+
continue;
|
|
45
|
+
const idx = session.recordedActions.findIndex((a, actionIdx) => (!used.has(actionIdx) &&
|
|
46
|
+
a.action === edge.action.type &&
|
|
47
|
+
a.selector === locatorValue &&
|
|
48
|
+
a.provenance?.originalScreenSignature === edge.preActionState));
|
|
49
|
+
if (idx >= 0) {
|
|
50
|
+
used.add(idx);
|
|
51
|
+
actions.push(session.recordedActions[idx]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return actions;
|
|
55
|
+
}
|
|
56
|
+
export function registerExplore(server, sessions) {
|
|
57
|
+
server.registerTool('qa_explore', {
|
|
58
|
+
title: 'Guided exploration',
|
|
59
|
+
description: 'Explore a launched app like a practical QA engineer: bounded, safe-by-default crawl that observes screens, ranks safe actions, taps them, checks health after each, and builds a SCREEN GRAPH (JSON + Markdown artifacts). Skips destructive actions (delete/pay/send/logout) in strict mode; verifies map/canvas screens visually with qa_assert_visual; stops with NeedsInput on an auth wall when credentials are missing. Records durable taps so qa_suite_generate can promote paths. Runs as a JOB ā the terminal state (completed/blocked) + graphUri are in the job result (poll qa_job_status). Requires a prepared device (qa_test_this / qa_prepare_target first).',
|
|
60
|
+
inputSchema: {
|
|
61
|
+
sessionId: z.string(),
|
|
62
|
+
goal: z.string().optional().describe('Optional natural-language focus (e.g. "exercise the main tabs").'),
|
|
63
|
+
depth: z.number().optional().describe('Max navigation depth (default 3).'),
|
|
64
|
+
maxActions: z.number().optional().describe('Max actions to try (default 20).'),
|
|
65
|
+
maxScreens: z.number().optional().describe('Max distinct screens to visit (default 12).'),
|
|
66
|
+
maxDurationMs: z.number().optional(),
|
|
67
|
+
strategy: z.enum(['crawl', 'task_planner', 'hybrid']).optional().describe('crawl (default): deterministic screen crawl; task_planner: infer semantic QA tasks before acting; hybrid: task planning plus crawl.'),
|
|
68
|
+
safeMode: z.enum(['strict', 'balanced', 'dry_run_destructive', 'approved_destructive_candidate', 'approved_destructive']).optional().describe('strict (default): safe actions only; balanced: unknown-risk allowed; dry_run_destructive: discover/list destructive candidates without tapping; approved_destructive_candidate: allow exactly one candidate-bound destructive action. approved_destructive is deprecated and refused.'),
|
|
69
|
+
destructiveCandidate: z
|
|
70
|
+
.object({
|
|
71
|
+
screenSignature: z.string(),
|
|
72
|
+
candidateSignature: z.string(),
|
|
73
|
+
label: z.string().optional(),
|
|
74
|
+
locator: z.object({ strategy: z.string().optional(), value: z.string().optional() }).optional(),
|
|
75
|
+
riskClass: z.string().optional(),
|
|
76
|
+
})
|
|
77
|
+
.optional()
|
|
78
|
+
.describe('Exact candidate returned by a dry_run_destructive exploration. Required with safeMode approved_destructive_candidate.'),
|
|
79
|
+
confirmHighImpact: z.boolean().optional().describe('Required true for high-impact destructive candidates such as payment, send/share, permission change, account delete, or bulk delete.'),
|
|
80
|
+
generateSuite: z.boolean().optional().describe('After exploration, score promotable paths and include suite-promotion guidance.'),
|
|
81
|
+
includeTextEntry: z.boolean().optional().describe('Allow typing into fields (only with a value source ā default false).'),
|
|
82
|
+
stopOnAuth: z.boolean().optional().describe('Return NeedsInput when an auth wall blocks exploration and credentials are missing (default true).'),
|
|
83
|
+
accountCycle: z
|
|
84
|
+
.boolean()
|
|
85
|
+
.optional()
|
|
86
|
+
.describe('SWIPIUM-REQ-07 controlled account-cycle workflow: on a DISPOSABLE generated account, permit LOGOUT (and only logout) as an expected step; delete/pay/send stay refused. Requires allowGeneratedData. Off by default.'),
|
|
87
|
+
allowGeneratedData: z.boolean().optional().describe('Allow safe generated disposable-account data (test/staging) ā required to use accountCycle.'),
|
|
88
|
+
consentId: z.string().optional(),
|
|
89
|
+
approve: z.boolean().optional(),
|
|
90
|
+
},
|
|
91
|
+
}, async ({ sessionId, goal, depth, maxActions, maxScreens, maxDurationMs, strategy, safeMode, destructiveCandidate, confirmHighImpact, generateSuite, includeTextEntry, stopOnAuth, accountCycle, allowGeneratedData, consentId, approve }) => {
|
|
92
|
+
const session = sessions.get(sessionId);
|
|
93
|
+
if (!session)
|
|
94
|
+
return qaError({ what: `Unknown sessionId ${sessionId}`, changedState: false, retrySafe: true, nextSteps: ['Call qa_start_session first.'] });
|
|
95
|
+
const { driver } = await getDriver(session);
|
|
96
|
+
if (!driver) {
|
|
97
|
+
return qaError({ what: 'No device attached to this session', changedState: false, retrySafe: true, nextSteps: ['Prepare a device first: qa_test_this { mode:"execute" } or qa_prepare_target, then qa_explore.'] });
|
|
98
|
+
}
|
|
99
|
+
if (safeMode === 'approved_destructive') {
|
|
100
|
+
return qaError({
|
|
101
|
+
what: 'Blanket destructive exploration approval has been removed',
|
|
102
|
+
changedState: false,
|
|
103
|
+
retrySafe: false,
|
|
104
|
+
failureCode: 'DESTRUCTIVE_REFUSED',
|
|
105
|
+
nextSteps: ['Run qa_explore with safeMode:"dry_run_destructive" to discover candidates, then approve one exact candidate with safeMode:"approved_destructive_candidate" and disposable test state.'],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
let destructiveApproval;
|
|
109
|
+
if (safeMode === 'approved_destructive_candidate') {
|
|
110
|
+
if (!destructiveCandidate) {
|
|
111
|
+
return qaError({
|
|
112
|
+
what: 'approved_destructive_candidate requires an exact destructiveCandidate',
|
|
113
|
+
changedState: false,
|
|
114
|
+
retrySafe: false,
|
|
115
|
+
failureCode: 'DESTRUCTIVE_REFUSED',
|
|
116
|
+
nextSteps: ['Run safeMode:"dry_run_destructive" first and copy one candidate signature/screen/locator into destructiveCandidate.'],
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (!hasDisposableState(session)) {
|
|
120
|
+
return qaError({
|
|
121
|
+
what: 'Destructive exploration requires disposable test state',
|
|
122
|
+
changedState: false,
|
|
123
|
+
retrySafe: false,
|
|
124
|
+
failureCode: 'MISSING_FIXTURE',
|
|
125
|
+
nextSteps: ['Declare a fixture with disposable:true or environment:"test" before approving delete/pay/send/logout workflows.'],
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (needsHighImpactConfirmation(destructiveCandidate.riskClass) && confirmHighImpact !== true) {
|
|
129
|
+
return qaError({
|
|
130
|
+
what: `High-impact destructive candidate "${destructiveCandidate.label ?? destructiveCandidate.candidateSignature}" requires confirmHighImpact:true`,
|
|
131
|
+
changedState: false,
|
|
132
|
+
retrySafe: false,
|
|
133
|
+
failureCode: 'DESTRUCTIVE_REFUSED',
|
|
134
|
+
nextSteps: ['Re-run with confirmHighImpact:true only if this is disposable test state and the action can be safely verified or rolled back.'],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const approval = {
|
|
138
|
+
sessionId: session.id,
|
|
139
|
+
...destructiveCandidate,
|
|
140
|
+
consentId,
|
|
141
|
+
confirmHighImpact: confirmHighImpact === true,
|
|
142
|
+
expiresAt: Date.now() + 5 * 60_000,
|
|
143
|
+
singleUse: true,
|
|
144
|
+
requiresDisposableState: true,
|
|
145
|
+
};
|
|
146
|
+
const affects = {
|
|
147
|
+
sessionId: session.id,
|
|
148
|
+
screenSignature: destructiveCandidate.screenSignature,
|
|
149
|
+
candidateSignature: destructiveCandidate.candidateSignature,
|
|
150
|
+
label: destructiveCandidate.label ?? null,
|
|
151
|
+
locator: destructiveCandidate.locator ?? null,
|
|
152
|
+
riskClass: destructiveCandidate.riskClass ?? null,
|
|
153
|
+
confirmHighImpact: confirmHighImpact === true,
|
|
154
|
+
requiresDisposableState: true,
|
|
155
|
+
};
|
|
156
|
+
const gate = consumeConsent(consentId, approve, { action: 'destructive_ui_candidate', affects });
|
|
157
|
+
if (!gate.approved) {
|
|
158
|
+
sessions.recordMutation(session, {
|
|
159
|
+
tool: 'qa_explore',
|
|
160
|
+
action: 'destructive_ui_candidate',
|
|
161
|
+
risk: 'high',
|
|
162
|
+
target: affects,
|
|
163
|
+
consent: { required: true, approved: false },
|
|
164
|
+
status: 'requested',
|
|
165
|
+
});
|
|
166
|
+
return requireConsent({
|
|
167
|
+
action: 'destructive_ui_candidate',
|
|
168
|
+
risk: 'high',
|
|
169
|
+
affects,
|
|
170
|
+
explain: `Approve exactly one destructive exploration candidate (${destructiveCandidate.label ?? destructiveCandidate.candidateSignature}) on the current screen signature? ` +
|
|
171
|
+
'This approval is single-use, expires quickly, and requires disposable test state.',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
sessions.addEnvChange(session, `CONSENT destructive candidate ${destructiveCandidate.candidateSignature} on ${destructiveCandidate.screenSignature}`);
|
|
175
|
+
sessions.recordMutation(session, {
|
|
176
|
+
tool: 'qa_explore',
|
|
177
|
+
action: 'destructive_ui_candidate',
|
|
178
|
+
risk: 'high',
|
|
179
|
+
target: affects,
|
|
180
|
+
consent: { required: true, consentId, approved: true },
|
|
181
|
+
status: 'approved',
|
|
182
|
+
});
|
|
183
|
+
destructiveApproval = approval;
|
|
184
|
+
}
|
|
185
|
+
const accountCycleCtx = accountCycle ? { enabled: true, disposableAccount: allowGeneratedData === true } : undefined;
|
|
186
|
+
const job = sessions.createJob(session, 'explore');
|
|
187
|
+
void runExploreJob(sessions, session, job, { goal, depth, maxActions, maxScreens, maxDurationMs, strategy, safeMode, destructiveApproval, generateSuite, includeTextEntry, stopOnAuth, accountCycle: accountCycleCtx, allowGeneratedData });
|
|
188
|
+
return qaOk({ sessionId: session.id, state: 'running', jobId: job.jobId, kind: job.kind }, `š§ guided exploration started as job ${job.jobId}. Poll qa_job_status { sessionId:"${session.id}", jobId:"${job.jobId}" } for the screen graph + terminal state.`);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async function runExploreJob(sessions, session, job, opts) {
|
|
192
|
+
const signal = sessions.abortSignal(session, job.jobId);
|
|
193
|
+
const upd = (patch) => sessions.updateJobIfRunning(session, job, patch);
|
|
194
|
+
const prog = startProgress(sessions, session, job, 'exploring', { statusText: 'Exploring the app safely.', nextExpected: 'Build a screen graph.' });
|
|
195
|
+
try {
|
|
196
|
+
const { driver } = await getDriver(session);
|
|
197
|
+
if (!driver) {
|
|
198
|
+
upd({ status: 'failed', error: 'no driver', endedAt: Date.now() });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const res = await runExplore(sessions, session, driver, opts, { signal, onProgress: (p) => prog.event(p) });
|
|
202
|
+
if (signal?.aborted)
|
|
203
|
+
return;
|
|
204
|
+
// Persist the screen graph as JSON + Markdown artifacts.
|
|
205
|
+
const at = Date.now();
|
|
206
|
+
const generatedAt = new Date(at).toISOString();
|
|
207
|
+
const serializedGraph = res.graph.serialize(generatedAt);
|
|
208
|
+
const graphUri = sessions.saveArtifact(session, 'explore', `graph-${at}.json`, JSON.stringify(serializedGraph, null, 2), 'application/json', 'exploration screen graph');
|
|
209
|
+
const graphMdUri = sessions.saveArtifact(session, 'explore', `graph-${at}.md`, res.graph.toMarkdown(new Date(at).toISOString()), 'text/markdown', 'exploration screen graph (readable)');
|
|
210
|
+
const historyPath = appendExploreMemory(session.root, session.appId, {
|
|
211
|
+
appId: session.appId ?? 'unknown-app',
|
|
212
|
+
sessionId: session.id,
|
|
213
|
+
at: generatedAt,
|
|
214
|
+
graphUri,
|
|
215
|
+
graphMdUri,
|
|
216
|
+
stoppedReason: res.stoppedReason,
|
|
217
|
+
state: res.state,
|
|
218
|
+
summary: res.summary,
|
|
219
|
+
tasks: serializedGraph.tasks,
|
|
220
|
+
hypotheses: serializedGraph.hypotheses,
|
|
221
|
+
coverageClaims: serializedGraph.coverageClaims,
|
|
222
|
+
blockedPreconditions: serializedGraph.blockedPreconditions,
|
|
223
|
+
reflection: serializedGraph.reflection,
|
|
224
|
+
});
|
|
225
|
+
const promotedActions = opts.generateSuite ? promotedActionsFor(session, res.graph, res.suitePromotion) : [];
|
|
226
|
+
const generatedSuite = opts.generateSuite
|
|
227
|
+
? promotedActions.length
|
|
228
|
+
? generateAndCompileSuite(sessions, session, { name: 'explore-promoted', actions: promotedActions, save: true, compile: true })
|
|
229
|
+
: {
|
|
230
|
+
skipped: true,
|
|
231
|
+
skippedReason: res.suitePromotion.some((p) => p.status === 'promote') ? 'promoted path did not map to recorded replay actions' : 'no promoted exploration path met the replay threshold',
|
|
232
|
+
recommendation: 'Review suitePromotion reasons, improve locator readiness, then run qa_suite_generate after replayable actions are recorded.',
|
|
233
|
+
written: [],
|
|
234
|
+
compiledFlows: [],
|
|
235
|
+
suiteRunnable: false,
|
|
236
|
+
readinessLabels: [],
|
|
237
|
+
}
|
|
238
|
+
: undefined;
|
|
239
|
+
const record = { at, graphUri, graphMdUri, state: res.state, stoppedReason: res.stoppedReason, summary: res.summary };
|
|
240
|
+
sessions.setExploration(session, record);
|
|
241
|
+
// SWIPIUM-REQ-01: merge this exploration into the durable App Knowledge Map by default. Best-effort
|
|
242
|
+
// ā a map failure must never fail the exploration job.
|
|
243
|
+
try {
|
|
244
|
+
buildAppMap(session.root, { mode: 'runtime_merge', at: generatedAt, sessionId: session.id, exploreGraph: serializedGraph, persist: true });
|
|
245
|
+
}
|
|
246
|
+
catch (e) {
|
|
247
|
+
log('warn', 'app map merge after explore failed', { jobId: job.jobId, err: String(e) });
|
|
248
|
+
}
|
|
249
|
+
// Fix 9: keep the persistent suite current directly after exploration ā don't wait for a later
|
|
250
|
+
// qa_report. Best-effort: a suite-merge failure is a warning, never an exploration failure.
|
|
251
|
+
const suiteMerge = mergeFromExploration(session.root, record, { source: 'exploration', now: generatedAt, runId: `explore-${at}`, sourceUri: graphUri, appId: session.appId, sessionId: session.id });
|
|
252
|
+
prog.done(`explored ${res.summary.screensVisited} screens`);
|
|
253
|
+
const nextRecommendedAction = res.needsInput
|
|
254
|
+
? { tool: 'qa_continue_from_blocker', args: { sessionId: session.id, kind: 'credentials' }, why: 'Provide credentials to explore authenticated screens' }
|
|
255
|
+
: { tool: 'qa_report', args: { sessionId: session.id }, why: 'Summarize the exploration with the screen graph' };
|
|
256
|
+
upd({
|
|
257
|
+
status: 'done',
|
|
258
|
+
progress: res.state,
|
|
259
|
+
result: {
|
|
260
|
+
state: res.state,
|
|
261
|
+
stoppedReason: res.stoppedReason,
|
|
262
|
+
summary: res.summary,
|
|
263
|
+
destructiveCandidates: res.destructiveCandidates,
|
|
264
|
+
graphUri,
|
|
265
|
+
graphMdUri,
|
|
266
|
+
historyPath,
|
|
267
|
+
needsInput: res.needsInput ?? null,
|
|
268
|
+
suitePromotion: res.suitePromotion,
|
|
269
|
+
generatedSuite: generatedSuite ?? null,
|
|
270
|
+
suiteDelta: suiteMerge.delta ?? null,
|
|
271
|
+
suiteUri: suiteMerge.suiteUri ?? null,
|
|
272
|
+
suiteWarning: suiteMerge.warning ?? null,
|
|
273
|
+
nextRecommendedAction,
|
|
274
|
+
},
|
|
275
|
+
resultText: `š§ exploration ${res.state} ā ${res.summary.screensVisited} screens, ${res.summary.actionsTried} actions, ${res.summary.workflowsFound} transitions, ${res.summary.visualOnlyScreens} visual-only, ${res.summary.unsafeActionsSkipped} unsafe skipped, ${res.summary.appErrors} app errors.\n` +
|
|
276
|
+
`reason: ${res.stoppedReason}\ngraph: ${graphUri}` +
|
|
277
|
+
(generatedSuite && !generatedSuite.skipped ? `\npromoted suite: ${generatedSuite.name}` : '') +
|
|
278
|
+
(res.needsInput ? `\nā ${res.needsInput.question}` : ''),
|
|
279
|
+
endedAt: Date.now(),
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
catch (e) {
|
|
283
|
+
if (signal?.aborted)
|
|
284
|
+
return;
|
|
285
|
+
log('error', 'explore job failed', { jobId: job.jobId, err: String(e) });
|
|
286
|
+
upd({ status: 'failed', error: String(e), resultText: `ā exploration error: ${String(e)}`, endedAt: Date.now() });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=explore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explore.js","sourceRoot":"","sources":["../../src/tools/explore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// SWIPIUM-REQ-02 ā first-run MCP tools.
|
|
2
|
+
// qa_first_run_plan read-only: classify the current screen + return the safe plan (no acting).
|
|
3
|
+
// qa_first_run_continue execute one bounded step or a bounded first-run sequence (mode-driven).
|
|
4
|
+
//
|
|
5
|
+
// These drive the pure planning layer (src/firstRun/*) and the bounded driver loop (firstRunRunner).
|
|
6
|
+
// Secrets (generated passwords) are added to the session redaction set and never appear in output;
|
|
7
|
+
// generated emails are recorded as evidence so a developer can reproduce the throwaway account.
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { qaOk, qaError } from '../lib/result.js';
|
|
10
|
+
import { qaNeedsInput, NeedsInput } from '../lib/needsInput.js';
|
|
11
|
+
import { getDriver } from '../session/attach.js';
|
|
12
|
+
import { planFirstRun } from '../firstRun/firstRunPlanner.js';
|
|
13
|
+
import { observeScreen, resolveFirstRunPolicy, runFirstRun } from '../firstRun/firstRunRunner.js';
|
|
14
|
+
function needsInputPayload(kind, reason) {
|
|
15
|
+
if (kind === 'otp_or_manual_verification')
|
|
16
|
+
return NeedsInput.otp(reason);
|
|
17
|
+
if (kind === 'create_test_data')
|
|
18
|
+
return NeedsInput.createTestData(reason);
|
|
19
|
+
return NeedsInput.credentials(reason);
|
|
20
|
+
}
|
|
21
|
+
export function registerFirstRun(server, sessions) {
|
|
22
|
+
// ---- qa_first_run_plan (read-only) ----
|
|
23
|
+
server.registerTool('qa_first_run_plan', {
|
|
24
|
+
title: 'First-run plan (read-only)',
|
|
25
|
+
description: 'Read-only. Classifies the CURRENT screen of a launched app (login / create-account / login-or-create / OTP / onboarding / permissions / paywall / home / feature / error) using the UI snapshot + visible text + app-map/code context, then returns the SAFE first-run plan WITHOUT acting: the classification + confidence + evidence, the required inputs, the planned actions, the environment classification, and whether safe generated-account creation is allowed here. No taps, no typing, no secrets. Requires a prepared device (qa_test_this / qa_prepare_target first). To actually execute the plan, call qa_first_run_continue.',
|
|
26
|
+
inputSchema: {
|
|
27
|
+
sessionId: z.string(),
|
|
28
|
+
allowGeneratedAccount: z.boolean().optional().describe('Override the policy decision on creating a throwaway account (true to allow, false to forbid).'),
|
|
29
|
+
testDataPolicyPath: z.string().optional().describe('Path to a test-data policy JSON (default .swipium/test-data-policy.json).'),
|
|
30
|
+
},
|
|
31
|
+
}, async ({ sessionId, allowGeneratedAccount, testDataPolicyPath }) => {
|
|
32
|
+
const session = sessions.get(sessionId);
|
|
33
|
+
if (!session)
|
|
34
|
+
return qaError({ what: `Unknown sessionId ${sessionId}`, changedState: false, retrySafe: true, nextSteps: ['Call qa_start_session first.'] });
|
|
35
|
+
const { driver } = await getDriver(session);
|
|
36
|
+
if (!driver)
|
|
37
|
+
return qaError({ what: 'No device attached to this session', changedState: false, retrySafe: true, nextSteps: ['Prepare a device first: qa_test_this { mode:"execute" } or qa_prepare_target, then qa_first_run_plan.'] });
|
|
38
|
+
const { policy, policySource, environment, decision } = resolveFirstRunPolicy(session, { testDataPolicyPath, allowGeneratedAccount });
|
|
39
|
+
const obs = await observeScreen(sessions, session, driver);
|
|
40
|
+
const plan = planFirstRun({ ...obs, screenSignature: obs.screenSignature, appError: obs.appError }, session, { policy, decision });
|
|
41
|
+
const summary = `š first-run plan ā screen: ${plan.classification.purpose} (confidence ${plan.classification.confidence})\n` +
|
|
42
|
+
`environment: ${environment.environment} (prodRisk=${environment.productionRisk}); generated account ${decision.allowed ? 'ALLOWED' : 'NOT allowed'} ā ${decision.reason}\n` +
|
|
43
|
+
`state: ${plan.state}${plan.pathTaken ? ` [${plan.pathTaken}]` : ''}; planned actions: ${plan.actions.length}` +
|
|
44
|
+
(plan.needsInput ? `\nā ${plan.needsInput.reason}` : '') +
|
|
45
|
+
`\nā execute with qa_first_run_continue { sessionId:"${session.id}", mode:"one_step" }`;
|
|
46
|
+
return qaOk({
|
|
47
|
+
sessionId: session.id,
|
|
48
|
+
classification: plan.classification,
|
|
49
|
+
state: plan.state,
|
|
50
|
+
pathTaken: plan.pathTaken,
|
|
51
|
+
actions: plan.actions, // no raw values ā secrets stay in the secure store
|
|
52
|
+
expectedNextPurposes: plan.expectedNextPurposes,
|
|
53
|
+
stopConditions: plan.stopConditions,
|
|
54
|
+
appMapPatch: plan.mapUpdates,
|
|
55
|
+
environment,
|
|
56
|
+
generatedAccountDecision: decision,
|
|
57
|
+
policySource,
|
|
58
|
+
needsInput: plan.needsInput ?? null,
|
|
59
|
+
nextRecommendedTool: plan.nextRecommendedTool ?? 'qa_first_run_continue',
|
|
60
|
+
evidence: obs.screenshotUri ? [obs.screenshotUri] : [],
|
|
61
|
+
}, summary);
|
|
62
|
+
});
|
|
63
|
+
// ---- qa_first_run_continue (executes) ----
|
|
64
|
+
server.registerTool('qa_first_run_continue', {
|
|
65
|
+
title: 'First-run continue (execute)',
|
|
66
|
+
description: 'Executes the first-run plan as a practical QA engineer: classifies each screen and, in a TEST/STAGING environment, safely fills login/create-account forms with generated data (email swipium_<timestamp>@yopmail.com + a strong password stored as a secret), moves through onboarding via safe Next/Continue/Skip, records paywall coverage WITHOUT purchasing, and hands permission prompts to the guardrails. mode: one_step (one screen) | until_gate (until a paywall/OTP/permission gate) | until_home (until home/feature). Refuses automatic account creation in unknown/production-like environments and returns ONE NeedsInput question instead. Stops with NeedsInput on OTP/verification. Returns screen classifications, generated variables (secrets redacted), actions attempted, the resulting state, an appMapPatch, evidence URIs, and the next recommended tool. Requires a prepared device.',
|
|
67
|
+
inputSchema: {
|
|
68
|
+
sessionId: z.string(),
|
|
69
|
+
mode: z.enum(['one_step', 'until_gate', 'until_home']).optional().describe('one_step (default): one screen; until_gate: until a paywall/OTP/permission gate; until_home: until home/feature.'),
|
|
70
|
+
allowGeneratedAccount: z.boolean().optional().describe('Override the policy decision on creating a throwaway account.'),
|
|
71
|
+
testDataPolicyPath: z.string().optional().describe('Path to a test-data policy JSON (default .swipium/test-data-policy.json).'),
|
|
72
|
+
maxSteps: z.number().optional(),
|
|
73
|
+
maxDurationMs: z.number().optional(),
|
|
74
|
+
},
|
|
75
|
+
}, async ({ sessionId, mode, allowGeneratedAccount, testDataPolicyPath, maxSteps, maxDurationMs }) => {
|
|
76
|
+
const session = sessions.get(sessionId);
|
|
77
|
+
if (!session)
|
|
78
|
+
return qaError({ what: `Unknown sessionId ${sessionId}`, changedState: false, retrySafe: true, nextSteps: ['Call qa_start_session first.'] });
|
|
79
|
+
const { driver } = await getDriver(session);
|
|
80
|
+
if (!driver)
|
|
81
|
+
return qaError({ what: 'No device attached to this session', changedState: false, retrySafe: true, nextSteps: ['Prepare a device first: qa_test_this { mode:"execute" } or qa_prepare_target, then qa_first_run_continue.'] });
|
|
82
|
+
const res = await runFirstRun(sessions, session, driver, {
|
|
83
|
+
mode: (mode ?? 'one_step'),
|
|
84
|
+
allowGeneratedAccount, testDataPolicyPath, maxSteps, maxDurationMs,
|
|
85
|
+
});
|
|
86
|
+
// Fix Group 5: fold first-run classifications into the durable app map (not just a detached
|
|
87
|
+
// artifact) so a runtime login/onboarding/paywall screen updates .swipium/app-map.json.
|
|
88
|
+
let appMapUri;
|
|
89
|
+
if (res.mapUpdates.length) {
|
|
90
|
+
try {
|
|
91
|
+
const { buildAppMap } = await import('../appMap/build.js');
|
|
92
|
+
const built = buildAppMap(session.root, { mode: 'runtime_merge', at: new Date().toISOString(), sessionId: session.id, firstRunPatches: res.mapUpdates, persist: true });
|
|
93
|
+
appMapUri = built.save?.resourceUri;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* best-effort: the forward-compatible artifact still carries the patches */
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const payload = {
|
|
100
|
+
sessionId: session.id,
|
|
101
|
+
state: res.state,
|
|
102
|
+
stoppedReason: res.stoppedReason,
|
|
103
|
+
steps: res.steps,
|
|
104
|
+
classifications: res.steps.map((s) => ({ purpose: s.purpose, confidence: s.confidence, state: s.state, screenSignature: s.screenSignature })),
|
|
105
|
+
environment: res.environment,
|
|
106
|
+
generatedAccountDecision: res.decision,
|
|
107
|
+
policySource: res.policySource,
|
|
108
|
+
generatedVariables: res.generatedVariables, // secrets already redacted
|
|
109
|
+
appMapPatch: res.mapUpdates,
|
|
110
|
+
appMapArtifactUri: res.mapArtifactUri ?? null,
|
|
111
|
+
appMapUri: appMapUri ?? null,
|
|
112
|
+
evidence: res.evidenceUris,
|
|
113
|
+
pathTaken: res.pathTaken,
|
|
114
|
+
accountOutcome: res.accountOutcome,
|
|
115
|
+
nextRecommendedTool: res.nextRecommendedTool ?? null,
|
|
116
|
+
needsInput: res.needsInput ?? null,
|
|
117
|
+
};
|
|
118
|
+
const summary = `š¦ first-run ${res.state} ā ${res.steps.length} screen(s); path: ${res.pathTaken}; account: ${res.accountOutcome}\n` +
|
|
119
|
+
`environment: ${res.environment.environment} (prodRisk=${res.environment.productionRisk}); generated account ${res.decision.allowed ? 'allowed' : 'refused'}\n` +
|
|
120
|
+
`reason: ${res.stoppedReason}` +
|
|
121
|
+
(res.generatedVariables.length ? `\ngenerated: ${res.generatedVariables.map((g) => `${g.varName}=${g.value}`).join(', ')}` : '') +
|
|
122
|
+
(res.mapArtifactUri ? `\napp-map: ${res.mapArtifactUri}` : '') +
|
|
123
|
+
(res.nextRecommendedTool ? `\nā next: ${res.nextRecommendedTool}` : '');
|
|
124
|
+
// A genuine pause ā surface the single NeedsInput question (not an error).
|
|
125
|
+
if ((res.state === 'needs_input' || res.state === 'unsafe') && res.needsInput) {
|
|
126
|
+
return qaNeedsInput(needsInputPayload(res.needsInput.kind, res.needsInput.reason), {
|
|
127
|
+
sessionId: session.id,
|
|
128
|
+
state: res.state,
|
|
129
|
+
attempted: res.steps.map((s) => `classified "${s.purpose}" (confidence ${s.confidence})`),
|
|
130
|
+
firstRun: payload,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return qaOk(payload, summary);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=firstRun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firstRun.js","sourceRoot":"","sources":["../../src/tools/firstRun.ts"],"names":[],"mappings":"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"}
|