agent-scenario-loop 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/app/profile-session.ts +812 -0
  4. package/core/config-template.json +41 -0
  5. package/dist/core/agent-summary.d.ts +15 -0
  6. package/dist/core/agent-summary.js +177 -0
  7. package/dist/core/artifact-contract.d.ts +151 -0
  8. package/dist/core/artifact-contract.js +897 -0
  9. package/dist/core/artifact-layout.d.ts +56 -0
  10. package/dist/core/artifact-layout.js +61 -0
  11. package/dist/core/artifact-writer.d.ts +44 -0
  12. package/dist/core/artifact-writer.js +55 -0
  13. package/dist/core/comparison.d.ts +133 -0
  14. package/dist/core/comparison.js +294 -0
  15. package/dist/core/evidence-interpreter.d.ts +28 -0
  16. package/dist/core/evidence-interpreter.js +69 -0
  17. package/dist/core/execution-plan.d.ts +44 -0
  18. package/dist/core/execution-plan.js +95 -0
  19. package/dist/core/planner.d.ts +132 -0
  20. package/dist/core/planner.js +812 -0
  21. package/dist/core/ports.d.ts +198 -0
  22. package/dist/core/ports.js +146 -0
  23. package/dist/core/run-index.d.ts +62 -0
  24. package/dist/core/run-index.js +143 -0
  25. package/dist/core/schema-validator.d.ts +86 -0
  26. package/dist/core/schema-validator.js +407 -0
  27. package/dist/index.d.ts +11 -0
  28. package/dist/index.js +27 -0
  29. package/dist/runner/agent-device-driver.d.ts +126 -0
  30. package/dist/runner/agent-device-driver.js +168 -0
  31. package/dist/runner/agent-device.d.ts +295 -0
  32. package/dist/runner/agent-device.js +1271 -0
  33. package/dist/runner/android-adb-driver.d.ts +175 -0
  34. package/dist/runner/android-adb-driver.js +399 -0
  35. package/dist/runner/android-adb.d.ts +254 -0
  36. package/dist/runner/android-adb.js +1618 -0
  37. package/dist/runner/argent-driver.d.ts +183 -0
  38. package/dist/runner/argent-driver.js +297 -0
  39. package/dist/runner/argent.d.ts +349 -0
  40. package/dist/runner/argent.js +1211 -0
  41. package/dist/runner/check-plan.d.ts +45 -0
  42. package/dist/runner/check-plan.js +210 -0
  43. package/dist/runner/cli.d.ts +20 -0
  44. package/dist/runner/cli.js +23 -0
  45. package/dist/runner/compare-latest.d.ts +99 -0
  46. package/dist/runner/compare-latest.js +233 -0
  47. package/dist/runner/compare.d.ts +58 -0
  48. package/dist/runner/compare.js +157 -0
  49. package/dist/runner/demo-loop.d.ts +45 -0
  50. package/dist/runner/demo-loop.js +170 -0
  51. package/dist/runner/example-android-live.d.ts +137 -0
  52. package/dist/runner/example-android-live.js +454 -0
  53. package/dist/runner/example-ios-live.d.ts +137 -0
  54. package/dist/runner/example-ios-live.js +471 -0
  55. package/dist/runner/host-doctor.d.ts +131 -0
  56. package/dist/runner/host-doctor.js +628 -0
  57. package/dist/runner/init-project.d.ts +88 -0
  58. package/dist/runner/init-project.js +263 -0
  59. package/dist/runner/ios-simctl-driver.d.ts +69 -0
  60. package/dist/runner/ios-simctl-driver.js +97 -0
  61. package/dist/runner/ios-simctl.d.ts +254 -0
  62. package/dist/runner/ios-simctl.js +1415 -0
  63. package/dist/runner/live-android.d.ts +137 -0
  64. package/dist/runner/live-android.js +539 -0
  65. package/dist/runner/live-comparison.d.ts +67 -0
  66. package/dist/runner/live-comparison.js +147 -0
  67. package/dist/runner/live-ios.d.ts +137 -0
  68. package/dist/runner/live-ios.js +460 -0
  69. package/dist/runner/live-proof-summary.d.ts +263 -0
  70. package/dist/runner/live-proof-summary.js +465 -0
  71. package/dist/runner/live-proof.d.ts +467 -0
  72. package/dist/runner/live-proof.js +920 -0
  73. package/dist/runner/local-env.d.ts +64 -0
  74. package/dist/runner/local-env.js +155 -0
  75. package/dist/runner/profile-android.d.ts +82 -0
  76. package/dist/runner/profile-android.js +671 -0
  77. package/dist/runner/profile-ios.d.ts +108 -0
  78. package/dist/runner/profile-ios.js +532 -0
  79. package/dist/runner/profile-mobile.d.ts +254 -0
  80. package/dist/runner/profile-mobile.js +1307 -0
  81. package/dist/runner/validate-project.d.ts +273 -0
  82. package/dist/runner/validate-project.js +1501 -0
  83. package/docs/adapters.md +145 -0
  84. package/docs/api.md +94 -0
  85. package/docs/authoring.md +196 -0
  86. package/docs/concepts.md +136 -0
  87. package/docs/consumer-rehearsal.md +115 -0
  88. package/docs/contracts.md +267 -0
  89. package/docs/live-proofs.md +270 -0
  90. package/docs/principles.md +46 -0
  91. package/examples/event-logs/app-startup-baseline.log +4 -0
  92. package/examples/event-logs/app-startup-current.log +4 -0
  93. package/examples/minimal-app/README.md +70 -0
  94. package/examples/mobile-app/README.md +302 -0
  95. package/examples/mobile-app/app.json +22 -0
  96. package/examples/mobile-app/asl/package-scripts.json +32 -0
  97. package/examples/mobile-app/asl.config.json +37 -0
  98. package/examples/mobile-app/event-logs/android-app-startup.log +4 -0
  99. package/examples/mobile-app/event-logs/android-open-close-cycle.log +12 -0
  100. package/examples/mobile-app/event-logs/android-scroll-settle.log +12 -0
  101. package/examples/mobile-app/event-logs/app-startup.log +4 -0
  102. package/examples/mobile-app/event-logs/open-close-cycle.log +12 -0
  103. package/examples/mobile-app/event-logs/scroll-settle.log +12 -0
  104. package/examples/mobile-app/index.ts +20 -0
  105. package/examples/mobile-app/metro.config.js +20 -0
  106. package/examples/mobile-app/package.json +62 -0
  107. package/examples/mobile-app/patches/expo-modules-jsi@56.0.10.patch +19 -0
  108. package/examples/mobile-app/plugins/with-ios-build-compat.js +271 -0
  109. package/examples/mobile-app/pnpm-lock.yaml +4440 -0
  110. package/examples/mobile-app/runner-manifests/evidence-provider.json +79 -0
  111. package/examples/mobile-app/runner-manifests/primary-runner.json +19 -0
  112. package/examples/mobile-app/scenarios/android/app-startup-video.json +73 -0
  113. package/examples/mobile-app/scenarios/android/app-startup.json +44 -0
  114. package/examples/mobile-app/scenarios/android/open-close-cycle.json +54 -0
  115. package/examples/mobile-app/scenarios/android/scroll-settle.json +49 -0
  116. package/examples/mobile-app/scenarios/ios/app-startup.json +44 -0
  117. package/examples/mobile-app/scenarios/ios/open-close-cycle.json +54 -0
  118. package/examples/mobile-app/scenarios/ios/scroll-settle.json +49 -0
  119. package/examples/mobile-app/scenarios/mobile/app-startup.json +91 -0
  120. package/examples/mobile-app/scenarios/mobile/open-close-cycle.json +160 -0
  121. package/examples/mobile-app/scenarios/mobile/scroll-settle.json +148 -0
  122. package/examples/mobile-app/scripts/asl-capture-accessibility-provider.mjs +112 -0
  123. package/examples/mobile-app/scripts/asl-capture-profiler-provider.mjs +127 -0
  124. package/examples/mobile-app/src/devtools/profile-session.ts +7 -0
  125. package/examples/mobile-app/src/example-screen.tsx +322 -0
  126. package/examples/mobile-app/tsconfig.json +16 -0
  127. package/examples/mobile-app/tsconfig.typecheck.json +13 -0
  128. package/examples/runners/README.md +44 -0
  129. package/examples/runners/adb-android.json +25 -0
  130. package/examples/runners/agent-device-android.json +27 -0
  131. package/examples/runners/agent-device-ios.json +27 -0
  132. package/examples/runners/argent-android.json +32 -0
  133. package/examples/runners/argent-ios.json +32 -0
  134. package/examples/runners/argent-react-profiler-provider.json +15 -0
  135. package/examples/runners/axe-accessibility-provider.json +24 -0
  136. package/examples/runners/manual-log-ingest.json +9 -0
  137. package/examples/runners/rozenite-profiler-provider.json +9 -0
  138. package/examples/runners/script-accessibility-provider.json +24 -0
  139. package/examples/runners/script-memory-provider.json +24 -0
  140. package/examples/runners/script-network-provider.json +24 -0
  141. package/examples/runners/script-profiler-provider.json +30 -0
  142. package/examples/runners/xcodebuildmcp-ios.json +29 -0
  143. package/examples/scenarios/ios/app-startup.json +28 -0
  144. package/examples/scenarios/ios/open-close-cycle.json +35 -0
  145. package/examples/scenarios/mobile/app-startup.json +72 -0
  146. package/examples/scenarios/mobile/media-open-close.json +141 -0
  147. package/examples/scenarios/mobile/open-close-cycle.json +135 -0
  148. package/examples/scenarios/mobile/scroll-settle.json +106 -0
  149. package/package.json +240 -0
  150. package/schemas/budget-verdict.schema.json +115 -0
  151. package/schemas/causal-run.schema.json +279 -0
  152. package/schemas/comparison.schema.json +196 -0
  153. package/schemas/health.schema.json +108 -0
  154. package/schemas/live-proof-set.schema.json +195 -0
  155. package/schemas/live-proof.schema.json +413 -0
  156. package/schemas/manifest.schema.json +204 -0
  157. package/schemas/metrics.schema.json +137 -0
  158. package/schemas/project-validation.schema.json +343 -0
  159. package/schemas/runner-capabilities.schema.json +217 -0
  160. package/schemas/scenario.schema.json +400 -0
  161. package/schemas/verdict.schema.json +88 -0
  162. package/templates/evidence-provider.json +83 -0
  163. package/templates/gitignore-snippet +9 -0
  164. package/templates/integration-readme.md +125 -0
  165. package/templates/mobile-scenario.json +133 -0
  166. package/templates/package-scripts.json +32 -0
  167. package/templates/primary-runner.json +19 -0
  168. package/templates/project.config.json +37 -0
  169. package/templates/scripts/asl-capture-accessibility-provider.mjs +112 -0
  170. package/templates/scripts/asl-capture-profiler-provider.mjs +127 -0
@@ -0,0 +1,64 @@
1
+ type LocalEnvLoadOptions = {
2
+ cwd?: string;
3
+ env?: NodeJS.ProcessEnv;
4
+ fileName?: string;
5
+ override?: boolean;
6
+ };
7
+ type LoadedLocalEnvFile = {
8
+ filePath: string;
9
+ keys: string[];
10
+ };
11
+ declare const LOCAL_ENV_FILE_NAME = ".asl.local.env";
12
+ /**
13
+ * Finds the nearest ASL local env file from a working directory upward.
14
+ *
15
+ * @param {string} cwd
16
+ * @param {string} fileName
17
+ * @returns {string | null}
18
+ */
19
+ declare function findNearestLocalEnvFile(cwd?: string, fileName?: string): string | null;
20
+ /**
21
+ * Parses one simple KEY=value line from an ASL local env file.
22
+ *
23
+ * @param {string} line
24
+ * @returns {{key: string, value: string} | null}
25
+ */
26
+ declare function parseLocalEnvLine(line: string): {
27
+ key: string;
28
+ value: string;
29
+ } | null;
30
+ /**
31
+ * Loads `.asl.local.env` into the provided environment without overriding explicit values.
32
+ *
33
+ * @param {LocalEnvLoadOptions} options
34
+ * @returns {LoadedLocalEnvFile | null}
35
+ */
36
+ declare function loadAslLocalEnv({ cwd, env, fileName, override, }?: LocalEnvLoadOptions): LoadedLocalEnvFile | null;
37
+ /**
38
+ * Reads the first non-empty environment value for a list of supported names.
39
+ *
40
+ * @param {string[]} names
41
+ * @param {NodeJS.ProcessEnv} env
42
+ * @returns {string | undefined}
43
+ */
44
+ declare function readEnvValue(names: string[], env?: NodeJS.ProcessEnv): string | undefined;
45
+ /**
46
+ * Reads a CLI value first, then falls back to environment names.
47
+ *
48
+ * @param {unknown} value
49
+ * @param {string[]} envNames
50
+ * @param {NodeJS.ProcessEnv} env
51
+ * @returns {string | undefined}
52
+ */
53
+ declare function readStringArgOrEnv(value: unknown, envNames: string[], env?: NodeJS.ProcessEnv): string | undefined;
54
+ /**
55
+ * Returns true when a CLI flag or environment value enables an option.
56
+ *
57
+ * @param {unknown} value
58
+ * @param {string[]} envNames
59
+ * @param {NodeJS.ProcessEnv} env
60
+ * @returns {boolean}
61
+ */
62
+ declare function readBooleanArgOrEnv(value: unknown, envNames: string[], env?: NodeJS.ProcessEnv): boolean;
63
+ export { LOCAL_ENV_FILE_NAME, findNearestLocalEnvFile, loadAslLocalEnv, parseLocalEnvLine, readBooleanArgOrEnv, readEnvValue, readStringArgOrEnv, };
64
+ export type { LoadedLocalEnvFile, LocalEnvLoadOptions, };
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LOCAL_ENV_FILE_NAME = void 0;
4
+ exports.findNearestLocalEnvFile = findNearestLocalEnvFile;
5
+ exports.loadAslLocalEnv = loadAslLocalEnv;
6
+ exports.parseLocalEnvLine = parseLocalEnvLine;
7
+ exports.readBooleanArgOrEnv = readBooleanArgOrEnv;
8
+ exports.readEnvValue = readEnvValue;
9
+ exports.readStringArgOrEnv = readStringArgOrEnv;
10
+ const fs = require('node:fs');
11
+ const path = require('node:path');
12
+ const LOCAL_ENV_FILE_NAME = '.asl.local.env';
13
+ exports.LOCAL_ENV_FILE_NAME = LOCAL_ENV_FILE_NAME;
14
+ const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/u;
15
+ /**
16
+ * Finds the nearest ASL local env file from a working directory upward.
17
+ *
18
+ * @param {string} cwd
19
+ * @param {string} fileName
20
+ * @returns {string | null}
21
+ */
22
+ function findNearestLocalEnvFile(cwd = process.cwd(), fileName = LOCAL_ENV_FILE_NAME) {
23
+ let current = path.resolve(cwd);
24
+ while (true) {
25
+ const candidate = path.join(current, fileName);
26
+ try {
27
+ if (fs.statSync(candidate).isFile()) {
28
+ return candidate;
29
+ }
30
+ }
31
+ catch {
32
+ // Missing local env files are expected on CI and fresh installs.
33
+ }
34
+ const parent = path.dirname(current);
35
+ if (parent === current) {
36
+ return null;
37
+ }
38
+ current = parent;
39
+ }
40
+ }
41
+ /**
42
+ * Removes matching single or double quotes from an env file value.
43
+ *
44
+ * @param {string} value
45
+ * @returns {string}
46
+ */
47
+ function unquoteEnvValue(value) {
48
+ const trimmed = value.trim();
49
+ if (trimmed.length >= 2) {
50
+ const first = trimmed[0];
51
+ const last = trimmed[trimmed.length - 1];
52
+ if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
53
+ return trimmed.slice(1, -1);
54
+ }
55
+ }
56
+ return trimmed;
57
+ }
58
+ /**
59
+ * Parses one simple KEY=value line from an ASL local env file.
60
+ *
61
+ * @param {string} line
62
+ * @returns {{key: string, value: string} | null}
63
+ */
64
+ function parseLocalEnvLine(line) {
65
+ const trimmed = line.trim();
66
+ if (!trimmed || trimmed.startsWith('#')) {
67
+ return null;
68
+ }
69
+ const exportPrefix = 'export ';
70
+ const assignment = trimmed.startsWith(exportPrefix)
71
+ ? trimmed.slice(exportPrefix.length).trim()
72
+ : trimmed;
73
+ const equalsIndex = assignment.indexOf('=');
74
+ if (equalsIndex <= 0) {
75
+ return null;
76
+ }
77
+ const key = assignment.slice(0, equalsIndex).trim();
78
+ if (!ENV_KEY_PATTERN.test(key)) {
79
+ return null;
80
+ }
81
+ return {
82
+ key,
83
+ value: unquoteEnvValue(assignment.slice(equalsIndex + 1)),
84
+ };
85
+ }
86
+ /**
87
+ * Loads `.asl.local.env` into the provided environment without overriding explicit values.
88
+ *
89
+ * @param {LocalEnvLoadOptions} options
90
+ * @returns {LoadedLocalEnvFile | null}
91
+ */
92
+ function loadAslLocalEnv({ cwd = process.cwd(), env = process.env, fileName = LOCAL_ENV_FILE_NAME, override = false, } = {}) {
93
+ const filePath = findNearestLocalEnvFile(cwd, fileName);
94
+ if (!filePath) {
95
+ return null;
96
+ }
97
+ const keys = [];
98
+ const content = fs.readFileSync(filePath, 'utf8');
99
+ for (const line of content.split(/\r?\n/u)) {
100
+ const parsed = parseLocalEnvLine(line);
101
+ if (!parsed) {
102
+ continue;
103
+ }
104
+ if (!override && Object.prototype.hasOwnProperty.call(env, parsed.key)) {
105
+ continue;
106
+ }
107
+ env[parsed.key] = parsed.value;
108
+ keys.push(parsed.key);
109
+ }
110
+ return { filePath, keys };
111
+ }
112
+ /**
113
+ * Reads the first non-empty environment value for a list of supported names.
114
+ *
115
+ * @param {string[]} names
116
+ * @param {NodeJS.ProcessEnv} env
117
+ * @returns {string | undefined}
118
+ */
119
+ function readEnvValue(names, env = process.env) {
120
+ for (const name of names) {
121
+ const value = env[name];
122
+ if (typeof value === 'string' && value.length > 0) {
123
+ return value;
124
+ }
125
+ }
126
+ return undefined;
127
+ }
128
+ /**
129
+ * Reads a CLI value first, then falls back to environment names.
130
+ *
131
+ * @param {unknown} value
132
+ * @param {string[]} envNames
133
+ * @param {NodeJS.ProcessEnv} env
134
+ * @returns {string | undefined}
135
+ */
136
+ function readStringArgOrEnv(value, envNames, env = process.env) {
137
+ return typeof value === 'string' && value.length > 0
138
+ ? value
139
+ : readEnvValue(envNames, env);
140
+ }
141
+ /**
142
+ * Returns true when a CLI flag or environment value enables an option.
143
+ *
144
+ * @param {unknown} value
145
+ * @param {string[]} envNames
146
+ * @param {NodeJS.ProcessEnv} env
147
+ * @returns {boolean}
148
+ */
149
+ function readBooleanArgOrEnv(value, envNames, env = process.env) {
150
+ if (value === true || value === 'true' || value === '1') {
151
+ return true;
152
+ }
153
+ const envValue = readEnvValue(envNames, env);
154
+ return envValue === '1' || envValue === 'true' || envValue === 'yes';
155
+ }
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ declare const parseArgs: any, usage: any;
3
+ type AndroidProfileOptions = {
4
+ agentDeviceExecutor?: import('./agent-device').CommandExecutor;
5
+ comparisonLane?: string;
6
+ delay?: (ms: number) => Promise<void>;
7
+ executor?: import('./android-adb').CommandExecutor;
8
+ };
9
+ type AndroidAdbProfileCommand = {
10
+ command: string;
11
+ label?: string;
12
+ waitMs?: number;
13
+ };
14
+ type AndroidAdbDriverStep = import('./android-adb').AndroidAdbDriverStep;
15
+ /**
16
+ * Derives a logcat-backed profile capture window from scenario waits and cycles.
17
+ *
18
+ * @param {Record<string, unknown>} scenario
19
+ * @returns {number}
20
+ */
21
+ declare function deriveProfileSessionCaptureWaitMs(scenario: Record<string, any>): number;
22
+ /**
23
+ * Resolves the Android adb capture wait, keeping explicit CLI waits authoritative.
24
+ *
25
+ * @param {{args: import('./profile-mobile').CliArgs, scenario: Record<string, unknown>, profileSessionEnabled: boolean}} options
26
+ * @returns {number}
27
+ */
28
+ declare function resolveProfileSessionCaptureWaitMs({ args, profileSessionEnabled, scenario, }: {
29
+ args: import('./profile-mobile').CliArgs;
30
+ profileSessionEnabled: boolean;
31
+ scenario: Record<string, any>;
32
+ }): number;
33
+ /**
34
+ * Expands normalized scenario evidence steps into Android adb driver actions.
35
+ *
36
+ * @param {Record<string, unknown>} scenario
37
+ * @returns {import('./android-adb').AndroidAdbDriverStep[]}
38
+ */
39
+ declare function resolveAndroidAdbDriverSteps(scenario: Record<string, any>): AndroidAdbDriverStep[];
40
+ /**
41
+ * Reads the first video capture produced by adb driver actions.
42
+ *
43
+ * @param {Record<string, unknown>} metadata
44
+ * @returns {string | null}
45
+ */
46
+ declare function readAndroidAdbVideoCapturePath(metadata: Record<string, unknown>): string | null;
47
+ /**
48
+ * Returns profile-time validation errors for adb driver steps.
49
+ *
50
+ * @param {import('./android-adb').AndroidAdbDriverStep[]} driverSteps
51
+ * @returns {string[]}
52
+ */
53
+ declare function validateAndroidAdbDriverSteps(driverSteps: AndroidAdbDriverStep[]): string[];
54
+ /**
55
+ * Expands scenario-declared Android commands for an adb capture profile session.
56
+ *
57
+ * @param {Record<string, unknown>} scenario
58
+ * @returns {AndroidAdbProfileCommand[]}
59
+ */
60
+ declare function resolveAndroidAdbProfileCommands(scenario: Record<string, any>): AndroidAdbProfileCommand[];
61
+ /**
62
+ * Summarizes failed adb capture checks for CLI errors.
63
+ *
64
+ * @param {Record<string, unknown>} health
65
+ * @returns {string}
66
+ */
67
+ declare function summarizeFailedAndroidChecks(health: Record<string, unknown>): string;
68
+ /**
69
+ * Runs the Android profile artifact pipeline.
70
+ *
71
+ * @param {import('./profile-mobile').CliArgs} args
72
+ * @param {AndroidProfileOptions} [options]
73
+ * @returns {Promise<import('./profile-mobile').ProfileRunResult>}
74
+ */
75
+ declare function runProfileAndroid(args: import('./profile-mobile').CliArgs, options?: AndroidProfileOptions): Promise<import('./profile-mobile').ProfileRunResult>;
76
+ /**
77
+ * Runs the profile-android CLI.
78
+ *
79
+ * @returns {Promise<void>}
80
+ */
81
+ declare function main(): Promise<void>;
82
+ export { deriveProfileSessionCaptureWaitMs, main, parseArgs, resolveAndroidAdbProfileCommands, resolveAndroidAdbDriverSteps, resolveProfileSessionCaptureWaitMs, readAndroidAdbVideoCapturePath, validateAndroidAdbDriverSteps, runProfileAndroid, summarizeFailedAndroidChecks, usage, };