_global:price-parser-repair
Repair a pricing-page parser after a provider redesigns its page, once a human has settled what the price actually is. Opens a draft PR; never edits a rate table.
Manifest
_global/tasks.yaml- Address
_global:price-parser-repair— alsoglobal:price-parser-repair- Runner
- claude-code
- Policy
- pr may push a countryos/* branch and open a draft PR — the review is the gate
- Workspace
- countries/_global/
- Schedule
- on demand only
- Model
- sonnet
- Budget
- 60 turns · 30 minutes
- Triggerable
- yes — free text can reach it
- Notifies
- every run — 🟢 on success, 🔴 on failure
- Description (manifest)
- Repair a pricing-page parser after a provider redesigns its page, once a human has settled what the price actually is. Opens a draft PR; never edits a rate table.
Nothing recorded yet.
The skill it runs
countries/_global/skills/price-parser-repair/SKILL.md · 74 linesRead the skill
Repair a pricing-page parser
tools/bin/price-watch reads each provider's published pricing page and compares
it to orchestrator/src/rates/<provider>.json. When a provider restructures that
page the parser stops being able to read it, the rate is marked disputed, and an
entry is opened in countries/_global/decisions.md.
This task fixes the parser. It never decides what a price is. A human settles that in the register first; you are repairing the deterministic path so the next weekly check does not need a human at all.
Before you start
Read the register: countries/_global/decisions.md. Find the open P- entry
naming the provider you were triggered for.
If its Status is not résolu, stop. Report that the price has not been
settled yet and do nothing else. A parser written to reproduce a number nobody has
confirmed is a parser that hard-codes a guess.
What to do
Fetch the page yourself and read its structure:
curl -sL "<the Source URL from the entry>" > /tmp/page.htmlOnly that URL. This task makes no other network calls.Run the parser as it stands and see how it fails:
price-watch check --provider <name> --no-llm --dry-runFix the parser function in
tools/bin/price-watch(parseDeepSeek,parseAnthropic, or a new one registered inPARSERS).Anchor on labels, never on position. The parser must find a value by the text next to it — the model's name, the row's caption — and return
nullwhen that text is absent. A parser that reads "the third number on the page" keeps working after a redesign and silently returns the wrong column, which is the single failure this whole tool exists to prevent. Returning nothing is a good outcome; guessing is not.Verify against the numbers the human accepted in the register:
price-watch check --provider <name> --no-llm --dry-runmust now read exactly those values, and reportokfor every model the entry did not dispute.Check you have not broken the other provider:
price-watch check --no-llm --dry-run— every other model must still sayok.
What you must not do
- Never edit a file under
orchestrator/src/rates/. Prices are applied byprice-watch applyafter a human accepts them, never by an agent, and never as a side effect of fixing a parser. If your parser only passes once you have changed a stored rate, your parser is wrong. - Never remove the
disputedmarker by hand — the next successfulcheckclears it on its own, which is the proof that the repair worked. - Never weaken
invariants()to make a value pass. That function is the only check that catches a plausible-but-wrong reading; loosening it to get a green result removes the guard that would have caught your own mistake.
Finishing
Open a draft PR with the parser change alone. In the description: the entry
id, what changed on the page, what the parser now anchors on, and the before/after
output of price-watch check.
This is code that decides what money costs, so it is reviewed by a human and
merged by a human. Append the usual dated entry to memory/journal.md: which
provider moved, what the page does now, and what the parser keys off — so the next
repair starts from what this one learned.