Skip to content

Diagnostics: Only deliver discovery reports that carry a mapping - #36

Merged
d4rken merged 2 commits into
mainfrom
diagnostics/require-device-details
Jul 28, 2026
Merged

Diagnostics: Only deliver discovery reports that carry a mapping#36
d4rken merged 2 commits into
mainfrom
diagnostics/require-device-details

Conversation

@d4rken

@d4rken d4rken commented Jul 28, 2026

Copy link
Copy Markdown
Member

What changed

The "Help add support" wizard no longer produces reports that a maintainer can't act on.

  • It now asks for the battery-protection feature name and your software version before you start capturing, instead of leaving both optional.
  • If switching modes changed no settings at all, there's no longer a way to send the result. The step explains the likely causes and offers a restart.
  • If settings did change but none are included in the report, sending is blocked until at least one row is included, with an explanation of the reveal step. Withholding individual rows still works exactly as before.

Also adds a support-assistant knowledge file for Amply under docs/support/.

Technical Context

Prompted by the first device-support email to reach support@darken.eu: a HONOR report with changed_rows=0, feature_name=unspecified and rom_version=unspecified. Nothing was broken. PR #31 shipped in 0.2.1-beta0 and behaved as designed: it blocks a single-capture session and warns on an empty matrix, but deliberately let an empty two-mode result through, because "this ROM keeps the mode somewhere else" is a real finding. The report was delivered via the app's own "Send by email instead" button, so the contributor followed the flow correctly.

That #31 decision is reversed here. The negative result is real but indistinguishable from the two capture mishaps that produce identical output, so it was never trustworthy enough to justify the reports it admitted.

Two commits:

  1. detailsComplete gates DETATLS -> CAPTURE. Those two fields are the only part of a report that survives a zero-diff capture and often identify the ROM family on their own, so they move ahead of CAPTURE rather than sitting optional on a step users skip. Whitespace-only input doesn't count.
  2. deliverable (review.any { it.included }) gates REVIEW -> DELIVER, covering both dead ends with one predicate: an empty matrix leaves review empty, an all-withheld matrix leaves nothing included. nothingIncluded distinguishes the fixable case so the second card can name the reveal step. The contribution_next_empty ("Continue anyway") string is gone.

Worth a look during review: the all-withheld gate is the one with a real cost. A new OEM's key is redacted by default, so this is the normal state of the highest-value reports, and the gate pushes on people who may have stopped out of uncertainty. It does not force disclosure of any particular row, and the two-stage reveal/include model is unchanged.

ContributionReport.formatContributionReport keeps its zero-row wordings. They're now unreachable from the wizard but the formatter is a pure, separately-tested function and the schema-2 output stays correct.

docs/support/kindmail-system-prompt.md is content for the support mail assistant, not app code. It's here because it documents Amply's device-support matrix and discovery-report triage, both of which drift with the adapters. It records that zero-setting reports can now only come from 0.2.1-beta0 or older. It also overrides the shared prompt's Pro/refund/Play-rating sections, none of which apply to a pre-launch app with no billing.

The first device-support email to reach support@ arrived with
changed_rows=0 and both context fields empty. An empty matrix is still a
deliverable finding ("this ROM keeps the mode elsewhere"), but only if
the report says which feature and which ROM it came from -- without
those, a zero-diff capture is unattributable and there is nothing left to
follow up on except asking the contributor over email.

Feature name and software version were optional and sat on a step users
walk straight past. Both are now required before CAPTURE, gated in the
ViewModel with the bottom bar mirroring it, and the step says why they
are needed rather than leaving a disabled Next unexplained.

Also adds the KindMail support prompt for Amply under docs/support: the
mail assistant had no app knowledge and answered the contributor that
Amply was not one of ours.
@github-actions github-actions Bot added the enhancement New feature or request label Jul 28, 2026
A discovery report is only actionable if it names at least one candidate
key. Two shapes reached delivery without one, and both cost a maintainer
a round-trip that ends in "there is nothing here".

An empty matrix was deliverable on purpose: "this ROM keeps the mode
elsewhere" is a real result. In practice it is indistinguishable from the
two capture mishaps that produce the same output, so the negative result
was never trustworthy enough to pay for the reports it let through.
REVIEW now has no forward path at all when nothing differed, and the card
says so instead of offering "Continue anyway".

The second shape is a matrix whose rows were all withheld. A new device's
key is never on the auto-disclose allowlist by construction, so the
reports worth the most are exactly the ones that arrive empty when the
contributor skips the reveal step. Delivery now needs one included row,
with a card naming the step rather than leaving Next disabled and
unexplained. Withholding individual rows is untouched.

Both gates are one predicate, ContributionUiState.deliverable.
@d4rken d4rken changed the title Diagnostics: Require the device details before capturing Diagnostics: Only deliver discovery reports that carry a mapping Jul 28, 2026
@d4rken
d4rken merged commit 6dba6d5 into main Jul 28, 2026
12 of 13 checks passed
@d4rken
d4rken deleted the diagnostics/require-device-details branch July 28, 2026 17:31
d4rken added a commit that referenced this pull request Jul 28, 2026
Finishes the restructuring #36 landed half of: rules/release.md was renamed
to skills/release/SKILL.md there as a pure rename, so it had been sitting in
main without YAML frontmatter and could not load as a skill.

Three bodies of reference now live in .claude/skills/, each with frontmatter,
and the always-loaded rules keep only what every session needs:

- release — regains its frontmatter, and takes back the screenshot workflow
  that build-commands.md was duplicating
- device-qualification — qualification protocol, verified-device ledger and
  per-OEM known gaps, out of privileged-access.md
- oem-adapters — per-OEM adapter detail (keys, value domains, write ordering,
  session overrides), out of architecture.md

Content is unchanged in the move. architecture.md goes 208 -> 95 lines and
privileged-access.md 231 -> 136; each keeps a pointer to its skill, and
CLAUDE.md states the no-nested-CLAUDE.md rule explicitly so the adapter
detail is not re-nested next to the code later.

Source comments that pointed at the ledger in .claude/rules/privileged-access.md
now point at the skill. Comment-only; compileFossDebugKotlin passes. The
CLAUDE.md status line claimed 0.1.0-beta1 and now defers to VERSION.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant