# P1-market-journey — findings

| | |
| --- | --- |
| Reviewer | Zayed |
| Reviewed | 2026-09-15 |
| Status | locked |
| Supersedes | — |
| Superseded by | — |

**The outcome cells below are deliberately empty. The reviewer fills them.**
Everything else — the decisions, the evidence, the write-back destinations and
the exact shape each story has to take — is already in place, so recording an
answer is a sentence, not a research task.

## Outcome per decision

"Outcome" is the answer chosen, in a sentence. "Evidence" is the screenshot the
answer rests on. A decision with no evidence is not settled.

| Id | Decision | Outcome | Evidence | Writes back to |
| --- | --- | --- | --- | --- |
| D1 | Is a profile detail a route of its own or a side sheet over the results? | A full route (`/profiles/{id}`). Decided against the Livewire baseline: the shipped screen has no detail, and A3.4 already specifies a detail page; a shareable route is the destination and the sheet is not adopted. | `screenshots/detail--basic--ar.png`, `screenshots/index--sheet--ar.png` | (a) epic **A3.4** |
| D2 | Where does the filter panel live, and where do the facet counts and the three callouts live with it? | The sidebar, exactly as the Livewire screen: one collapsible section per registry group, a facet count against every option, the three callouts above the results column; on mobile the same panel opens in a sheet. The top bar is not adopted. | `screenshots/index--default--ar.png`, `screenshots/index--default--ar--topbar.png`, `screenshots/index--stranded--en.png` | (a) epic **A0.8** |
| D3 | How much does a result carry — in the card and in the table? | Regular density, as today: four summary fields and four metric pills per card, fixed, not a user setting; the table keeps today's four columns (name, details, availability, tier). The compact card and the per-group table are not adopted. | `screenshots/index--default--ar.png`, `screenshots/index--compact--ar.png`, `screenshots/index--table--ar.png`, `screenshots/index--table-groups--ar.png` | (a) epic **A0.8** + (c) a rule |
| D4 | Where does the sport switch live — the market header, or above the market? | The market header, next to the sort, as today; switching re-resolves the whole screen (tabs and counts, panel, presets, sorts, cards, open profile). | `screenshots/index--default--ar.png`, `screenshots/index--basketball--ar.png`, `screenshots/index--basketball-coach--ar.png` | (a) epic **A0.8** |

### Secondary questions the same screens answer

These are not decisions of their own, but the review should not close without an
answer, because each one has a write-back destination waiting for it.

| Question | Outcome | Evidence | Writes back to |
| --- | --- | --- | --- |
| Does the locked placeholder name the tier clearly enough that a basic-tier club knows what it is missing and why? | Yes: it names the tier and lists the four hidden groups; kept as built. | `screenshots/detail--basic--ar.png` vs `screenshots/detail--private--ar.png` | (a) epic **A1.5** |
| Should the private-tier rule reach the **filter panel** as well as the detail — the salary-band filter renders as "available at the private tier" rather than disappearing? | Follow the Livewire rule (A0.8): a field a member may not see is not filterable, so it disappears from the panel; the placeholder is for detail only. | `screenshots/detail--basic--ar.png`, `index.html?panel=sidebar&tier=basic` | (b) note on **A1.5** |
| Is "Send request" in the right place on both the page and the sheet, and does the stub dialog ask for the right two things (deal type, message)? | On the page only (sheet not adopted); deal type and message are the right two inputs, per A3.1. | `screenshots/detail--basic--ar.png`, `screenshots/index--sheet--ar.png` | (a) epic **A3.1** |
| Is one shared list per club enough, or does a card need to say who added it? The watchlist card says; the market card does not. | One shared list; the watchlist card shows who added it, the market card only the watch state. Kept as built. | `screenshots/watchlist--default--ar.png` | (b) note on **A3.4** |
| Do the three callouts read as three different problems, or as one repeated warning? | Kept as the Livewire screen renders them: three separate callouts with their own copy. | `screenshots/index--dropped--ar.png`, `screenshots/index--partial--ar.png`, `screenshots/index--stranded--ar.png` | (b) note on **A0.8** |
| Does a role at zero stay legible as a role rather than reading as a bug? | Yes; the Livewire rule (a role stays visible at zero) holds. | `screenshots/index--empty--ar.png` | (b) note on **A0.8** |
| Does the panel read as the same screen in both sports, or as two screens? Basketball adds three physical fields and drops training status; the metric group is a different set of names entirely. | The same screen; the registry decides the fields, as in Livewire. No change. | `screenshots/index--default--ar.png` vs `screenshots/index--basketball--ar.png` | (b) note on **A0.8** |
| Does a basketball card answer as much per name as a football one, given that it leads with position and height rather than position and tier? | Yes; the summary fields are the registry's card set per sport. No change. | `screenshots/index--basketball--ar.png`, `screenshots/index--basketball-table--ar.png` | (b) note on **A0.8** |

---

# Write-back

Three destinations, one section each. Everything below is copy-paste ready.
Leave a section empty rather than inventing an entry for it.

**No requirement id from any parked requirement document may appear anywhere
below.** Restate it in the project's own words or drop it.

## The exact story format

Every story appended under (a) is **two lines**, the second indented by two
spaces, and nothing else:

```
- **As a <actor>**, I <do>, so that <outcome>.
  - Accept: <criteria>.
```

Rules that the format does not show but the manifest enforces:

- Stories are **append-only**. Add to the end of that epic's `## Stories`
  block; never reorder, renumber or reword a story already there, because
  `story_notes` points at stories by their 1-based position.
- `<actor>` matches the actors already used on that epic — "Club member" on
  A0.8, "club user" on A3.1 and A3.4, "signed-in club user at the basic tier"
  and "club user at the private tier" on A1.5.
- One `Accept:` line, one sentence, testable. If it needs two sentences it is
  two stories.
- The story says what the user does, not which component renders it.

## (a) New stories

### Epic `A0.8` — Market search (shipped) — from the **search** findings

No new user story: every search outcome equals the shipped behaviour. The payload consequence of D3 was written as a story on **A0.12** (Market search endpoint) in the manifest on 2026-09-15, and the locked shape is recorded in the Scope of **D1.1**.

### Epic `A3.4` — Favourites and full profile view — from the **detail** and **watchlist** findings

No new story: A3.4 already specifies a detail page and one shared list per club. The D1 outcome (route, no sheet) is recorded in A3.4's Notes and in D1.2's Scope.

### Epic `A1.5` — Visibility tiers — from the **tier rendering** finding

No new story: the locked placeholder naming the tier is already A1.5's first acceptance criterion; the panel keeps the A0.8 rule (not visible, not filterable).

### Epic `A3.1` — Send a request to a professional — from the **request entry** finding

No new story: the send action on the detail page with deal type and message is already A3.1's first story.

## (b) Notes on existing stories

Keyed by the story's 1-based position in that epic's `## Stories` block. Merge
into the epic's `story_notes` object; do not replace it.

```json
"story_notes": {
  "<n>": "partial: <what the prototype found about that story>."
}
```

| Epic | Story position | Which story it is | Note |
| --- | --- | --- | --- |
| A0.8 | | | |
| A1.5 | | | |
| A3.4 | | | |

## (c) Rules for the code repo — `.ai/rules/`

Recorded with the `record-rule` tool, never pasted into `CLAUDE.md`.

| Glob | Title | Note |
| --- | --- | --- |
| | | |

Candidate rules this prototype surfaced, for the reviewer to accept or drop:

- The card's summary and metric counts are resolved **server-side**; whichever
  density wins in D3 decides whether the payload carries the regular set always
  or exactly what renders. See the `ProfileCard` table in `screens.md`.
- If `table=groups` wins, the table's column set depends on the role, so the
  header is data rather than markup.
- Dates shown inside an Arabic sentence use a month name, never the ISO form:
  `2027-06-30` inside an RTL run reorders to `30-06-2027` in the browser, while
  `30 يونيو 2027` does not. Bare dates in their own cell are safe with
  `unicode-bidi: plaintext`.

---

## Rejected options

What was tried and abandoned, and why. This is the part that stops the same
argument being had again in three months.

| Option | Why it was rejected | Evidence |
| --- | --- | --- |
| Detail as a side sheet | The sheet crops the private-tier block, career history and per-season metrics; a route is shareable and is what A3.4 specifies. | `screenshots/index--sheet--ar.png` vs `screenshots/detail--basic--ar.png` |
| Top-bar filter panel | Six visible filters and counts folded into option labels lose the facet-count reading the sidebar gives every option; the sidebar is the shipped shape and nothing in the review argued for changing it. | `screenshots/index--default--ar--topbar.png` |
| Compact card (2 + 2) | Fits more names, answers fewer questions per name; the review kept the shipped regular density. | `screenshots/index--compact--ar.png` |
| Per-group table | Column set would depend on the role (header as data); the shipped four columns are kept. | `screenshots/index--table-groups--ar.png` |
| Sport switch above the market | The switch already re-resolves the whole screen from the header; moving it adds a level without adding clarity. | `screenshots/index--basketball--ar.png` |

## Not settled

Decisions the timebox ran out on. Each names what would settle it.

- Nothing. Locked on 2026-09-15 against the Livewire baseline: every decision keeps the shipped shape where one exists; the detail route is the one addition. The three candidate rules under (c) are carried to the API foundation epic's `.ai/rules` work.
