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,160 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "id": "open-close-cycle",
4
+ "flowId": "example-card-open-close",
5
+ "description": "Open and dismiss the example app detail card repeatedly from one portable scenario.",
6
+ "journey": {
7
+ "name": "Example card open and close",
8
+ "intent": "Open a stable example card, prove it rendered, dismiss it, and prove the app returned to the list.",
9
+ "actor": "mobile app user",
10
+ "startState": "example app home screen ready",
11
+ "endState": "example card dismissed"
12
+ },
13
+ "platforms": ["ios", "android"],
14
+ "requiredCapabilities": ["launch", "sessionControl", "command", "logCapture", "artifactWrite"],
15
+ "optionalCapabilities": ["screenshot", "video", "uiTree"],
16
+ "truthEvents": {
17
+ "openRequested": {
18
+ "event": "card_open_requested",
19
+ "required": true,
20
+ "phase": "intent"
21
+ },
22
+ "opened": {
23
+ "event": "card_opened",
24
+ "required": true,
25
+ "timeoutMs": 2500,
26
+ "phase": "visual"
27
+ },
28
+ "closeRequested": {
29
+ "event": "card_close_requested",
30
+ "required": true,
31
+ "phase": "intent"
32
+ },
33
+ "dismissed": {
34
+ "event": "card_dismissed",
35
+ "required": true,
36
+ "timeoutMs": 2500,
37
+ "phase": "completion"
38
+ }
39
+ },
40
+ "milestones": [
41
+ {
42
+ "id": "openRequested",
43
+ "event": "card_open_requested",
44
+ "description": "The app received the command to open the first example card.",
45
+ "required": true,
46
+ "phase": "intent"
47
+ },
48
+ {
49
+ "id": "opened",
50
+ "event": "card_opened",
51
+ "description": "The first example card became visible.",
52
+ "required": true,
53
+ "timeoutMs": 2500,
54
+ "phase": "visual"
55
+ },
56
+ {
57
+ "id": "closeRequested",
58
+ "event": "card_close_requested",
59
+ "description": "The app received the command to close the example card.",
60
+ "required": true,
61
+ "phase": "intent"
62
+ },
63
+ {
64
+ "id": "dismissed",
65
+ "event": "card_dismissed",
66
+ "description": "The example card was dismissed cleanly.",
67
+ "required": true,
68
+ "timeoutMs": 2500,
69
+ "phase": "completion"
70
+ }
71
+ ],
72
+ "expectedEvents": [
73
+ "card_open_requested",
74
+ "card_opened",
75
+ "card_close_requested",
76
+ "card_dismissed"
77
+ ],
78
+ "cycles": {
79
+ "iterations": 3,
80
+ "warmupIterations": 0,
81
+ "stopOnFailure": true
82
+ },
83
+ "budgets": [
84
+ {
85
+ "name": "open close cycle p95",
86
+ "source": "milestone",
87
+ "metric": "p95",
88
+ "unit": "ms",
89
+ "limit": 1350,
90
+ "fromMilestone": "openRequested",
91
+ "toMilestone": "dismissed"
92
+ },
93
+ {
94
+ "name": "open p95",
95
+ "source": "milestone",
96
+ "metric": "p95",
97
+ "unit": "ms",
98
+ "limit": 650,
99
+ "fromMilestone": "openRequested",
100
+ "toMilestone": "opened"
101
+ },
102
+ {
103
+ "name": "close p95",
104
+ "source": "milestone",
105
+ "metric": "p95",
106
+ "unit": "ms",
107
+ "limit": 500,
108
+ "fromMilestone": "closeRequested",
109
+ "toMilestone": "dismissed"
110
+ }
111
+ ],
112
+ "steps": [
113
+ {
114
+ "id": "launch",
115
+ "kind": "launch"
116
+ },
117
+ {
118
+ "id": "open-example-card",
119
+ "kind": "command",
120
+ "command": "activate-target:example-card-1",
121
+ "adapterOptions": {
122
+ "androidAdb": {
123
+ "waitMs": 300
124
+ },
125
+ "iosSimctl": {
126
+ "waitMs": 300
127
+ }
128
+ }
129
+ },
130
+ {
131
+ "id": "wait-card-opened",
132
+ "kind": "waitForMilestone",
133
+ "milestone": "opened",
134
+ "timeoutMs": 2500
135
+ },
136
+ {
137
+ "id": "close-example-card",
138
+ "kind": "command",
139
+ "command": "activate-target:close-card",
140
+ "adapterOptions": {
141
+ "androidAdb": {
142
+ "waitMs": 300
143
+ },
144
+ "iosSimctl": {
145
+ "waitMs": 300
146
+ }
147
+ }
148
+ },
149
+ {
150
+ "id": "wait-card-dismissed",
151
+ "kind": "waitForMilestone",
152
+ "milestone": "dismissed",
153
+ "timeoutMs": 2500
154
+ }
155
+ ],
156
+ "artifacts": {
157
+ "required": ["logs", "signals"],
158
+ "optional": ["screenshot", "video", "uiTree"]
159
+ }
160
+ }
@@ -0,0 +1,148 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "id": "scroll-settle",
4
+ "flowId": "example-feed-scroll",
5
+ "description": "Scroll the example feed and measure app-owned evidence until visible content settles.",
6
+ "journey": {
7
+ "name": "Example feed scroll settle",
8
+ "intent": "Trigger a deterministic feed scroll, prove content became visible, and prove the feed reached a settled state.",
9
+ "actor": "mobile app user",
10
+ "startState": "example app feed visible and idle",
11
+ "endState": "example app feed settled after scroll"
12
+ },
13
+ "platforms": ["ios", "android"],
14
+ "requiredCapabilities": ["launch", "sessionControl", "command", "logCapture", "artifactWrite"],
15
+ "optionalCapabilities": ["screenshot", "video", "uiTree", "profiler"],
16
+ "truthEvents": {
17
+ "openRequested": {
18
+ "event": "feed_scroll_started",
19
+ "required": true,
20
+ "phase": "intent"
21
+ },
22
+ "opened": {
23
+ "event": "feed_first_content_visible",
24
+ "required": true,
25
+ "timeoutMs": 2500,
26
+ "phase": "visual"
27
+ },
28
+ "closeRequested": {
29
+ "event": "feed_scroll_settle_requested",
30
+ "required": true,
31
+ "phase": "render"
32
+ },
33
+ "dismissed": {
34
+ "event": "feed_scroll_settled",
35
+ "required": true,
36
+ "timeoutMs": 2500,
37
+ "phase": "completion"
38
+ }
39
+ },
40
+ "milestones": [
41
+ {
42
+ "id": "openRequested",
43
+ "event": "feed_scroll_started",
44
+ "description": "The app started the deterministic feed scroll.",
45
+ "required": true,
46
+ "phase": "intent"
47
+ },
48
+ {
49
+ "id": "opened",
50
+ "event": "feed_first_content_visible",
51
+ "description": "The first target content became visible after scrolling.",
52
+ "required": true,
53
+ "timeoutMs": 2500,
54
+ "phase": "visual"
55
+ },
56
+ {
57
+ "id": "closeRequested",
58
+ "event": "feed_scroll_settle_requested",
59
+ "description": "The app requested a settled-state check for the feed.",
60
+ "required": true,
61
+ "phase": "render"
62
+ },
63
+ {
64
+ "id": "dismissed",
65
+ "event": "feed_scroll_settled",
66
+ "description": "The feed reached a stable settled state.",
67
+ "required": true,
68
+ "timeoutMs": 2500,
69
+ "phase": "completion"
70
+ }
71
+ ],
72
+ "expectedEvents": [
73
+ "feed_scroll_started",
74
+ "feed_first_content_visible",
75
+ "feed_scroll_settle_requested",
76
+ "feed_scroll_settled"
77
+ ],
78
+ "cycles": {
79
+ "iterations": 3,
80
+ "warmupIterations": 0,
81
+ "stopOnFailure": true
82
+ },
83
+ "budgets": [
84
+ {
85
+ "name": "scroll settle p95",
86
+ "source": "milestone",
87
+ "metric": "p95",
88
+ "unit": "ms",
89
+ "limit": 1050,
90
+ "fromMilestone": "openRequested",
91
+ "toMilestone": "dismissed"
92
+ },
93
+ {
94
+ "name": "first content visible p95",
95
+ "source": "milestone",
96
+ "metric": "p95",
97
+ "unit": "ms",
98
+ "limit": 500,
99
+ "fromMilestone": "openRequested",
100
+ "toMilestone": "opened"
101
+ },
102
+ {
103
+ "name": "settle completion p95",
104
+ "source": "milestone",
105
+ "metric": "p95",
106
+ "unit": "ms",
107
+ "limit": 350,
108
+ "fromMilestone": "closeRequested",
109
+ "toMilestone": "dismissed"
110
+ }
111
+ ],
112
+ "steps": [
113
+ {
114
+ "id": "launch",
115
+ "kind": "launch"
116
+ },
117
+ {
118
+ "id": "scroll-example-feed",
119
+ "kind": "command",
120
+ "command": "activate-target:scroll-feed",
121
+ "adapterOptions": {
122
+ "androidAdb": {
123
+ "waitMs": 300
124
+ },
125
+ "iosSimctl": {
126
+ "waitMs": 300
127
+ }
128
+ }
129
+ },
130
+ {
131
+ "id": "wait-feed-settled",
132
+ "kind": "waitForMilestone",
133
+ "milestone": "dismissed",
134
+ "timeoutMs": 2500
135
+ },
136
+ {
137
+ "id": "capture-final-screen",
138
+ "kind": "captureEvidence",
139
+ "artifact": "screenshot",
140
+ "driverAction": "screenshot",
141
+ "required": false
142
+ }
143
+ ],
144
+ "artifacts": {
145
+ "required": ["logs", "signals"],
146
+ "optional": ["screenshot", "video", "uiTree", "profiler"]
147
+ }
148
+ }
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+
6
+ /**
7
+ * Parses simple `--key value` CLI arguments.
8
+ *
9
+ * @param {string[]} argv
10
+ * @returns {Record<string, string | boolean>}
11
+ */
12
+ function parseArgs(argv) {
13
+ const args = {};
14
+ for (let index = 0; index < argv.length; index += 1) {
15
+ const token = argv[index];
16
+ if (!token?.startsWith('--')) {
17
+ continue;
18
+ }
19
+
20
+ const key = token.slice(2);
21
+ const value = argv[index + 1];
22
+ if (value && !value.startsWith('--')) {
23
+ args[key] = value;
24
+ index += 1;
25
+ } else {
26
+ args[key] = true;
27
+ }
28
+ }
29
+ return args;
30
+ }
31
+
32
+ /**
33
+ * Reads a required string CLI argument.
34
+ *
35
+ * @param {Record<string, string | boolean>} args
36
+ * @param {string} key
37
+ * @returns {string}
38
+ */
39
+ function requireStringArg(args, key) {
40
+ const value = args[key];
41
+ if (typeof value !== 'string' || value.length === 0) {
42
+ throw new Error(`Missing required --${key} value.`);
43
+ }
44
+ return value;
45
+ }
46
+
47
+ /**
48
+ * Writes a formatted JSON artifact.
49
+ *
50
+ * @param {string} outPath
51
+ * @param {Record<string, unknown>} payload
52
+ * @returns {void}
53
+ */
54
+ function writeJsonArtifact(outPath, payload) {
55
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
56
+ fs.writeFileSync(outPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
57
+ }
58
+
59
+ /**
60
+ * Writes deterministic accessibility evidence for the example-app provider command.
61
+ *
62
+ * @param {{outPath: string, platform: string, runId: string, scenarioId: string}} options
63
+ * @returns {void}
64
+ */
65
+ function writeAccessibilityEvidence({
66
+ outPath,
67
+ platform,
68
+ runId,
69
+ scenarioId,
70
+ }) {
71
+ writeJsonArtifact(outPath, {
72
+ checks: [
73
+ {
74
+ id: 'app-title-visible',
75
+ selector: {
76
+ kind: 'testId',
77
+ value: 'asl-example-title',
78
+ },
79
+ status: 'passed',
80
+ },
81
+ ],
82
+ platform,
83
+ providerId: 'example-mobile-app-evidence-provider',
84
+ runId,
85
+ scenarioId,
86
+ schemaVersion: '1.0.0',
87
+ summary: 'Deterministic example accessibility evidence for package and consumer rehearsal.',
88
+ violations: [],
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Runs the provider script.
94
+ *
95
+ * @returns {void}
96
+ */
97
+ function main() {
98
+ const args = parseArgs(process.argv.slice(2));
99
+ writeAccessibilityEvidence({
100
+ outPath: requireStringArg(args, 'out'),
101
+ platform: requireStringArg(args, 'platform'),
102
+ runId: requireStringArg(args, 'run-id'),
103
+ scenarioId: requireStringArg(args, 'scenario'),
104
+ });
105
+ }
106
+
107
+ try {
108
+ main();
109
+ } catch (error) {
110
+ console.error(error instanceof Error ? error.message : String(error));
111
+ process.exitCode = 1;
112
+ }
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+
6
+ /**
7
+ * Parses simple `--key value` CLI arguments.
8
+ *
9
+ * @param {string[]} argv
10
+ * @returns {Record<string, string | boolean>}
11
+ */
12
+ function parseArgs(argv) {
13
+ const args = {};
14
+ for (let index = 0; index < argv.length; index += 1) {
15
+ const token = argv[index];
16
+ if (!token?.startsWith('--')) {
17
+ continue;
18
+ }
19
+
20
+ const key = token.slice(2);
21
+ const value = argv[index + 1];
22
+ if (value && !value.startsWith('--')) {
23
+ args[key] = value;
24
+ index += 1;
25
+ } else {
26
+ args[key] = true;
27
+ }
28
+ }
29
+ return args;
30
+ }
31
+
32
+ /**
33
+ * Reads a required string CLI argument.
34
+ *
35
+ * @param {Record<string, string | boolean>} args
36
+ * @param {string} key
37
+ * @returns {string}
38
+ */
39
+ function requireStringArg(args, key) {
40
+ const value = args[key];
41
+ if (typeof value !== 'string' || value.length === 0) {
42
+ throw new Error(`Missing required --${key} value.`);
43
+ }
44
+ return value;
45
+ }
46
+
47
+ /**
48
+ * Writes a formatted JSON artifact.
49
+ *
50
+ * @param {string} outPath
51
+ * @param {Record<string, unknown>} payload
52
+ * @returns {void}
53
+ */
54
+ function writeJsonArtifact(outPath, payload) {
55
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
56
+ fs.writeFileSync(outPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
57
+ }
58
+
59
+ /**
60
+ * Writes deterministic evidence for the example-app provider command.
61
+ *
62
+ * @param {{memoryOutPath: string, networkOutPath: string, outPath: string, platform: string, runId: string, scenarioId: string}} options
63
+ * @returns {void}
64
+ */
65
+ function writeProviderEvidence({
66
+ memoryOutPath,
67
+ networkOutPath,
68
+ outPath,
69
+ platform,
70
+ runId,
71
+ scenarioId,
72
+ }) {
73
+ const shared = {
74
+ platform,
75
+ providerId: 'example-mobile-app-evidence-provider',
76
+ runId,
77
+ scenarioId,
78
+ schemaVersion: '1.0.0',
79
+ };
80
+
81
+ writeJsonArtifact(outPath, {
82
+ ...shared,
83
+ samples: [],
84
+ summary: 'Deterministic example profiler evidence for package and consumer rehearsal.',
85
+ });
86
+ writeJsonArtifact(memoryOutPath, {
87
+ ...shared,
88
+ jsHeapBytes: null,
89
+ nativeHeapBytes: null,
90
+ summary: 'Deterministic example memory signal for package and consumer rehearsal.',
91
+ });
92
+ writeJsonArtifact(networkOutPath, {
93
+ log: {
94
+ creator: {
95
+ name: 'agent-scenario-loop example provider',
96
+ version: '1.0.0',
97
+ },
98
+ entries: [],
99
+ version: '1.2',
100
+ },
101
+ ...shared,
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Runs the provider script.
107
+ *
108
+ * @returns {void}
109
+ */
110
+ function main() {
111
+ const args = parseArgs(process.argv.slice(2));
112
+ writeProviderEvidence({
113
+ memoryOutPath: requireStringArg(args, 'memory-out'),
114
+ networkOutPath: requireStringArg(args, 'network-out'),
115
+ outPath: requireStringArg(args, 'out'),
116
+ platform: requireStringArg(args, 'platform'),
117
+ runId: requireStringArg(args, 'run-id'),
118
+ scenarioId: requireStringArg(args, 'scenario'),
119
+ });
120
+ }
121
+
122
+ try {
123
+ main();
124
+ } catch (error) {
125
+ console.error(error instanceof Error ? error.message : String(error));
126
+ process.exitCode = 1;
127
+ }
@@ -0,0 +1,7 @@
1
+ export {
2
+ emitProfileEvent,
3
+ registerProfileCommandTargetHandler,
4
+ storeProfileSignal,
5
+ useProfileSession,
6
+ useProfileSessionBootstrap,
7
+ } from '../../../../app/profile-session';