Skip to content

adr: 0017 Law 2 (cost is telemetry) + 0018 catalog-scale content factory - #62

Merged
ninan-versioning merged 4 commits into
mainfrom
adr/0017-0018-cost-telemetry-catalog-factory
Jul 29, 2026
Merged

adr: 0017 Law 2 (cost is telemetry) + 0018 catalog-scale content factory#62
ninan-versioning merged 4 commits into
mainfrom
adr/0017-0018-cost-telemetry-catalog-factory

Conversation

@ninan-versioning

Copy link
Copy Markdown
Owner

What lands

Two new ADRs and the contract updates they force: the $299/mo Managed price is reopened and not replaced, and the catalog-scale content factory becomes the target demonstration.

Decision summary

ADR 0017 — Product quality defines architecture; cost is telemetry (Law 2)

  • $0 OSS self-host is unchanged and still locked.
  • The $299/mo Managed price is reopened and deliberately not replaced with another number. It is set only after (a) measured production unit economics, (b) stated reliability requirements, (c) stated support requirements — in a new ADR citing those figures. Until then no Shoploop surface states a Managed price.
  • Binding rule: no PR may remove, cap, downgrade, or defer a product capability to preserve a price point or a $/mo target. If the economics do not work, the price changes; the product does not. Fidelity gates (usdchecker, OpenPBR ≥0.85) are never relaxed to reduce render cost.
  • This is not permission for unbounded or unobserved spend. Every PR still states a monthly cost delta. The ≥$50/mo ADR trigger is unchanged — its purpose changes from an affordability veto to a disclosure gate answering "is this right for the product, what does it cost, and how is that cost observed?" Such an ADR may no longer conclude "rejected, too expensive" as a standalone reason; rejection must rest on licence, Law 0, a second source of truth, absent capability, or a genuinely equivalent cheaper option. Runtime spend is attributed per tenant / per run / per asset by the Temporal workflow that produces the asset. Budget alarms notify and never auto-degrade.
  • An explicit "What this ADR does not unlock" section keeps Polotno, every interactive canvas editor, TwinMaker, cheap Three.js and the $99/enterprise tiers rejected — those were rejected on licence, architecture and Law 0 grounds, not affordability.

ADR 0018 — The catalog-scale content factory is the target demonstration

one existing brand/product website URL
  → catalog discovery: public PDPs on that same domain
  → page-parser per PDP: product facts, variants, brand rules, product rules
  → Pimcore PXM graph (canonical; one object per accepted SKU)
  →                    ◆ HITL GATE ◆  (the only routine human step)
  → usd-runtime: one OpenUSD twin per accepted SKU → usdchecker + OpenPBR ≥0.85
  → recipe / camera / output manifests × shared twins
  → Kit on AWS GPU, Temporal fan-out
  → 5 compositions × 5 aspect ratios per SKU
  • First acceptance: ≥10 accepted SKUs → ≥250 assets. Aspect ratios are fixed and explicit: 9:16, 1:1, 16:9, 3:4, 4:5. 50 SKUs / 1,250 assets is a scale run that produces the cost curve, not a first-acceptance gate.
  • discoverCatalog(url) → product_url[] resolves sitemap.xml → JSON-LD ItemList (with pagination) → DOM product anchors → NO_PRODUCT_FOUND. Still exactly one URL in. Same-domain only, robots.txt honoured, rate-limited, authorized domains only.
  • product_rules (regulated claims, disclaimers, prohibited wording, jurisdictional flags, age gating) live as a Pimcore Classification Store group with Data Quality rules — writing a product_rules.schema.json would be a Law 0 violation and is forbidden.
  • The HITL gate is a Pimcore object workflow reviewed in the Pimcore admin UI. No new frontend, no new service. After approval everything downstream is automatic; changing brand_rules or product_rules regenerates every dependent asset.
  • Manifests, not hand-built scenes: a composition is a .usda scene layer with the product slot as a reference; aspect ratio is an output parameter with a declared safe area. No "Template Engine" (ADR 0013), no interactive canvas (ADR 0009).
  • No fidelity gate is relaxed to make a catalog run cheaper or faster. usdchecker and OpenPBR ≥0.85 apply to every one of the 250+ assets.

Superseded / amended contracts

Nothing is silently contradicted. Every conflict is resolved by supersession metadata.

Record Effect
ADR 0011 (any URL, first product wins) Amended by 0018 — its "no multi-product intake" non-goal only. Every other boundary stands: one URL, same-domain, OFF_DOMAIN_PRODUCT_LINK, UNSUPPORTED_INTAKE, intake_url/product_url/resolver recorded. First-product-wins is retained as the hero-SKU and ordering tie-break rule. A discovery field is added.
ADR 0013 (Law 1; stock containers) Amended by 0018 — recipe cardinality only. §4.5's "exactly one ingest recipe at v1" still holds: one recipe, run 10–50 times, not a second recipe. Unsupported archetypes route to the HITL gate with a typed exclusion reason.
ADR 0009 (no editor) Decision unaffected. A one-line historical note marks its $299/mo figures as the record of their moment; Polotno and canvas editors were rejected on licence and architecture, and stay rejected under Law 2.
AGENTS.md §Locked model, §Non-negotiables, decision gate Q6 $299 bullet rewritten; Law 2 section added; catalog discovery added to the one-URL bullet; two new non-negotiables; Q6 reframed as telemetry.
docs/BUILD_ORDER.md Phase 1 reframed as the plumbing gate; Phase 2 rewritten as the catalog-scale content factory; Phase 4 narrowed to the operator frontend over Phase 2 manifests. Issue numbers #52#57 unchanged.
MILESTONES.md v0.1 labelled the plumbing gate; new v0.1.5 catalog-factory milestone with date TBD (no date fabricated); commercial target keeps the customer count and drops the revenue figure.
COSTS.md, POSITIONING.md, README.md, LOOP_SPEC.md, competitive docs, landing copy, .cursor/rules/, PR template, CONTRIBUTING.md, docs/decisions/README.md Live price claims replaced with TBD language; Law 2 mirrored into the compiled agent contract and the PR gate.

Old ADR text is preserved. Only status/supersession metadata was added to 0009, 0011 and 0013 — no historical reasoning was rewritten.

Acceptance target

Phase 2 acceptance evidence, per ADR 0018 and docs/BUILD_ORDER.md:

  • The intake URL plus the discovered PDP list with resolver/discovery per SKU
  • Pimcore object IDs for all accepted SKUs, and a typed exclusion reason for each rejected one — never force-shipped, never silently dropped
  • usdchecker + fidelity score per twin, all ≥0.85
  • The manifest set, with authored-scene count far below output count
  • ≥250 assets, each traceable to (twin@SdfLayer hash, scene-layer@version, rule-set@version, renderer@version, seed)
  • A propagation run — change one brand_rules and one product_rules value, show every dependent asset regenerated, with count and wall-clock
  • A HITL round trip — one low-confidence SKU corrected, approved, then generated automatically
  • The measured cost table at 10 SKUs
  • Confirmation that no third-party brand name, domain, logo, or asset appears in the run or its evidence

Cost

$0/mo delta. This PR is documentation, contract and marketing-copy only; it adds no service, no dependency and no runtime.

Catalog-scale GPU and render figures are benchmark-required/TBD, not estimatedCOSTS.md gains a "Benchmark required" table (GPU-min per twin, $/twin, GPU-min per composition, $/aspect-ratio output, total $/run, steady-state $/mo/tenant, cache hit rate) at 10 and 50 SKUs. Fabricating those numbers would corrupt the unit economics ADR 0017 requires before a Managed price is set.

Known baselines are preserved with scope now explicitly labelled, which resolves a pre-existing ambiguity in COSTS.md: today ~$2/mo; Phase 1 plumbing gate ~$202/mo (Pimcore 55 + Temporal 40 + GPU 90 + S3/CloudFront 15); fuller reference deployment ~$325/mo (adds PostHog 70 + Postiz 35 + Nango 20, all Phase 5 lines). One GPU line — g5.xlarge spot — unchanged.

ADRs touched

Adds 0017, 0018. Amends 0011 (metadata), 0013 (metadata), 0009 (historical note only). Does not reopen 0001, 0003, 0004, 0005, 0006, 0008, 0012, 0014, 0015, 0016.

Test evidence

Check Command Result
Typecheck (CI) pnpm -r --if-present run typecheck ✅ 3 projects — apps/landing, packages/connector-shopify, packages/connector-google-ads
Tests (CI) pnpm -r --if-present run test ✅ 6 files, 43 tests passed
Horizontal invariant bash scripts/check-horizontal-invariant.sh ✅ clean
JSON validity apps/landing/public/.well-known/a2ui.json ✅ parses
Relative link check all 21 changed docs 0 broken links
Live $299 claims repo-wide grep ✅ none — every remaining occurrence is either historical record inside an accepted ADR (0009) or text explicitly stating the price was reopened
Forbidden vocabulary grep for scrape/crawl (per .cursor/rules/00-laws.mdc) ✅ new ADR text reworded to fetch/discovery; no violations introduced

Partner-neutrality statement

No partner-specific material is included in this PR. A repo-wide case-insensitive grep for the design partner's name returns zero results. No partner or prospect brand name, domain, contact, logo, commercial term, or IP appears in any file, fixture, commit message or copy string. All examples are generic, and ADR 0018 adds a binding neutrality section plus an AGENTS.md §Dogfood amendment restricting catalog discovery to the brand-neutral ashwagandha.shoploop.studio reference tenant or the founder's own DTC brand — never a partner's or prospect's domain.

Non-negotiables touched

  • No cheap Three.js product rendering — unchanged and reaffirmed; every one of the 250+ assets is a real streamed twin or a Cycles-baked fallback
  • Brand-rules gate runs before any publish path — extended: manifests validate against BrandRulesAPI and product_rules
  • No design-partner or customer brand names in code, docs, commits, or fixtures
  • No GPU workload on Vercel; no frontend on AWS
  • One new stack component, max — zero new components; every component named is already adopted
  • Law 0 — no new JSON Schema, content hash, validator, queue, OAuth flow or sampler. product_rules is a Pimcore Classification Store group; the HITL gate is a Pimcore object workflow; identity stays SdfLayer + Ar 2.0
  • Law 2 — no capability removed, capped, downgraded or deferred to hold a price; no fidelity gate relaxed
  • No Managed price asserted anywhere

New component?

None. Pimcore, pimcore-sdk, page-parser, usd-runtime, brand-rules, Kit-App-Template, OVAS, Temporal, usd-content-agents, Deadline Cloud and S3/CloudFront are all already adopted.

Unresolved contradictions (pre-existing, not introduced here)

Flagged rather than silently fixed — each predates this branch and needs its own decision:

  1. MILESTONES.md v0.1 item 4 vs docs/BUILD_ORDER.md Phase 1. MILESTONES accepts "either a Kit-streamed twin or a Blender/Cycles still + baked MP4"; BUILD_ORDER Phase 1 acceptance requires a Kit RTX Ready log and a live stream URL. Both were last dated 2026-07-27. BUILD_ORDER is the stricter and more recent statement of the gate.
  2. POSITIONING.md "trilingual" vs ADR 0008. Two comparison-table cells still advertise trilingual as a differentiator while §Languages correctly states English-only at v0.
  3. apps/landing/public/llms.txt vs ADR 0008. Still claims "Hindi (हिन्दी), English, Marathi (मराठी) day one", and apps/landing/app/layout.tsx JSON-LD still declares inLanguage: ['en','hi','mr'].

Items 2 and 3 are ADR 0008 copy debt outside this PR's scope; item 1 is a v0.1 acceptance question for PA.

🤖 Generated with Claude Code

Product quality defines architecture; cost is telemetry, not a constraint.

ADR 0017 reopens the locked $299/mo Managed price and deliberately does not
replace it with another number — Managed pricing is set only after measured
production unit economics plus stated reliability and support requirements,
in a new ADR citing those figures. $0 OSS self-host stays locked. Cost
governance is retained and tightened, not relaxed: every PR still states a
monthly delta, >=$50/mo still triggers an ADR (now a disclosure gate rather
than an affordability veto), runtime spend is attributed per tenant/run/asset,
and budget alarms notify without ever auto-degrading a capability.

ADR 0018 makes the catalog-scale content factory the target demonstration:
one brand website URL in, same-domain PDP discovery, >=10 accepted tabletop
SKUs in Pimcore with brand_rules and product_rules, one real OpenUSD twin per
accepted SKU, and >=250 assets out across 5 compositions x 5 aspect ratios
(9:16, 1:1, 16:9, 3:4, 4:5) from shared twins and manifests. The sole routine
human step is a Pimcore object workflow on the record. Phase 1 is reframed as
the plumbing gate; Phase 4 narrows to the operator frontend.

No new repo, service, framework, frontend surface, or placeholder renderer.
No fidelity gate relaxed. Catalog-scale GPU and render figures are marked
benchmark-required rather than estimated.

Cost: $0/mo delta (documentation and copy only).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
shoploop Ready Ready Preview, Comment Jul 29, 2026 12:59am

Request Review

Law 2 was asserted in ADR 0017 but contradicted in the docs that
implement it, and the ADR 0018 landing pass left the customer-facing
copy describing the pre-catalog intake model. This makes the contract
self-consistent.

- LOOP_SPEC Loop 4: usdchecker + OpenPBR >=0.85 become hard constraints,
  cost leaves the fitness function entirely and becomes a tie-breaker
  among candidates that already passed. The $50/day/customer hard-stop
  becomes alert-and-escalate; Loop 5's customer-owned ad-spend cap is
  kept and labelled as the customer's budget, not a Shoploop limiter.
- ADR 0018 + BUILD_ORDER no longer revive ADR 0010's superseded >2%
  clipping and dpi_effective <220 thresholds. HITL routes on the live
  ADR 0012 contract; any numeric tolerance goes on BrandRulesAPI via
  its own ADR.
- The "two links out" quantifier is stated as amended rather than
  asserted unchanged: two entry links per tenant, one Pimcore catalog
  graph with one object per accepted SKU.
- Supersession made symmetric across ADRs 0009/0014/0016 with the
  treatment differing by kind, and ADR 0016's $10k/mo tier removed as
  an invented price rather than historicised as a real one.
- One Phase 1 acceptance contract in both BUILD_ORDER and MILESTONES:
  a live Kit stream. The Cycles bake stays as required spot-preemption
  evidence, not a second way to close the gate. v0.2 and the commercial
  target are marked contingent rather than dated behind an undated
  upstream.
- demo-tenants/ashwagandha stated as required acceptance work in all
  three places, because it is not in the tree.
- Landing intake copy, llms.txt and a2ui.json moved to the catalog
  model, brand_rules.json dropped for BrandRulesAPI across the active
  docs, and hi/mr marked deferred wherever it still read as shipped.
The prior pass updated the marketing surfaces but left the gates that
actually reject future PRs — the PR template, CONTRIBUTING, and
.cursor/rules/00-laws.mdc — still requiring single-product intake, so
the next PR would have been failed for doing what ADR 0018 legalises.

Also removes two claims this repo cannot back: that the ashwagandha
fixture resolves today (it is unauthored), and that BrandRulesAPI
carries a safe-area assertion (ADR 0012 defines none and
packages/brand-rules has no schema.usda). The safe area joins the
label-projection tolerances already deferred to one future ADR.

ADR 0011 gains an "Amended by ADR 0012" marker and a struck line rather
than a silent rewrite, so the superseded artifact shape stays legible.
The surviving brand_rules.json references in connector scaffolding are
recorded as known debt in BUILD_ORDER against ADR 0012, scheduled with
Phase 1 step 4, so they cannot be mistaken for the contract.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The prior commit added "these two files must agree" to 00-laws.mdc:64
and shipped it violated: shoploop.mdc:31 still led with "Any product
web page URL", the phrasing AGENTS.md:174 retires in the same commit,
and omitted the brand-owned-domain scope that every other enforced
surface now carries. Since ADR 0018 widens discovery across a whole
domain, that scope is the load-bearing half of the clause.

Lead clause only. The rest of the bullet is unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ninan-versioning
ninan-versioning merged commit 590fa6f into main Jul 29, 2026
4 checks passed
@ninan-versioning
ninan-versioning deleted the adr/0017-0018-cost-telemetry-catalog-factory branch July 29, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant