pythia-plsql 0.4.9__tar.gz → 0.4.10__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. {pythia_plsql-0.4.9/scripts/pythia_plsql.egg-info → pythia_plsql-0.4.10}/PKG-INFO +1 -1
  2. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/pyproject.toml +1 -1
  3. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/scripts/pythia.py +99 -8
  4. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10/scripts/pythia_plsql.egg-info}/PKG-INFO +1 -1
  5. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-setup/SKILL.md +23 -0
  6. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-write/SKILL.md +3 -1
  7. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/tests/test_install.py +23 -0
  8. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/LICENSE +0 -0
  9. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/README.md +0 -0
  10. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/compile-errors.sql +0 -0
  11. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/dependencies.sql +0 -0
  12. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/impact.sql +0 -0
  13. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/invalid-objects.sql +0 -0
  14. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/name-occupants.sql +0 -0
  15. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/object-source.sql +0 -0
  16. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/plscope-enabled.sql +0 -0
  17. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/plscope-statements.sql +0 -0
  18. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/plscope-usages.sql +0 -0
  19. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/session-privileges.sql +0 -0
  20. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/similar-candidates.sql +0 -0
  21. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/queries/source.sql +0 -0
  22. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/scripts/pythia_plsql.egg-info/SOURCES.txt +0 -0
  23. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/scripts/pythia_plsql.egg-info/dependency_links.txt +0 -0
  24. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/scripts/pythia_plsql.egg-info/entry_points.txt +0 -0
  25. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/scripts/pythia_plsql.egg-info/requires.txt +0 -0
  26. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/scripts/pythia_plsql.egg-info/top_level.txt +0 -0
  27. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/setup.cfg +0 -0
  28. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-apply/SKILL.md +0 -0
  29. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-explore/SKILL.md +0 -0
  30. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-explore/reference/data-dictionary.md +0 -0
  31. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-impact/SKILL.md +0 -0
  32. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-review/SKILL.md +0 -0
  33. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-review/reference/antipatterns.md +0 -0
  34. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-skill-author/SKILL.md +0 -0
  35. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/skills/pythia-write/reference/patterns.md +0 -0
  36. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/tests/test_phase1.py +0 -0
  37. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/tests/test_phase2.py +0 -0
  38. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/tests/test_phase3.py +0 -0
  39. {pythia_plsql-0.4.9 → pythia_plsql-0.4.10}/tests/test_phase5.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythia-plsql
3
- Version: 0.4.9
3
+ Version: 0.4.10
4
4
  Summary: PL/SQL development for AI agents on Oracle Database - expert data-dictionary queries, impact analysis, and a snapshot-verified write path with honest rollback.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/thaildhe172591/pythia
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pythia-plsql"
7
- version = "0.4.9"
7
+ version = "0.4.10"
8
8
  description = "PL/SQL development for AI agents on Oracle Database - expert data-dictionary queries, impact analysis, and a snapshot-verified write path with honest rollback."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1332,6 +1332,78 @@ def cmd_plscope(conn, schema, ns):
1332
1332
  emit_table(ns, stmt_cols, *clip(stmt_rows, ns.limit))
1333
1333
 
1334
1334
 
1335
+ CONVENTIONS_TEMPLATE = """{
1336
+ "naming": {
1337
+ "TABLE": "^T_[A-Z0-9_]+$",
1338
+ "PROCEDURE": "^P_[A-Z0-9_]+$",
1339
+ "FUNCTION": "^F_[A-Z0-9_]+$",
1340
+ "PACKAGE": "^PKG_[A-Z0-9_]+$",
1341
+ "SEQUENCE": "^S_[A-Z0-9_]+$",
1342
+ "TRIGGER": "^TRG_[A-Z0-9_]+$"
1343
+ }
1344
+ }
1345
+ """
1346
+
1347
+ CONVENTIONS_PROSE_TEMPLATE = """# Project conventions
1348
+
1349
+ Rules for anyone — human or agent — writing PL/SQL in this schema. Agents are
1350
+ told to read this before writing, and it outranks the generic patterns the
1351
+ skill pack ships with.
1352
+
1353
+ `conventions.json` next to this file holds the naming patterns as regexes;
1354
+ every `pythia apply` preview warns when a new object's name does not match.
1355
+ Keep the two in step: this file explains, that file enforces.
1356
+
1357
+ ## Naming
1358
+
1359
+ Replace the patterns in `conventions.json` with yours, then describe them
1360
+ here so the reasoning survives. `pythia similar <A_TYPICAL_NAME>` shows what
1361
+ the schema already does — copy that rather than inventing a scheme.
1362
+
1363
+ | Kind | Rule | Example |
1364
+ |---|---|---|
1365
+ | Table | | |
1366
+ | Procedure | | |
1367
+ | Function | | |
1368
+
1369
+ ## Rules that carry a cost when broken
1370
+
1371
+ State the consequence, not just the rule — a rule with a named cost gets
1372
+ followed. For example: which parameter prefixes the calling layer depends on,
1373
+ which column every query must filter by, where a transaction may commit.
1374
+
1375
+ | Rule | Cost of breaking it |
1376
+ |---|---|
1377
+ | | |
1378
+
1379
+ ## Known exceptions
1380
+
1381
+ Objects that break the pattern on purpose, and why renaming them is worse
1382
+ than the warning they produce on every apply.
1383
+ """
1384
+
1385
+
1386
+ def scaffold_conventions(root):
1387
+ """Write the conventions pair, skipping anything that already exists.
1388
+ Returns the paths actually created.
1389
+
1390
+ The docs used to say "copy examples/conventions.example.json", which is
1391
+ no help to anyone who installed the wheel: there is no examples directory
1392
+ there. The tool carries the templates instead.
1393
+ """
1394
+ d = pathlib.Path(root) / CONFIG_DIR
1395
+ made = []
1396
+ for name, body in (("conventions.json", CONVENTIONS_TEMPLATE),
1397
+ ("conventions.md", CONVENTIONS_PROSE_TEMPLATE)):
1398
+ path = d / name
1399
+ if path.is_file():
1400
+ continue
1401
+ path.parent.mkdir(parents=True, exist_ok=True)
1402
+ path.write_text(body, encoding="utf-8")
1403
+ made.append(path)
1404
+ return made
1405
+
1406
+
1335
1407
  def load_conventions(root):
1336
1408
  """Project house style from .pythia/conventions.json — the machine half of
1337
1409
  the customization surface (the prose half is conventions.md, for agents).
@@ -1790,23 +1862,39 @@ def cmd_journal(conn, schema, ns):
1790
1862
 
1791
1863
 
1792
1864
  def cmd_conventions(conn, schema, ns):
1793
- conv = load_conventions(ns.project_root)
1865
+ root = ns.project_root
1866
+ if getattr(ns, "init", False):
1867
+ made = scaffold_conventions(root)
1868
+ for path in made:
1869
+ print(f"Created {path}")
1870
+ if not made:
1871
+ print(f"Both files already exist in "
1872
+ f"{pathlib.Path(root) / CONFIG_DIR} — left untouched.")
1873
+ else:
1874
+ print(NL + "Edit the patterns to match this schema — "
1875
+ f"`{invocation()} similar <A_TYPICAL_NAME>` shows what "
1876
+ "it already does." + NL + "Every apply preview then "
1877
+ "warns when a name drifts from them.")
1878
+ return
1879
+ conv = load_conventions(root)
1794
1880
  if ns.json:
1795
1881
  print(json.dumps(conv or {}))
1796
1882
  return
1797
1883
  if not conv:
1798
1884
  print("No project conventions configured.")
1799
- print(f"Create {pathlib.Path(ns.project_root) / CONFIG_DIR / 'conventions.json'} "
1800
- "(see examples/conventions.example.json) and apply previews will "
1801
- "warn when a new object's name drifts from your patterns.\n"
1802
- "Put the prose rules in conventions.md next to it for your agents.")
1885
+ print(f"Create the starter pair with: {invocation()} conventions --init")
1886
+ print(" conventions.json naming patterns; apply previews warn on drift")
1887
+ print(" conventions.md the prose rules your agents read first")
1803
1888
  return
1804
1889
  print("Naming patterns — apply previews warn when a name drifts:")
1805
1890
  for otype, pattern in conv.get("naming", {}).items():
1806
1891
  print(f" {otype:<13} {pattern}")
1807
- md = pathlib.Path(ns.project_root) / CONFIG_DIR / "conventions.md"
1892
+ md = pathlib.Path(root) / CONFIG_DIR / "conventions.md"
1808
1893
  if md.is_file():
1809
- print(f"\nProse rules for agents: {md}")
1894
+ print(NL + f"Prose rules for agents: {md}")
1895
+ else:
1896
+ print(NL + f"No conventions.md yet — {invocation()} conventions "
1897
+ "--init writes one.")
1810
1898
 
1811
1899
 
1812
1900
  AGENT_USER_SQL = """\
@@ -2254,8 +2342,11 @@ def build_parser():
2254
2342
  help="apply without stopping; the full preview still prints and journals")
2255
2343
  s.add_argument("--depth", type=int, default=3,
2256
2344
  help="impact depth for the preview (default 3)")
2257
- sub.add_parser("conventions", parents=[common()],
2345
+ s = sub.add_parser("conventions", parents=[common()],
2258
2346
  help="show the project's house-style naming patterns")
2347
+ s.add_argument("--init", action="store_true",
2348
+ help="write starter conventions.json and conventions.md "
2349
+ "into .pythia/ (never overwrites)")
2259
2350
  s = sub.add_parser("agent-user", parents=[common()],
2260
2351
  help="SQL for a least-privilege proxy agent user; "
2261
2352
  "--save adds it to connections.json")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythia-plsql
3
- Version: 0.4.9
3
+ Version: 0.4.10
4
4
  Summary: PL/SQL development for AI agents on Oracle Database - expert data-dictionary queries, impact analysis, and a snapshot-verified write path with honest rollback.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/thaildhe172591/pythia
@@ -75,6 +75,29 @@ server: command `sql -mcp`. Example client config:
75
75
  `V$SESSION.ACTION` the LLM's name; generated SQL carries an
76
76
  `/* LLM in use */` comment.
77
77
 
78
+ ## 4. What lives in `.pythia/`, and what creates it
79
+
80
+ Only `connections.json` is written by `install`. The rest appear when you ask
81
+ for them, so an empty `.pythia/` is a working one — nothing here is missing
82
+ until you want it.
83
+
84
+ | File | Created by | What it does |
85
+ |---|---|---|
86
+ | `connections.json` | `pythia install` | Where to connect. Holds credentials; gitignored. |
87
+ | `journal/` | first write or snapshot | Every captured version, with a runnable rollback per entry. |
88
+ | `conventions.json` | `pythia conventions --init` | Naming patterns per object type. Every apply preview warns when a new name drifts. |
89
+ | `conventions.md` | `pythia conventions --init` | The house rules in prose. **`pythia-write` reads this before writing anything**, and it outranks the generic patterns this pack ships with. |
90
+ | `policy.json` | `pythia policy set <group> <value>` | Pins the write policy. Absent means the built-in defaults, which are already the safe ones. |
91
+ | `settings.json` | you, by hand | Optional switches, e.g. `{"auto_snapshot": false}`. |
92
+
93
+ **Capturing a team's house style is the highest-value optional step.** Run
94
+ `pythia conventions --init`, then replace the placeholder patterns with the
95
+ real ones — `pythia similar <A_TYPICAL_NAME>` shows what the schema already
96
+ does, which beats inventing a scheme. Fill in `conventions.md` with the rules
97
+ that carry a cost when broken, and say what the cost is; a rule with a named
98
+ consequence gets followed. Commit both files to the project repo so the whole
99
+ team and every agent session works from the same rules.
100
+
78
101
  ## Done when
79
102
 
80
103
  - `pythia check` connects, shows the right schema, and prints **no**
@@ -9,7 +9,9 @@ description: Use when writing or modifying PL/SQL source - a procedure, function
9
9
 
10
10
  **Before anything:** if the project has `.pythia/conventions.md`, read it —
11
11
  house rules there outrank every generic pattern below, and
12
- `pythia conventions` shows the naming patterns the apply preview will check.
12
+ `pythia conventions` shows the naming patterns the apply preview will check. If the project has none and the developer
13
+ describes a house style, offer `pythia conventions --init` — captured once,
14
+ it applies to every future session instead of being re-explained.
13
15
 
14
16
  A codebase with thousands of procedures has already decided how procedures
15
17
  look. Your job is to write one that a maintainer cannot tell from the
@@ -7,6 +7,7 @@ Run: python tests/test_install.py
7
7
  import json
8
8
  import os
9
9
  import pathlib
10
+ import re
10
11
  import sys
11
12
  import tempfile
12
13
 
@@ -325,6 +326,28 @@ def test_long_path_is_flagged_before_it_silently_truncates():
325
326
  assert "duplicate" in w.lower() # names the usual cause
326
327
 
327
328
 
329
+ def test_conventions_init_writes_both_halves_and_never_clobbers():
330
+ """Telling a pip user to copy examples/conventions.example.json is no help:
331
+ the wheel does not ship an examples directory. The tool writes the pair."""
332
+ import json
333
+ with tempfile.TemporaryDirectory() as td:
334
+ made = pythia.scaffold_conventions(td)
335
+ d = pathlib.Path(td) / ".pythia"
336
+ assert sorted(p.name for p in made) == ["conventions.json",
337
+ "conventions.md"]
338
+ rules = json.loads((d / "conventions.json").read_text(encoding="utf-8"))
339
+ assert "naming" in rules and rules["naming"] # usable as written
340
+ for otype, pattern in rules["naming"].items():
341
+ re.compile(pattern) # every one valid
342
+ assert pythia.load_conventions(td) is not None # accepted by the loader
343
+ prose = (d / "conventions.md").read_text(encoding="utf-8")
344
+ assert "conventions.json" in prose # the halves reference
345
+ # a second run leaves existing files alone
346
+ (d / "conventions.json").write_text('{"naming": {}}', encoding="utf-8")
347
+ assert pythia.scaffold_conventions(td) == []
348
+ assert (d / "conventions.json").read_text(encoding="utf-8") == '{"naming": {}}'
349
+
350
+
328
351
  def main():
329
352
  failed = 0
330
353
  for name, fn in sorted(globals().items()):
File without changes
File without changes
File without changes