Skip to content

fix(seed): anchor the Acme contract on the deal it was signed off - #1693

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-1661-acme-contract-provenance
Sep 6, 2026
Merged

fix(seed): anchor the Acme contract on the deal it was signed off#1693
os-steve merged 1 commit into
mainfrom
claude/issue-1661-acme-contract-provenance

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes #1661

What was wrong

src/data/revenue.seed.ts shipped an activated contract, signed daysAgo(32) for 150000, linked to Acme Platform Upgrade — a deal still at stage: 'proposal', probability: 60, closing daysFromNow(30).

The card asked for the intended reading to be established from the records before editing, and not to assume only the link was wrong. It was not only the link.

The proof is mechanical, not narrative. Two rules in the app make that pairing unreachable in both directions:

  • quote_on_accepted (src/objects/quote.hook.ts) close-wins the linked opportunity the moment a quote is accepted — so a settled commercial artifact drags its deal closed with it;
  • closed_won: [] in opportunity_stage_progression (src/objects/opportunity.object.ts) — closed_won is terminal, so a deal that closed can never return to proposal.

So the deal cannot still have been open when the paper was signed, and it cannot have been reopened afterwards. The contract's description prose ("Annual platform subscription with premium support tier") was the card's strongest clue but is used here only to form the hypothesis; the records above decide it.

The link and the value came from two different deals

Computed from the line items, which this seed treats as the one source of truth for deal value (dealValue() derives every amount from them rather than typing it in):

deal line-item total stage
Acme Platform Upgrade 150 000 proposal, closing daysFromNow(30)
Acme Annual Renewal 2025 220 000 closed_won, close_date: daysAgo(15)

150000 is the upgrade's total to the cent — so the contract's value was taken from the open deal, and re-pointing the link alone would have left a 220K deal carrying a 150K contract. 220000 is independently corroborated: it is the ARR the account description reports for the signed renewal ("ARR: $220K (signed Q1 2025 renewal)"), and no contract in the app carried it.

Three further fields agree with the renewal rather than the upgrade: contract_term_months: 12 and billing_frequency: 'annually' against an upgrade whose own next_step is negotiating an 18-month term; and auto_renewal: true.

What decided which record to believe

The upgrade being open is corroborated by four independent records — the account description PR #1657 just rewrote, the deal's own next_step, the crm_event workshop PR #1687 just re-dated ("the gate on signature"), and the renewal's own description ("they want to see how the platform upgrade lands first"). Nothing corroborates it being closed. So anything in a signed/accepted state pointing at it is the wrong half — which is the card's reading, arrived at from the records.

The contract must also stay activated: it is the only activated contract in the seed, and contract_renewal, contract_expiration and billing_handoff all filter on exactly that status. Demoting it to a draft on the upgrade would have stripped three scheduled flows of their only subject.

Changes

Contract — every contested field now derives from Acme Annual Renewal 2025:

  • crm_opportunityAcme Annual Renewal 2025
  • contract_value220000 (that deal's line-item total)
  • signed_datedaysAgo(15), its close_date — you sign when you win, and quote_on_accepted stamps that same day
  • start_datedaysAgo(1) = signature + 14 days, because that deal's description says it was "signed two weeks ahead of the renewal date"
  • end_datedaysFromNow(364), keeping the 365-day span every other contract row uses for a 12-month term (contract_validation measures 12 months exactly)

description is deliberately untouched — it is this seed's externalId, so an existing demo database updates the same row instead of growing a second one.

The third leg the card did not name. The PM flagged a fourth record without judging it: the accepted quote at revenue.seed.ts also linked to Acme Platform Upgrade. Verdict: (a), the same contradiction one object over — by the same two rules above, an accepted quote can only ever point at a closed_won deal. Not (b): the app cannot produce or tolerate this state. Not (c) #1253's territory: that card is about a contract having no back-link to its quote, which this does not touch.

  • Acme Platform Upgrade Quoteexpired. That is what quote_expiration computes for a presented quote past its expiration_date (daysAgo(15)), and it is what the deal assumes — the deal re-entered proposal 12 days ago and its next step is to send the revised proposal.
  • Moving it off accepted would have left the anti-vacuity half of test/quote-contact-required-when.test.ts with no accepted quote to check (expect(statuses.has('accepted')).toBe(true)), and no existing quote can hold accepted coherently because none of the others sits on a closed_won deal. So the renewal gains the accepted quote it should always have had: Acme Annual Renewal 2025 Quote, carrying that deal's line items via the existing OPPORTUNITY_LINES mapping, no discount (its own description says the multi-year option was declined this round), and 8.5% tax — the rate the other Acme quote bills at, where every non-Acme quote bills 8%. Totals come from quoteTotals(), so the rollup stays a no-op over the seeds.

That completes the chain a reader traces to learn the model: deal won, quote accepted, contract drafted, then completed and activated — which is exactly what quote_on_accepted implements.

Not touched

Verification

pnpm verify fully green, on the final commit 3a438d0b:

✓ validate  ✓ typecheck  ✓ lint  ✓ i18n gate  ✓ source hygiene  ✓ source token ratchet
✓ Build complete
Test Files  161 passed (161)
Tests  3414 passed | 1 skipped (3415)

Seed guards re-run explicitly and reported rather than absorbed — no movement: seed-consistency, seed-validation-warnings and activity-seed-coverage all pass unchanged, together with quote-contact-required-when, quote-discount-ceiling and account-renewal-model (131 tests across the six). seed-consistency's quote_total_rollup would be a no-op over the seeds covers the added quote's totals.

Adjacent finding, filed separately

Issue #1692 is not addressed here, and remains open: the account description dates the signed renewal to "Q1 2025" while the record it describes closes daysAgo(15). Every record involved is fenced by #1657 and #1646, and the seed derives period labels dynamically everywhere else, so it needs the triage seat rather than a rider on this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018xtjdpZFjgWh4Ad9Wcx68J


Generated by Claude Code

The seed shipped an `activated` contract, signed `daysAgo(32)` for `150000`,
linked to `Acme Platform Upgrade` — a deal still at `stage: 'proposal'`, 60%
probability, closing `daysFromNow(30)`. Nothing in this app can produce that
pairing, and the proof is mechanical rather than narrative: `quote_on_accepted`
close-wins an opportunity the moment its quote is accepted, and `closed_won` is
a terminal stage in `opportunity_stage_progression` (`closed_won: []`). A signed
contract can reach an open deal from neither direction — the deal cannot still
have been open when the paper was signed, and it cannot have been reopened
afterwards.

The link and the amount had come from two different deals, so repointing the
link alone would not have closed it. Computed from the line items, which this
seed treats as the one source of truth for deal value: `Acme Platform Upgrade`
totals exactly `150000`, the contract's own `contract_value`, while
`Acme Annual Renewal 2025` — the `closed_won` deal whose description says it was
"signed two weeks ahead of the renewal date" — totals `220000`, which is also
the ARR the account description reports for the signed renewal and which no
contract in the app carried.

Every contested field now derives from the renewal: `crm_opportunity` is
`Acme Annual Renewal 2025`; `contract_value` is `220000`; `signed_date` is that
deal's `close_date` (`daysAgo(15)`, the day `quote_on_accepted` would stamp);
`start_date` is signature + 14 days, which is what "two weeks ahead of the
renewal date" means; `end_date` keeps the 365-day span every other contract row
uses for a 12-month term. `description` is untouched, and it is this seed's
upsert identity, so an existing demo database updates the same row.

The same contradiction had a third leg: `Acme Platform Upgrade Quote` was seeded
`accepted` on that same open deal. It is now `expired` — the value
`quote_expiration` computes for a presented quote past its `expiration_date`,
and the state the deal's own next step assumes, since the revised Enterprise
proposal still has to go out.

Moving it off `accepted` would have left the anti-vacuity half of
`test/quote-contact-required-when.test.ts` with no accepted quote to check, so
the renewal gains the accepted quote it should always have had, carrying that
deal's line items, no discount (the multi-year option was declined this round)
and Acme's 8.5% San Francisco tax rate — the rate the other Acme quote bills at,
where every non-Acme quote bills 8%. That also completes the chain a reader
traces to learn the model: deal won, quote accepted, contract drafted, then
completed and activated.

`Acme Platform Upgrade` itself is untouched: its `stage`, `probability` and
`close_date` are the record the account description derives from.

Co-authored-by: Claude
@vercel

vercel Bot commented Sep 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Sep 6, 2026 11:02am UTC

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

2 participants