mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-25 22:10:25 +00:00
8c8deeeb898722009f94b3bf10a3eedce4515bc2
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e4224da26b |
fix(progress): an abandoned child leaves both the done count and the total, and 0/0 renders as no progress (BUG-3195) (#1510)
* fix(progress): an abandoned child leaves both the done count and the total, server side (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * test(progress): every progress door leaves abandoned children out, member and guest, through the router (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * test(store): done-field progress tests expect abandoned children out of both counts (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * fix(progress): the web's per-row child counts leave abandoned children out, and 0/0 renders as no progress (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * test(progress): e2e for a cancelled child left out of the parent's progress; the redundant TableView guard is reverted (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * test(progress): the web's abandoned resolver and its Go/TS negative-terminal parity are pinned (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * fix(progress): the web's per-row counts judge each child by its own collection's done field, case-insensitively, as the server does (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * fix(progress): the web resolvers fall back on odd stored JSON, and per-row counts ignore a collection store stamped for another workspace (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * fix(progress): the web done-field resolvers validate stored schema fields in one place and fall back as Go does on a mistyped schema (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * docs(progress): the schema validator's comment states its parity limit on corrupt data (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N * test(progress): one shared vector pins the Go and web abandoned-child rules, including the corrupt-schema divergence (BUG-3195) Claude-Session: https://claude.ai/code/session_01RYiqbqXmxQMoKHsGm8B77N |
||
|
|
3f567965bc |
fix(web): a refused title keeps the typed text, and a too-long one is refused before sending (BUG-3115) (#1437)
* fix(web): a refused title keeps the typed text, and a too-long one is refused before sending (BUG-3115)
The sidebar quick-add dialog closed and cleared itself before the create
request, and the item title editor closed before its PATCH and re-seeds from
the stored title on reopen, so a title the server refused was simply gone.
Both now keep the text on screen, editable, with the reason beside it.
Every web door that sends a typed title (11 doors, 12 call sites) now checks
it against the server's limit first, on the exact string it sends. The limit
lives in web/src/lib/items/titleLimit.ts and counts code points after Go's
TrimSpace set, which is not JS's trim set (U+FEFF, U+0085). A shared corpus,
testdata/item_title_limit.json, is asserted by a Go test and a vitest suite,
and the Go half proves the corpus's whitespace list is exactly
unicode.IsSpace over the whole rune range.
The roles page's create refusal was console-only; it and the playbook and
convention forms now show the server's message instead of a generic one.
* fix(web): an in-flight quick-add belongs to one opening of the dialog (BUG-3115, codex r1)
The old response recognised "its" dialog by collection, so dismissing and
reopening the SAME collection mid-request let it close the new dialog and
clear the new text (the store's $state list hands out one stable proxy per
collection, so the comparison matched). A per-opening session counter
replaces it; Sidebar.quickAdd.svelte.test.ts pins both outcomes against a
$state-backed double and fails on the old comparison.
Also: the playbook duplicate refusal names the server's reason, and the
comments claiming every web door is checked now say UI doors where a user
types a title — WebMCP's agent-supplied titles and generated titles such as a
playbook "(copy)" are not pre-checked.
* fix(web): quick-add is read-only while its create is in flight, and a new opening does not inherit the busy state (BUG-3115, codex r2)
* fix(web): the playbook editor no longer refuses to save an unchanged legacy over-limit title (BUG-3115, lead NO-GO)
The server re-validates a title only when it changes (the handler's early
refusal and the store's echo comparison), so a playbook whose title predates
the 255-rune bound stays saveable as long as its title is sent back as-is.
save() always sends the title, and
|
||
|
|
b6afbb8fca |
fix(links,web): align the JS wiki-link grammar with Go's . (BUG-2834)
The Go and JS wiki-link patterns were byte-identical source text and did not mean the same thing. Both spelled the escape alternative `\\.`, but Go's RE2 `.` excludes only LF while ECMAScript's also excludes CR, U+2028 and U+2029. A body with a backslash immediately before one of those three was INDEXED by the server and NOT RENDERED by the client: the backlink panel claimed a link the document refused to draw. CRLF line endings make the CR case the plausible one. Measured on both sides before deciding anything, over nine code points. Exactly three diverge; VT, FF and U+0085 agree, which bounds the divergence at precisely ECMAScript's LineTerminator set minus LF rather than leaving it open at "some whitespace controls". Aligns JS UP to Go (`\\[^\n]`) rather than narrowing Go, for three independent reasons: the grammar's other alternative already admits RAW CR/LS/PS in both languages, so narrowing Go would make `[[A<CR>B]]` legal and `[[A\<CR>B]]` illegal; narrowing Go would stop ExtractWikiLinks returning rows it currently returns, and the next reconcile would DELETE them, which is BUG-2805's damage shape; and markdown.ts's own splitWikiBody already treats `\<CR>` as an escape pair, so only its regex disagreed. LF stays excluded on both sides — scanBracketBody depends on that and is untouched. Also collapses the two duplicate regex literals in markdown.ts into one exported WIKI_LINK_PATTERN_SOURCE. Exported as source text, not a RegExp object, because a `/g` regex carries lastIndex and sharing one between a replace() and a test's exec() would couple them through it. The harness is the part meant to outlive the fix. testdata/wiki_grammar_corpus.json is read by BOTH languages, and carries expectations derived from the grammar spec rather than from either implementation — comparing the two implementations to each other would have reproduced the exact blind spot that hid this, since looking identical is what they already did. Pure ASCII with every control character as a \uXXXX escape: an early probe typed U+2028/U+2029 into a shell heredoc, silently lost them, and would have "confirmed" the bug on two cases that were actually spaces. JS assertions are split across the node and jsdom projects because renderMarkdown finishes through DOMPurify and returns '' without a DOM, where it would fail for a reason unrelated to the grammar. Same split, same reason, as the existing markdown.shareAttachments pair; the jsdom file carries a leg proving the DOM path is live, since '' satisfies every not.toContain assertion. Negative-controlled both ways: reverting the JS pattern fails exactly 9 assertions (3 corpus + 3 per call site) and nothing else; narrowing the GO pattern to JS semantics fails the same 3 cases from the other side, so both halves are live instruments rather than tests that cannot fail. |