Public: anyone can read this; the crew can change it.

Download a listing's launch kit: every asset in one file, marked approved or draft, to hand to an assistant #49

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Every listing page now has a **Download launch kit** link, and the same kit comes from the `launch_kit` MCP tool and from `k` in the terminal. The full suite passed once, except `src/deps.test.ts`'s "no lockfile or node_modules" test. My own `bun install` had created `node_modules`, so I deleted it and re-ran that file. After the last edits I re-ran only the server, walkthrough, deps and openapi t…

shipped production is serving it deploy 957b843

opened this

Every listing page now has a Download launch kit link, and the same kit comes from the launch_kit MCP tool and from k in the terminal. The full suite passed once, except src/deps.test.ts's "no lockfile or node_modules" test. My own bun install had created node_modules, so I deleted it and re-ran that file. After the last edits I re-ran only the server, walkthrough, deps and openapi tests, and they pass.

I did not run bun x tsc --noEmit: the repo has no tsconfig, so it only prints help. There is no scripts/gate.ts or scripts/fast.ts. scripts/design-lint.ts doesn't exist either; bun scripts/lint-design.ts ran with no findings.

What changed

  • Module: src/kit.ts turns a listing into the kit text. It starts with the address, price, facts, open house and agent, then every asset under == Label ==. Each asset is marked "Approved by NAME on DATE" or "DRAFT — not approved", with its open Fair Housing findings under it. The statuses and price-improvement assets are included when the listing has them. kitFilename builds the name from the address in [a-z0-9-], e.g. 412-alder-lane-portland-or-97214-launch-kit.txt. It falls back to listing-<id>-launch-kit.txt if the address leaves nothing.
  • Hostile text: control and bidi characters are stripped, and asset lines are indented so a hostile asset can't fake a heading or an approval line.
  • Permissions: launchKit in src/actions.ts reads the listing through getListing, so it goes through permit. No cell changed.
  • Doors:

- GET /listings/:id/kit.txt in src/routes.ts sends the file as an attachment with the security headers. - The listing page links to it. - The launch_kit MCP tool returns the same text. The MCP server now passes a string result through as plain text instead of JSON-quoting it. - In the terminal, k on an open listing shows the kit and esc goes back.

  • API description: the kit route declares an api entry with a new optional mime field, so contract/openapi.json lists it as text/plain. The file is re-emitted.
  • README: one plain-words step names the button. The technical details sit in the later section, because walkthrough.test.ts bans words like "MCP" in the first one.
  • Tests:

- src/kit.test.ts: every asset appears once, a draft is marked, an approval is named, a finding is listed, the filename is safe, MCP and the terminal match the page, and the route sends the attachment. - src/hostile.test.ts: the kit survives the hostile listing with no control characters. - src/server.test.ts: the expected MCP tool list now includes launch_kit.

Two existing tests I changed

  • k key: k was "move up" in the terminal's open-listing view, and the issue asks for k to show the kit. k now shows the kit there, and the arrow keys still move. I changed one line in src/tty.test.ts from k to the up arrow, and the help text now says j/↓↑.
  • Tool list: the MCP tool-list assertion in src/server.test.ts gained launch_kit.

Not done: the kit is plain text only, with no zip, and no sharing or emailing from the app.

To try it: open any listing, for example 412 Alder Lane, and press Download launch kit. Or run curl -OJ <app>/listings/1/kit.txt.

Closes #38

commented

Every listing page now has a Download launch kit link, and the same kit comes from the launch_kit MCP tool and from k in the terminal. The full suite passed once, except src/deps.test.ts's "no lockfile or node_modules" test. My own bun install had created node_modules, so I deleted it and re-ran that file. After the last edits I re-ran only the server, walkthrough, deps and openapi tests, and they pass.

I did not run bun x tsc --noEmit: the repo has no tsconfig, so it only prints help. There is no scripts/gate.ts or scripts/fast.ts. scripts/design-lint.ts doesn't exist either; bun scripts/lint-design.ts ran with no findings.

What changed

  • Module: src/kit.ts turns a listing into the kit text. It starts with the address, price, facts, open house and agent, then every asset under == Label ==. Each asset is marked "Approved by NAME on DATE" or "DRAFT — not approved", with its open Fair Housing findings under it. The statuses and price-improvement assets are included when the listing has them. kitFilename builds the name from the address in [a-z0-9-], e.g. 412-alder-lane-portland-or-97214-launch-kit.txt. It falls back to listing-<id>-launch-kit.txt if the address leaves nothing.
  • Hostile text: control and bidi characters are stripped, and asset lines are indented so a hostile asset can't fake a heading or an approval line.
  • Permissions: launchKit in src/actions.ts reads the listing through getListing, so it goes through permit. No cell changed.
  • Doors:

- GET /listings/:id/kit.txt in src/routes.ts sends the file as an attachment with the security headers. - The listing page links to it. - The launch_kit MCP tool returns the same text. The MCP server now passes a string result through as plain text instead of JSON-quoting it. - In the terminal, k on an open listing shows the kit and esc goes back.

  • API description: the kit route declares an api entry with a new optional mime field, so contract/openapi.json lists it as text/plain. The file is re-emitted.
  • README: one plain-words step names the button. The technical details sit in the later section, because walkthrough.test.ts bans words like "MCP" in the first one.
  • Tests:

- src/kit.test.ts: every asset appears once, a draft is marked, an approval is named, a finding is listed, the filename is safe, MCP and the terminal match the page, and the route sends the attachment. - src/hostile.test.ts: the kit survives the hostile listing with no control characters. - src/server.test.ts: the expected MCP tool list now includes launch_kit.

Two existing tests I changed

  • k key: k was "move up" in the terminal's open-listing view, and the issue asks for k to show the kit. k now shows the kit there, and the arrow keys still move. I changed one line in src/tty.test.ts from k to the up arrow, and the help text now says j/↓↑.
  • Tool list: the MCP tool-list assertion in src/server.test.ts gained launch_kit.

Not done: the kit is plain text only, with no zip, and no sharing or emailing from the app.

To try it: open any listing, for example 412 Alder Lane, and press Download launch kit. Or run curl -OJ <app>/listings/1/kit.txt.

Approved

Clean. The kit is read through getListing, so permit gates it and no contract cell moved. Filename and body are sanitised, and the security headers are on the attachment. The page, MCP and terminal doors all work and have tests. The preview serves the kit correctly. Minor, not blocking: the route could call launchKit instead of repeating getListing plus kit.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs