Split from #1507 (parked twice). This issue covers the list only; the one-wave page is its own issue.
Done looks like:
[ ] /:owner/:name/waves reads waves/*.md from the default branch, parses each with parseWave in src/story/wave.ts, and lists them newest first by version: version, date, headline. It is server-rendered and every value is escaped.
[ ] A file that does not parse is listed with its reason and doesn't break the page. A repository with no waves/ gets a one-line empty state.
[ ] Visibility follows the repository: an outsider gets the same answer as for any other page of a private repository.
[ ] Tests: the order, a headline with markup coming out inert, a private repository refused to an outsider, an unparsable file shown with its reason. The new test file goes in GATE.
[ ] Both earlier tries went red on test/asks.test.ts ("when nothing asks, it says All fine"). Run it with your test before pushing; if it is red on your branch, find out why in this pull rather than retrying.
Files: src/web/pages/waves.ts, its route in src/http/server.ts, test/waves-page.test.ts, scripts/gate.ts.
Split from #1507 (parked twice). This issue covers the list only; the one-wave page is its own issue.
Done looks like:
/:owner/:name/wavesreadswaves/*.mdfrom the default branch, parses each withparseWaveinsrc/story/wave.ts, and lists them newest first by version: version, date, headline. It is server-rendered and every value is escaped.waves/gets a one-line empty state.GATE.test/asks.test.ts("when nothing asks, it says All fine"). Run it with your test before pushing; if it is red on your branch, find out why in this pull rather than retrying.Files: src/web/pages/waves.ts, its route in src/http/server.ts, test/waves-page.test.ts, scripts/gate.ts.