feat(api): machine-readable code and args on every error body #228
No reviewers
Labels
No labels
bug
enhancement
needs-triage
ready-for-agent
ready-for-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle!228
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/224"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #224
Every error body the harness API sends now includes a machine-readable
codeand itsargsnext to the English text. The English text is unchanged, byte for byte. The server still translates nothing; the editor will translate by code (that is the follow-up issue).What changed
internal/apimsg. Every code is defined once, ininternal/apimsg/codes_*.go(288 codes), asvar X = define("dotted.code", "English template").{name},{name|q}(printed like Go's%q) and{name|list}(joined with,).apimsg.New(apimsg.X, apimsg.Args{...}), and its English text is always rendered from the template.TestCallSiteswalks every non-test Go file in the module and fails on:Code("…")conversion or aMessage{}literal;TestRegistrychecks that the parsed definitions are exactly the registry.TestExportcomparesweb/src/i18n/servermessages.json(code →{template, args}) with the registry. It fails, naming the file, when the file is stale or missing. Regenerate it withgo test ./internal/apimsg -run TestExport -update.{error, code, args}.argsis always an object,{}when there is nothing to interpolate.fields.summary {field, msg}.errors[]entry carries its own code and args.element.FieldErrorgainsCode/Argsand is built withNewFieldError.pageops,elemopsandmediaopserrors implementapimsg.Coded.writeError/apimsg.FromErrorkeep a coded error's code. Any other error goes out aserror.unexpected {detail}.args.detailunder a wrapper code that describes the step that failed.codebesidemessage. A publish job's state carriesmessageCodefor its message andcode/argsfor its error.code/args./api/git/stategainsreasonCode/reasonArgs; the badges and pending list gainunavailableCode/unavailableArgs.labelCode: the Enabled field, and the module filters' Enabled/Disabled/Yes/No options.titleCode.Deliberately unchanged
hugoOutputand all CLI output stay plain English with no code, as the issue decided.http.Error405 on/api/statusis left as is, because it is not a JSON body.scaffold/site/AGENTS.mdand the scaffolded skills don't need changes: they document sidecars and harness commands, not the HTTP error body, and no command, flag or scaffold file changed.Known compromises
(allowed: {allowed})in the page-type refusals. The arg is a JSON array, but the English text renders it the way Go's%vdoes ([post section]) so the text stays byte-identical.publish.mediaMissing {refs}. The arg is the pre-rendered list text, which still contains English fragments such as "(referenced by …)" and "and N more". It can't be split byte-identically with the current template grammar.body.inlineParam. It carries the inner field error's English text asdetail.Verification
go test ./...,go vet ./...and gofmt are clean;make buildworks;npm testinweb/passes (2800 tests).internal/server/codes_test.go,codes_publish_test.go) cover:page.rootRenamepage.exists {slug}fields.summarywitherrors[0]=field.numberrequest.methodandrequest.missingParamcodeand anargsobjectharness serveon a copy oftestdata/site:{"error":"the content root page cannot be renamed","code":"page.rootRename","args":{}}{"error":"a page named \"posts\" already exists here","code":"page.exists","args":{"slug":"posts"}}{"error":"unknown language: \"xx\"","code":"editor.unknownLang","args":{"lang":"xx"}}web/src/i18n/servermessages.jsonmakesgo test ./internal/apimsgfail withweb/src/i18n/servermessages.json is missing …; run go test ./internal/apimsg -run TestExport -update.🤖 Generated with Claude Code
Handlers write coded messages: plain errors as {error, code, args}, the 422 summary as fields.summary, and the publish, media and git bodies with code/args beside their errors and codes beside their messages and labels. pagetree's unknown language and l10n's translate refusals are coded at their origin. The registry is exported to web/src/i18n/servermessages.json and the README documents the contract. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>[autoland] verdict: pass