Public: anyone can read this; the crew can change it.
See the launch week on one page: which approved post and email goes out on which day, and add it to your calendar #69
Check · Review · Land · Live done — Landed and live in production.
Each listing now has a launch-week page at `GET /listings/:id/schedule` and a calendar file at `GET /listings/:id/schedule.ics`. The full `bun test` suite passes (246 tests). I could not run `bun scripts/design-lint.ts`, `scripts/gate.ts` or `scripts/fast.ts` because they don't exist in this clone. `bun x tsc --noEmit` only printed tsc's help text because the repo has no tsconfig, so nothing was t…
shipped production is serving it deploy 957b843
Each listing now has a launch-week page at GET /listings/:id/schedule and a calendar file at GET /listings/:id/schedule.ics. The full bun test suite passes (246 tests). I could not run bun scripts/design-lint.ts, scripts/gate.ts or scripts/fast.ts because they don't exist in this clone. bun x tsc --noEmit only printed tsc's help text because the repo has no tsconfig, so nothing was type-checked.
- Plan:
src/schedule.tsbuilds the day-by-day rows from the listing's status, open houses and assets. It is pure and writes nothing.
- Launch day: MLS description, the three social posts and the email blast. - Coming soon: the teaser post and email, listed before the launch-day rows. - Other statuses: the status post and email. - Price drop: the price improvement post and email. - Open houses: a reminder post the day before and the open house itself, with its times.
- Rows: each row names the asset, links to it on the listing page, and says "Approved by … on …" or "Draft — not approved yet, so it does not go out". The page also says nothing is sent from here.
- Calendar file:
/listings/:id/schedule.icsis hand-built text/calendar with CRLF lines, escaped text and lines folded at 75 bytes. It has one event per row, and a draft's title starts with "DRAFT:".
- Dates: open houses are floating local times and every other event lasts all day. Nothing is converted between time zones.
- Escaping: a test with a hostile address containing ;, ,, \ and a newline shows it can't add an event.
- Reachability: the listing page has a "Launch week" button, and the schedule page has an "Add to calendar" link. Both pages print cleanly via the existing print styles. The README has a new step 14 describing it.
- Other changes: a few CSS classes in
static/app.css, documented indocs/design/areas/schedule.md. The OpenAPI file is regenerated. - Tests:
src/schedule.test.tscovers the 412 Alder Lane rows, draft versus approved, the coming-soon teaser order, open-house reminders, the.icsshape and escaping, and 404s. I also added the schedule page to the a11y and hostile-input page lists. - Permissions: reads go through
getListing, sopermitdecides as it does for the report, and I changed nocontract.jsoncell.
The listing has no stored launch date, so "launch day" is the date the listing was created. A coming-soon listing's teaser and its launch-day rows therefore share that same day.
The reminder post uses the Short post asset, and the open house row links to the Flyer copy.
I left out a separate go-live date field, the sign-in sheet as a schedule row, and any sending.
To try it, open a listing and press Launch week, then Add to calendar.
🤖 Generated with Claude Code
The web side is sound: reads go through getListing/permit, text is escaped, the .ics is hand-built with CRLF, escaping and folding, and no contract cell is loosened. Changes needed, all in this round:
- Both doors (blocking): the terminal has no way to see the launch week. The seller report has
Rin src/tty.ts (line ~287); add the same for the schedule, e.g. a key that shows the day-by-day rows as text (reuse scheduleDays, approved/Draft per row, gated exactly as the page is), with help-line text and a tty test. The README step 14 must then say how to use it in the terminal. - Tests: 'nothing is written by a read' is only a 404 check. Assert the database is unchanged after reading /schedule and /schedule.ics (or drop the claim). Remove the stray
/schedule-not-herecall in the first test. Add a test where a listing a test approved shows as approved, so draft vs approved is proved beyond the sample. - Contract/speed: add the schedule routes to the per-door rows in src/contract.test.ts if routes are enumerated there, and confirm src/speed.test.ts covers /schedule and the .ics.
- Box 7 asks for a paragraph in the README's agent section; the change adds only walkthrough step 14. Add the paragraph there.
- design-lint, gate and tsc were not run; run design-lint if it exists and say what could not be run.
All five review points are addressed and pushed to the same branch. The full bun test suite passes (251 tests).
- Terminal:
won an open listing shows the launch week as text.
- Each row reads all day · What · Asset · Approved by … on … (an open house shows its start–end times instead of "all day"), or "Draft — not approved yet, so it does not go out". Esc goes back, and the help line names w.
- It is gated like the R seller report: it appears only once the listing has been read.
- New tests in src/tty.test.ts cover a draft, an approved asset, and the help line.
- Tests:
- I removed the stray /schedule-not-here call.
- A new test snapshots the listing, asset, audit and event tables, reads /schedule and /schedule.ics, and asserts nothing changed. It also still checks the 404s.
- Another test approves the MLS description on a test-made listing through the page. That row then shows "Approved by pat", the other rows stay Draft, and the .ics marks exactly those as DRAFT:.
- Contract and speed:
src/contract.test.tsdoesn't list per-route rows for the report, the kit or any other listing page, so I added nothing there.src/speed.test.tsnow includes/listings/1/scheduleand/listings/1/schedule.ics, and both pass under the 50 ms bar. - README: I added the paragraph on the launch week to the agent section, in the same place as the launch kit, and step 14 now mentions
win the terminal. - Checks:
- Design lint: bun scripts/lint-design.ts is clean. The script is named lint-design.ts, not design-lint.ts as the instructions had it.
- Not run: there is no scripts/gate.ts or scripts/fast.ts in this clone. bun x tsc --noEmit only prints tsc's help text because the repo has no tsconfig, so nothing was type-checked.
- OpenAPI: I regenerated contract/openapi.json.
No contract.json cell changed.
🤖 Generated with Claude Code
I merged main into the branch and pushed; the full bun test suite passes (260 tests) and bun scripts/lint-design.ts is clean.
src/hostile.test.ts: both sides edited the same list of pages. I keptmain's/listings/:id/cardand my/listings/:id/schedule.static/app.css: both sides added a block at the end of the file. I kept both, and put back the closing braces of my@media printblock, which the conflict had split. One stylesheet test failed on those braces until I did.contract/openapi.json: I regenerated it after the merge.
🤖 Generated with Claude Code
Clean. Reads go through getListing/permit, nothing is mutated, no contract cell changed. The terminal has the same plan on w, gated like R. Output is escaped and the .ics is hand-built with CRLF, escaping and folding, with tests for a hostile address. The preview serves the page. I could not diff against my last head because the commit is not in the clone, so this is a read of the whole change.
Each listing now has a launch-week page at
GET /listings/:id/scheduleand a calendar file atGET /listings/:id/schedule.ics. The fullbun testsuite passes (246 tests). I could not runbun scripts/design-lint.ts,scripts/gate.tsorscripts/fast.tsbecause they don't exist in this clone.bun x tsc --noEmitonly printed tsc's help text because the repo has no tsconfig, so nothing was type-checked.src/schedule.tsbuilds the day-by-day rows from the listing's status, open houses and assets. It is pure and writes nothing.- Launch day: MLS description, the three social posts and the email blast. - Coming soon: the teaser post and email, listed before the launch-day rows. - Other statuses: the status post and email. - Price drop: the price improvement post and email. - Open houses: a reminder post the day before and the open house itself, with its times.
/listings/:id/schedule.icsis hand-built text/calendar with CRLF lines, escaped text and lines folded at 75 bytes. It has one event per row, and a draft's title starts with "DRAFT:".- Dates: open houses are floating local times and every other event lasts all day. Nothing is converted between time zones. - Escaping: a test with a hostile address containing
;,,,\and a newline shows it can't add an event.static/app.css, documented indocs/design/areas/schedule.md. The OpenAPI file is regenerated.src/schedule.test.tscovers the 412 Alder Lane rows, draft versus approved, the coming-soon teaser order, open-house reminders, the.icsshape and escaping, and 404s. I also added the schedule page to the a11y and hostile-input page lists.getListing, sopermitdecides as it does for the report, and I changed nocontract.jsoncell.The listing has no stored launch date, so "launch day" is the date the listing was created. A coming-soon listing's teaser and its launch-day rows therefore share that same day.
The reminder post uses the Short post asset, and the open house row links to the Flyer copy.
I left out a separate go-live date field, the sign-in sheet as a schedule row, and any sending.
To try it, open a listing and press Launch week, then Add to calendar.
🤖 Generated with Claude Code
Closes #63