oficina / memoria Public

The door's button says Sign in; a quiet Title hint; /add's back link is the breadcrumb

Paul, 2026-10-01: the sign-in door's submit button says "Sign in", not
"Email me a link" (Memoria supplies the label). Polish audit r3 B7:
the Title hint was the label's bold; it is "(optional)", muted and
regular. C5: /add's back link was a paragraph with a section rule
under it; it is the breadcrumb nav the document page uses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 917e2b6d86e0c181bd8b56e24cfb8b30d6c13836 parent 89fcf99
5 files changed, +33 −8
  • internal/memoria/handlers.go +2 −2
  • internal/memoria/static/memoria.css +3 −0
  • internal/memoria/templates/add.html +3 −3
  • internal/memoriatest/chrome_test.go +20 −0
  • internal/memoriatest/signin_door_test.go +5 −3

CI passed — run details

CI log
=== vet ===
go vet ./...
=== fmt ===
=== test ===
go test ./...
?   	amadan.net/oficina/memoria/cmd/memoria	[no test files]
ok  	amadan.net/oficina/memoria/internal/memoria	6.476s
ok  	amadan.net/oficina/memoria/internal/memoria/chunk	(cached)
ok  	amadan.net/oficina/memoria/internal/memoria/fact	(cached)
?   	amadan.net/oficina/memoria/internal/memoria/icons	[no test files]
ok  	amadan.net/oficina/memoria/internal/memoria/index	(cached)
ok  	amadan.net/oficina/memoria/internal/memoria/notion	(cached)
ok  	amadan.net/oficina/memoria/internal/memoria/provider	(cached)
ok  	amadan.net/oficina/memoria/internal/memoria/query	(cached)
ok  	amadan.net/oficina/memoria/internal/memoria/seal	(cached)
ok  	amadan.net/oficina/memoria/internal/memoria/sibling	(cached)
ok  	amadan.net/oficina/memoria/internal/memoriatest	3.457s
?   	amadan.net/oficina/memoria/scripts/writeestilo	[no test files]
?   	amadan.net/oficina/memoria/tools/bench	[no test files]
?   	amadan.net/oficina/memoria/tools/drive	[no test files]
?   	amadan.net/oficina/memoria/tools/seed	[no test files]
?   	amadan.net/oficina/memoria/tools/vendorassets	[no test files]
=== migration-check ===
go run github.com/carlosframework/rastrillo/cmd/rastrillo migration check
rastrillo migration check: models and migrations agree
diff --git a/internal/memoria/handlers.go b/internal/memoria/handlers.go
index 8804b57..4670d5e 100644
--- a/internal/memoria/handlers.go
+++ b/internal/memoria/handlers.go
@@ -399,7 +399,7 @@ func newDropZone() dropZone {
MaxFiles: maxDropFiles,
SniffBytes: sniffBytes,
- TitleHint: "(Optional. Gives a title to pasted text)",
+ TitleHint: "(optional)",
FileLabel: "…or upload text files",
// Derived, so the hint cannot come to disagree with the caps it
// describes — nor with the refusals, which say them in the same
@@ -1261,7 +1261,7 @@ func (a *app) localSignin(w http.ResponseWriter, r *http.Request) {
Action: "/auth/begin",
AddressLabel: "Email address",
Help: signinHelp,
- Submit: "Email me a link",
+ Submit: "Sign in", // Paul, 2026-10-01: the door says "Sign in"
OpenSource: &chrome.Link{Href: "/help/open-source", Label: "Open source"},
}
if hasReturn {
diff --git a/internal/memoria/static/memoria.css b/internal/memoria/static/memoria.css
index 5ada8c7..13c4bdc 100644
--- a/internal/memoria/static/memoria.css
+++ b/internal/memoria/static/memoria.css
@@ -49,6 +49,9 @@ html { scrollbar-gutter: stable; }
[rst-stack] [rst-form-bar] { position: static; margin-top: 1rem; }
[rst-stack] { display: flex; flex-direction: column; gap: 0.35rem; }
[rst-stack] label { font-weight: 560; margin-top: 0.6rem; }
+/* A hint inside a label is quiet: muted and regular weight, not the
+ * label's 560 (polish audit r3 B7). */
+[rst-hint] { font-weight: 400; }
/* border-box: the fields are width 100% PLUS their padding otherwise,
* which ran 22px past the column at 1440 and off the screen at 390
* (polish audit §B6). Password fields are here too: the Notion token
diff --git a/internal/memoria/templates/add.html b/internal/memoria/templates/add.html
index d67b390..2687f85 100644
--- a/internal/memoria/templates/add.html
+++ b/internal/memoria/templates/add.html
@@ -5,11 +5,11 @@
here unchanged; POST /documents still receives them, and now redirects
back HERE with its outcome rather than to the index. The index keeps
search and the document list, and links here. */}}
-<p><a href="/">← Back to search</a></p>
-<section rst-section>
+<nav rst-breadcrumb><a href="/">← Back to search</a></nav>
+<section>
<h1>Add content</h1>
<form method="post" action="/documents" enctype="multipart/form-data" rst-stack>
- <label for="title">Title <span rst-muted>{{.Drop.TitleHint}}</span></label>
+ <label for="title">Title <span rst-muted rst-hint>{{.Drop.TitleHint}}</span></label>
<input type="text" id="title" name="title">
<label for="body">Paste text</label>
<textarea id="body" name="body" rows="8" placeholder="Paste a document, notes, minutes…"></textarea>
diff --git a/internal/memoriatest/chrome_test.go b/internal/memoriatest/chrome_test.go
index e266538..933856a 100644
--- a/internal/memoriatest/chrome_test.go
+++ b/internal/memoriatest/chrome_test.go
@@ -576,3 +576,23 @@ func TestEstilosChromeUsesOnlyDefinedTokens(t *testing.T) {
t.Fatalf("only %d token references in estilo's chrome; the walk is broken", seen)
}
}
+
+// polish audit r3 B7 and C5: the Title hint read as bold label text, and
+// /add put a section rule between "← Back to search" and its h1, where the
+// document page uses the breadcrumb nav.
+func TestTheAddPageReadsLikeTheDocumentPage(t *testing.T) {
+ b := get(t, newApp(t), "/add").Body.String()
+ if !strings.Contains(b, `<label for="title">Title <span rst-muted rst-hint>(optional)</span></label>`) {
+ t.Error("the Title hint is not a quiet \"(optional)\"")
+ }
+ if !strings.Contains(b, `<nav rst-breadcrumb><a href="/">← Back to search</a></nav>`) {
+ t.Error("/add's back link is not the breadcrumb the document page uses")
+ }
+ if regexp.MustCompile(`(?s)<section rst-section>\s*<h1>Add content</h1>`).MatchString(b) {
+ t.Error("a section rule still sits between the back link and the h1")
+ }
+ css, _ := os.ReadFile(filepath.Join("..", "memoria", "static", "memoria.css"))
+ if !regexp.MustCompile(`\[rst-hint\] \{[^}]*font-weight: 400`).Match(css) {
+ t.Error("the hint inherits the label's weight")
+ }
+}
diff --git a/internal/memoriatest/signin_door_test.go b/internal/memoriatest/signin_door_test.go
index d94155c..1aceb81 100644
--- a/internal/memoriatest/signin_door_test.go
+++ b/internal/memoriatest/signin_door_test.go
@@ -45,16 +45,18 @@ func TestSigninPageIsTheDoor(t *testing.T) {
"We’ll email you a link that signs you in. It works once and expires in 15 minutes.",
`href="/help/open-source"`,
`action="/auth/begin"`,
- `>Email me a link</button>`,
+ // Paul, 2026-10-01: the door's button says "Sign in".
+ `>Sign in</button>`,
} {
if !strings.Contains(html.UnescapeString(body), html.UnescapeString(want)) {
t.Errorf("the sign-in page lacks %q", want)
}
}
- // Retired (§9.2): the lede "Memoria holds your team's work…", and the
+ // Retired (§9.2): "Email me a link" (Paul, 2026-10-01), the lede
+ // "Memoria holds your team's work…", and the
// footer's egress claim, which is about searching and is said only to
// somebody signed in.
- for _, gone := range []string{"holds your team", "<footer", "leaves this instance"} {
+ for _, gone := range []string{"Email me a link", "holds your team", "<footer", "leaves this instance"} {
if strings.Contains(body, gone) {
t.Errorf("the sign-in page still carries %q", gone)
}