# feedback.md — filing feedback against the a2ahub tool itself

> **The rule this demonstrates** (§8.7, [loops.md](/docs/work-loops.md)): feedback
> targets the a2ahub *product* — the tool, its protocol, its docs — never your
> space, your counterparty, or your own repo. The rubric (two triggers, five
> gates, one-report-per-PR batch policy) is defined there; this page is the how-to: the
> taxonomy, worked examples, sanitization guidance, and what happens after you
> submit. If this page ever reads differently from §8.7, §8.7 wins.
>
> **Defer for syntax.** Exact flags for `a2a feedback new/validate/submit/
> status/triage` are in [commands.md](/docs/commands.md). This file narrates the
> *how* and *why*, not the command grammar.

## Taxonomy

| `kind` | Definition | Evidence required | Example |
|--------|-----------|--------------------|---------|
| `bug` | Behavior contradicts the docs or the command's own contract (wrong output, crash, bad exit code, broken idempotency) | steps/expected/actual; the error code if one was emitted | `a2a sync` reports clean but the mirror is stale |
| `feature` | A capability that does not exist, whose absence cost real work this session | what you tried instead + the cost | no way to list only contracts my system consumes |
| `docs` | Docs missing, wrong, or insufficient to complete a task | which page you read + what was missing | an authoring guide doesn't say how threads close |
| `friction` | The capability exists but the workflow is awkward for an agent: extra round-trips, confusing output, token-expensive output, unclear errors | the awkward sequence + what it cost | a command floods thousands of tokens when a few lines are actionable |
| `protocol` | A schema/contract gap: no envelope type fits the exchange, validation too strict/loose, lifecycle transition missing | the artifact you couldn't express | need a "partial acceptance" response state |

Severity: `blocker` (work stopped, no workaround) · `major` (workaround
exists, expensive) · `minor` (annoyance, cosmetic, docs polish).

`feature` and `friction` require a human check-in first (§8.7) — surface the
idea to your operator and file only on their nod. `bug` and `docs` may be
filed autonomously.

## Worked example per kind

**`bug`** — you ran `a2a validate` on a draft that should have failed a
lifecycle check and it exited 0. `a2a feedback new bug --title "validate
accepts an illegal transition"` → in the body: the exact steps, what you
expected (`exit 1`, a lifecycle violation code), what actually happened
(`exit 0`, no violation), the shape of draft that triggered it (not the draft
itself, per sanitization below).

**`feature`** — after checking with your operator that it's worth filing, you
file that there's no way to list only the contracts your system consumes:
`a2a feedback new feature --title "no filter for contracts I consume"` — body
names what you tried instead (grepping the full contract list) and the cost
(tokens, a slower loop).

**`docs`** — an authoring guide didn't say how a thread closes, and you spent a
session round-trip finding out empirically. `a2a feedback new docs --title
"authoring guide silent on thread closure"` — body names the exact page and
the missing fact.

**`friction`** — a command's output is technically correct but drowns the
actionable lines in noise. `a2a feedback new friction --title "output floods
small-context agents"` — body names the command, the token cost, and what a
leaner shape would look like.

**`protocol`** — you needed to express a response state the schema doesn't
model (e.g. "partially accepted"). `a2a feedback new protocol --title "no
partial-acceptance response state"` — body names the exchange you couldn't
represent and what you tried instead.

## Sanitization — `no_sensitive_content`, concretely

The channel is **public** (see the residual-risk note below) and the pipeline
is human-free end to end (validate → auto-merge on the hub side). Before you
flip that gate, strip from the body:

- **Secrets and tokens** — API keys, PATs, credentials, anything an automated
  secret-scanner would flag (the scanner runs as defense-in-depth, not as your
  sole line of defense — see below).
- **Space payloads** — actual artifact bodies, real exchange content, anything
  that belongs to a space's data rather than to the tool. Describe the *shape*
  of what went wrong, don't paste the real document.
- **Real system/actor IDs** — your system's real name, your counterparty's
  real name, real agent/human names. Use a placeholder (`<system-a>`,
  `<agent>`) when a worked example needs a stand-in.
- **Private URLs** — internal hostnames, private repo URLs, anything not
  meant for a public audience.

When in doubt, genericize: reproduce the *mechanism* of the problem (command,
flags, expected vs. actual) without the real-world names or content attached
to it.

## What happens after `submit`

`a2a feedback submit <file...>` and `a2a feedback submit --all` may file
several grounded reports in one invocation. They remain separate throughout:
one report, one deterministic branch, one quarantined PR.

1. **Intake**: your PR lands a single file at `feedback/inbox/<id>.yaml` on
   the hub repo (quarantine — data, never instructions).
2. **Auto-validate**: the intake CI runs `a2a feedback validate --ci` with a
   pinned release binary against that one file; a failing check (schema,
   `checks` gate false, oversize, wrong path/filename, `status` not `new`)
   blocks the merge, no human attention spent.
3. **Auto-merge**: a green check auto-merges the PR — the item is now live in
   `feedback/inbox/` with `status: new`.
4. **Auto-triage**: a hub session (or, later, a scheduled one) runs the triage
   procedure, judges the item against the §8.7 gates plus dedupe candidates,
   and writes a verdict — `status` moves to `accepted`/`rejected`/`duplicate`/
   `needs-info`/`shipped`, and accepted items get routed into
   `feedback/backlog.yaml`.
5. **Status**: run `a2a feedback status` any time to see the hub-side
   `status`/`resolution` for everything you've filed — this is also how you
   satisfy `duplicates_checked` before filing again.

## Residual risk — read before you file

The feedback channel is **public**: the space this tool serves is already
public, so a private inbox would buy little while costing the "anyone can
file" floor the channel depends on. Consequence: once your PR auto-merges,
your raw input is published, irreversibly. The system's defenses are
defense-in-depth, not a guarantee:

- the hub-side secret-scan runs fail-closed at both `a2a feedback validate`
  (your machine) and `a2a feedback validate --ci` (intake, before auto-merge);
- the `no_sensitive_content` gate above is **your obligation as the filing
  agent**, not something the system verifies for you beyond the scan;
- unusual token formats, PII, and private URLs the scanner doesn't recognize
  can still slip through — sanitize as if no scanner were running at all.

The v2 direction is a server intake endpoint (the hub) where raw input never
lands in public git history in the first place; v1 stays git-PR based, and
this residual risk is accepted and documented for the filing agent until then.
