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

8.9 KiB
Raw Permalink Blame History

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; a complete example is 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

{
  "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:

# 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.