mxkuzn commited on
Commit
05b8a9f
·
verified ·
1 Parent(s): 1499ec4

solvi 0.8.0

Browse files
app.js CHANGED
@@ -222,10 +222,10 @@ async function loadPython() {
222
  $("py-line").textContent = "Python (Pyodide) + solvi: installing numpy and solvi…";
223
  await py.loadPackage(["numpy", "micropip"]);
224
  try { // solvi's own code needs only numpy at import time: skip scipy (another ~10 MB)
225
- await py.runPythonAsync("import micropip\nawait micropip.install('solvi>=0.2.1', deps=False)\nimport solvi");
226
  } catch (e) {
227
  console.warn("solvi without dependencies failed, installing with dependencies", e);
228
- await py.runPythonAsync("import micropip\nawait micropip.install('solvi>=0.2.1')\nimport solvi");
229
  }
230
  const src = await (await fetch(new URL("solvi_docs.py", import.meta.url))).text();
231
  py.FS.writeFile("/home/pyodide/solvi_docs.py", src);
 
222
  $("py-line").textContent = "Python (Pyodide) + solvi: installing numpy and solvi…";
223
  await py.loadPackage(["numpy", "micropip"]);
224
  try { // solvi's own code needs only numpy at import time: skip scipy (another ~10 MB)
225
+ await py.runPythonAsync("import micropip\nawait micropip.install('solvi==0.8.0', deps=False)\nimport solvi");
226
  } catch (e) {
227
  console.warn("solvi without dependencies failed, installing with dependencies", e);
228
+ await py.runPythonAsync("import micropip\nawait micropip.install('solvi==0.8.0')\nimport solvi");
229
  }
230
  const src = await (await fetch(new URL("solvi_docs.py", import.meta.url))).text();
231
  py.FS.writeFile("/home/pyodide/solvi_docs.py", src);
solvi_docs.py CHANGED
@@ -212,8 +212,8 @@ def run(payload_json):
212
  res = system.ask(init)
213
  except Exception as e: # noqa: BLE001
214
  return json.dumps({"error": f"{type(e).__name__}: {e}", "traceback": traceback.format_exc(limit=4)})
215
- rep = res.trace.replay(cat)
216
- _last.update(cat=cat, res=res)
217
  by = {r.name: r for r in res.trace.records}
218
  kinds = {n: part.kind for n, part in cat.parts.items()}
219
  answers = []
@@ -234,7 +234,7 @@ def run(payload_json):
234
  return json.dumps({
235
  "answers": answers, "records": records, "flow": flow, "flow_text": str(res.flow),
236
  "not_taken": sorted(res.flow.skipped.items()), "skipped_at_run": [list(x) for x in res.trace.skipped],
237
- "computed_state": res.computed_state, "init_hash": res.trace.init_hash,
238
  "replay": {"ok": rep["ok"], "steps": rep["steps"], "mismatches": [[str(x) for x in m] for m in rep["mismatches"]]},
239
  "ms": res.ms, "n_parts": len(cat.parts) + len(cat.rules), "auto": auto,
240
  }, default=str)
@@ -256,7 +256,7 @@ def tamper():
256
  """Simulate a careful forger: change one computed fact in a copy of the trace and re-hash that record, then replay."""
257
  if not _last:
258
  return json.dumps({"error": "run the use case first"})
259
- cat, res = _last["cat"], _last["res"]
260
  tr = copy.deepcopy(res.trace)
261
  target = None
262
  for kind in ("fn", "extract", "check"):
@@ -272,7 +272,7 @@ def tamper():
272
  old = target.value
273
  target.value = _tampered(old)
274
  target.hash = vhash(target.body()) # re-hash the edited record so it looks self-consistent
275
- rep = tr.replay(cat)
276
  return json.dumps({"name": target.name, "step": target.step, "from": _r(old), "to": _r(target.value),
277
  "replay": {"ok": rep["ok"], "steps": rep["steps"],
278
  "mismatches": [[str(x) for x in m] for m in rep["mismatches"]]}}, default=str)
 
212
  res = system.ask(init)
213
  except Exception as e: # noqa: BLE001
214
  return json.dumps({"error": f"{type(e).__name__}: {e}", "traceback": traceback.format_exc(limit=4)})
215
+ rep = res.trace.replay(system) # with the System, replay also checks the stored answers
216
+ _last.update(cat=cat, res=res, system=system)
217
  by = {r.name: r for r in res.trace.records}
218
  kinds = {n: part.kind for n, part in cat.parts.items()}
219
  answers = []
 
234
  return json.dumps({
235
  "answers": answers, "records": records, "flow": flow, "flow_text": str(res.flow),
236
  "not_taken": sorted(res.flow.skipped.items()), "skipped_at_run": [list(x) for x in res.trace.skipped],
237
+ "computed_state": res.state_text(), "init_hash": res.trace.init_hash,
238
  "replay": {"ok": rep["ok"], "steps": rep["steps"], "mismatches": [[str(x) for x in m] for m in rep["mismatches"]]},
239
  "ms": res.ms, "n_parts": len(cat.parts) + len(cat.rules), "auto": auto,
240
  }, default=str)
 
256
  """Simulate a careful forger: change one computed fact in a copy of the trace and re-hash that record, then replay."""
257
  if not _last:
258
  return json.dumps({"error": "run the use case first"})
259
+ res, system = _last["res"], _last["system"]
260
  tr = copy.deepcopy(res.trace)
261
  target = None
262
  for kind in ("fn", "extract", "check"):
 
272
  old = target.value
273
  target.value = _tampered(old)
274
  target.hash = vhash(target.body()) # re-hash the edited record so it looks self-consistent
275
+ rep = tr.replay(system)
276
  return json.dumps({"name": target.name, "step": target.step, "from": _r(old), "to": _r(target.value),
277
  "replay": {"ok": rep["ok"], "steps": rep["steps"],
278
  "mismatches": [[str(x) for x in m] for m in rep["mismatches"]]}}, default=str)
usecases/bol.js CHANGED
@@ -34,7 +34,7 @@ def release(consignee, containers):
34
  return "release" if found(containers) else "hold"
35
 
36
  QUESTIONS = [
37
- Question("release", "Release the shipment?", Answer.choice(["release", "hold"]), checkpoints=["port_allowed"]),
38
  Question("insurance_by", "Who arranges cargo insurance?", Answer.choice(["buyer", "seller"])),
39
  ]
40
  `,
 
34
  return "release" if found(containers) else "hold"
35
 
36
  QUESTIONS = [
37
+ Question("release", "Release the shipment?", Answer.choice(["release", "hold"]), requires=["port_allowed"]),
38
  Question("insurance_by", "Who arranges cargo insurance?", Answer.choice(["buyer", "seller"])),
39
  ]
40
  `,
usecases/dpa.js CHANGED
@@ -35,7 +35,7 @@ def transfers_safeguarded(transfer_mechanism):
35
 
36
  QUESTIONS = [
37
  Question("approve", "Approve the vendor?", Answer.choice(["approve", "review", "reject"]),
38
- checkpoints=["breach_within_72h"]),
39
  Question("transfers_safeguarded", "Transfers outside the EEA safeguarded?", Answer.yes_no()),
40
  ]
41
  `,
 
35
 
36
  QUESTIONS = [
37
  Question("approve", "Approve the vendor?", Answer.choice(["approve", "review", "reject"]),
38
+ requires=["breach_within_72h"]),
39
  Question("transfers_safeguarded", "Transfers outside the EEA safeguarded?", Answer.yes_no()),
40
  ]
41
  `,
usecases/insurance.js CHANGED
@@ -36,8 +36,8 @@ def payout_band(payout, claim_amount):
36
  return "full" if payout >= money(claim_amount) else "partial"
37
 
38
  QUESTIONS = [
39
- Question("covered", "Is the claim covered?", Answer.yes_no(), checkpoints=["cause_not_excluded"]),
40
- Question("payout_band", "Payout", Answer.choice(["full", "partial", "none"]), checkpoints=["cause_not_excluded"]),
41
  ]
42
  `,
43
  docs: [
 
36
  return "full" if payout >= money(claim_amount) else "partial"
37
 
38
  QUESTIONS = [
39
+ Question("covered", "Is the claim covered?", Answer.yes_no(), requires=["cause_not_excluded"]),
40
+ Question("payout_band", "Payout", Answer.choice(["full", "partial", "none"]), requires=["cause_not_excluded"]),
41
  ]
42
  `,
43
  docs: [
usecases/invoice.js CHANGED
@@ -42,7 +42,7 @@ def days_left(due, today):
42
 
43
  QUESTIONS = [
44
  Question("pay", "Payment decision", Answer.choice(["schedule", "escalate", "reject"]),
45
- checkpoints=["iban_checksum", "not_overdue"]),
46
  Question("days_left", "Time left to pay", Answer.choice(["overdue", "under a week", "a week or more"])),
47
  ]
48
  `,
 
42
 
43
  QUESTIONS = [
44
  Question("pay", "Payment decision", Answer.choice(["schedule", "escalate", "reject"]),
45
+ requires=["iban_checksum", "not_overdue"]),
46
  Question("days_left", "Time left to pay", Answer.choice(["overdue", "under a week", "a week or more"])),
47
  ]
48
  `,
usecases/lease.js CHANGED
@@ -39,7 +39,7 @@ def sign(notice_days):
39
  return "sign" if notice_days <= 60 else "negotiate" # tenant should be able to leave on two months' notice
40
 
41
  QUESTIONS = [
42
- Question("sign", "Sign as is?", Answer.choice(["sign", "negotiate"]), checkpoints=["deposit_within_cap"]),
43
  Question("pets_allowed", "Are pets allowed?", Answer.choice(["yes", "no", "not stated"])),
44
  ]
45
  `,
 
39
  return "sign" if notice_days <= 60 else "negotiate" # tenant should be able to leave on two months' notice
40
 
41
  QUESTIONS = [
42
+ Question("sign", "Sign as is?", Answer.choice(["sign", "negotiate"]), requires=["deposit_within_cap"]),
43
  Question("pets_allowed", "Are pets allowed?", Answer.choice(["yes", "no", "not stated"])),
44
  ]
45
  `,
usecases/offer.js CHANGED
@@ -38,7 +38,7 @@ def starts_within_60_days(start_date, today):
38
  return (parse_date(start_date) - today).days <= 60
39
 
40
  QUESTIONS = [
41
- Question("send", "Send the offer as is?", Answer.choice(["send", "revise"]), checkpoints=["probation_legal"]),
42
  Question("band", "Salary vs approved band", Answer.choice(["below", "in band", "above"])),
43
  Question("starts_within_60_days", "Starts within 60 days?", Answer.yes_no()),
44
  ]
 
38
  return (parse_date(start_date) - today).days <= 60
39
 
40
  QUESTIONS = [
41
+ Question("send", "Send the offer as is?", Answer.choice(["send", "revise"]), requires=["probation_legal"]),
42
  Question("band", "Salary vs approved band", Answer.choice(["below", "in band", "above"])),
43
  Question("starts_within_60_days", "Starts within 60 days?", Answer.yes_no()),
44
  ]
usecases/receipt.js CHANGED
@@ -39,7 +39,7 @@ def weekend(purchase_date):
39
  return purchase_date.weekday() >= 5
40
 
41
  QUESTIONS = [
42
- Question("reimburse", "Reimburse this receipt?", Answer.yes_no(), checkpoints=["not_too_old"]),
43
  Question("change_correct", "Is the change right (cash - total)?", Answer.yes_no()),
44
  Question("weekend", "Bought on a weekend?", Answer.yes_no()),
45
  ]
 
39
  return purchase_date.weekday() >= 5
40
 
41
  QUESTIONS = [
42
+ Question("reimburse", "Reimburse this receipt?", Answer.yes_no(), requires=["not_too_old"]),
43
  Question("change_correct", "Is the change right (cash - total)?", Answer.yes_no()),
44
  Question("weekend", "Bought on a weekend?", Answer.yes_no()),
45
  ]
usecases/support.js CHANGED
@@ -36,7 +36,7 @@ def urgency(deadline, today):
36
 
37
  QUESTIONS = [
38
  Question("route", "Which queue?", Answer.choice(["billing", "fulfilment", "general", "ask for order number"]),
39
- checkpoints=["has_order_number"]),
40
  Question("urgency", "Urgency", Answer.choice(["high", "normal"])),
41
  ]
42
  `,
 
36
 
37
  QUESTIONS = [
38
  Question("route", "Which queue?", Answer.choice(["billing", "fulfilment", "general", "ask for order number"]),
39
+ requires=["has_order_number"]),
40
  Question("urgency", "Urgency", Answer.choice(["high", "normal"])),
41
  ]
42
  `,