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

A lead who buys or sells with the agent is marked closed with a date, and a year later a home-anniversary check-in draft waits on the desk #110

opened this

Check · Review · Land · Live — It conflicts with its base. Next: builder, it conflicts with its base.

first in the queue: no estimate: nothing landed in the last hour

Conflicts with main

A lead can now be marked closed — bought or sold — with a closing date, and a year later a "happy home anniversary" check-in draft waits on the desk. `bun test` is green (527) and `bun run lint:design` is clean. I could not run `bun x tsc --noEmit` because the repo has no `tsconfig.json`, and there is no `scripts/gate.ts`.

22 files · +772 −47

look it conflicts with main in src/db.ts, src/leads.ts — bring the branch up to date and it can land deploy 2cad6ad

Conflicts in 2 filesdeploy 2cad6ad

Website spec: 4 findings, 4 the edge owns (report only)

Look

1 page beside main · 0 new to this pull

main

at aba151a ·

this pull

In the dark

main

at aba151a ·

this pull

at 2cad6ad ·

opened this

A lead can now be marked closed — bought or sold — with a closing date, and a year later a "happy home anniversary" check-in draft waits on the desk. bun test is green (527) and bun run lint:design is clean. I could not run bun x tsc --noEmit because the repo has no tsconfig.json, and there is no scripts/gate.ts.

What changed

  • Marking closed. From a lead's page, PATCH /leads/:id or POST /leads/:id/state with {"state":"closed","kind":"bought|sold","closed_on":"YYYY-MM-DD"}, the MCP mark_lead tool, and y in the terminal all go through one action. It is a lead update through permit, recorded in the audit log as closed with the kind and date. No contract cell changed.
  • Validation. The date must be a real day from 1990 on and no more than a year ahead, counted on the agent's calendar. A bad kind or date is a 422 naming kind or closed_on.
  • Undo and follow-ups. The lead stays qualified and gains closedKind and closedOn, so follow-ups stop exactly as with qualified. state: "open" (the #23 re-open) undoes it and clears both.
  • Counts and filter. The Activity page's lost-reason block now has a "Closed in the last 30 days" block beside it, and closed leads sit under Closed. The CSV export gains closed and closed on columns.
  • Anniversary draft. On each anniversary of closed_on in the agent's time zone, the clock's turn creates one draft. It names the address when the lead has a showing, and it is numbered by year (days 101–199), so a year never gets two. It goes out only on approval. The new src/closed.ts holds the date rules and wording.
  • Sample data. "Tom Whitfield" is a past client who bought exactly one year ago today, so his draft is on a fresh desk. The sample desk is now 21 leads.
  • Docs. The README has a one-line tour sentence plus a reference paragraph, and AGENTS.md documents the shape. contract/openapi.json is regenerated.
  • Tests. New src/closed.test.ts covers marking, undoing, the 422s, the draft firing once per year, the time zone, the leap day, the address, counts, export, MCP, terminal, HTTP, and migrating an existing database.

What I chose differently

  • No table rebuild. The issue's risk note expected one, but the state stays qualified and I added two columns (closed_kind, closed_on), so the state CHECK is untouched. I tested migrating an old database.
  • Needs you now includes closed leads. A closed lead with an anniversary draft appears in both Needs you and Closed. I changed the existing views test to allow that, and to count each lead once.
  • Other existing tests I edited. I updated them only for the count (20 to 21 leads) and the two new CSV columns.
  • No catch-up for missed days. The draft appears only if the clock ticks on the anniversary day itself. If the server is down that whole day, that year's draft does not appear.
  • Stale drafts. A draft left unsent is set aside when the next year's arrives. There is no manual skip for it.

To try it Open a lead, use "Mark closed", and pick a kind and date; Put back in follow-ups undoes it. On a fresh desk, open Tom Whitfield for the draft, and check Activity for the deal counts.

Closes #90

commented

A lead can now be marked closed — bought or sold — with a closing date, and a year later a "happy home anniversary" check-in draft waits on the desk. bun test is green (527) and bun run lint:design is clean. I could not run bun x tsc --noEmit because the repo has no tsconfig.json, and there is no scripts/gate.ts.

What changed

  • Marking closed. From a lead's page, PATCH /leads/:id or POST /leads/:id/state with {"state":"closed","kind":"bought|sold","closed_on":"YYYY-MM-DD"}, the MCP mark_lead tool, and y in the terminal all go through one action. It is a lead update through permit, recorded in the audit log as closed with the kind and date. No contract cell changed.
  • Validation. The date must be a real day from 1990 on and no more than a year ahead, counted on the agent's calendar. A bad kind or date is a 422 naming kind or closed_on.
  • Undo and follow-ups. The lead stays qualified and gains closedKind and closedOn, so follow-ups stop exactly as with qualified. state: "open" (the #23 re-open) undoes it and clears both.
  • Counts and filter. The Activity page's lost-reason block now has a "Closed in the last 30 days" block beside it, and closed leads sit under Closed. The CSV export gains closed and closed on columns.
  • Anniversary draft. On each anniversary of closed_on in the agent's time zone, the clock's turn creates one draft. It names the address when the lead has a showing, and it is numbered by year (days 101–199), so a year never gets two. It goes out only on approval. The new src/closed.ts holds the date rules and wording.
  • Sample data. "Tom Whitfield" is a past client who bought exactly one year ago today, so his draft is on a fresh desk. The sample desk is now 21 leads.
  • Docs. The README has a one-line tour sentence plus a reference paragraph, and AGENTS.md documents the shape. contract/openapi.json is regenerated.
  • Tests. New src/closed.test.ts covers marking, undoing, the 422s, the draft firing once per year, the time zone, the leap day, the address, counts, export, MCP, terminal, HTTP, and migrating an existing database.

What I chose differently

  • No table rebuild. The issue's risk note expected one, but the state stays qualified and I added two columns (closed_kind, closed_on), so the state CHECK is untouched. I tested migrating an old database.
  • Needs you now includes closed leads. A closed lead with an anniversary draft appears in both Needs you and Closed. I changed the existing views test to allow that, and to count each lead once.
  • Other existing tests I edited. I updated them only for the count (20 to 21 leads) and the two new CSV columns.
  • No catch-up for missed days. The draft appears only if the clock ticks on the anniversary day itself. If the server is down that whole day, that year's draft does not appear.
  • Stale drafts. A draft left unsent is set aside when the next year's arrives. There is no manual skip for it.

To try it Open a lead, use "Mark closed", and pick a kind and date; Put back in follow-ups undoes it. On a fresh desk, open Tom Whitfield for the draft, and check Activity for the deal counts.

Approved

Closing a deal goes through the one setState action and permit, with no new contract cell. The date and kind are validated (422 naming the field), and the migration is additive with a CHECK. The anniversary draft is numbered by year, so it fires once a year and only an approval sends it. Tests cover marking, undoing, the 422s, the time zone, the leap day, MCP, terminal, HTTP and migrating an old database. I could not sign in to the preview, so I judged the code from the diff and its tests. The diff I was given was cut off, so I did not read all of routes.ts, sample.ts, terminal.ts and the page form. Non-blocking nits: drafts.ts dayLabel has a misindented ternary arm; anniversaries() repeats the MAX_YEARS check that anniversaryOf already makes; a server that is down for the whole anniversary day skips that year's draft, as the builder disclosed.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs