mobile-debug-mcp 0.32.2 → 0.33.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/.agents/plugins/marketplace.json +20 -0
- package/{skills → .agents/skills}/mcp-builder/SKILL.md +1 -2
- package/{skills → .agents/skills}/spec-review/SKILL.md +1 -1
- package/{skills → .agents/skills}/test-authoring/SKILL.md +1 -1
- package/.claude-plugin/marketplace.json +14 -0
- package/.cursor-plugin/marketplace.json +16 -0
- package/.github/copilot-instructions.md +7 -0
- package/AGENTS.md +21 -10
- package/README.md +67 -5
- package/agent-plugin/.claude-plugin/plugin.json +20 -0
- package/agent-plugin/.codex-plugin/plugin.json +34 -0
- package/agent-plugin/.cursor-plugin/plugin.json +23 -0
- package/agent-plugin/.mcp.json +14 -0
- package/agent-plugin/LICENSE +201 -0
- package/agent-plugin/README.md +29 -0
- package/agent-plugin/assets/mobile-debug-tools.svg +28 -0
- package/agent-plugin/mcp.json +11 -0
- package/agent-plugin/plugin.json +29 -0
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +124 -0
- package/dist/interact/android.js +10 -4
- package/dist/interact/conditional-action.js +68 -0
- package/dist/interact/index.js +54 -14
- package/dist/interact/ios.js +14 -8
- package/dist/manage/android.js +4 -3
- package/dist/manage/ios.js +3 -2
- package/dist/observe/android.js +27 -22
- package/dist/observe/evidence.js +273 -0
- package/dist/observe/index.js +33 -6
- package/dist/observe/ios.js +25 -6
- package/dist/observe/readiness-service.js +115 -0
- package/dist/observe/readiness.js +81 -0
- package/dist/observe/recording.js +165 -0
- package/dist/observe/snapshot-metadata.js +10 -2
- package/dist/server/common.js +9 -0
- package/dist/server/condition-schema.js +32 -0
- package/dist/server/journey-schema.js +3 -2
- package/dist/server/readiness-schema.js +12 -0
- package/dist/server/tool-definitions.js +46 -0
- package/dist/server/tool-handlers.js +99 -17
- package/dist/server-core.js +1 -1
- package/dist/utils/ios/utils.js +4 -4
- package/dist/utils/operation-budget.js +24 -2
- package/dist/utils/resolve-device.js +7 -0
- package/docs/CHANGELOG.md +16 -2
- package/docs/benchmarks/ui-tree-performance/README.md +4 -3
- package/docs/specs/020-conditional-actions/intent.md +62 -0
- package/docs/specs/020-conditional-actions/plan.md +214 -0
- package/docs/specs/020-conditional-actions/spec.md +301 -0
- package/docs/specs/021-app-readiness-signals/intent.md +40 -0
- package/docs/specs/021-app-readiness-signals/plan.md +102 -0
- package/docs/specs/021-app-readiness-signals/spec.md +144 -0
- package/docs/specs/022-correlated-evidence/device-evidence.json +60 -0
- package/docs/specs/022-correlated-evidence/intent.md +37 -0
- package/docs/specs/022-correlated-evidence/modul8-evidence.json +1062 -0
- package/docs/specs/022-correlated-evidence/modul8-selector-fix-evidence.json +336 -0
- package/docs/specs/022-correlated-evidence/plan.md +171 -0
- package/docs/specs/022-correlated-evidence/spec.md +123 -0
- package/docs/specs/process.md +213 -0
- package/docs/tools/TOOLS.md +3 -0
- package/docs/tools/evidence.md +79 -0
- package/docs/tools/interact.md +125 -2
- package/docs/tools/observe.md +64 -2
- package/package.json +4 -2
- package/scripts/agent-plugin.mjs +98 -0
- package/src/interact/android.ts +10 -4
- package/src/interact/conditional-action.ts +75 -0
- package/src/interact/index.ts +42 -14
- package/src/interact/ios.ts +14 -8
- package/src/manage/android.ts +4 -3
- package/src/manage/ios.ts +3 -2
- package/src/observe/android.ts +35 -21
- package/src/observe/evidence.ts +255 -0
- package/src/observe/index.ts +32 -8
- package/src/observe/ios.ts +32 -8
- package/src/observe/readiness-service.ts +89 -0
- package/src/observe/readiness.ts +78 -0
- package/src/observe/snapshot-metadata.ts +12 -1
- package/src/server/common.ts +7 -0
- package/src/server/condition-schema.ts +32 -0
- package/src/server/journey-schema.ts +3 -2
- package/src/server/readiness-schema.ts +12 -0
- package/src/server/tool-definitions.ts +44 -0
- package/src/server/tool-handlers.ts +93 -17
- package/src/server-core.ts +1 -1
- package/src/types.ts +30 -1
- package/src/utils/ios/utils.ts +4 -4
- package/src/utils/operation-budget.ts +22 -2
- package/src/utils/resolve-device.ts +8 -0
- package/test/device/automated/observe/correlated-evidence.smoke.ts +70 -0
- package/test/device/manual/interact/conditional_actions.manual.ts +95 -0
- package/test/device/manual/interact/modul8_selector_tap.manual.ts +63 -0
- package/test/device/manual/interact/readiness.manual.ts +99 -0
- package/test/fixtures/readiness-app/MainActivity.java +23 -0
- package/test/fixtures/readiness-app/README.md +12 -0
- package/test/fixtures/readiness-app/build.ts +37 -0
- package/test/fixtures/readiness-app/main.m +27 -0
- package/test/unit/observe/android_tree_acquisition.test.ts +6 -0
- package/test/unit/observe/capture_debug_snapshot.test.ts +42 -32
- package/test/unit/observe/compact_tree_error.test.ts +24 -0
- package/test/unit/observe/conditional_snapshots.test.ts +33 -0
- package/test/unit/observe/correlated-evidence.test.ts +128 -0
- package/test/unit/observe/ios-getlogs.test.ts +3 -3
- package/test/unit/observe/ios_tree_acquisition.test.ts +2 -0
- package/test/unit/observe/readiness.test.ts +39 -0
- package/test/unit/observe/readiness_native.test.ts +68 -0
- package/test/unit/server/conditional_actions.test.ts +299 -0
- package/test/unit/server/conditional_schema.test.ts +59 -0
- package/test/unit/server/correlated-evidence.test.ts +194 -0
- package/test/unit/server/readiness.test.ts +170 -0
- package/test/unit/server/selector_tap_target.test.ts +79 -0
- package/test/unit/server/tap_selector.test.ts +2 -0
- package/skills/mobile-debug-tools-usage/SKILL.md +0 -74
- package/src/observe/android-tree-bridge.ts +0 -178
- package/test/device/automated/ui-tree-performance/bridge-probe.ts +0 -197
- package/test/fixtures/ui-tree-bridge/AndroidManifest.xml +0 -6
- package/test/fixtures/ui-tree-bridge/build.ts +0 -34
- package/test/fixtures/ui-tree-bridge/src/TreeInstrumentation.java +0 -126
- package/test/unit/observe/android_tree_bridge_cleanup.test.ts +0 -95
- /package/{skills → .agents/skills}/README.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/references/build-flags.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/references/diagnostics-schema.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/references/toolchain-details.md +0 -0
- /package/{skills → .agents/skills}/spec-review/references/spec-review-checklist.md +0 -0
- /package/{skills → .agents/skills}/spec-review/references/spec-review-template.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/references/repo-test-layout.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/references/test-authoring-workflow.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/references/test-quality-checklist.md +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Spec 021: app readiness signals
|
|
2
|
+
|
|
3
|
+
Date: 2026-10-29. Status: approved — implementation authorised.
|
|
4
|
+
Source: [issue #65](https://github.com/clivejefferies/mobile-debug-tools/issues/65).
|
|
5
|
+
[Intent](intent.md) approved by the originator’s “yes” in this conversation.
|
|
6
|
+
|
|
7
|
+
## Behaviour and scope
|
|
8
|
+
|
|
9
|
+
Report readiness of the observed foreground device UI on Android/iOS. This is
|
|
10
|
+
not proof of a particular app’s identity, backend completion, or safe input.
|
|
11
|
+
Reuse snapshot signatures, loading observations, device resolution, and budgets.
|
|
12
|
+
Do not infer readiness from screenshots or input-dispatch success.
|
|
13
|
+
|
|
14
|
+
Initial supported states are `loading`, `transitioning`, `settled`, and `unknown`.
|
|
15
|
+
Reserve `unresponsive` and `debugger_paused`, but report their capabilities as
|
|
16
|
+
unsupported on both platforms: there is currently no authoritative process-health
|
|
17
|
+
or debugger-session provider. A timeout must never manufacture either state.
|
|
18
|
+
Adding those providers requires a subsequent spec decision; this feature does
|
|
19
|
+
not implement a debugger, recovery, restart, or performance profiling.
|
|
20
|
+
|
|
21
|
+
## Public contracts
|
|
22
|
+
|
|
23
|
+
Add tools `get_app_readiness` and `wait_for_app_ready`, requiring `platform`
|
|
24
|
+
(`android`/`ios`) and optionally accepting `deviceId`. Resolve and pin one concrete
|
|
25
|
+
device per call. Both accept strict integer controls:
|
|
26
|
+
|
|
27
|
+
| Control | Default | Range |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `timeoutMs` | get: 15000; wait: 30000 | 100–60000 |
|
|
30
|
+
| `stabilityMs` | 500 | 100–10000 |
|
|
31
|
+
| `pollIntervalMs` (wait only) | 500 | 100–1000 |
|
|
32
|
+
|
|
33
|
+
Reject invalid/unknown arguments as `INVALID_ARGUMENT` before device work.
|
|
34
|
+
`get_app_readiness` takes at most two fresh samples, separating their acquisitions
|
|
35
|
+
by at least `stabilityMs`. A loading first sample can return immediately. The
|
|
36
|
+
wait tool samples until settled or its deadline. Reads are sequential; never
|
|
37
|
+
start a background poller or overlap hierarchy dumps within a call.
|
|
38
|
+
|
|
39
|
+
Both return `{ success, device, readiness, elapsed_ms, failure_code? }`.
|
|
40
|
+
For get, success means a supported state was established; `unknown` is unsuccessful.
|
|
41
|
+
For wait, only `settled` is successful. Unsuccessful codes are
|
|
42
|
+
`READINESS_UNAVAILABLE` (get), `READINESS_TIMEOUT` (wait deadline), and
|
|
43
|
+
`DEVICE_UNAVAILABLE` (resolution/disconnection prevents continuation).
|
|
44
|
+
|
|
45
|
+
`readiness` contains:
|
|
46
|
+
|
|
47
|
+
- `state`, `scope: device_ui`, and `basis` (`observed`, `heuristic`, or `insufficient`).
|
|
48
|
+
- `captured_at_ms` (latest successful sample, or null), `sample_count`,
|
|
49
|
+
`stable_for_ms`, and nullable `snapshot_session_id`/`snapshot_revision`.
|
|
50
|
+
- `evidence`: bounded records of signal code, source, capture time, and snapshot
|
|
51
|
+
revision; maximum eight, newest retained. No full text, logs, screenshots, or trees.
|
|
52
|
+
- `limitations`: applicable codes from `INSUFFICIENT_SAMPLES`, `OBSERVATION_FAILED`,
|
|
53
|
+
`OBSERVATION_INVALID`, `DEADLINE_EXCEEDED`, `NORMALIZED_UI_ONLY`,
|
|
54
|
+
`FOREGROUND_APP_UNVERIFIED`, `UNRESPONSIVE_SIGNAL_UNSUPPORTED`, and
|
|
55
|
+
`DEBUGGER_SIGNAL_UNSUPPORTED`.
|
|
56
|
+
- `capabilities`: true for loading/transition/stability observation; false for
|
|
57
|
+
unresponsive/debugger-paused detection in this version.
|
|
58
|
+
|
|
59
|
+
Add the same `readiness` summary to debug/compact `get_ui_tree` and nested tree
|
|
60
|
+
observations without additional reads. Single-sample summaries can only report
|
|
61
|
+
loading or unknown; separate calls never silently share a stability window.
|
|
62
|
+
Preserve existing fields, compact error evidence, and delta behaviour.
|
|
63
|
+
|
|
64
|
+
Add opt-in `requireReady: boolean` (default false) to `wait_for_ui` and
|
|
65
|
+
`wait_for_ui_change`. When enabled, success requires the existing predicate and
|
|
66
|
+
settled readiness on the same current samples. Reuse those waits’ samples and
|
|
67
|
+
single existing deadline; do not add another wait budget or unrelated tree reads.
|
|
68
|
+
Return `readiness` alongside the existing envelope. On expiry retain the existing
|
|
69
|
+
timeout/failure shape and include readiness limitations. Default calls retain
|
|
70
|
+
existing predicate semantics; no new journey assertion type is introduced.
|
|
71
|
+
|
|
72
|
+
## Classification rules
|
|
73
|
+
|
|
74
|
+
| Evidence | State / basis |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| Visible native `android.widget.ProgressBar`, `ActivityIndicator`, or `ProgressIndicator` | loading / observed |
|
|
77
|
+
| Visible label exactly “Loading” or “Please wait”, ignoring case, whitespace, and trailing full stops/ellipsis | loading / heuristic |
|
|
78
|
+
| Two valid consecutive signatures differ | transitioning / observed |
|
|
79
|
+
| At least two valid identical signatures spanning `stabilityMs`, without loading evidence | settled / observed |
|
|
80
|
+
| Missing, failed, invalid, or insufficient evidence | unknown / insufficient |
|
|
81
|
+
|
|
82
|
+
Loading takes precedence over stability. Do not reuse the broad existing
|
|
83
|
+
`loading_state` keyword heuristic as proof: a button named “Progress” is not an
|
|
84
|
+
active loader. Keep that legacy field unchanged for compatibility.
|
|
85
|
+
|
|
86
|
+
Use full normalized snapshot signatures, including state and bounds, not the
|
|
87
|
+
coarser screen fingerprint or truncated delta. A change resets stability;
|
|
88
|
+
failed reads break consecutive-sample continuity. Validate device/session,
|
|
89
|
+
revision, a finite capture timestamp from this acquisition, nonempty elements,
|
|
90
|
+
and positive finite resolution. Never accept retained metadata as a fresh read.
|
|
91
|
+
Track elapsed/stability intervals with a monotonic clock; expose wall-clock
|
|
92
|
+
capture timestamps only as evidence. Results describe their capture window,
|
|
93
|
+
not a guarantee that the UI stays settled afterward.
|
|
94
|
+
|
|
95
|
+
## Failure, lifecycle, and privacy
|
|
96
|
+
|
|
97
|
+
Bound acquisition, retries, and delays by the remaining operation budget and any
|
|
98
|
+
outer deadline. No late sample may produce success. Terminate/await owned timed-out
|
|
99
|
+
subprocesses; perform no follow-up snapshot after expiry. Waits can retry transient
|
|
100
|
+
observation failures within budget, with continuity reset; disconnect is terminal.
|
|
101
|
+
Retain the last supported state on wait timeout only as timestamped evidence,
|
|
102
|
+
with `DEADLINE_EXCEEDED`; if the latest read failed, current state is unknown.
|
|
103
|
+
There is no cancellation argument. Existing transport cancellation does not
|
|
104
|
+
currently abort platform reads; those reads remain bounded by their deadlines.
|
|
105
|
+
Do not claim immediate cancellation support or create persistent sessions.
|
|
106
|
+
Do not reset network windows, dispatch input, or retain cross-request histories.
|
|
107
|
+
Do not log UI payloads or input text. No permissions, dependencies, migrations,
|
|
108
|
+
or automatic package release are required.
|
|
109
|
+
|
|
110
|
+
## Acceptance and verification
|
|
111
|
+
|
|
112
|
+
- Loading outranks identical trees; changing trees transition; consecutive stable
|
|
113
|
+
valid trees settle. Text-only loading is explicitly heuristic.
|
|
114
|
+
- A frozen-looking screenshot, stable tree, slow dump, timeout, or missing loader
|
|
115
|
+
cannot establish responsiveness, debugger pause, or app/backend completion.
|
|
116
|
+
- Error/empty/stale-session/wrong-device samples never settle; failures reset
|
|
117
|
+
continuity. Deadlines prevent late success and background work.
|
|
118
|
+
- New summaries preserve compact/debug evidence and existing defaults; opt-in
|
|
119
|
+
waits require both their predicate and readiness.
|
|
120
|
+
- Every state has evidence and limitations; unsupported capabilities are explicit.
|
|
121
|
+
|
|
122
|
+
Use deterministic native-adapter/clock fixtures for transitions, failures,
|
|
123
|
+
timeouts, isolation, and schema parity. Run `npm run verify`, `npm run test:device`,
|
|
124
|
+
and updated-server Android/iOS journeys for stable content, a controlled loader
|
|
125
|
+
transition, bounded waiting, and opt-in predicate waits. Record simulator/build,
|
|
126
|
+
results, and unsupported coverage in the plan after approval.
|
|
127
|
+
|
|
128
|
+
## Investigation and approval
|
|
129
|
+
|
|
130
|
+
Existing owners: `src/observe/snapshot-metadata.ts`, `src/observe/index.ts`,
|
|
131
|
+
`src/interact/index.ts`, server schemas/handlers, shared types and operation budgets.
|
|
132
|
+
The legacy idle wait can compare null fingerprints; the new classifier must not
|
|
133
|
+
copy that inference. No debugger/readiness module currently exists.
|
|
134
|
+
|
|
135
|
+
Read-only reconnaissance used the connected server (exact build not reported;
|
|
136
|
+
local checkout 0.32.4). Android 16 `emulator-5554`: two fresh 15-element trees,
|
|
137
|
+
same revision 9, no loading hint, reads about 4.4/3.0 seconds. iOS 26.4 iPhone 17
|
|
138
|
+
Pro `F9243BAF-62A8-4990-8A99-17F527F56FDA`: two fresh 14-element trees, revision
|
|
139
|
+
10, no loading hint, reads about 3.4/2.0 seconds. These establish available
|
|
140
|
+
observation routes, not feature passes; no inputs or settings were changed.
|
|
141
|
+
|
|
142
|
+
Approved by the originator’s “yep” on 2026-10-29 in direct response to this
|
|
143
|
+
spec and first-version scope, including unsupported unresponsive/debugger-paused
|
|
144
|
+
detection and opt-in existing-wait integration.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"verified_on": "2026-10-30",
|
|
3
|
+
"source_base": "3701f3987940a8abc76ed893b575ed370e3fb673",
|
|
4
|
+
"source_state": "working tree with correlated evidence changes",
|
|
5
|
+
"node_version": "23.11.0",
|
|
6
|
+
"build_sha256": {
|
|
7
|
+
"dist/server/tool-handlers.js": "4ae4aef2467518216e3b987112aadb91e5ff560679782fe08aefdb389209cc50",
|
|
8
|
+
"dist/observe/evidence.js": "bd7c6ac046ad4adde08117dcb66f68682e0036a83308c0c84f6d5ce141f8a386"
|
|
9
|
+
},
|
|
10
|
+
"journeys": [
|
|
11
|
+
{
|
|
12
|
+
"status": "PASS",
|
|
13
|
+
"server": {
|
|
14
|
+
"name": "mobile-debug-mcp",
|
|
15
|
+
"version": "0.32.4"
|
|
16
|
+
},
|
|
17
|
+
"platform": "android",
|
|
18
|
+
"device": "emulator-5554",
|
|
19
|
+
"osVersion": "16",
|
|
20
|
+
"startingApp": "com.android.settings",
|
|
21
|
+
"actionId": "5fdfe5a0-cfd3-4182-a12b-c440d855cec5",
|
|
22
|
+
"phases": {
|
|
23
|
+
"dispatchStarted": 1793350325789,
|
|
24
|
+
"dispatchCompleted": 1793350326584,
|
|
25
|
+
"screenshotStarted": 1793350327002,
|
|
26
|
+
"screenshotCompleted": 1793350327334
|
|
27
|
+
},
|
|
28
|
+
"screenshot": "captured",
|
|
29
|
+
"logs": "captured",
|
|
30
|
+
"uiTree": "captured",
|
|
31
|
+
"disabledComponents": "omitted",
|
|
32
|
+
"foreignReference": "unavailable",
|
|
33
|
+
"cleanup": "No settings, app data or streams changed; Settings remains foreground. No content artifacts saved."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"status": "PASS",
|
|
37
|
+
"server": {
|
|
38
|
+
"name": "mobile-debug-mcp",
|
|
39
|
+
"version": "0.32.4"
|
|
40
|
+
},
|
|
41
|
+
"platform": "ios",
|
|
42
|
+
"device": "F9243BAF-62A8-4990-8A99-17F527F56FDA",
|
|
43
|
+
"osVersion": "iOS 26.4",
|
|
44
|
+
"startingApp": "com.apple.Preferences",
|
|
45
|
+
"actionId": "99a4cdc4-8be1-4194-acab-3d08e7bd4a41",
|
|
46
|
+
"phases": {
|
|
47
|
+
"dispatchStarted": 1793350335131,
|
|
48
|
+
"dispatchCompleted": 1793350335486,
|
|
49
|
+
"screenshotStarted": 1793350335806,
|
|
50
|
+
"screenshotCompleted": 1793350336212
|
|
51
|
+
},
|
|
52
|
+
"screenshot": "captured",
|
|
53
|
+
"logs": "captured",
|
|
54
|
+
"uiTree": "captured",
|
|
55
|
+
"disabledComponents": "omitted",
|
|
56
|
+
"foreignReference": "unavailable",
|
|
57
|
+
"cleanup": "No settings, app data or streams changed; Settings remains foreground. No content artifacts saved."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Intent: correlated evidence
|
|
2
|
+
|
|
3
|
+
Originator: repository maintainer (current conversation).
|
|
4
|
+
Date: 2026-10-29. Status: approved.
|
|
5
|
+
Source: [issue #66](https://github.com/clivejefferies/mobile-debug-tools/issues/66), roadmap priority 3 of 9.
|
|
6
|
+
|
|
7
|
+
## Problem and outcome
|
|
8
|
+
|
|
9
|
+
MCP clients need to connect Android/iOS actions with screenshots and logs without
|
|
10
|
+
mistaking older observations for evidence of later actions. Existing action IDs,
|
|
11
|
+
snapshot metadata, and elapsed timings do not provide a consistent correlation
|
|
12
|
+
contract.
|
|
13
|
+
|
|
14
|
+
Clients should identify related evidence, distinguish observation capture, input
|
|
15
|
+
dispatch, and verification completion, and recognise stale observations.
|
|
16
|
+
Association must not imply causality or simultaneous capture.
|
|
17
|
+
|
|
18
|
+
## Scope and success criteria
|
|
19
|
+
|
|
20
|
+
- Extend existing conventions with shared identifiers and explicit phase timing.
|
|
21
|
+
- Identify stale evidence; preserve uncertainty when freshness is unknown.
|
|
22
|
+
- Preserve device targeting and report platform limitations.
|
|
23
|
+
- Allow future system traces to use the same correlation conventions.
|
|
24
|
+
- Preserve behaviour except for changes accepted in the specification.
|
|
25
|
+
|
|
26
|
+
## Exclusions and decisions
|
|
27
|
+
|
|
28
|
+
Exclude trace capture, runtime debugger, heap dumps, automatic recovery, and
|
|
29
|
+
background recording. Specification must resolve identifier lifetime, association,
|
|
30
|
+
clock semantics, freshness, log windows, compatibility, and resource/privacy
|
|
31
|
+
handling, building on existing helpers.
|
|
32
|
+
|
|
33
|
+
## Approval
|
|
34
|
+
|
|
35
|
+
The maintainer’s “yes” on 2026-10-29 approved the complete linked intent in this
|
|
36
|
+
conversation. This shorter version preserves that scope; specification approval
|
|
37
|
+
remains pending.
|