Skip to content

docs(requirements): file REQ-0003 … REQ-0006, the four Track A triage records REQ-0002 mandates - #1912

Merged
os-elon-musk merged 1 commit into
mainfrom
claude/issue-1911-track-a-requirement-records
Sep 15, 2026
Merged

os-elon-musk merged 1 commit into
mainfrom
claude/issue-1911-track-a-requirement-records

Conversation

@os-elon-musk

Copy link
Copy Markdown
Collaborator

Fixes #1911

REQ-0002's Product response rules its Track A — the sales half of an IT-services customer's
40-step CRM-to-delivery process, steps 1–14 — as:

B (Track A) — to be filed as REQ-0003 onward, one record per object, each carrying its own standard-versus-overlay split.

This PR files those four records. No metadata change: the whole diff is docs/requirements/
plus one changeset. Nothing under src/ is touched.

Record Object REQ-0002 steps
docs/requirements/0003-account-registration-category-and-approval.md crm_account 1 · 3 · 4 · 5
docs/requirements/0004-contact-buying-centre-map.md crm_contact 2
docs/requirements/0005-lead-need-type-value-and-approval.md crm_lead 6 · 7
docs/requirements/0006-opportunity-qualification-and-status-approval.md crm_opportunity 8 … 14

Each follows TEMPLATE.md's sections, carries Status: Triaged, Disposition: B standard-enhancement,
and reuses REQ-0002's Source / Raised (same customer, 2026-09-14). REQ-0002's Product response
and docs/requirements/README.md's index gain the four links in the same change.

The two things this PR proves rather than asserts

1 · The Raw requirement sections are verbatim. The rows were not retyped. They were extracted
from REQ-0002 by a script keyed on the step number, spliced into each file, and then read back out of
the four written files and compared byte-for-byte against the source table:

0003-account-registration-category-and-approval.md steps: 1,3,4,5 expected: 1,3,4,5 setMatch: true byteIdentical: true headerPresent: true
0004-contact-buying-centre-map.md steps: 2 expected: 2 setMatch: true byteIdentical: true headerPresent: true
0005-lead-need-type-value-and-approval.md steps: 6,7 expected: 6,7 setMatch: true byteIdentical: true headerPresent: true
0006-opportunity-qualification-and-status-approval.md steps: 8,9,10,11,12,13,14 expected: 8,9,10,11,12,13,14 setMatch: true byteIdentical: true headerPresent: true
VERBATIM CHECK: PASS (all rows byte-identical to REQ-0002, no extra rows)

No rewriting, no translating, no normalising — and no row from a neighbouring object leaking in.

2 · The Standard product analysis sections are written against measured fields. Re-measured on
main (9f13c77) with grep -oE "^ [a-z_]+: Field\.[a-zA-Z]+" src/sales/objects/ACCOUNT.object.ts
and its three siblings: crm_account 25 · crm_contact 23 · crm_lead 36 · crm_opportunity 23 —
counts and named fields both agree with the rosters on the card, so no correction was needed.

Claims that go past a field roster were read out of the source rather than assumed:

  • The account category gates nothing today. account.object.ts declares no validations[] and no
    requiredWhen / readonlyWhen / visibleWhen; the only two places that touch type write it or
    branch on it for promotion (account.hook.ts, and opportunity.hook.ts flipping a won deal's
    account to customer). That is what makes "a category that restricts what the account may do"
    the most valuable primitive in REQ-0003 rather than a second picklist.
  • The only approvals in the app are the two amount tiers in src/sales/flows/opportunity-approval.flow.ts
    (grep -rn "type: 'approval'" src/sales/flows/ returns those two nodes and nothing else) — so
    "no approval on the account", "no approval before lead conversion" and "no approval on status
    change" are each measured, not inferred.
  • Conversion is ungated today: convert_lead's visible predicate excludes only already-converted
    and unqualified leads, so any open lead can be converted by its owner.
  • Stage transitions are constrained but not refused: the opportunity_stage_progression validation
    is type: 'state_machine' with severity: 'warning'.
  • Step 4 has no gap and is recorded as such: account.object.ts already declares enable.files: true.

Rulings quoted, never re-decided

The C and D verdicts REQ-0002 already gave are quoted from it verbatim — the signing-entity list
(软通签约主体), the revenue-recognition vocabulary, the US EAR flag and the 铁三角 role model. REQ-0006
adds the boundary that makes the last one readable: 铁三角 is a role model on our deal team (C),
while REQ-0004's buying-centre role is a role in the customer's buying centre (B) — different
facts on different objects, so the C verdict on the first does not reach the second.

The registration identifier is deliberately country-neutral. The customer says 社会信用代码
because they register in China; that string appears in these records only inside the verbatim
quote
. REQ-0003 states the rule explicitly: the core field carries any country's registry number
(法人番号, Handelsregisternummer, EIN …) and is never named after one country's registry.

Verification

Every gate run individually first, then the whole chain as pnpm verify — package.json is the
authority for what that chain is, and it was not narrowed. Exit codes were written to a file before
being read, never off a pipe. All measured on the pushed head ff3f923:

validate EXIT=0
typecheck EXIT=0
lint EXIT=0
lint:i18n-gate EXIT=0
hygiene EXIT=0
hygiene:tokens EXIT=0
build EXIT=0
test EXIT=0          # Test Files 166 passed (166) · Tests 3479 passed | 1 skipped (3480)
pnpm verify EXIT=0   # the full chain, re-run end to end

pnpm build prints 8 author-time warnings (a page:card prop, four approval-staffing notices on the
existing approval flows, three carrier-only fields, one enterprise capability). All pre-existing: this
diff touches no file the build reads.

Changeset

.changeset/track-a-requirement-records.md, empty frontmatter — the sanctioned "releases nothing"
declaration that .github/workflows/changeset-check.yml documents on par with the skip-changeset
label. Reasoning for the level: nothing reaches a HotCRM user. No object, view, flow, dataset, widget,
translation or exported symbol changed, and the artifact is byte-identical — the diff is maintainer
documentation under docs/requirements/ only. This is the same class, and the same declaration, as the
changeset that shipped REQ-0002 itself. A patch would publish a release-notes line describing a change
no install can observe.

Acceptance notes

  • docs/README.md gets no row. Its "Start Here" table points at requirements/README.md as the one
    entry for the requirements log, and REQ-0002 set the precedent: a requirement record is indexed in the
    log's own README, while docs/README.md rows name trees and top-level documents.
  • Each record's Acceptance is written as that record's own acceptance (what a HotCRM install must
    do once the record is built), not as this PR's.
  • Track B (PSA, steps 15–40) is untouched, and nothing in these four records anticipates it.
  • Observation, not filed: docs/README.md's standing rule reads "a PR that adds … a document under
    docs/ updates the tables below", which taken literally would ask for four "Start Here" rows; the
    precedent set by REQ-0002 reads it as "the tables that index this document's tree". Whoever adds the
    next docs/ document meets the same ambiguity.

Generated by Claude Code

… records REQ-0002 mandates

REQ-0002's *Product response* rules its Track A (the sales half of an IT-services
customer's 40-step CRM-to-delivery process, steps 1-14) as "to be filed as REQ-0003
onward, one record per object, each carrying its own standard-versus-overlay split".
This files those four records. No metadata change: the whole diff is under
`docs/requirements/`.

- 0003 `crm_account` (steps 1 3 4 5) — a country-neutral registration identifier
  (⛔ never named after one country's registry), a category that GATES what the
  account may do rather than merely classifying it, the business-profile block,
  and account approval. `enable.files: true` already covers step 4: no gap.
- 0004 `crm_contact` (step 2) — the buying-centre map: role in the purchase
  decision, attitude toward us, relationship strength.
- 0005 `crm_lead` (steps 6 7) — need type, estimated value, and a configurable
  approval gate before conversion.
- 0006 `crm_opportunity` (steps 8-14) — the qualification block, customer-side
  milestone dates, subcontracting, the deal narrative block, and approval on
  STATUS CHANGE rather than on amount alone.

Each *Raw requirement* section reproduces its rows from REQ-0002's table
byte-for-byte; each *Standard product analysis* is written against the field
rosters measured on this commit's parent, and names what exists as well as what is
missing. The C and D verdicts REQ-0002 already gave are quoted, never re-decided.

REQ-0002's *Product response* and the requirements index gain their links here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3YsvpK1PvYf9n1YUhYP6W
@vercel

vercel Bot commented Sep 15, 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 15, 2026 1:54pm UTC

Request Review

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

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Track A: file REQ-0003 … REQ-0006, one triage record per sales object (account · contact · lead · opportunity) — the split REQ-0002 mandates

2 participants