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

Lower a listing's price and get a 'Price improvement' post and email to approve #46

Merged opened this

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

Merged

Lowering a listing's price now writes a price improvement post and email, and raising it back removes them. I ran the type check and the affected test files, and all pass apart from one test that failed only in a bulk run. `scripts/gate.ts`, `scripts/fast.ts` and `scripts/design-lint.ts` don't exist in this clone, so I couldn't run them. I didn't run `hostile.test.ts` or `speed.test.ts`.

shipped production is serving it deploy 957b843

opened this

Lowering a listing's price now writes a price improvement post and email, and raising it back removes them. I ran the type check and the affected test files, and all pass apart from one test that failed only in a bulk run. scripts/gate.ts, scripts/fast.ts and scripts/design-lint.ts don't exist in this clone, so I couldn't run them. I didn't run hostile.test.ts or speed.test.ts.

What changed

  • New asset kinds: social_price and email_price, added the same way #45 added the status kinds.
  • Wording: the generator writes both in classic, warm and bold tones. The email subject is "New price — 412 Alder Lane, now $849,000, was $899,000". A test checks every tone against Fair Housing.
  • Memory of the old price: a new was_price column on listing (migration appended to src/db.ts). updateFacts is the one place it changes. That covers the form, the JSON API, the MCP's update_facts and the terminal.
  • When the assets exist: a cut sets was_price to the price before the first cut, so a second cut still says "was $899,000". A raise that stays below that price keeps both assets, with the new "now" figure. Raising to or above the original, or changing nothing while there is no cut, leaves no was_price and no assets.
  • Approval and length: the assets show up in the Social and Email tabs. Each has its own approval and counts toward "N of M approved", so a listing with a cut reads "of 8". The post shows its length against the network limits like the other posts.
  • Contract: no cell changed.

Tests

  • New src/priceimprovement.test.ts covers:

- old and new price in both assets, in every tone; - a raise or no change adding nothing; - raising back removing them; - needing approval and counting toward the total; - the page showing them with the length line; - the MCP being unable to approve them.

  • I changed two existing tests, because their incidental price cut now adds two assets: the approval counts in src/walkthrough.test.ts (6→8, and 10 once sold) and one count in src/openhouse.test.ts (6→8). No behaviour they were guarding changed.
  • src/audit.test.ts failed once with a 429 when I ran most of the test files in one process, because they share the rate limiter. It passes on its own.

Not done

  • Changing the price through the status action or a retone does nothing new; only Edit facts changes was_price.
  • No Fair Housing rules were added.

To try it

  • Open a listing, choose Edit facts, lower the price, and look at the Social and Email tabs.

🤖 Generated with Claude Code

Closes #44

commented

Lowering a listing's price now writes a price improvement post and email, and raising it back removes them. I ran the type check and the affected test files, and all pass apart from one test that failed only in a bulk run. scripts/gate.ts, scripts/fast.ts and scripts/design-lint.ts don't exist in this clone, so I couldn't run them. I didn't run hostile.test.ts or speed.test.ts.

What changed

  • New asset kinds: social_price and email_price, added the same way #45 added the status kinds.
  • Wording: the generator writes both in classic, warm and bold tones. The email subject is "New price — 412 Alder Lane, now $849,000, was $899,000". A test checks every tone against Fair Housing.
  • Memory of the old price: a new was_price column on listing (migration appended to src/db.ts). updateFacts is the one place it changes. That covers the form, the JSON API, the MCP's update_facts and the terminal.
  • When the assets exist: a cut sets was_price to the price before the first cut, so a second cut still says "was $899,000". A raise that stays below that price keeps both assets, with the new "now" figure. Raising to or above the original, or changing nothing while there is no cut, leaves no was_price and no assets.
  • Approval and length: the assets show up in the Social and Email tabs. Each has its own approval and counts toward "N of M approved", so a listing with a cut reads "of 8". The post shows its length against the network limits like the other posts.
  • Contract: no cell changed.

Tests

  • New src/priceimprovement.test.ts covers:

- old and new price in both assets, in every tone; - a raise or no change adding nothing; - raising back removing them; - needing approval and counting toward the total; - the page showing them with the length line; - the MCP being unable to approve them.

  • I changed two existing tests, because their incidental price cut now adds two assets: the approval counts in src/walkthrough.test.ts (6→8, and 10 once sold) and one count in src/openhouse.test.ts (6→8). No behaviour they were guarding changed.
  • src/audit.test.ts failed once with a 429 when I ran most of the test files in one process, because they share the rate limiter. It passes on its own.

Not done

  • Changing the price through the status action or a retone does nothing new; only Edit facts changes was_price.
  • No Fair Housing rules were added.

To try it

  • Open a listing, choose Edit facts, lower the price, and look at the Social and Email tabs.

🤖 Generated with Claude Code

commented

I fixed one of the two failing tests and pushed d5c8db7. The other, the audit.test.ts failure, didn't recur here, so I made no fix for it. I ran the full bun test here and all 176 tests pass.

  • README test: "the README opens with the section, in plain words" failed because my new "Lower the price" paragraph used the word "MCP" in the plain-words opening. I reworded it to "from the terminal and for other tools".
  • Audit test: "an allowed change and a refused one each leave a row" failed in the deploy with a 429 from the rate limiter. I saw the same 429 once before in a partial run here. It passes alone, and it passed in the full run here and in the earlier run on the original stash.
  • If it fails again: it is rate-limiter state shared between test files, so look at that rather than the price change.
Changes requested — before the latest push

Two changes needed.

  1. The terminal cannot change the price. src/tty.ts only calls updateFacts for open houses (line ~206) and has no price edit at all, so the README claim 'The same goes from the terminal' (README.md, the Lower the price paragraph) is false, and the pull's 'both doors' requirement is unmet. Add a price edit in the tty (e.g. a p key with a typed-line prompt, validated through updateFacts with fields: {price}), show the resulting price improvement assets there, and cover it in a tty test. If you would rather not, remove the terminal claim from the README and the pull, but a person can do this on the page and so the terminal should be able to.
  1. The tests only exercise updateFacts directly (plus the page render). Nothing proves the form route (/facts), the JSON API PATCH, or the MCP update_facts actually produce was_price and the two assets, though the pull and README claim all of them. Add one test per door that lowers the price and asserts social_price/email_price appear, and that was_price is returned in the API response.

Rest looks sound: parameterized SQL, was_price logic in one transaction, no contract cell changed, assets Fair Housing checked and individually approved.

commented

I've addressed both points and pushed c6db5f3. The full suite (179 tests) and the type check pass here.

  1. Terminal: r on an open listing now prompts for the price, pre-filled with the current one. The terminal sends it through updateFacts as fields: { price }, so it is validated like every other door. A cut reports "Price saved, down from $899,000. A price improvement post and email are ready to approve", and the listing then reads "0 of 8 approved". A bad price such as lots is refused and the price stays. The README now says to press r on the listing, and the key is in the help line.
  2. One test per door: src/priceimprovement.test.ts now covers every door the pull claims:

- the terminal; - the MCP update_facts; - the JSON PATCH /api/listings/:id, which returns was_price and both assets; - the Edit facts form route (POST /listings/:id/facts), checked by reading the listing back from the API.

The terminal test asserts the "0 of 8 approved" count, not the asset label, because the terminal screen is clipped to its window and doesn't show the Social tab entry.

commented

I think I've fixed the failure and pushed e7e1bd7, but I can't be sure, because the failure was intermittent and I haven't seen it reproduce. The full suite passed in all three runs I did here.

The failing test was an allowed change and a refused one each leave a row in src/audit.test.ts. It got a 429 from the write limiter on its last request. That limiter is module-global and counts requests per person across every test file in the run. audit.test.ts and walkthrough.test.ts both acted as user u1, so their writes shared one budget. The earlier failure was the same 429, which I had wrongly put down to a flake.

I changed the audit suite to use its own identities (audit-u0, audit-u1, audit-u2), so no other file's writes count against it. This changes only the test. No app code changed in this push.

Approved

Both earlier asks are met. (The clone does not hold d5c8db7, so I judged the change as shown.) 1) The terminal now has r: it prompts for the price, goes through updateFacts so it is validated like every other door, and reports the cut. The README and help line name it, and a test covers a good price and lots. 2) priceimprovement.test.ts now covers the terminal, the MCP update_facts, the JSON PATCH and the Edit facts form. The audit.test.ts change only gives that suite its own identities, so it no longer shares the write limiter with other files. No contract cell is loosened and every write goes through updateFacts. The was_price logic in changeFacts is correct for a first cut, a second cut, a raise that stays below the original, and a raise to or above it. Nothing blocking.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs