Attribute pricing RFC, build plan, and catalog inventory
This PR creates the written contract and read-only inventory that gates the 16-PR attribute-pricing stack; it does not ship product behavior.
A complete RFC set for condition- and attribute-based pricing: roles, predicate datapoint resolution, conformance scenarios, and one workstream packet per implementation slice.
Adds a read-only WS0 inventory script under apps/server/src/dealops4/__scripts__ plus Mocha tests for its pure analyzer.
The checked-in V2 seed corpus has real selector-tag and round-trip constraints: 12/21 seed datasheets round-trip today; 9/21 are blocked by existing type or page-id behavior.
No migrations, no tRPC routes, no runtime pricing engine changes, and no product UI changes. The only shared code tweak is exporting an existing converter map for inventory classification.
1. Why this exists
This is the foundation PR for the attribute-pricing stack, not an implementation PR.
- Attribute pricing spans model, publish, engine, lifecycle, approvals, totals, writeback, and UI.
- Later PRs need stable names, decisions, fixtures, and workstream boundaries to avoid re-litigating core semantics.
- WS3 depends on knowing which real datasheets can survive V2→V3→V2 parity checks today.
- Commit the RFCs and workstream packets under
rfcs/attribute-pricing/. - Commit the reviewed scenario catalog used by the future conformance corpus.
- Commit a read-only inventory tool that surveys checked-in V2 seed datasheets and, optionally, one live org.
RFC, build plan, inventory
Org setting
Shared types and roles
Conformance corpus
Engine, tables, UI, lifecycle, goldens
Each PR is intended to merge independently and in order; this one supplies the reference documents the rest cite.
2. What changes
The diff is mostly documentation, plus one pure analyzer and a thin CLI shell.
| Area | Files | Reviewer read |
|---|---|---|
| RFC docs | rfcs/2026-09-02-condition-attribute-based-pricing.mdrfcs/2026-09-08-predicate-datapoint-resolution.mdrfcs/2026-09-23-attribute-pricing-test-scenarios.md |
Defines the architecture, predicate resolution rationale, and scenario catalog later PRs turn into tests. |
| Build plan | rfcs/attribute-pricing/README.mdrfcs/attribute-pricing/01-model.md–04-conformance.mdrfcs/attribute-pricing/10-ws-model.md–18-ws-approvals.md |
Handoff packets per workstream. The README is the intended first review stop; decisions D13–D18 remain the active debate surface. |
| Inventory script | apps/server/src/dealops4/__scripts__/inventoryAttributePricing.lib.tsapps/server/src/dealops4/__scripts__/inventoryAttributePricing.tsapps/server/src/dealops4/__scripts__/__tests__/inventoryAttributePricing.test.ts |
Pure analyzer, CLI wrapper, and Mocha tests. It reads seed files by default and writes only the report file path requested by the user. |
| WS0 report | rfcs/2026-09-03-ws0-attribute-pricing-inventory.md |
Generated inventory of checked-in V2 seed datasheets: round-trip gates, extra selector keys, ambiguous groups, sibling counts, and grid equivalents. |
| Architecture docs | knowledge/architecture/dealops-1-vs-2.mdknowledge/architecture/index.md |
Clarifies that dealops3 and dealops4 are Dealops 2 layers, and that attribute-pricing feature code lives under apps/server/src/dealops4/. |
| Export-only code | apps/server/src/dealops3/datasheet/converter.ts |
Exports VALUE_TYPE_MAP so the inventory can test type membership without invoking a throwing converter path. |
rfcs/attribute-pricing/README.md first.01–04 as the executable spec spine.3. How it works
The only executable path added here is the inventory tool; it is intentionally pure-core / thin-shell.
analyzeOrg(args)builds one org inventory rowcollectProductInputSelects(flowSpec)finds pricing-role precedentsbuildGateVerdict(inventories)aggregates corpus blockersrenderMarkdownReport(...)formats the WS0 report
--source=diskreadsdealops2/onboarding/*--source=db --org=<name>reads one live org--out=<path>writes the markdown report- DB import is lazy, so default disk mode never opens Prisma
| Question | Rule in code | Why it matters for later PRs |
|---|---|---|
| Which selector keys are “extra”? | Everything except type, productId, and pricebookId. |
WS3 needs to know whether unknown selector keys can safely become predicate clauses. |
| Which datapoint types block conversion? | Types absent from both VALUE_TYPE_MAP and VARIANT_TYPE_MAP. |
Those orgs cannot be in a byte-identity V2→V3→V2 parity corpus. |
| Which page IDs block byte identity? | Anything other than listPrice, because the V3→V2 converter writes that page ID. |
Some failures predate attribute pricing; the stack should not treat them as regressions. |
| Where is lookup ambiguous? | Groups with the same (type, productId, pricebookId) and multiple datapoints. |
Dimension-less lookups already resolve by array order in live seed data. |
| Which attributes already act like pricing dimensions? | VARIANT_TYPE_MAP usage plus select product inputs in V2 flow specs. |
WS1 backfill can classify only the small set with real precedent. |
The headline consequence: WS3 should scope byte-identity parity to the convertible orgs and separately assert the blocked orgs remain unchanged.
The shared converter change is export-only:
// Exported so the WS0 inventory can test type membership.
export const VALUE_TYPE_MAP: Record<string, V3DataPointValueType> = {
LIST_PRICE: 'list_price',
MIN_PRICE: 'min_price',
DISCOUNT_APPROVAL: 'discount_approval',
...
};
- Default source is disk, not database.
- DB mode requires
--organd prints the sanitized host before querying. - The analyzer is pure; filesystem and Prisma stay in the shell.
- The script writes only the requested markdown report.
4. What it doesn’t change
- No Prisma schema migration.
- No new tRPC route, REST route, or client UI.
- No pricing engine behavior change.
- No quote lifecycle, approvals, totals, renewal, or CRM writeback behavior change.
- No retirement of
VARIANT_TYPE_MAPor the Dealops Voice AI registry path. - No generated conformance corpus yet; this PR adds the scenario catalog and plan that later PRs consume.
- No product data rewrite; the inventory reads checked-in seeds or one requested live org.
5. Risks / rollback / open questions
Rollback is straightforward: revert the docs, the read-only script, its tests, and the export of VALUE_TYPE_MAP. No persisted product behavior depends on this PR.
- Decisions D13–D18 in
rfcs/attribute-pricing/README.mdare still the intended debate surface. - The truncated diff prevents line-by-line validation of every workstream packet.
Later implementation PRs should cite these docs by section. If reviewers change a core decision here, the stack should be updated before downstream PRs merge.
- Read
rfcs/attribute-pricing/README.mdfirst. - Confirm the WS0 inventory findings are framed as gates, not product changes.
- Check the script remains read-only except for the report output path.
- Confirm
dealops4placement matches the updated architecture docs. - Focus debate on D13–D18 before #7354+ start relying on them.