@jabworks/condux 0.28.0 → 0.29.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jabworks/condux",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "OpenCode plugin for the condux workflow toolkit — bundles the condux skills and injects the specialist agents (coder, explorer, planner, researcher) plus an opt-in plan-review listener.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -20,7 +20,7 @@ between "the pipeline passed" and "I watched it do the thing".
20
20
 
21
21
  | Change touches | Run this? |
22
22
  |---|---|
23
- | A rendered surface — page, component, story, dialog | **Yes** |
23
+ | A rendered surface — page, component, story, dialog, a mobile app screen | **Yes** |
24
24
  | An endpoint, procedure, or CLI a human will call | **Yes** |
25
25
  | Behaviour behind a flag or a state the tests don't reach | **Yes** |
26
26
  | Types, docs, comments, config with no runtime effect | No — say so and skip |
@@ -43,6 +43,14 @@ Do not assume a dev server. In order:
43
43
  Start it in the background, wait for it to actually serve (poll the URL — do
44
44
  not `sleep` and hope), and note the URL in the report.
45
45
 
46
+ **Mobile app: load the native recipe.** If the project is a mobile app —
47
+ finalize's native-change test: an `expo` or `react-native` dependency, or a
48
+ committed `android/` or `ios/` — read `references/native-app.md` now. Its
49
+ target order replaces the list above; it picks the driving rung once (adb,
50
+ `agent-device`, mobile-mcp, Expo's skills — recommended, never installed) and
51
+ resolves `adb` to an absolute path. The claims, verdicts and report below are
52
+ unchanged.
53
+
46
54
  **Mobile app: rebuild first when the change is native.** If finalize's
47
55
  `Native` line said *native rebuild* (or the diff touches the native layer —
48
56
  see finalize's native-change check), the installed app does not contain the
@@ -81,6 +89,12 @@ Order of checks, because this is where the defects were:
81
89
  4. **Keyboard.** Tab to it, Escape out of it, confirm focus lands somewhere
82
90
  sensible.
83
91
 
92
+ **Mobile app:** the same four checks, translated — both themes via
93
+ `cmd uimode night`; pressed, disabled and in-flight states in place of hover;
94
+ the failure path in airplane mode; the system back (`keyevent 4`) in place of
95
+ Tab and Escape, which must close what it opened. Every tap follows
96
+ `native-app.md`'s stale-UI rules.
97
+
84
98
  ### Step 4 — Capture evidence
85
99
 
86
100
  One artifact per claim that has a visual or observable outcome — screenshot,
@@ -91,6 +105,12 @@ evidence file for the claim it supports and reference it from the report's
91
105
  claim table. Console errors and failed network requests seen along the way
92
106
  get reported even when they belong to another feature.
93
107
 
108
+ **Mobile app:** evidence is a screenshot you have read back, or a recording
109
+ for motion, and `native-app.md`'s log sweep stands in for console and network.
110
+ A claim the emulator cannot settle — haptics, camera, push, feel — gets the
111
+ `device-only` verdict and a line under the report's `For the phone:`, never ✓.
112
+ The report adds the `Device` and `Build` header keys.
113
+
94
114
  Then write `report.md` into the same dir, in the shape of
95
115
  `references/report-template.md` — every run writes one, including runs where
96
116
  nothing could be driven (the template carries the fallback shape).
@@ -127,11 +147,16 @@ Wait timed out
127
147
 
128
148
  Two failed attempts on the same claim is the ceiling. Report and move on.
129
149
 
150
+ On a mobile app, the device-side failures — an offline device, an emulator
151
+ that won't boot, a stale binary — are in `native-app.md`'s part 8, under the
152
+ same ceiling.
153
+
130
154
  ## Output Format
131
155
 
132
- The report shape — the fixed header table (Date / Target / Diff / Themes),
133
- the claim table (Claim | Evidence | Verdict), "Also seen", and the outcome
134
- line — lives in `references/report-template.md`, the canonical home. It also
156
+ The report shape — the fixed header table (Date / Target / Diff / Themes,
157
+ plus Device / Build on a native app run), the claim table (Claim | Evidence |
158
+ Verdict), the phone checklist for `device-only` claims, "Also seen", and the
159
+ outcome line — lives in `references/report-template.md`, the canonical home. It also
135
160
  carries the fallback shape for when nothing could be driven; that run still
136
161
  writes `report.md`, because an absent report is indistinguishable from a run
137
162
  that never happened. Fixed header keys and a fixed claim-table shape are what
@@ -142,7 +167,8 @@ make two runs of the same surface comparable.
142
167
  ```
143
168
  ✗ Reporting a claim as verified because the code looks right
144
169
  ✗ Inventing a screenshot, a response, or a result that wasn't observed
145
- ✗ Installing a browser driver or scaffolding a test harness to get a result
170
+ ✗ Installing a browser or device driver, or scaffolding a test harness to get a result
171
+ ✗ Reporting a device-only claim as ✓
146
172
  ✗ sleep-then-check instead of polling for the condition
147
173
  ✗ Retrying the same selector more than twice
148
174
  ✗ Killing processes the run didn't start
@@ -0,0 +1,157 @@
1
+ # Native app verification (Android)
2
+
3
+ Loaded from Step 1 when the project is a mobile app — the same test as
4
+ finalize's native-change check: an `expo` or `react-native` dependency in
5
+ `package.json`, or a committed `android/` or `ios/` directory. A web project
6
+ never reads this file.
7
+
8
+ The claim/verdict/report contract in SKILL.md does not change. This file only
9
+ says how to reach the app, drive it, and read its errors — and which claims an
10
+ emulator cannot settle.
11
+
12
+ ## 1. Pick the rung
13
+
14
+ Decide once, at the start of the run, and name the choice in the report's
15
+ `Target` row. Three rungs, each optional, none ever installed by you:
16
+
17
+ | Concern | Use, first match wins |
18
+ |---|---|
19
+ | Build and install | the `expo` plugin's `expo-dev-client` / `eas-simulator` skills, when they are in your skill list → the project's own build script → `npx expo run:android` |
20
+ | Drive and read logs | `agent-device` on PATH (`command -v agent-device`) → mobile-mcp's `mobile_*` tools, when you have them → the core adb recipe below |
21
+
22
+ When a driver rung is in use, follow **its** documentation for the commands
23
+ (`agent-device help`, its bundled skills, the MCP tools' own descriptions) —
24
+ this file deliberately does not restate them. Parts 5–7 below apply on every
25
+ rung: they are about what counts as evidence, not about which tool taps.
26
+
27
+ No driver installed is the normal case, not a gap — never install one, and
28
+ never stop the run to ask.
29
+
30
+ ## 2. Target
31
+
32
+ In order, before booting or building anything:
33
+
34
+ 1. **The project's own setup wins.** `AGENTS.md`, `README.md`, a
35
+ project-local skill for running the app, `package.json` scripts
36
+ (`android`, `start`, a dev-client script), and anything under `scripts/`
37
+ that boots an emulator or installs a build. Use them as written. When they
38
+ disagree, the prose that is newest wins over a script name — a script can
39
+ outlive the emulator it boots.
40
+ 2. **Is a device already attached?** `adb devices` (with the resolved path,
41
+ part 3). One device in the `device` state → use it. `offline` or
42
+ `unauthorized` → part 8.
43
+ 3. **No device** → boot the emulator the project's script names, or
44
+ `emulator -list-avds` and the first one. Poll until
45
+ `adb shell getprop sys.boot_completed` prints `1` — never a fixed sleep.
46
+ 4. **Metro.** A dev client loads JS from Metro: check port 8081 before
47
+ starting it, and run `adb reverse tcp:8081 tcp:8081` once per boot.
48
+ 5. **Package and scheme.** Read `android.package` and `scheme` from the app
49
+ config (`app.json` / `app.config.*`), or `applicationId` from
50
+ `android/app/build.gradle*`. Every launch and log filter below needs them.
51
+ An `app.config.*` can change both per build variant (a dev client often
52
+ carries a `.dev` suffix and its own scheme) — confirm the installed one
53
+ with `adb shell pm list packages <name>` before launching.
54
+
55
+ ## 3. Resolve adb once
56
+
57
+ `adb` is often on the user's interactive PATH only, and an agent's shell keeps
58
+ no state between calls — an `export PATH=…` or an `ADB=…` variable lasts one
59
+ command.
60
+
61
+ **A project-provided adb wins.** Some setups run the emulators on another
62
+ host or OS and reach them through a wrapper script or a non-default adb
63
+ server; the project's docs (part 2) name it. Use that, by absolute path.
64
+ Otherwise resolve the absolute path once:
65
+
66
+ ```bash
67
+ command -v adb || ls "$ANDROID_HOME/platform-tools/adb" "$ANDROID_SDK_ROOT/platform-tools/adb" 2>/dev/null | head -1
68
+ ```
69
+
70
+ Then **write that literal path into every later command**. An adb that lists
71
+ no devices while the project documents a running one is the wrong adb, not an
72
+ empty machine — go back to the project's docs. Nothing found →
73
+ stop and report the blocker with the exact next command to try (set
74
+ `ANDROID_HOME`, or install platform-tools). Never install the SDK yourself.
75
+
76
+ ## 4. Drive
77
+
78
+ The core recipe, written with `adb` for brevity — use the resolved path.
79
+
80
+ | Need | Command |
81
+ |---|---|
82
+ | Launch at a screen | `adb shell am start -W -a android.intent.action.VIEW -d "<scheme>://<path>" <package>` |
83
+ | Tap / swipe | `adb shell input tap <x> <y>` · `adb shell input swipe <x1> <y1> <x2> <y2> <ms>` |
84
+ | Long-press | `adb shell input swipe <x> <y> <x> <y> 800` (a swipe that does not move) |
85
+ | Drag, multi-step gestures | `adb shell input motionevent DOWN/MOVE/UP <x> <y>`, where the device's `input` lists it |
86
+ | Type / keys | `adb shell input text '<text>'` · `adb shell input keyevent 4` (back) |
87
+ | Screenshot | `adb exec-out screencap -p > <claim>.png` — then Read the PNG; an unread screenshot proves nothing |
88
+ | Motion | `adb shell screenrecord --time-limit <s> /sdcard/<claim>.mp4`, then `adb pull` — a still cannot prove an animation |
89
+ | UI tree | `adb exec-out uiautomator dump /dev/tty` — element text, ids and `bounds` |
90
+ | Theme | `adb shell cmd uimode night yes` / `no` — both themes still gate a themed change |
91
+ | Offline | `adb shell cmd connectivity airplane-mode enable` / `disable` |
92
+ | Fresh state | `adb shell pm clear <package>` — only when the claim needs it; it wipes the user's app data |
93
+
94
+ ## 5. Stale UI
95
+
96
+ Most wrong taps in the field came from acting on a picture of a screen that
97
+ had already changed.
98
+
99
+ - **Take a fresh screenshot before any tap that changes state**, and look at it.
100
+ - **A `uiautomator dump` is true only for the moment it ran.** Re-dump after
101
+ every navigation, dialog, or list change.
102
+ - **Coordinates come from a dump's `bounds`**, never estimated from an image.
103
+ - **"could not get idle state"** means an animation is running. Poll the dump
104
+ again; a screen that never goes idle is a finding, not a reason to guess.
105
+
106
+ ## 6. Log sweep
107
+
108
+ Runtime errors are part of the evidence — the same rule as the browser
109
+ console.
110
+
111
+ 1. Before driving: `adb logcat -c`.
112
+ 2. After driving, the app's errors: `adb logcat -d -v time --pid=$(adb shell pidof -s <package>) '*:E'`.
113
+ 3. The JS layer: `adb logcat -d -v time -s ReactNativeJS:V`, plus Metro's own output.
114
+ 4. The app is gone (no pid) → it crashed: `adb logcat -d -b crash`. A crash on a
115
+ claim's path fails that claim.
116
+
117
+ A LogBox or RedBox overlay is a finding: read it, record its message, then
118
+ dismiss it. A RedBox on a claim's path fails that claim. Everything found here
119
+ goes in the report's "Also seen", even when it belongs to another feature.
120
+
121
+ ## 7. What the emulator can't prove
122
+
123
+ These claims get the **`device-only`** verdict, with the reason, and go on the
124
+ report's phone checklist. Never ✓, whatever the emulator showed:
125
+
126
+ | Claim touches | Why the emulator can't settle it |
127
+ |---|---|
128
+ | Haptics | no vibration hardware |
129
+ | Camera, QR scanning, biometrics | simulated sources, not the real sensor path |
130
+ | Push notification delivery | needs real FCM delivery on a signed-in device |
131
+ | Feel — scroll, animation smoothness, startup time | judged on the slowest device you support, on a release build |
132
+ | Sensors — GPS movement, motion, NFC, Bluetooth | mocked or absent |
133
+
134
+ The emulator can still verify the *surrounding* behaviour — the button that
135
+ triggers the haptic, the screen the scan result lands on. Split such a claim
136
+ in two rather than giving the whole thing one verdict.
137
+
138
+ ## 8. When it goes wrong
139
+
140
+ Environmental failures are results, not things to retry into the ground. The
141
+ two-attempt ceiling from SKILL.md applies.
142
+
143
+ | Failure | Response |
144
+ |---|---|
145
+ | `device offline` / `unauthorized` | one `adb reconnect`; still failing → report it |
146
+ | Emulator won't boot, or no AVD exists | report it with the next command to try; never kill an emulator you did not start |
147
+ | Metro port taken | report it; do not kill the process holding it |
148
+ | The app shows old behaviour | the binary is stale — Step 1's rebuild-first rule; record what you drove in the `Build` key |
149
+ | A tap does nothing | re-dump (part 5) and retry once; second miss → claim unchecked |
150
+
151
+ ## 9. iOS
152
+
153
+ The core recipe is Android-only. It has not been verified against the iOS
154
+ simulator, so this file does not pretend to cover it. For an iOS claim: use
155
+ the driver rung (agent-device and mobile-mcp both drive the simulator) when
156
+ one is present; otherwise report the claim **unchecked** with the blocker
157
+ named — "no iOS driver; the core recipe is Android-only".
@@ -27,6 +27,37 @@ Also seen: <console errors, failed requests, off-feature breakage — or "nothin
27
27
  <n> claims failed. <fix + re-verify note, or "all green">
28
28
  ```
29
29
 
30
+ A **native app run** (SKILL.md Step 1 detected a mobile app) adds two header
31
+ keys and one block, and has a fourth verdict:
32
+
33
+ ```markdown
34
+ # Live verification: <change>
35
+
36
+ | | |
37
+ |---|---|
38
+ | Date | YYYY-MM-DD |
39
+ | Target | <package> on <device> via <rung: adb / agent-device / mobile-mcp> |
40
+ | Device | <emulator AVD + API level, or the physical model> |
41
+ | Build | JS only / rebuilt at <commit> (from finalize's Native line) |
42
+ | Diff | <branch or commit under test> |
43
+ | Themes | light ✓ dark ✓ |
44
+
45
+ | Claim | Evidence | Verdict |
46
+ |---|---|---|
47
+ | <behavior asserted, one line> | <file in this dir, or —> | ✓ / ✗ <what actually happened> |
48
+ | <hardware-bound behavior> | <file, or —> | device-only — <why the emulator can't show it> |
49
+
50
+ For the phone:
51
+ - [ ] <claim> — <what to do on the device> — passes when <what you observe>
52
+
53
+ Also seen: <logcat errors, LogBox/RedBox messages, Metro errors — or "nothing">
54
+
55
+ <n> failed · <m> device-only (on the phone list) · <k> verified. <fix + re-verify note>
56
+ ```
57
+
58
+ `For the phone:` carries one checkbox per `device-only` row and is omitted
59
+ when there are none. A web run never shows `Device`, `Build`, or this block.
60
+
30
61
  When nothing could be driven, the report is still written — an absent
31
62
  `report.md` is indistinguishable from a run that never happened:
32
63
 
@@ -50,5 +81,6 @@ When nothing could be driven, the report is still written — an absent
50
81
  |---|---|
51
82
  | Everything a run produces lives inside its run dir — nothing at the verification root | Root-level orphans belonging to no run were observed in the wild; the dir is the unit of a run |
52
83
  | Evidence files are named for the claim they support and referenced from the claim table | The table is the index — an evidence file it doesn't reference is uncontextualized in a week |
53
- | Header keys are fixed: Date, Target, Diff, Themes (Themes only for UI surfaces) | Two runs of the same surface are diffable only when their headers line up |
84
+ | Header keys are fixed: Date, Target, Diff, Themes (Themes only for UI surfaces); a native app run adds Device and Build | Two runs of the same surface are diffable only when their headers line up |
85
+ | `device-only` is a verdict, not a pass — it never counts toward verified, and every one lands on the phone checklist | "Never report hardware validation that was not performed": a deferred check written as ✓ is read as done |
54
86
  | Every run writes `report.md`, including runs where nothing could be driven | Absence of a report must mean absence of a run, nothing else |
@@ -151,7 +151,7 @@ UIs), the combined menu must still carry the full CP-1 option set.
151
151
 
152
152
  | Option | What it does |
153
153
  |---|---|
154
- | **Verify it live** *(recommended when the change has a runnable surface)* | Load `live-verification` — drive the real UI or endpoint and check each claim against observed behaviour |
154
+ | **Verify it live** *(recommended when the change has a runnable surface — an app on an emulator counts)* | Load the `live-verification` skill and follow it — including on a mobile app: drive the real UI, endpoint or emulator, check each claim against observed behaviour, and write its report |
155
155
  | **Code review** *(recommended)* | `/code-review` the diff before merging |
156
156
  | **Commit** | Load the `git-commit` skill if installed (conventional message from the diff, safe staging); otherwise follow the repo's commit conventions |
157
157
  | **Cut a release** | Load the `release` skill if installed — machinery detection, dry-run plan, then tag → push → GitHub release; otherwise follow the repo's release conventions |
@@ -269,6 +269,7 @@ Stop if you catch yourself doing any of these:
269
269
  | Silently skipping discovery on a LARGE task | Ask — it's a soft gate, not a free pass |
270
270
  | Rewriting a test spec to make it pass | Stop and ask — never silently edit specs |
271
271
  | Auto-running code-review, commits, or agents | They're checkpoint choices; run only when picked |
272
+ | Verifying live without loading `live-verification` | Load it — its `report.md` is the evidence (9 of 11 ad-hoc runs in a mobile eval left none) |
272
273
  | Auto-advancing past a checkpoint on MEDIUM/LARGE | The user owns every transition |
273
274
  | Expanding scope past the confirmed tier | Stop, report, re-confirm |
274
275