Stockroom Intake, Inventory and Pricing Design

Part of the Simple Agility stack. Canonical copy: ~/source/stockroom/docs/superpowers/specs/2026-10-03-stockroom-intake-inventory-pricing-design.md. This page mirrors it for retrieval. Status: approved 2026-10-03; implementation not started.

Context

The operator runs two small businesses — a reseller business and a short-term rental in Pacific Beach — on a self-built software stack, Simple Agility: Wikantik (knowledge and business context), Roller (outreach blogs) and jakemon (the observability plane). Everything built so far sits upstream of the transaction — knowledge, outreach and signals. Nothing in the stack records the things the businesses actually do.

Asked where the most manual time or lost money goes, the operator named reseller listing work, with photographing, writing, pricing, crosslisting and delisting all roughly equal. This design covers the shared front half of that pipeline — everything every listing needs, regardless of where it is eventually posted:

item in hand → identify → inventory record → price per route → triage → channel-neutral listing content

Price is the only part allowed to vary by channel. Stockroom is a new Simple Agility component in its own repository, ~/source/stockroom. A lightweight warehouse-management (WMS) capability will grow there later; this design leaves room for it without building it.

What the operator said

Assumptions

Decisions

DecisionChoice
Repository and stack~/source/stockroom, following Wealthview: Java 25, Spring Boot, Maven multi-module, React 19 + Vite, PostgreSQL 18, Flyway, Docker Compose
ClientOne responsive web app; React Native only if phone camera scanning proves to matter
Boundary with Amazon toolsEvery item enters Stockroom; triage compares FBA with every other route; FBA-bound items continue into the existing FBA tool (handoff out of scope)
Intake shapeTwo passes: a fast scan pass, then pricing + triage, then preparation only for routes that need it
TriageA pure function of (item facts, quotes, rules version) → decision; no I/O
Business rulesNumeric thresholds in a versioned triage_rules table; prose rules and rationale in Wikantik pages, read by name
GenAIListingDrafter and ItemIdentifier ports with Claude and Ollama adapters, chosen per task by configuration
Default modelClaude Opus 5.5 (claude-opus-5-5) through the official Anthropic Java SDK
MoneyInteger cents, USD
TelemetrySimple Agility telemetry contract from the first commit

Non-goals

Architecture

 phone / desk browser (responsive web app)
   │ scan ISBN/UPC · photos · cost · bin
   ▼
 ┌──────────────── stockroom (Spring Boot) ─────────────────┐
 │ Intake ──► Catalog lookup ──► Pricing ──► Triage          │──► Amazon SP-API · eBay Browse
 │   │         (Open Library,    (source      (pure core)    │    · buyback quotes
 │   │          Google Books)     adapters)       │          │
 │   ▼                                            ▼          │
 │ Inventory (Postgres) ◄──────────────── Listing preparer ──│──► Wikantik (rules pages)
 │   photos on a volume                     (Claude | Ollama)│
 └───────────────────────────────────────────────────────────┘
        /metrics · JSON logs · /healthz ──► jakemon
UnitDoesDepends on
IntakeCreates items from a scan or photos, inside an acquisition sessionInventory
Catalog lookupIdentifier → facts, cached per identifierCatalogSource adapters
PricingCollects quotes per routePriceSource adapters, rules
TriagePicks a route and explains whyNothing — pure
Listing preparerWrites channel-neutral content; FBA notes by templateListingDrafter, RulesSource
IdentificationPhoto-first identification proposalsItemIdentifier
InventoryItems, acquisitions, locations, events, photosPostgreSQL, photo volume
Work runnerDurable background jobs with per-source rate limitsPostgreSQL

Calls to Amazon, eBay and buyback vendors are functional inputs to pricing, not observation, so they belong to Stockroom and not to jakemon — per the rule that decides where data lives on SimpleAgilityObservabilityPlane. Wikantik supplies context, not storage: inventory never lives in wiki pages.

Data model

All tables come from Flyway migrations.

Item lifecycle

intake ─► identified ─► (pricing + triage) ─┬─► needs_prep ─► ready      (ebay, local, lot member)
   │                                         ├─► ready                    (fba, buyback)
   └─► needs_identification                  ├─► needs_price
                                             └─► needs_decision ─► (you pick a route)
StatusMeaningWork queue
intakecreated; lookup running—
needs_identificationlookup failed or record too thinNeeds identification
identifiedfacts known; pricing pendingReady to price
needs_priceno usable quotesNeeds price
needs_decisionhigh value or flagged; triage deferred to the operatorLook closer
needs_preprouted somewhere that needs photos or contentNeeds prep
readyhas everything its route needsRouted

Later components (posting, sales) add statuses after ready without changing these.

Intake

Intake starts by opening an acquisition session — e.g. "Library sale, $40, bin B-2" — so every item scanned gets its cost share and default location.

Pass 1 — scan. The code is normalised (ISBN-10 → 13, check digits, price add-on stripped, 978/979 EANs treated as ISBNs) and the item is created immediately. Catalog lookup runs in the background (cache, then Open Library, then Google Books), so scanning never waits on the network. Grading is one tap (defaulting to the last grade) with optional flaw chips. Suspected first editions, signed copies and oddities get a look-closer flag; pricing also sets it above the high-value threshold. Scanning the same identifier twice within 10 seconds asks whether it is another copy.

Photo-first path. For pre-ISBN books, vintage, collectibles and tools without a barcode: 1–3 photos (for books the copyright page matters most — the printing line identifies the edition). The identifier model proposes an identification with a confidence level; the operator confirms or corrects it.

Weight is estimated for books from page count and binding, entered for everything else, and always editable.

Listing preparation

Preparation runs only for items that need it. FBA condition notes come from the grade and flags by template — no model call. Buyback needs nothing. eBay and local get photos and a full draft; a lot gets one lot photo and a lot draft.

Draft inputs are the catalog facts, grade and flags, photos, and rules pages from Wikantik read by slug, never searched — a general style guide plus category pages in a reselling cluster (hub ResellingHub, created with phase 3). Page versions are recorded with each draft. If Wikantik is unreachable the last cached copy is used and marked stale.

The output is one channel-neutral, schema-validated version: title, description, condition text, item specifics, keywords and claims. Honesty rules, enforced in the prompt and checked after generation:

Drafts are reviewed beside their photos; approving marks that version approved, edits create new versions, and books can be approved in bulk.

GenAI providers

Two ports — ItemIdentifier and ListingDrafter — each with a Claude adapter (official Java SDK, claude-opus-5-5, structured output, explicit effort per task, prompt caching on the system prompt and rules, explicit refusal handling with server-side fallbacks) and an Ollama adapter (/api/chat with base64 images, the JSON schema in format, and think: false). The provider and model are chosen per task by configuration; both adapters share the same prompt templates and must satisfy the same schemas, and every draft records which provider and model produced it.

A golden set of about 20 real items, run on demand against either provider, scores schema validity, field accuracy and honesty-rule violations — the measured answer to "is the local model good enough?" before switching. With Claude, cost is on the order of cents per draft and a few dollars a week at this volume.

Pricing and triage

RouteSourceNet to the operator
FBAAmazon SP-API: Catalog Items (ISBN → ASIN, sales rank), Product Pricing, Product Fees, Listings Restrictionsprice − Amazon fees − inbound shipping per unit
eBayeBay Browse API: active listings by GTIN/ISBN, comparable conditionprice − fees − shipping from a weight table
LocalDerived: eBay/Amazon prices × a local discount; low confidence until own history existsprice
BuybackA vendor quote API if one is available; otherwise manual entryquote
LotMembers' local values × a lot factor; low confidenceprice

Responses are cached per identifier, condition and day; stale quotes are refreshed before triage.

Triage is a pure function, checked in order:

  1. High value or look-closer → needs_decision, never automatic.
  2. FBA net ≥ a small minimum and sales rank ≤ a velocity cap and not restricted → FBA.
  3. Best individual net (eBay or local) ≥ a time-cost floor → that route.
  4. Buyback quote ≥ its minimum → buyback.
  5. Otherwise → lot, with grouping suggestions by author, series or subject.
  6. No usable quotes → needs_price, with the reason.

Every decision records the rule that fired, the quotes used, the expected net and every route passed over with measured versus required values — meeting the three mandatory properties of the Simple Agility feedback-loop pattern. Overrides record a reason and never erase the recommendation.

Failure handling and telemetry

A DB-backed job queue runs lookups, quotes, triage and drafts with per-source rate limits and backoff; exhausted retries land the item in the matching work queue with the reason shown. A failure never blocks other items and never loses a scan. Credentials come from the environment or Compose secrets. Telemetry follows the contract from the first deploy: JSON log envelope with correlation_id, /metrics, /healthz, and events as log lines.

Testing and rollout

Test-driven throughout: table-driven triage tests plus invariants (never automatic above the high-value threshold, never a route without a quote, the FBA rule honours rank and restrictions); identifier-normalisation tests; source adapters tested against recorded responses; Testcontainers PostgreSQL with real migrations; the honesty validator unit-tested; the golden set on demand; a ratcheting coverage floor.

  1. Foundation — scaffold, telemetry, auth, acquisitions, locations, scan-by-ISBN intake, catalog lookup, inventory, queues. Start the Amazon SP-API developer registration immediately.
  2. Pricing and triage — eBay first, SP-API once approved, then buyback and lots.
  3. Listing preparation — both drafter adapters, golden set, reselling rules pages, review screen.
  4. Photo-first identification.

Each phase is usable on its own and gets its own implementation plan.

Risks and open questions