makepad/docs/agents/change-report.md
Admin 012e6f7df5 tools, libs and the rest
cargo-makepad, makepad-builder (with an Android step on every OS), CI tools
and tiles, and the remaining libraries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

196 lines
8.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Change reports: sending your changes to Makepad
People who install Makepad apps with the Makepad Builder change the apps'
source with their own coding agent (Codex desktop, Codex CLI, Claude Code or
any other). A change report tells Makepad what they changed, as concepts:
what is different for someone using the app, and why. The person reads the
report before it is sent; nothing leaves their machine without that.
This document is the format and the rules. `AGENTS.md` ("Sending your
changes to Makepad") tells an agent how to write one; `libs/change_report`
checks one exactly as described here, in the Builder before sending and on
the server when it arrives. The JSON schema of `report.json` is
[change-report.schema.json](change-report.schema.json); a complete example
is [change-report-example/report.json](change-report-example/report.json).
## The zip
A change report is one zip file of at most **256 KB** holding exactly:
| file | | |
|------|---|---|
| `report.json` | required | the list of changes (schema below), at most 128 KB |
| `REPORT.md` | required | the same list for people, at most 128 KB; this is what the person reads before sending |
| `changes.diff` | only if the person opted in | a trimmed unified diff of the changes that matter, at most 1 MB unpacked |
No other files, no folders, no binaries: each file is UTF-8 text without NUL
or other control characters (tabs and newlines are fine). A diff holds no
`GIT binary patch`; leave images and other binary files out.
The Builder can make the zip itself: an agent may leave the three files in
a folder, `builder/changes/<app>-report/`, instead of a zip at
`builder/changes/<app>-report.zip`.
## report.json
```json
{
"format": "makepad-change-report",
"version": 1,
"app": {"id": "calculator", "release": "2026-09-20"},
"base": [{"repository": "makepad", "commit": "7a533b61ee0c4e1f9d2b3a4c5d6e7f8091a2b3c4"}],
"summary": "Two small changes so the calculator suits a keyboard-first workflow.",
"changes": [
{
"title": "Enter repeats the last operation",
"kind": "feature",
"what": "Pressing Enter again after a result applies the same operation and operand once more.",
"why": "Adding the same amount several times took retyping the operand each time.",
"areas": ["calculator keypad", "apps/calculator/src/app.rs"]
},
{
"title": "Larger result text",
"kind": "ui",
"what": "The result line uses a larger font and stays right-aligned when the window is narrow.",
"why": "The result was hard to read from a distance.",
"areas": ["result display"],
"snippet": {"language": "splash", "text": "draw_text +: {text_style: theme.font_regular{font_size: 28}}"}
}
],
"redactions": [
{"what": "home folder path", "count": 2},
{"what": "personal name in a comment", "count": 1}
],
"diff": false
}
```
| field | | |
|-------|---|---|
| `format`, `version` | required | `"makepad-change-report"` and `1` |
| `app.id` | required | the app's id in the Builder (`scope`, `stage`, `calculator`, ...) |
| `app.release` | required | the release the edits were made against: `"release"` in `builder/installed/<app>.json` |
| `base` | optional | that release's repositories and commits (`"repositories"` in the same file), at most 8 |
| `summary` | optional | one paragraph, at most 2000 characters |
| `changes` | required | 1 to 100 items |
| `changes[].title` | required | one line, at most 120 characters |
| `changes[].kind` | required | `fix`, `feature`, `tweak`, `ui`, `performance`, `refactor`, `docs` or `other` |
| `changes[].what` | required | what changed, as the person using the app sees it; concepts, not code; at most 2000 characters |
| `changes[].why` | optional | why, at most 1000 characters |
| `changes[].areas` | optional | up to 16 screens, components or modules by name (repo-relative paths are fine), 80 characters each |
| `changes[].snippet` | optional | `{"language", "text"}`, only when the change cannot be told without it; at most 1500 characters and 40 lines |
| `redactions` | required | what was taken out, by kind and count, never the removed value; `[]` when nothing was |
| `diff` | required | `true` exactly when the zip holds `changes.diff` |
Text fields hold no control characters other than newlines and tabs; titles
and areas are one line. Unknown fields are refused, so a report carries
nothing the person did not see listed.
## REPORT.md
The same changes, for people. It must name every change by its exact title;
otherwise its form is free. The Builder's own rendering, which agents may
copy:
```markdown
# Changes to calculator (release 2026-09-20)
Two small changes so the calculator suits a keyboard-first workflow.
## 1. Enter repeats the last operation (feature)
Pressing Enter again after a result applies the same operation and operand once more.
Why: Adding the same amount several times took retyping the operand each time.
Areas: calculator keypad, apps/calculator/src/app.rs
## Taken out before sending
- home folder path × 2
- personal name in a comment × 1
No code diff is included.
```
## Anonymisation
The agent scans everything that goes into the zip (the list, REPORT.md and
the diff) and replaces personal and secret data with a bracketed
placeholder, then lists each kind it replaced in `redactions`:
| take out | replace with |
|----------|--------------|
| names of people, usernames, handles | `[name]` |
| email addresses | `[email]` |
| absolute paths and home folders (`/Users/…`, `/home/…`, `C:\Users\…`, `\\server\share`) | a repo-relative path, or `[path]` |
| host and machine names, private IP addresses (`10.x`, `192.168.x`, `172.16-31.x`, `.local`, `.internal`, `.lan`) | `[host]` |
| API keys, tokens, passwords, private keys, credentials in URLs | `[secret]` |
| URLs of private or internal services | `[private-url]` |
| personal data in strings and comments (addresses, phone numbers, customer data) | `[personal]` |
Public URLs (makepad.nl, github.com/makepad, documentation) and placeholder
addresses (`@example.com`) may stay. Use these bracketed placeholders, not
`<angle brackets>`, so every report reads the same.
The Builder and the server run a safety-net scan of every file and refuse a
report that still holds an email address (other than `@example.*` and
`@makepad.nl`), an absolute or home folder path, a well-known key or token
format (`sk-…`, `ghp_…`, `AKIA…`, `xoxb-…`, private key blocks, `Bearer …`,
`password = "…"`-style assignments), credentials in a URL, or a private
network address. The refusal names the file, line and kind of each finding.
Names of people and personal details in prose cannot be found this way:
they are the agent's to take out and the person's to check when reading.
## Sending
The person sends the report from the Builder (`e` on the app's row: the
review page lists the changes, then Send anonymously, Send with my email,
Read it all or Don't send), or the agent sends it after the person approved
the list in the conversation:
makepad-builder.exe send-changes <app> [PATH] [--yes] [--with-email] (Windows)
./makepad-builder.sh send-changes <app> [PATH] [--yes] [--with-email] (macOS, Linux)
Without `--yes` it only checks the report and prints what would be sent.
`--with-email` includes the address the Builder is logged in with, so
Makepad can reply; the agent never sees it. A sent report is renamed
`<app>-report-sent-<id>` in `builder/changes/`.
`makepad-builder.exe changes <app>` / `./makepad-builder.sh changes <app>` prints the
edits to describe: the diff of the app's source snapshot against the
release it was checked out at (`--files` lists the files).
## The endpoint
POST https://makepad.nl/api/feedback/changes
X-Makepad-Feedback: 1
Content-Type: application/zip
X-Makepad-Reply-To: name@example.com (optional)
<the zip>
`MAKEPAD_FEEDBACK_URL`, when set, names the feedback endpoint instead
(`http://127.0.0.1:8080/api/feedback`); change reports then go to that URL
followed by `/changes`.
| answer | |
|--------|---|
| `200 {"ok":true,"id":N}` | stored; N is the report id |
| `400 {"error":…}` | invalid `X-Makepad-Reply-To` |
| `403` | no `X-Makepad-Feedback: 1`, or a browser `Origin` |
| `413` | larger than 256 KB |
| `415` | not `application/zip`, or not a zip |
| `422 {"error":…}` | the report fails a check; the reason says which (scan findings one per line) |
| `429` | rate limit (shared with app feedback: 10 per client address and 300 overall per hour) |
| `507` | feedback storage full |
Without the Builder (a plain HTTP fallback):
curl -sS -X POST -H 'X-Makepad-Feedback: 1' -H 'Content-Type: application/zip' \
--data-binary @changes.zip https://makepad.nl/api/feedback/changes
The server keeps the zip as sent and REPORT.md as the text of a feedback
item in the admin Feedback inbox (source "changes"), with the release, the
change titles, what was taken out and whether a diff is included. No IP
address or other request data is stored.