Simplify Bottle classifier terms and boundaries
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 103
- Forks
- 18
- Avg merge
- 1h 19m
- Merged PRs (30d)
- 555
Description
Goal
Make the classifier system easier to understand and maintain.
Use one domain term for each concept. Use each term with one meaning. A Bottle is one complete product release. Do not use Concrete Bottle as a second name for Bottle.
Use these boundaries:
- Reference classification identifies a Bottle.
- It returns
match,create_bottle, orno_match. - A catalog change is a separate proposal.
- The server validates and applies an approved change.
- Callers use flat Bottle input.
- The server keeps
BottleGroupstorage details private.
Language rule
Use ASD-STE100 Simplified Technical English, Issue 9 for new classifier terms, prompts, schemas, documentation, and user text.
Apply these rules:
- Use one term for one concept.
- Use one meaning for each term.
- Prefer a short and common word.
- Use short, active sentences.
- Give one instruction in each sentence.
- Put each necessary Peated technical noun or verb in a small controlled glossary.
- Do not add a synonym for an existing glossary term.
- Do not use an adjective only to distinguish a domain object from an internal storage object.
STE permits project-specific technical nouns and technical verbs. The Peated glossary must define them and control their use.
Current problems
The data model changed from a parent Bottle and a release to one Bottle. The code still exposes both concepts.
- Active code uses
ConcreteBottlefor Bottle. - Different boundaries use
stable/exact,shared/exact, andshared/exact/siblings. - Manual creation and classifier creation can give the same field to different storage owners.
statedAgeis one example. repair_bottlehas a different meaning in the prompt, reference resolver, photo flow, and price flow.- Photo identification runs a local-identification agent and then runs the full classifier.
reviewPolicy.tsis approximately 2,255 lines. It does fuzzy semantic comparison and can change a classifier decision.- Output schemas and fixtures still contain release terms such as
releaseTraits,releaseId,createsRelease,matched_release, andcandidate_release.
References:
- Whisky identity model
- Bottle classifier architecture
- Catalog identity schema
- Concrete Bottle schemas
- Flat input adapter
- Classifier create-input mapping
- Classifier context contract
- Classifier instructions
- Runtime review policy
- Reference resolution
- Price matching proposals
- Photo identification
- Existing value audit
Work slices
Each slice must be a small PR. Each PR must leave the system ready to deploy.
Use existing tests and evals in the PR that changes behavior. Do not create a standalone baseline document, metrics subsystem, or measurement-only PR.
1. Define the controlled Peated glossary
Create a short classifier glossary next to the classifier architecture document.
Start with:
-
Bottle: one complete product release.
-
Bottle Group: an internal storage group for fields that multiple Bottles share.
-
Match: the reference identifies an existing Bottle.
-
Create Bottle: the reference identifies a Bottle that is not in the catalog.
-
No Match: the system cannot identify a Bottle safely.
-
Suggested Change: an untrusted catalog change from an agent.
-
Review Operation: a validated and permission-checked change that the server can apply.
-
Each domain concept has one term and one definition.
-
Prompts, schemas, code names, documents, and user text use the glossary.
-
A CI or review check can find prohibited legacy terms.
-
The glossary defines each necessary technical noun or verb that is not in the STE general dictionary.
2. Remove old Bottle and release terms
Make a hard cut in active internal names:
-
ConcreteBottleV1→BottleV1 -
createConcreteBottle→createBottle -
updateConcreteBottle→updateBottle -
mergeConcreteBottles→mergeBottles -
Apply the change to schemas, helpers, errors, tests, and active eval data.
-
Remove old release-result terms from active eval schemas and fixtures.
-
Historical migrations and archived records can keep historical text.
-
Do not change classifier behavior.
-
Do not add internal compatibility aliases.
-
Run targeted tests and package type checks.
Dependency: slice 1.
3. Remove the local-identification agent
Keep the deterministic exact-alias check. Use the full Bottle classifier as the only model-based identification pass.
- Photo identification makes no more than one model-based Bottle classification.
- Delete local-identification prompts, wrappers, schemas, and evals when no production caller remains.
- An exact alias still resolves without a model call. (#600)
- Record quality, candidate recall, time, tokens, and tool calls before and after the change in this PR.
- Run photo-identification integration tests.
4. Give repair one meaning
Remove repair_bottle as an identity result. Identity classification returns only match, create_bottle, or no_match.
A required catalog correction is a separate Suggested Change. The system must not silently use a match that requires a correction.
- Make the prompt, schemas, reference resolver, photo flow, and price flow use the same three results.
- Do not let later fuzzy logic change
create_bottleto a match or correction. - Add a boundary test that proves a required correction cannot silently become
match. - Give each old repair fixture an identity result and, when necessary, a Suggested Change.
5. Separate identification from catalog changes
The reference classifier must only identify a Bottle. Move Bottle and entity change tools to the catalog review path.
- Remove catalog-change tools from the reference classifier.
- Make the Bottle review path own Suggested Changes for catalog data.
- Let a caller identify a Bottle without a catalog review.
- Keep validation, permission checks, and application on the server.
- Measure identity quality and Suggested Change precision separately.
Dependency: slice 4.
6. Use one flat Bottle write boundary
Give all callers a flat BottleCreateInput and BottlePatch. One server service owns field storage, shared-field changes, and the list of Bottle and Bottle Group fields.
- Make manual entry, classifier creation, imports, and administrator edits use one flat service.
- Give the same input the same storage owner for every caller.
- Prove that manual and classifier creation handle
statedAgein the same way. - Do not expose
BottleGroupin public classifier or route input types. - Delete caller-side
stable/exact,shared/exact, and flattening adapters after the cutover. - Test shared-field changes at the service boundary.
Dependency: slice 2.
7. Remove output that has no reader
Find every reader before you remove a field. Start with nested identityBasis data, transitional releaseTraits, duplicate model-reported tool data, and old release fields in eval data.
- Give every remaining output field a named production or eval reader.
- Remove an unused field from the prompt, schema, mapping, fixture, and document.
- Do not add an abstraction only to keep the old shape.
- Run the existing classifier evals after each removal.
8. Make review policy a validation boundary
Reduce reviewPolicy.ts after the earlier contract changes.
Keep checks for schema validity, known IDs, impossible result combinations, direct contradictions, permissions, and automation policy. Remove fuzzy name comparison, sparse-name interpretation, duplicate inference, and general decision changes.
- Do not change a valid model result with a second fuzzy name classifier.
- Make invalid IDs, impossible combinations, and permission failures fail closed.
- Separate validation tests from semantic classification tests.
- Make the review-policy module and its vocabulary materially smaller.
- Run the existing classifier evals and report regressions by result type.
- Complete the open semantic-reclassification work in task 5.1.
Dependencies: slices 4, 5, and 7.
9. Align the entity classifier
The entity classifier uses numeric confidence without a comparable live eval set. Bottle review can also suggest entity changes.
- Give one component ownership of entity Suggested Changes.
- Use the same Suggested Change and Review Operation boundary, or limit the entity classifier to advice.
- Remove duplicate change terms.
- Remove confidence values that do not have measured meaning.
- Add deterministic contract tests before adding more work to this classifier.
Dependency: slice 5. This slice does not block the Bottle work.
Order
- Start with slice 1.
- Slice 2 depends on slice 1.
- Slices 3, 4, and 7 can start immediately.
- Slice 5 depends on slice 4.
- Slice 6 depends on slice 2.
- Slice 8 depends on slices 4, 5, and 7.
- Slice 9 depends on slice 5.
Not in this issue
- Do not rewrite the full prompt before you simplify the contracts.
- Do not add a multi-agent classifier.
- Do not delete the
BottleGroupdatabase model in this work. - Do not keep internal aliases for old names.
- Do not add settings or extension points for possible future classifiers.
- Do not put all slices in one PR.
Follow-up: classifier eval root causes
The 2026-08-11 classifier run passed 67/97 cases. Treating all 30 failures as model-semantic misses was incorrect. The failure traces split into three owners:
- 8 proven contract or eval defects: Eight fixtures require structured age or series traits to be duplicated in
name, contrary toProposedBottleSchema. - 12 unresolved product-policy or catalog-semantic cases: Nine dirty or incomplete candidate cases, including Rogues' Banquet, need one compatibility rule. Mars needs a canonical name/edition split. High Country needs a batch-versus-observation rule. Watchpost needs a choice between two plausible Westland entities.
- 10 genuine agent/runtime gaps: Three create results omitted supported fields. Talisker inferred an age from dates. Ardbeg chose the wrong alias scope. Skrewball crossed the product-scope boundary. Four audits returned missing or over-broad patches.
Do not tune the agent against contradictory or undecided expectations.
Follow-up work
- Align the eight canonical-name fixtures with the chosen
namecontract. - Define candidate compatibility for missing fields, populated conflicts, broad products, and exact-cask rows. Updated nine fixtures and the prompt; focused live evidence passed Elijah Craig and Rogues Banquet, then Mastersons failed conservatively and stopped the remaining selected cases.
- Decide the Mars field split, High Country batch semantics, and canonical Watchpost/Westland entity. Mars uses
Komagatakeplus2022 Edition; High Country lot 23J12 matches ongoing Bottle 12825; Watchpost is an unaged complete blend using Westland Distillery 1987. - Require product-level evidence before generic marketing language, production lot codes, or component facts become Bottle identity. The ordered-workflow follow-up passed Watchpost and three marketed-edition controls, but Mars and High Country still followed secondary pages that repeated label wording without proving producer product structure. The remaining gap is evidence retrieval and source selection, not another prompt exception.
- Add a final evidence-to-output completeness check for create results.
- Add the no-date-arithmetic, alias-scope, and flavored-whiskey scope rules to the runtime contract.
- Make Bottle audits compare every supported field before they finalize one sparse patch.
- Run one focused follow-up slice for the resolved contract and prompt rules. It passed Talisker, Creag Isle, Hibiki, and SMWS 10.258; remaining field-completeness and audit-patch misses stay open.
- Run the full suite only after the contract and focused cases are stable. Require the 80% floor, zero unsafe scope creates, and no deterministic-ignore regression.
Completion conditions
- Peated uses Bottle for one complete product release.
- The controlled glossary follows ASD-STE100 rules.
- Reference classification has three identity results.
- Catalog corrections use a separate reviewed change boundary.
- All Bottle writers use one flat service.
- Runtime review checks trust and structure. It does not repeat semantic classification.
- Transitional and unused fields are gone.
- Existing classifier evals show no unexplained loss of identity quality.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the Bottle classifier architecture, whisky identity model, and the linked TypeScript contracts, then inspect the remaining unchecked work and existing classifier evals. For each slice, use the named schemas, helpers, routes, and tests as entry points; done means the stated contract is applied consistently, unused output has no readers, and the existing targeted tests and evals pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, backend-api-design
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100