nabla-cli 0.9.1__tar.gz → 0.9.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/PKG-INFO +1 -1
  2. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/__init__.py +1 -1
  3. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/cli.py +6 -1
  4. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/pusher.py +8 -1
  5. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla_cli.egg-info/PKG-INFO +1 -1
  6. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/pyproject.toml +1 -1
  7. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_cli_ux.py +3 -1
  8. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_push.py +3 -1
  9. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/README.md +0 -0
  10. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/__main__.py +0 -0
  11. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/branding.py +0 -0
  12. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/config.py +0 -0
  13. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/contract.py +0 -0
  14. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/induce.py +0 -0
  15. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/profile.py +0 -0
  16. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/prompt_recon.py +0 -0
  17. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/puller.py +0 -0
  18. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/recorder.py +0 -0
  19. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/samplegen.py +0 -0
  20. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/scanner.py +0 -0
  21. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/schema_resolver.py +0 -0
  22. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/schemas/site_profile.schema.json +0 -0
  23. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/term.py +0 -0
  24. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla/ui.py +0 -0
  25. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla_cli.egg-info/SOURCES.txt +0 -0
  26. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla_cli.egg-info/dependency_links.txt +0 -0
  27. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla_cli.egg-info/entry_points.txt +0 -0
  28. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla_cli.egg-info/requires.txt +0 -0
  29. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/nabla_cli.egg-info/top_level.txt +0 -0
  30. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/setup.cfg +0 -0
  31. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_config.py +0 -0
  32. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_e2e_profile.py +0 -0
  33. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_induce.py +0 -0
  34. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_prompt_recon.py +0 -0
  35. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_pull.py +0 -0
  36. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_recorder.py +0 -0
  37. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_samplegen.py +0 -0
  38. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_scanner.py +0 -0
  39. {nabla_cli-0.9.1 → nabla_cli-0.9.2}/tests/test_schema_resolver.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nabla-cli
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Call-site harvester: scan OpenAI call sites, record real traffic, emit site profiles
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -1,3 +1,3 @@
1
1
  """nabla — call-site harvester CLI (pre-Phase-0)."""
2
2
 
3
- __version__ = "0.9.1"
3
+ __version__ = "0.9.2"
@@ -14,7 +14,7 @@ from rich.console import Console
14
14
  from . import __version__
15
15
  from .branding import print_banner
16
16
  from .config import PROVIDERS, apply_to_env, save_config
17
- from .contract import Example, Verifiability, is_supported
17
+ from .contract import Example, Verifiability, compute_site_id, is_supported
18
18
  from .profile import build_profile, find_site
19
19
  from .recorder import RecordSource, ZeroTrafficError, record
20
20
  from .scanner import scan
@@ -947,6 +947,11 @@ def _build_one(args, site, final_rail: bool = False, mode: str = "profile") -> i
947
947
 
948
948
  if mode == "jeremy":
949
949
  seed = {
950
+ # Stable site identity (template+schema hash) — the thread that
951
+ # lets `pull` later match a fine-tuned deployment back to this
952
+ # exact call site. Same value as the profile's site_id.
953
+ "site_id": compute_site_id(template.template, schema),
954
+ "symbol": site.symbol,
950
955
  "goal": _compose_seed_goal(goal),
951
956
  "system_prompt": template.system_prompt or "",
952
957
  "examples": [
@@ -50,9 +50,15 @@ def resolve_endpoint(flag_value: str | None = None) -> str:
50
50
 
51
51
  def to_run_task(kind: str, artifact: dict) -> dict:
52
52
  """Translate a build/jeremy artifact into the dispatcher's
53
- RunTaskRequest shape. Pure rearrangement — nothing invented."""
53
+ RunTaskRequest shape. Pure rearrangement — nothing invented.
54
+
55
+ site_id (the profile/seed's stable template+schema hash) rides along so
56
+ the backend can key the eventual fine-tuned deployment to the exact
57
+ call site — `nabla pull` joins on it later. Never file:line, never the
58
+ bare symbol: both are ambiguous across drift and duplicates."""
54
59
  if kind == "jeremy":
55
60
  return {
61
+ "site_id": artifact.get("site_id"),
56
62
  "goal": artifact.get("goal", ""),
57
63
  "examples": artifact.get("examples", []),
58
64
  "student_system_prompt": artifact.get("system_prompt", "") or "",
@@ -65,6 +71,7 @@ def to_run_task(kind: str, artifact: dict) -> dict:
65
71
  + [str(c).rstrip(".") + "." for c in goal_block.get("constraints", [])]
66
72
  ).strip()
67
73
  return {
74
+ "site_id": artifact.get("site_id"),
68
75
  "goal": goal_text,
69
76
  "examples": [
70
77
  {"problem": e.get("prompt", ""), "solution": e.get("completion", "")}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nabla-cli
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Call-site harvester: scan OpenAI call sites, record real traffic, emit site profiles
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nabla-cli"
3
- version = "0.9.1"
3
+ version = "0.9.2"
4
4
  description = "Call-site harvester: scan OpenAI call sites, record real traffic, emit site profiles"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -547,7 +547,9 @@ def test_jeremy_single_site_writes_seed_spec(tmp_path, monkeypatch, capsys):
547
547
 
548
548
  assert rc == 0
549
549
  seed = json.loads((tmp_path / "extract_receipt.jeremy.json").read_text(encoding="utf-8"))
550
- assert set(seed) == {"goal", "system_prompt", "examples"}
550
+ assert set(seed) == {"site_id", "symbol", "goal", "system_prompt", "examples"}
551
+ assert len(seed["site_id"]) == 64 # matches the profile's stable hash
552
+ assert seed["symbol"] == "extract_receipt"
551
553
  assert seed["goal"].startswith("Solve a grade-school word problem")
552
554
  assert "final answer is a bare number" in seed["goal"]
553
555
  assert "Extract the receipt fields" in seed["system_prompt"]
@@ -70,6 +70,7 @@ def test_push_artifact_translates_jeremy_to_run_task():
70
70
  ok, detail = push_artifact(backend.url, "s", "jeremy", artifact)
71
71
  assert ok and "200" in detail
72
72
  assert backend.received == [{
73
+ "site_id": None,
73
74
  "goal": "Solve problems.",
74
75
  "examples": [{"problem": "p", "solution": "s"}],
75
76
  "student_system_prompt": "You are a tutor.",
@@ -114,7 +115,8 @@ def test_cmd_push_sweeps_site_artifacts(tmp_path, monkeypatch, capsys):
114
115
 
115
116
  assert rc == 0
116
117
  assert len(backend.received) == 2
117
- assert all(set(r) == {"goal", "examples", "student_system_prompt", "student_goal"}
118
+ assert all(set(r) == {"site_id", "goal", "examples",
119
+ "student_system_prompt", "student_goal"}
118
120
  for r in backend.received)
119
121
  assert "pushed 2 artifact(s)" in capsys.readouterr().out
120
122
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes