Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions .agents/commands/pr.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ If no base branch argument provided, detect the repo's default branch:
- Use result as default (typically `main` or `master`)
- If command fails, fall back to `master`

### 2.6. Regenerate the Journeys Index
- Run `python3 scripts/journeys_index.py`
- If `journeys/index.json` changed, commit it as `chore: update journeys index`
- If it reports an identifier that no source file declares, stop and report the journey and the identifier

### 3. Gather Context
- Get current branch name: `git branch --show-current`
- Extract repo identifier: `git remote get-url origin | sed 's/\.git$//' | sed -E 's#.*[:/]([^/]+/[^/]+)$#\1#'` (e.g., `synonymdev/bitkit-ios`)
- Read PR template from `.github/pull_request_template.md`
- Fetch 10 most recent PRs (open or closed) from the extracted repo for writing style reference
- Run `git log $base..HEAD --oneline` for commit messages
- Run `git diff $base...HEAD --stat` for understanding scope of changes
- List the journeys the branch adds or updates: `git diff --name-only --diff-filter=d $base...HEAD -- journeys | grep '\.xml$'`

### 4. Extract Linked Issues
Scan commits for issue references:
Expand Down Expand Up @@ -127,9 +133,13 @@ When the user provides custom instructions after `--`:
- Always use this structure:
```md
### QA Notes
#### Journeys
#### Manual Tests
#### Automated Checks
```
- Under `#### Journeys`, list each journey the branch adds or updates (Step 3) as a list item with its repo path. Write `N/A — no user-visible behaviour change.` only when the diff changes no user-visible behaviour; when it does and the list is empty, stop and report the flows that need a journey.
- Stop and report any journey whose `sources` in `journeys/index.json` include a file the branch changes and whose route no longer matches the diff.
- Under `#### Manual Tests`, keep only what a journey cannot express, such as hardware, push notifications, or a companion app, and end each item with the reason. Write no manual test for a flow a listed journey covers.
- Keep local verification commands, `xcodebuild`, Swift tests, SwiftFormat, translation validation, unit tests, build passes, cargo test, cargo clippy, npm test, typecheck, CI coverage, or similar automated checks out of `#### Manual Tests`; summarize them under `#### Automated Checks` when they add useful context.
- Use `#### Automated Checks` to summarize automated verification evidence, prioritizing coverage added, modified, or removed with file paths and a short explanation.
- For removed automated coverage, state why it was removed.
Expand All @@ -140,7 +150,7 @@ When the user provides custom instructions after `--`:
- If no automated checks were run and no automated coverage changed, write `N/A` under `#### Automated Checks`.
- Write manual tests using this template:
```md
- [ ] **{numbering}.** {optional_condition + →} {screen_action} → {next_screen_action}: expectation
- [ ] **{numbering}.** {optional_condition + →} {screen_action} → {next_screen_action}: expectation — {reason a journey cannot express it}
```
- Use a list of unchecked checkboxes for each individual test.
- Use a numbered prefix for each test, in bold, for example `**1.**`, `**2.**`.
Expand Down Expand Up @@ -168,16 +178,13 @@ Example:
Concrete style target:
```md
### QA Notes
#### Journeys
- `journeys/amount-limits/send-amount-over-balance.xml`
- `journeys/widgets/add-widgets-flow.xml`
#### Manual Tests
- [ ] **1.** No usable channels/spending balance → scan LN invoice: error shows immediately, not after 15s.
- [ ] **2.** Scanner → scan fixed amount LN invoice: Send Confirm or QuickPay opens directly.
- [ ] **3a.** `regression:` Send → scanner/paste fixed amount LN invoice: in-sheet nav to Confirm or QuickPay.
- [ ] **3b.** `regression:` Variable amount LN invoice/LNURL-pay: lands on Amount view.
- [ ] **4a.** Activity Detail of LN transfer → tap Connection: lands on Channel Detail.
- [ ] **4b.** back: returns to Activity Detail.
- [ ] **5a.** Settings → Lightning Connections → tap channel: still opens Channel Detail.
- [ ] **5b.** back: returns to Connections List.
- [ ] **6.** `regression:` Channel Detail → tap Close Connection: works.
- [ ] **1a.** Physical device → Scanner → scan a printed fixed amount LN invoice QR: Send Confirm opens directly — needs a device camera.
- [ ] **1b.** `regression:` Printed LNURL-pay QR: lands on Amount view — needs a device camera.
- [ ] **2.** Pubky Ring installed → Profile → sign in with Pubky Ring: profile shows as connected — needs the Pubky Ring app.
#### Automated Checks
- Unit tests added: cover invoice timeout handling in `BitkitTests/TransferViewModelTests.swift`.
- Unit tests modified: update channel navigation assertions in `BitkitTests/ChannelDetailsViewModelTests.swift`.
Expand Down
14 changes: 14 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,17 @@ Add any links to GitHub issues or Asana tasks that are relevant to this pull req
### Screenshot / Video

Insert relevant screenshot / recording

### QA Notes

#### Journeys

<!-- Repo path of each journey this PR adds or updates, one per line, or: N/A — no user-visible behaviour change. -->

#### Manual Tests

<!-- Only what a journey cannot express (hardware, push notifications, a companion app), each item ending with the reason. -->

#### Automated Checks

<!-- List the tests you ran, including regression tests if applicable. -->
22 changes: 22 additions & 0 deletions .github/workflows/journeys.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Journeys

on:
push:
branches: [master]
pull_request:

permissions:
contents: read

jobs:
index:
name: Check journeys index
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- name: Checkout
uses: actions/checkout@v7

- name: Check journeys index
run: python3 scripts/journeys_index.py --check
16 changes: 10 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ xcodebuildmcp simulator test

Separately from the test suites, `journeys/` holds XML walkthroughs of app behaviour that an agent
evaluates by driving a running simulator — number pad caps, notification permission, widget flows,
hardware wallet pairing and transfers. They are developer assistance rather than a test layer:
nothing runs them in CI and they gate nothing. Read `journeys/README.md` before running or writing
one, and see the Journeys section under Code Style & Conventions.
hardware wallet pairing and transfers. They are the QA contract for PRs rather than a test suite:
CI does not run them, and it checks that `journeys/index.json` matches them. Read `journeys/README.md`
before running or writing one, and see the Journeys section under Code Style & Conventions.

## Architecture

Expand Down Expand Up @@ -377,9 +377,13 @@ Ensure accessibility modifiers and labels are added to custom components.
`<description>` and the suite README — never assert Android behaviour iOS does not have.
- SKIP a journey only when the iOS feature does not exist, and record it under "Not ported" in
`journeys/README.md` with what is missing.
- Journeys are developer-assistance specs, not a QA gate. Nothing runs them in CI and no runner is
wired up for them; `ai-device-tests.yml` runs `TrezorBridgeDashboardUITests` and never reads
`journeys/`. An agent runs one on request.
- ADD or UPDATE, in the same PR, the journeys that prove a user-visible behaviour change and every
journey whose route the PR changes; `journeys/index.json` lists the source files each journey's
identifiers are declared in. List those journeys under `#### Journeys` in the PR's QA Notes.
- NAME an identifier in a journey action as `id "Name"`.
- RUN `python3 scripts/journeys_index.py` after changing a journey or an identifier it names, and
commit `journeys/index.json`. CI fails on a stale index or an undeclared identifier; it does not run
the journeys themselves.
- A journey that disagrees with the app is most likely stale rather than evidence of a bug. Say what
you found and update the journey; escalate only once you have separately confirmed the app is wrong.

Expand Down
6 changes: 2 additions & 4 deletions journeys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ and deliberately keep the same file names, journey names and `<action>` prose so
stay diffable. Only the platform mechanics differ — `adb` becomes `xcodebuildmcp`, and Android
`testTag`s become iOS `accessibilityIdentifier`s (the vocabulary is shared; see [Identifiers](#identifiers)).

**Journeys are not a QA gate.** They are agent-evaluated and non-deterministic, nothing runs them in
CI, and there is no runner wired up for them yet — `ai-device-tests.yml` runs `TrezorBridgeDashboardUITests`
and does not read `journeys/`. Treat a journey as a well-written description of a flow, not as an
authority on what the app owes you.
**Journeys are the QA contract for PRs** (see the Journeys section in `AGENTS.md`). They are
agent-evaluated and non-deterministic, so CI does not run them; it only checks `journeys/index.json`.

A journey that no longer matches the app is most likely **stale**, not evidence of a bug. The corpus
is new on iOS and has not been run end to end, so when the two disagree the first assumption should be
Expand Down
Loading