fix(workflows): bom_cost_rollup was written against entities that do not exist - #70
Merged
Merged
Conversation
…not exist
It passed the raw-ERP gate because it was already `business-entity` shaped. It
was still fiction against `agentos_neo_xentral`:
- a `BillOfMaterials` entity — the core has 50 entities and that is not one of
them. The bill of materials is a section ON the product, `bom.items`, filled
on a single read.
- `Product` filtered on `isBom` — Product filters on number, status, name,
project, ean, manufacturerNumber, variant.isMatrix and updatedAt. Nothing else.
- `purchasePrice` and `calculatedPurchasePrice` as flat fields — the model has
`prices.purchase`.
- `.get('data')` on a list result, which ADR-0002 removed.
The rewrite reads the bill from the product and writes `prices.purchase` with
`source: 'calculated'` — the one value that makes Xentral treat the number as a
calculated purchase price rather than a manually maintained one.
**The seeding got better, not just correct.** There is no "is a bill of
materials" filter, but the list PAYLOAD already carries
`production.hasBillOfMaterials` and `prices.purchase` per product. So the work
list starts with the bills alone and most components never need a read at all.
Measured on a real instance: 2 of 25 products are bills, and in the fixtures the
nested case dropped from 4 reads to 2, the diamond from 6 to 3.
**Two failure modes the original did not survive.** A bill containing itself
looped until the run's time limit killed the job; it is now detected and logged.
And a cycle no longer poisons everything above it: anything built on a component
we could not cost is left untouched rather than written as 0. Overwriting a
maintained purchase price with a number we know is wrong is worse than doing
nothing.
Verified live against mvp (dry-run, writes suppressed, reads real):
prd_62005 = 2 x prd_62004 @ 1.20 -> 2.4 (stored: 2.40)
prd_61989 = 1x + 4x + 2x @ 0.00 -> 0.0 (stored: 0.00)
Both writes idempotent on that instance, so the numbers are confirmed against
data neither I nor the fixtures invented. Plus four fixture scenarios — nested,
cycle, diamond, and a component outside the listed page — and `validate_graph` /
`check_workflow` clean in both locales.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The non-recursive sibling of the two templates fixed in #69. It passed the raw-ERP gate because it was already
business-entityshaped — it was still fiction againstagentos_neo_xentral.BillOfMaterialsentitybom.items, filled on a single readProductfiltered onisBompurchasePrice,calculatedPurchasePriceprices.purchase.get('data')on a listBetter seeding, not just correct
There is no "is a bill of materials" filter — but the list payload already carries
production.hasBillOfMaterialsandprices.purchaseper product. So the work list starts with the bills alone, and most components never need a read at all.Measured on a real instance: 2 of 25 products are bills. In the fixtures the nested case dropped from 4 reads to 2, the diamond from 6 to 3.
Two failure modes the original did not survive
0. Overwriting a maintained purchase price with a number we know is wrong is worse than doing nothing.Also:
source: 'calculated'on the write — the one value that makes Xentral treat the number as a calculated purchase price rather than a manually maintained one.Verified live against mvp
Dry-run: writes suppressed, reads real.
Both writes idempotent on that instance — the numbers are confirmed against data neither I nor the fixtures invented.
Plus four fixture scenarios (nested, cycle, diamond, and a component outside the listed page), and
validate_graph/check_workflowclean in both locales.One thing this uncovered, fixed separately
The live run made the validator warn that
page[size]"does nothing" and recommendquery.page = {"size": N}instead. Measured:page[size]returns 100 rows, the recommended form returns 50. The validator was warning about the only form that works. Fixed in agent-os #107.Not changed
The schedule ships without
active: true, so it does not start itself on install. That is consistent across all six scheduled templates, so I left it alone rather than making this one the odd one out.