# Feedback and preferred edits

People can tell a chat two useful things about a reply: a **rating**, whether it was good, and a **preferred edit**, what it should have said instead.

Recording feedback changes no model, prompt or agent by itself. It appends evidence to the session's journal, next to the reply it judges. `june/train`, and applications such as the [Copy Agent](https://github.com/johno/june/blob/main/apps/copy-agent/README.md), decide later how to use that evidence.

```text
turn.completed (the reply, never changed)
  └ feedback.recorded  rating, comment, tags
  └ feedback.recorded  preferred: the reply a person would have wanted
        │
        ▼  later, when you choose
june/train: conversation datasets, preference pairs, eval cases
```

## Recording feedback

Record feedback on the session, by turn id:

```ts
import type { Session } from "june/chat";

declare const session: Session;

const turn = session.send("Explain the render loop.");
await turn.result;

await session.feedback(turn.id, {
  rating: "negative",
  comment: "Too verbose.",
});
await session.feedback(turn.id, {
  preferred: "June re-renders only the steps whose inputs changed.",
  tags: ["verbosity"],
});

console.log(session.turns().at(-1)?.feedback);
```

- **`rating`** is `"positive"`, `"negative"`, or a number on your own scale. It judges the reply as it is.
- **`preferred`** is the reply a person would have wanted: a human edit. It's stored next to the original, which never changes, so a later preference dataset can use the edit as chosen and the original as rejected.
- **`comment`** and **`tags`** are free text and labels for whoever curates the data.

Each call validates the feedback, needs at least one field, and appends one `feedback.recorded` entry. Nothing is edited in place: a turn's `feedback` lists every entry oldest first, with its `id` and `at`, and a later rating doesn't erase an earlier one, so curation can decide which to trust. Feedback is only recorded on completed turns; running, failed, canceled and interrupted turns have no reply to judge, and `feedback()` rejects them before writing anything.

In the terminal, `june chat`'s `/feedback up` and `/feedback down` rate the last reply; see the [CLI reference](https://june.dev/docs/cli.md#june-chat). Edits and comments come from your own interface: a text box, an editor, or a command, as the [Copy Agent](https://github.com/johno/june/blob/main/apps/copy-agent/README.md#write-and-correct-it) does with `/edit`.

Feedback is written to the session's store like any other entry, so it's subject to the same [one writer per session](https://june.dev/docs/chat/sessions.md#filestore) rule. Record feedback through the `Session` that's running the conversation, or after it's closed, not from a second process while it's open.

## Feedback in context

By default, feedback is stored for later improvement and isn't shown to later turns: `fullContext()` and `summaryContext()` send the original replies, as they were, and never the ratings or edits. If you want later turns to see it, say so in a custom context, for example by showing the model a person's preferred edit instead of its own reply; see [Custom context](https://june.dev/docs/chat/context.md#custom-context).

## Knowing what was judged

Feedback is only useful if you know what produced the reply it judges. Every completed turn records its responder's `kind`, `id` and `version`, the model, usage and finish reason: see [Provenance](https://june.dev/docs/chat/responders.md#provenance). Set a responder's `version` whenever its prompt, model or workflow changes, so feedback on old replies isn't mistaken for feedback on new ones. When you later compare a candidate with what's active, that's what tells you which version each piece of evidence judged.

## From feedback to improvement

`june/chat` only records the signal. Turning it into training data and eval cases is `june/train`'s job, which reads sessions and never the other way around:

- a turn with a preferred edit becomes a conversation example that teaches the edit, a preference pair with the edit chosen over the original, and an eval case that expects the edit;
- a positively rated turn can become a training target and a regression case;
- a negatively rated turn without an edit is eval material, never a training target.

Nothing here changes what answers your chats. Evaluating a candidate on cases from these sessions, and switching the chat to it, is a step a person takes. Feedback is written by people and can contain anything, including personal data, so review it before training on it; see [Privacy and security](https://june.dev/docs/chat/privacy.md).

**Next:** [Learning from chat](https://june.dev/docs/chat/learning.md) turns recorded feedback into datasets and eval cases, with its curation rules and provenance. [`src/examples/chat/learning.ts`](https://github.com/johno/june/blob/main/packages/june/src/examples/chat/learning.ts) does it in one script.
