pythia-plsql 0.5.0__tar.gz → 0.6.1__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.
- {pythia_plsql-0.5.0/scripts/pythia_plsql.egg-info → pythia_plsql-0.6.1}/PKG-INFO +66 -20
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/README.md +65 -19
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/pyproject.toml +1 -1
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia.py +119 -2
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1/scripts/pythia_plsql.egg-info}/PKG-INFO +66 -20
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-apply/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-conventions/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-explore/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-impact/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-review/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-setup/SKILL.md +3 -1
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-skill-author/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-write/SKILL.md +2 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/tests/test_install.py +13 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/tests/test_phase1.py +40 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/tests/test_phase5.py +50 -5
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/LICENSE +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/compile-errors.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/dependencies.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/impact.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/invalid-objects.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/name-occupants.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/object-names.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/object-source.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/plscope-enabled.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/plscope-statements.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/plscope-usages.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/session-privileges.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/similar-candidates.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/queries/source.sql +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia_plsql.egg-info/SOURCES.txt +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia_plsql.egg-info/dependency_links.txt +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia_plsql.egg-info/entry_points.txt +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia_plsql.egg-info/requires.txt +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia_plsql.egg-info/top_level.txt +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/setup.cfg +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-explore/reference/data-dictionary.md +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-review/reference/antipatterns.md +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-write/reference/patterns.md +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/tests/test_phase2.py +0 -0
- {pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/tests/test_phase3.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythia-plsql
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
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
|
|
@@ -26,10 +26,16 @@ Dynamic: license-file
|
|
|
26
26
|
[](LICENSE)
|
|
27
27
|

|
|
28
28
|
|
|
29
|
-
An Agent Skills + CLI kit for developing PL/SQL on Oracle Database with AI
|
|
30
|
-
agents (Claude Code, Codex, Cursor — any of the 76 agents `npx skills`
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
An Agent Skills + CLI kit for developing PL/SQL on Oracle Database with AI
|
|
30
|
+
coding agents (Claude Code, Codex, Cursor — any of the 76 agents `npx skills`
|
|
31
|
+
supports).
|
|
32
|
+
|
|
33
|
+
pythia is a **harness**: a book of working rules an agent studies and follows
|
|
34
|
+
when it sits next to a developer. Not a chatbot, not an autopilot — a
|
|
35
|
+
disciplined assistant with three properties a good one has: **knowledge** (it
|
|
36
|
+
asks the live schema, never its memory of one), **judgment** (it measures
|
|
37
|
+
before it proposes), and **obedience to rules it can recite** (gates it will
|
|
38
|
+
quote back to you rather than quietly skip).
|
|
33
39
|
|
|
34
40
|
## Why ask the database instead of reading dumps
|
|
35
41
|
|
|
@@ -47,23 +53,63 @@ Code that "reads fine" against the dump references types and packages the dump n
|
|
|
47
53
|
heard of. Every pythia command asks the live data dictionary instead — and every
|
|
48
54
|
truncated output says so, so an agent never mistakes a partial answer for a full one.
|
|
49
55
|
|
|
50
|
-
##
|
|
56
|
+
## The operating model: Learn → Ask → Do
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
skills/ teach the agent when to ask, when to stop, when to ask YOU
|
|
56
|
-
│
|
|
57
|
-
pythia CLI — expert queries, impact analysis, the six-step write path
|
|
58
|
-
│
|
|
59
|
-
Oracle data dictionary: ALL_SOURCE, ALL_DEPENDENCIES, ALL_ERRORS, PL/Scope
|
|
60
|
-
```
|
|
58
|
+
Give the agent a problem — "add a column and every procedure that maintains
|
|
59
|
+
it", "why does this report double rows", "port this fix" — and the kit walks
|
|
60
|
+
it through the same three movements a careful senior developer makes.
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
### 1 · Learn — understand before proposing
|
|
63
|
+
|
|
64
|
+
The agent studies four things, in order, with tools instead of guesses:
|
|
65
|
+
|
|
66
|
+
| It learns | How | Instead of |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| the problem's real shape | `deps`, `impact`, `plscope` — the exact dependency graph and usage sites | skimming code and hoping |
|
|
69
|
+
| the schema's ground truth | `src`, `cols`, `args`, `ddl`, `errors` against the live database | trusting a dump that drifted |
|
|
70
|
+
| the house style | `.pythia/conventions.md` + `conventions --scan/--check` — rules measured against real names | inventing a style per session |
|
|
71
|
+
| how this codebase already solves it | `similar` — the neighbours to imitate | writing the first thing that compiles |
|
|
72
|
+
|
|
73
|
+
Nothing in this phase writes. Reading is free, so the bar is: **no proposal
|
|
74
|
+
before the blast radius is known** (`pythia-impact`'s iron law) and **no line
|
|
75
|
+
written before the neighbours have been read** (`pythia-write`'s).
|
|
76
|
+
|
|
77
|
+
### 2 · Ask — the questions are part of the method, not an interruption
|
|
78
|
+
|
|
79
|
+
The kit makes the agent stop at exactly the moments where a human's judgment
|
|
80
|
+
is the missing input, and forbids it to guess past them:
|
|
81
|
+
|
|
82
|
+
- **Before any write**: the full preview — diff, dependents, warnings — is
|
|
83
|
+
relayed verbatim, and the agent waits for a real yes. A compliment is not a
|
|
84
|
+
yes. Silence is not a yes.
|
|
85
|
+
- **When the blast radius is large**: ten or more dependents, or anything
|
|
86
|
+
cross-schema, goes to the developer *before code is written*, not after.
|
|
87
|
+
- **When sources of truth disagree**: a standards document says one thing,
|
|
88
|
+
the schema does another — that gap is a question ("rule nobody follows,
|
|
89
|
+
new-code-only, or drift?"), never a silent pick.
|
|
90
|
+
- **When something breaks**: exit 3 means *written but broken*. The agent
|
|
91
|
+
reports it exactly so, with the ready rollback — reporting success here is
|
|
92
|
+
the one sin the whole kit is built to prevent.
|
|
93
|
+
- **When policy refuses**: the refusal is relayed as information, not routed
|
|
94
|
+
around.
|
|
95
|
+
|
|
96
|
+
### 3 · Do — act inside a pipeline that cannot lie
|
|
97
|
+
|
|
98
|
+
Only after Learn and Ask does anything touch the database, and then only
|
|
99
|
+
through one door: **snapshot → impact → preview → token → apply → verify →
|
|
100
|
+
report**. DDL self-commits in Oracle, so the snapshot is the only real undo —
|
|
101
|
+
it runs first and no flag disables it. A content-bound token guarantees what
|
|
102
|
+
lands is byte-for-byte what was approved. And the CLI enforces the gates
|
|
103
|
+
itself: a headless agent cannot `--yes` its own writes or loosen policy —
|
|
104
|
+
that takes a human at a real terminal.
|
|
105
|
+
|
|
106
|
+
The same discipline holds when the *developer* does the work: `src` and
|
|
107
|
+
`impact` silently snapshot what they read, so even a change made by hand in
|
|
108
|
+
SQL Developer has a rollback file waiting (`history` lists them, drift is
|
|
109
|
+
reported when source moved with no apply behind it).
|
|
110
|
+
|
|
111
|
+
**Học – Hỏi – Làm** — Learn, Ask, Do. If the agent cannot show which phase it
|
|
112
|
+
is in, it is doing none of them.
|
|
67
113
|
|
|
68
114
|
## Install
|
|
69
115
|
|
|
@@ -12,10 +12,16 @@
|
|
|
12
12
|
[](LICENSE)
|
|
13
13
|

|
|
14
14
|
|
|
15
|
-
An Agent Skills + CLI kit for developing PL/SQL on Oracle Database with AI
|
|
16
|
-
agents (Claude Code, Codex, Cursor — any of the 76 agents `npx skills`
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
An Agent Skills + CLI kit for developing PL/SQL on Oracle Database with AI
|
|
16
|
+
coding agents (Claude Code, Codex, Cursor — any of the 76 agents `npx skills`
|
|
17
|
+
supports).
|
|
18
|
+
|
|
19
|
+
pythia is a **harness**: a book of working rules an agent studies and follows
|
|
20
|
+
when it sits next to a developer. Not a chatbot, not an autopilot — a
|
|
21
|
+
disciplined assistant with three properties a good one has: **knowledge** (it
|
|
22
|
+
asks the live schema, never its memory of one), **judgment** (it measures
|
|
23
|
+
before it proposes), and **obedience to rules it can recite** (gates it will
|
|
24
|
+
quote back to you rather than quietly skip).
|
|
19
25
|
|
|
20
26
|
## Why ask the database instead of reading dumps
|
|
21
27
|
|
|
@@ -33,23 +39,63 @@ Code that "reads fine" against the dump references types and packages the dump n
|
|
|
33
39
|
heard of. Every pythia command asks the live data dictionary instead — and every
|
|
34
40
|
truncated output says so, so an agent never mistakes a partial answer for a full one.
|
|
35
41
|
|
|
36
|
-
##
|
|
42
|
+
## The operating model: Learn → Ask → Do
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
skills/ teach the agent when to ask, when to stop, when to ask YOU
|
|
42
|
-
│
|
|
43
|
-
pythia CLI — expert queries, impact analysis, the six-step write path
|
|
44
|
-
│
|
|
45
|
-
Oracle data dictionary: ALL_SOURCE, ALL_DEPENDENCIES, ALL_ERRORS, PL/Scope
|
|
46
|
-
```
|
|
44
|
+
Give the agent a problem — "add a column and every procedure that maintains
|
|
45
|
+
it", "why does this report double rows", "port this fix" — and the kit walks
|
|
46
|
+
it through the same three movements a careful senior developer makes.
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
### 1 · Learn — understand before proposing
|
|
49
|
+
|
|
50
|
+
The agent studies four things, in order, with tools instead of guesses:
|
|
51
|
+
|
|
52
|
+
| It learns | How | Instead of |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| the problem's real shape | `deps`, `impact`, `plscope` — the exact dependency graph and usage sites | skimming code and hoping |
|
|
55
|
+
| the schema's ground truth | `src`, `cols`, `args`, `ddl`, `errors` against the live database | trusting a dump that drifted |
|
|
56
|
+
| the house style | `.pythia/conventions.md` + `conventions --scan/--check` — rules measured against real names | inventing a style per session |
|
|
57
|
+
| how this codebase already solves it | `similar` — the neighbours to imitate | writing the first thing that compiles |
|
|
58
|
+
|
|
59
|
+
Nothing in this phase writes. Reading is free, so the bar is: **no proposal
|
|
60
|
+
before the blast radius is known** (`pythia-impact`'s iron law) and **no line
|
|
61
|
+
written before the neighbours have been read** (`pythia-write`'s).
|
|
62
|
+
|
|
63
|
+
### 2 · Ask — the questions are part of the method, not an interruption
|
|
64
|
+
|
|
65
|
+
The kit makes the agent stop at exactly the moments where a human's judgment
|
|
66
|
+
is the missing input, and forbids it to guess past them:
|
|
67
|
+
|
|
68
|
+
- **Before any write**: the full preview — diff, dependents, warnings — is
|
|
69
|
+
relayed verbatim, and the agent waits for a real yes. A compliment is not a
|
|
70
|
+
yes. Silence is not a yes.
|
|
71
|
+
- **When the blast radius is large**: ten or more dependents, or anything
|
|
72
|
+
cross-schema, goes to the developer *before code is written*, not after.
|
|
73
|
+
- **When sources of truth disagree**: a standards document says one thing,
|
|
74
|
+
the schema does another — that gap is a question ("rule nobody follows,
|
|
75
|
+
new-code-only, or drift?"), never a silent pick.
|
|
76
|
+
- **When something breaks**: exit 3 means *written but broken*. The agent
|
|
77
|
+
reports it exactly so, with the ready rollback — reporting success here is
|
|
78
|
+
the one sin the whole kit is built to prevent.
|
|
79
|
+
- **When policy refuses**: the refusal is relayed as information, not routed
|
|
80
|
+
around.
|
|
81
|
+
|
|
82
|
+
### 3 · Do — act inside a pipeline that cannot lie
|
|
83
|
+
|
|
84
|
+
Only after Learn and Ask does anything touch the database, and then only
|
|
85
|
+
through one door: **snapshot → impact → preview → token → apply → verify →
|
|
86
|
+
report**. DDL self-commits in Oracle, so the snapshot is the only real undo —
|
|
87
|
+
it runs first and no flag disables it. A content-bound token guarantees what
|
|
88
|
+
lands is byte-for-byte what was approved. And the CLI enforces the gates
|
|
89
|
+
itself: a headless agent cannot `--yes` its own writes or loosen policy —
|
|
90
|
+
that takes a human at a real terminal.
|
|
91
|
+
|
|
92
|
+
The same discipline holds when the *developer* does the work: `src` and
|
|
93
|
+
`impact` silently snapshot what they read, so even a change made by hand in
|
|
94
|
+
SQL Developer has a rollback file waiting (`history` lists them, drift is
|
|
95
|
+
reported when source moved with no apply behind it).
|
|
96
|
+
|
|
97
|
+
**Học – Hỏi – Làm** — Learn, Ask, Do. If the agent cannot show which phase it
|
|
98
|
+
is in, it is doing none of them.
|
|
53
99
|
|
|
54
100
|
## Install
|
|
55
101
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pythia-plsql"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.1"
|
|
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" }
|
|
@@ -1988,6 +1988,117 @@ def _schema_objects(conn, schema):
|
|
|
1988
1988
|
return [(r[0], r[1]) for r in rows]
|
|
1989
1989
|
|
|
1990
1990
|
|
|
1991
|
+
OPERATING_GUIDE = """\
|
|
1992
|
+
THE OPERATING MODEL — Learn, Ask, Do (Hoc - Hoi - Lam)
|
|
1993
|
+
|
|
1994
|
+
pythia is a harness: a book of working rules for an AI agent sitting next to
|
|
1995
|
+
a developer. Every task moves through the same three movements. If you cannot
|
|
1996
|
+
say which movement you are in, you are in none of them.
|
|
1997
|
+
|
|
1998
|
+
=== 1. LEARN — understand before proposing ======================
|
|
1999
|
+
Nothing here writes. Reading is free; guessing is not.
|
|
2000
|
+
|
|
2001
|
+
the problem's shape deps · impact · plscope the exact graph, not a skim
|
|
2002
|
+
the schema's truth src · args · cols · ddl · errors · invalid · check · ls · grep · sql
|
|
2003
|
+
what you can reach connections - names, users, targets. NEVER open
|
|
2004
|
+
connections.json yourself: it holds passwords, a
|
|
2005
|
+
permission gate should stop you, and this command
|
|
2006
|
+
is the answer you were reaching for.
|
|
2007
|
+
the house style conventions (--scan / --check) · the project's conventions.md
|
|
2008
|
+
how it is done here similar · history neighbours to imitate, versions that exist
|
|
2009
|
+
|
|
2010
|
+
Iron laws: no proposal before the blast radius is known; no line written
|
|
2011
|
+
before the neighbours have been read.
|
|
2012
|
+
|
|
2013
|
+
=== 2. ASK — the questions are the method =======================
|
|
2014
|
+
Stop at exactly these moments; a guess past any of them is a defect.
|
|
2015
|
+
|
|
2016
|
+
before any write relay the full preview (diff, dependents, warnings)
|
|
2017
|
+
verbatim, then wait. A compliment is not a yes.
|
|
2018
|
+
blast radius >= 10 or anything cross-schema: show the developer the
|
|
2019
|
+
list BEFORE writing code.
|
|
2020
|
+
truths disagree document says one thing, schema another - ask which:
|
|
2021
|
+
rule nobody follows, new-code-only, or drift.
|
|
2022
|
+
policy refuses relay the refusal (policy shows the rules). Never
|
|
2023
|
+
route around it.
|
|
2024
|
+
it broke exit 3 = written but broken. Say exactly that, with
|
|
2025
|
+
the rollback line. journal (show/diff) is your evidence.
|
|
2026
|
+
|
|
2027
|
+
=== 3. DO — act inside a pipeline that cannot lie ===============
|
|
2028
|
+
One door for writes: snapshot -> impact -> preview -> token -> apply ->
|
|
2029
|
+
verify -> report.
|
|
2030
|
+
|
|
2031
|
+
apply the six-step write; --confirm binds to the preview
|
|
2032
|
+
journal restore undo, through the same six steps
|
|
2033
|
+
unistr exact non-ASCII literals for what you are writing
|
|
2034
|
+
install · agent-user · guide setting the harness itself up
|
|
2035
|
+
|
|
2036
|
+
The CLI enforces the gates: headless --yes is refused, policy cannot be
|
|
2037
|
+
loosened without a human at a terminal, the snapshot cannot be switched off.
|
|
2038
|
+
|
|
2039
|
+
Skills carry the full method (pythia-explore, -impact, -conventions, -write,
|
|
2040
|
+
-apply, -review, -setup, -skill-author). No skill support on this platform?
|
|
2041
|
+
This page is the contract; follow it as written.
|
|
2042
|
+
"""
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
def connection_summary(cfg):
|
|
2046
|
+
"""Everything about the configured connections except the secrets.
|
|
2047
|
+
|
|
2048
|
+
An agent has to know which connections exist. Without a sanctioned way to
|
|
2049
|
+
ask, it reads connections.json itself — which is exactly the access a
|
|
2050
|
+
permission classifier should stop, and did. So this exists, and it is
|
|
2051
|
+
built to be provably safe: fields are copied in by name, never by
|
|
2052
|
+
iterating the entry, so a key added to the config later cannot leak
|
|
2053
|
+
through here by accident.
|
|
2054
|
+
"""
|
|
2055
|
+
cfg = dict(cfg or {})
|
|
2056
|
+
default = cfg.pop("default", None)
|
|
2057
|
+
rows = []
|
|
2058
|
+
for name, entry in cfg.items():
|
|
2059
|
+
if not isinstance(entry, dict):
|
|
2060
|
+
continue
|
|
2061
|
+
dsn = entry.get("dsn") or ""
|
|
2062
|
+
if not dsn and entry.get("host"):
|
|
2063
|
+
svc = entry.get("service_name") or entry.get("sid") or ""
|
|
2064
|
+
dsn = f"{entry['host']}:{entry.get('port', 1521)}"
|
|
2065
|
+
if svc:
|
|
2066
|
+
dsn += f"/{svc}"
|
|
2067
|
+
user = str(entry.get("user") or "")
|
|
2068
|
+
rows.append({
|
|
2069
|
+
"name": name,
|
|
2070
|
+
"user": user,
|
|
2071
|
+
"target": dsn or "\u2014",
|
|
2072
|
+
"schema": (entry.get("schema") or user.split("[")[-1].rstrip("]")
|
|
2073
|
+
or "\u2014").upper(),
|
|
2074
|
+
"default": isinstance(default, str) and default.upper() == name.upper(),
|
|
2075
|
+
})
|
|
2076
|
+
return rows
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
def cmd_connections(conn, schema, ns):
|
|
2080
|
+
cfg, _ = find_config(pathlib.Path.cwd(), os.environ)
|
|
2081
|
+
rows = connection_summary(cfg)
|
|
2082
|
+
if ns.json:
|
|
2083
|
+
print(json.dumps(rows, indent=2))
|
|
2084
|
+
return
|
|
2085
|
+
if not rows:
|
|
2086
|
+
print("No connections configured. "
|
|
2087
|
+
f"{invocation()} install scaffolds .pythia/connections.json.")
|
|
2088
|
+
return
|
|
2089
|
+
print(f"{'':1} {'NAME':<16} {'USER':<26} {'SCHEMA':<20} TARGET")
|
|
2090
|
+
for r in rows:
|
|
2091
|
+
mark = "*" if r["default"] else " "
|
|
2092
|
+
print(f"{mark} {r['name']:<16} {r['user']:<26} {r['schema']:<20} "
|
|
2093
|
+
f"{r['target']}")
|
|
2094
|
+
print("\n* default. Passwords are never printed — this command reads the "
|
|
2095
|
+
"config so you\n do not have to open it. Pick one with --conn NAME.")
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
def cmd_guide(conn, schema, ns):
|
|
2099
|
+
print(OPERATING_GUIDE)
|
|
2100
|
+
|
|
2101
|
+
|
|
1991
2102
|
def cmd_conventions(conn, schema, ns):
|
|
1992
2103
|
root = ns.project_root
|
|
1993
2104
|
if getattr(ns, "init", False):
|
|
@@ -2381,11 +2492,11 @@ COMMANDS = {"check": cmd_check, "ls": cmd_ls, "src": cmd_src, "args": cmd_args,
|
|
|
2381
2492
|
"invalid": cmd_invalid, "errors": cmd_errors, "deps": cmd_deps,
|
|
2382
2493
|
"impact": cmd_impact, "similar": cmd_similar, "plscope": cmd_plscope,
|
|
2383
2494
|
"policy": cmd_policy, "journal": cmd_journal, "apply": cmd_apply,
|
|
2384
|
-
"conventions": cmd_conventions, "install": cmd_install,
|
|
2495
|
+
"conventions": cmd_conventions, "guide": cmd_guide, "connections": cmd_connections, "install": cmd_install,
|
|
2385
2496
|
"unistr": cmd_unistr, "agent-user": cmd_agent_user,
|
|
2386
2497
|
"history": cmd_history}
|
|
2387
2498
|
|
|
2388
|
-
NO_DB_COMMANDS = {"policy", "journal", "install", "unistr",
|
|
2499
|
+
NO_DB_COMMANDS = {"policy", "journal", "install", "unistr", "guide", "connections",
|
|
2389
2500
|
"history"}
|
|
2390
2501
|
|
|
2391
2502
|
|
|
@@ -2483,6 +2594,12 @@ def build_parser():
|
|
|
2483
2594
|
help="apply without stopping; the full preview still prints and journals")
|
|
2484
2595
|
s.add_argument("--depth", type=int, default=3,
|
|
2485
2596
|
help="impact depth for the preview (default 3)")
|
|
2597
|
+
sub.add_parser("connections", parents=[common()],
|
|
2598
|
+
help="list configured connections — names, users, "
|
|
2599
|
+
"targets; never passwords")
|
|
2600
|
+
sub.add_parser("guide", parents=[common()],
|
|
2601
|
+
help="the operating model: Learn, Ask, Do — the whole "
|
|
2602
|
+
"harness on one page, no database needed")
|
|
2486
2603
|
s = sub.add_parser("conventions", parents=[common()],
|
|
2487
2604
|
help="show the project's house-style naming patterns")
|
|
2488
2605
|
s.add_argument("--init", action="store_true",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythia-plsql
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
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
|
|
@@ -26,10 +26,16 @@ Dynamic: license-file
|
|
|
26
26
|
[](LICENSE)
|
|
27
27
|

|
|
28
28
|
|
|
29
|
-
An Agent Skills + CLI kit for developing PL/SQL on Oracle Database with AI
|
|
30
|
-
agents (Claude Code, Codex, Cursor — any of the 76 agents `npx skills`
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
An Agent Skills + CLI kit for developing PL/SQL on Oracle Database with AI
|
|
30
|
+
coding agents (Claude Code, Codex, Cursor — any of the 76 agents `npx skills`
|
|
31
|
+
supports).
|
|
32
|
+
|
|
33
|
+
pythia is a **harness**: a book of working rules an agent studies and follows
|
|
34
|
+
when it sits next to a developer. Not a chatbot, not an autopilot — a
|
|
35
|
+
disciplined assistant with three properties a good one has: **knowledge** (it
|
|
36
|
+
asks the live schema, never its memory of one), **judgment** (it measures
|
|
37
|
+
before it proposes), and **obedience to rules it can recite** (gates it will
|
|
38
|
+
quote back to you rather than quietly skip).
|
|
33
39
|
|
|
34
40
|
## Why ask the database instead of reading dumps
|
|
35
41
|
|
|
@@ -47,23 +53,63 @@ Code that "reads fine" against the dump references types and packages the dump n
|
|
|
47
53
|
heard of. Every pythia command asks the live data dictionary instead — and every
|
|
48
54
|
truncated output says so, so an agent never mistakes a partial answer for a full one.
|
|
49
55
|
|
|
50
|
-
##
|
|
56
|
+
## The operating model: Learn → Ask → Do
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
skills/ teach the agent when to ask, when to stop, when to ask YOU
|
|
56
|
-
│
|
|
57
|
-
pythia CLI — expert queries, impact analysis, the six-step write path
|
|
58
|
-
│
|
|
59
|
-
Oracle data dictionary: ALL_SOURCE, ALL_DEPENDENCIES, ALL_ERRORS, PL/Scope
|
|
60
|
-
```
|
|
58
|
+
Give the agent a problem — "add a column and every procedure that maintains
|
|
59
|
+
it", "why does this report double rows", "port this fix" — and the kit walks
|
|
60
|
+
it through the same three movements a careful senior developer makes.
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
### 1 · Learn — understand before proposing
|
|
63
|
+
|
|
64
|
+
The agent studies four things, in order, with tools instead of guesses:
|
|
65
|
+
|
|
66
|
+
| It learns | How | Instead of |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| the problem's real shape | `deps`, `impact`, `plscope` — the exact dependency graph and usage sites | skimming code and hoping |
|
|
69
|
+
| the schema's ground truth | `src`, `cols`, `args`, `ddl`, `errors` against the live database | trusting a dump that drifted |
|
|
70
|
+
| the house style | `.pythia/conventions.md` + `conventions --scan/--check` — rules measured against real names | inventing a style per session |
|
|
71
|
+
| how this codebase already solves it | `similar` — the neighbours to imitate | writing the first thing that compiles |
|
|
72
|
+
|
|
73
|
+
Nothing in this phase writes. Reading is free, so the bar is: **no proposal
|
|
74
|
+
before the blast radius is known** (`pythia-impact`'s iron law) and **no line
|
|
75
|
+
written before the neighbours have been read** (`pythia-write`'s).
|
|
76
|
+
|
|
77
|
+
### 2 · Ask — the questions are part of the method, not an interruption
|
|
78
|
+
|
|
79
|
+
The kit makes the agent stop at exactly the moments where a human's judgment
|
|
80
|
+
is the missing input, and forbids it to guess past them:
|
|
81
|
+
|
|
82
|
+
- **Before any write**: the full preview — diff, dependents, warnings — is
|
|
83
|
+
relayed verbatim, and the agent waits for a real yes. A compliment is not a
|
|
84
|
+
yes. Silence is not a yes.
|
|
85
|
+
- **When the blast radius is large**: ten or more dependents, or anything
|
|
86
|
+
cross-schema, goes to the developer *before code is written*, not after.
|
|
87
|
+
- **When sources of truth disagree**: a standards document says one thing,
|
|
88
|
+
the schema does another — that gap is a question ("rule nobody follows,
|
|
89
|
+
new-code-only, or drift?"), never a silent pick.
|
|
90
|
+
- **When something breaks**: exit 3 means *written but broken*. The agent
|
|
91
|
+
reports it exactly so, with the ready rollback — reporting success here is
|
|
92
|
+
the one sin the whole kit is built to prevent.
|
|
93
|
+
- **When policy refuses**: the refusal is relayed as information, not routed
|
|
94
|
+
around.
|
|
95
|
+
|
|
96
|
+
### 3 · Do — act inside a pipeline that cannot lie
|
|
97
|
+
|
|
98
|
+
Only after Learn and Ask does anything touch the database, and then only
|
|
99
|
+
through one door: **snapshot → impact → preview → token → apply → verify →
|
|
100
|
+
report**. DDL self-commits in Oracle, so the snapshot is the only real undo —
|
|
101
|
+
it runs first and no flag disables it. A content-bound token guarantees what
|
|
102
|
+
lands is byte-for-byte what was approved. And the CLI enforces the gates
|
|
103
|
+
itself: a headless agent cannot `--yes` its own writes or loosen policy —
|
|
104
|
+
that takes a human at a real terminal.
|
|
105
|
+
|
|
106
|
+
The same discipline holds when the *developer* does the work: `src` and
|
|
107
|
+
`impact` silently snapshot what they read, so even a change made by hand in
|
|
108
|
+
SQL Developer has a rollback file waiting (`history` lists them, drift is
|
|
109
|
+
reported when source moved with no apply behind it).
|
|
110
|
+
|
|
111
|
+
**Học – Hỏi – Làm** — Learn, Ask, Do. If the agent cannot show which phase it
|
|
112
|
+
is in, it is doing none of them.
|
|
67
113
|
|
|
68
114
|
## Install
|
|
69
115
|
|
|
@@ -7,6 +7,8 @@ description: Use when a PL/SQL change is ready to reach the database - applying
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-apply — I'll preview the change first."
|
|
9
9
|
|
|
10
|
+
**Phase:** Ask → Do — the preview is relayed and approved before the one write door opens
|
|
11
|
+
|
|
10
12
|
DDL in Oracle commits itself. There is no transaction to roll back — the
|
|
11
13
|
snapshot pythia takes before writing is the only undo that exists. This skill
|
|
12
14
|
exists so that safety net is always used, and used honestly.
|
|
@@ -7,6 +7,8 @@ description: Use when a project's house style already exists somewhere and needs
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-conventions — I'll read the patterns off the schema first."
|
|
9
9
|
|
|
10
|
+
**Phase:** Learn → Ask — derive from the schema, ask where the document disagrees, only then write the config
|
|
11
|
+
|
|
10
12
|
Conventions already exist in every mature schema. They are in the object
|
|
11
13
|
names, in a standards document, or in a senior developer's head. This turns
|
|
12
14
|
them into two files: patterns the tool checks on every write, and prose every
|
|
@@ -7,6 +7,8 @@ description: Use when you need to understand anything in an Oracle schema - find
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-explore — asking the database directly."
|
|
9
9
|
|
|
10
|
+
**Phase:** Learn
|
|
11
|
+
|
|
10
12
|
## The principle: ask the database, never the dump
|
|
11
13
|
|
|
12
14
|
Repositories of exported `.sql` files go stale the day after export. A real
|
|
@@ -7,6 +7,8 @@ description: Use before proposing or writing any change to an Oracle object - a
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-impact to measure the blast radius first."
|
|
9
9
|
|
|
10
|
+
**Phase:** Learn — and the first Ask gate: a large blast radius reaches the developer before any code is written
|
|
11
|
+
|
|
10
12
|
Changing an Oracle object recompiles or invalidates everything that depends
|
|
11
13
|
on it — immediately, schema-wide, for every user of a shared database. The
|
|
12
14
|
cost of knowing first is one command.
|
|
@@ -7,6 +7,8 @@ description: Use when reviewing PL/SQL - a changed procedure or package, a propo
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-review — checking the database's signals first."
|
|
9
9
|
|
|
10
|
+
**Phase:** Learn → Ask — the database's own signals first, findings back to the developer
|
|
11
|
+
|
|
10
12
|
Review in two passes: what the database *knows* is wrong, then what the
|
|
11
13
|
checklist says is *likely* wrong. Machine signals first — they are free and
|
|
12
14
|
exact.
|
|
@@ -7,6 +7,8 @@ description: Use when setting pythia up for a project or a machine - writing con
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-setup to configure the database access."
|
|
9
9
|
|
|
10
|
+
**Phase:** Do — one-time harness setup; everything after runs through Learn → Ask → Do
|
|
11
|
+
|
|
10
12
|
Set up in this order: connection first (everything else needs it), the
|
|
11
13
|
least-privilege user second (the only protection that cannot be bypassed),
|
|
12
14
|
SQLcl MCP last (optional, reads only).
|
|
@@ -83,7 +85,7 @@ until you want it.
|
|
|
83
85
|
|
|
84
86
|
| File | Created by | What it does |
|
|
85
87
|
|---|---|---|
|
|
86
|
-
| `connections.json` | `pythia install` | Where to connect. Holds
|
|
88
|
+
| `connections.json` | `pythia install` | Where to connect. **Holds passwords — never open it**; `pythia connections` lists names, users, schemas and targets with no secrets. Gitignored. |
|
|
87
89
|
| `journal/` | first write or snapshot | Every captured version, with a runnable rollback per entry. |
|
|
88
90
|
| `conventions.json` | `pythia conventions --init` | Naming patterns per object type. Every apply preview warns when a new name drifts. |
|
|
89
91
|
| `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. |
|
|
@@ -7,6 +7,8 @@ description: Use when the developer wants their own way of working captured as a
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-skill-author — let's capture how you actually work."
|
|
9
9
|
|
|
10
|
+
**Phase:** Learn → Ask → Do — interview, mine the schema, verify triggering
|
|
11
|
+
|
|
10
12
|
A skill is a decision captured so it never has to be re-argued. Capture what
|
|
11
13
|
the team *actually does* — with evidence from the database — not what anyone
|
|
12
14
|
remembers about it.
|
|
@@ -7,6 +7,8 @@ description: Use when writing or modifying PL/SQL source - a procedure, function
|
|
|
7
7
|
|
|
8
8
|
**Announce at start:** "Using pythia-write — mining the codebase's conventions first."
|
|
9
9
|
|
|
10
|
+
**Phase:** Learn → Do — mine the neighbours first, then draft; landing it is pythia-apply's job
|
|
11
|
+
|
|
10
12
|
**Before anything:** if the project has `.pythia/conventions.md`, read it —
|
|
11
13
|
house rules there outrank every generic pattern below, and
|
|
12
14
|
`pythia conventions` shows the naming patterns the apply preview will check. If the project has none and the developer
|
|
@@ -348,6 +348,19 @@ def test_conventions_init_writes_both_halves_and_never_clobbers():
|
|
|
348
348
|
assert (d / "conventions.json").read_text(encoding="utf-8") == '{"naming": {}}'
|
|
349
349
|
|
|
350
350
|
|
|
351
|
+
def test_guide_places_every_command_in_the_model():
|
|
352
|
+
"""`pythia guide` is the book an agent can open on any platform, skills
|
|
353
|
+
support or not. Coherence is enforced: every command the CLI exposes must
|
|
354
|
+
appear somewhere in the guide -- adding a command without giving it a
|
|
355
|
+
place in Learn/Ask/Do fails here."""
|
|
356
|
+
text = pythia.OPERATING_GUIDE
|
|
357
|
+
for phase in ("LEARN", "ASK", "DO"):
|
|
358
|
+
assert phase in text, f"guide missing the {phase} movement"
|
|
359
|
+
for cmd in pythia.COMMANDS:
|
|
360
|
+
assert cmd in text, f"command {cmd!r} has no place in the guide"
|
|
361
|
+
assert "guide" in pythia.NO_DB_COMMANDS # the book opens with no database
|
|
362
|
+
|
|
363
|
+
|
|
351
364
|
def main():
|
|
352
365
|
failed = 0
|
|
353
366
|
for name, fn in sorted(globals().items()):
|
|
@@ -327,6 +327,46 @@ def test_oracle_account_taken_from_a_proxy_connect_string():
|
|
|
327
327
|
assert pythia.authenticating_account(None) is None
|
|
328
328
|
|
|
329
329
|
|
|
330
|
+
SECRET = "hunter2-do-not-leak"
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _cfg():
|
|
334
|
+
return {
|
|
335
|
+
"dev": {"host": "db.example.com", "port": 1521,
|
|
336
|
+
"service_name": "orcl", "user": "app_agent[app_owner]",
|
|
337
|
+
"password": SECRET, "schema": "APP_OWNER"},
|
|
338
|
+
"stage": {"dsn": "stage.example.com:1521/orcl", "user": "u2",
|
|
339
|
+
"password": SECRET},
|
|
340
|
+
"default": "dev",
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def test_connection_summary_never_carries_a_secret():
|
|
345
|
+
"""An agent needs to know which connections exist. Until it could ask,
|
|
346
|
+
it parsed connections.json itself -- which is exactly the read a
|
|
347
|
+
permission classifier should block. This is the sanctioned answer, so it
|
|
348
|
+
must be provably secret-free, in every field and both output modes."""
|
|
349
|
+
import json
|
|
350
|
+
rows = pythia.connection_summary(_cfg())
|
|
351
|
+
blob = json.dumps(rows)
|
|
352
|
+
assert SECRET not in blob
|
|
353
|
+
assert "password" not in blob.lower()
|
|
354
|
+
names = [r["name"] for r in rows]
|
|
355
|
+
assert names == ["dev", "stage"] # the "default" key is not one
|
|
356
|
+
dev = rows[0]
|
|
357
|
+
assert dev["default"] is True and rows[1]["default"] is False
|
|
358
|
+
assert dev["user"] == "app_agent[app_owner]" # proxy shape is safe to show
|
|
359
|
+
assert dev["target"] == "db.example.com:1521/orcl"
|
|
360
|
+
assert rows[1]["target"] == "stage.example.com:1521/orcl" # dsn form
|
|
361
|
+
assert dev["schema"] == "APP_OWNER"
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def test_connection_summary_survives_a_thin_entry():
|
|
365
|
+
rows = pythia.connection_summary({"env": {"user": "u"}})
|
|
366
|
+
assert rows[0]["target"] == "—" and rows[0]["schema"] == "U"
|
|
367
|
+
assert pythia.connection_summary(None) == []
|
|
368
|
+
|
|
369
|
+
|
|
330
370
|
def main():
|
|
331
371
|
failed = 0
|
|
332
372
|
for name, fn in sorted(globals().items()):
|
|
@@ -109,17 +109,62 @@ def test_reference_files_exist_where_promised():
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
def test_readme_carries_the_required_tables():
|
|
112
|
-
"""The
|
|
113
|
-
|
|
112
|
+
"""The line cap is gone by the owner's call — the README now explains
|
|
113
|
+
the operating model in full. What stays pinned is content: the drift
|
|
114
|
+
table, the honest-rollback and policy tables, the install channels, and
|
|
115
|
+
the Learn-Ask-Do frame the whole kit is organised around."""
|
|
114
116
|
text = (ROOT / "README.md").read_text(encoding="utf-8")
|
|
115
|
-
for needle in ("1,016", # drift table
|
|
117
|
+
for needle in ("1,016", # drift table
|
|
116
118
|
"Flashback Query", "Recycle Bin", # rollback honesty
|
|
117
119
|
"plsql_source", "data_dml", # policy table
|
|
118
120
|
"npx skills add", # install channel
|
|
119
|
-
"
|
|
121
|
+
"Learn", "Ask", "Do", # the operating model
|
|
122
|
+
"star-history.com",
|
|
120
123
|
"MIT"):
|
|
121
124
|
assert needle in text, f"README missing {needle!r}"
|
|
122
|
-
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_vietnamese_readme_carries_the_operating_model():
|
|
128
|
+
text = (ROOT / "README.vi.md").read_text(encoding="utf-8")
|
|
129
|
+
for needle in ("Học", "Hỏi", "Làm"):
|
|
130
|
+
assert needle in text, f"README.vi missing {needle!r}"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_every_skill_declares_its_phase():
|
|
134
|
+
"""The kit's operating model is Learn - Ask - Do. A skill that cannot say
|
|
135
|
+
which movement it serves is not part of the method, it is a loose page."""
|
|
136
|
+
for name in sorted(EXPECTED):
|
|
137
|
+
path = SKILLS / name / "SKILL.md"
|
|
138
|
+
if not path.is_file():
|
|
139
|
+
continue
|
|
140
|
+
text = path.read_text(encoding="utf-8")
|
|
141
|
+
m = re.search(r"\*\*Phase:\*\* (.+)", text)
|
|
142
|
+
assert m, f"{name}: no '**Phase:**' declaration"
|
|
143
|
+
words = set(re.findall(r"Learn|Ask|Do", m.group(1)))
|
|
144
|
+
assert words and words <= {"Learn", "Ask", "Do"}, \
|
|
145
|
+
f"{name}: phase must name Learn/Ask/Do, got {m.group(1)!r}"
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_no_manifest_hardcodes_a_stale_skill_count():
|
|
149
|
+
"""The pack grew from seven skills to eight and three shipped manifests
|
|
150
|
+
still said seven. Counting in prose is a contradiction waiting to happen,
|
|
151
|
+
so the check is: no manifest states a number the code can disprove."""
|
|
152
|
+
import json
|
|
153
|
+
n = len(EXPECTED)
|
|
154
|
+
words = {7: "seven", 8: "eight", 9: "nine"}
|
|
155
|
+
stale = [w for k, w in words.items() if k != n]
|
|
156
|
+
for rel in (".claude-plugin/marketplace.json", "npm/package.json",
|
|
157
|
+
"npm/README.md"):
|
|
158
|
+
text = (ROOT / rel).read_text(encoding="utf-8").lower()
|
|
159
|
+
for word in stale:
|
|
160
|
+
assert word + " skill" not in text and word + "-skill" not in text, \
|
|
161
|
+
f"{rel} claims {word} skills; there are {n}"
|
|
162
|
+
mk = json.loads((ROOT / ".claude-plugin/marketplace.json")
|
|
163
|
+
.read_text(encoding="utf-8"))
|
|
164
|
+
declared = {p.rsplit("/", 1)[-1] for p in mk["plugins"][0]["skills"]}
|
|
165
|
+
assert declared == EXPECTED, (
|
|
166
|
+
f"marketplace.json and the pack disagree: "
|
|
167
|
+
f"missing {sorted(EXPECTED - declared)}, extra {sorted(declared - EXPECTED)}")
|
|
123
168
|
|
|
124
169
|
|
|
125
170
|
def main():
|
|
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
|
{pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/scripts/pythia_plsql.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythia_plsql-0.5.0 → pythia_plsql-0.6.1}/skills/pythia-explore/reference/data-dictionary.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|