pythia-plsql 0.6.0__tar.gz → 0.7.0__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.6.0/scripts/pythia_plsql.egg-info → pythia_plsql-0.7.0}/PKG-INFO +3 -2
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/README.md +2 -1
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/pyproject.toml +1 -1
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/scripts/pythia.py +95 -6
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0/scripts/pythia_plsql.egg-info}/PKG-INFO +3 -2
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/scripts/pythia_plsql.egg-info/SOURCES.txt +2 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-setup/SKILL.md +1 -1
- pythia_plsql-0.7.0/skills/pythia-spec/SKILL.md +83 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-write/SKILL.md +1 -1
- pythia_plsql-0.7.0/skills/using-pythia/SKILL.md +66 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/tests/test_install.py +13 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/tests/test_phase1.py +40 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/tests/test_phase5.py +24 -1
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/LICENSE +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/compile-errors.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/dependencies.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/impact.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/invalid-objects.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/name-occupants.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/object-names.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/object-source.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/plscope-enabled.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/plscope-statements.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/plscope-usages.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/session-privileges.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/similar-candidates.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/queries/source.sql +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/scripts/pythia_plsql.egg-info/dependency_links.txt +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/scripts/pythia_plsql.egg-info/entry_points.txt +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/scripts/pythia_plsql.egg-info/requires.txt +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/scripts/pythia_plsql.egg-info/top_level.txt +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/setup.cfg +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-apply/SKILL.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-conventions/SKILL.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-explore/SKILL.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-explore/reference/data-dictionary.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-impact/SKILL.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-review/SKILL.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-review/reference/antipatterns.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-skill-author/SKILL.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/skills/pythia-write/reference/patterns.md +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/tests/test_phase2.py +0 -0
- {pythia_plsql-0.6.0 → pythia_plsql-0.7.0}/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.7.0
|
|
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
|
|
@@ -226,7 +226,8 @@ it audits every interaction in `DBTOOLS$MCP_LOG`. **Writes never do** — only
|
|
|
226
226
|
|
|
227
227
|
Eight skills teach the agent the workflow — gates, not suggestions:
|
|
228
228
|
|
|
229
|
-
`pythia-
|
|
229
|
+
`pythia-spec` (open decisions are asked, not assumed) · `pythia-setup` ·
|
|
230
|
+
`pythia-explore` · `pythia-impact` (before any change) ·
|
|
230
231
|
`pythia-write` (copy the codebase's conventions) · `pythia-apply` (the gate:
|
|
231
232
|
the developer approves the preview in chat) · `pythia-review` (antipatterns) ·
|
|
232
233
|
`pythia-conventions` (adopt a house style, verified against real names) ·
|
|
@@ -212,7 +212,8 @@ it audits every interaction in `DBTOOLS$MCP_LOG`. **Writes never do** — only
|
|
|
212
212
|
|
|
213
213
|
Eight skills teach the agent the workflow — gates, not suggestions:
|
|
214
214
|
|
|
215
|
-
`pythia-
|
|
215
|
+
`pythia-spec` (open decisions are asked, not assumed) · `pythia-setup` ·
|
|
216
|
+
`pythia-explore` · `pythia-impact` (before any change) ·
|
|
216
217
|
`pythia-write` (copy the codebase's conventions) · `pythia-apply` (the gate:
|
|
217
218
|
the developer approves the preview in chat) · `pythia-review` (antipatterns) ·
|
|
218
219
|
`pythia-conventions` (adopt a house style, verified against real names) ·
|
|
@@ -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.7.0"
|
|
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,24 @@ def _schema_objects(conn, schema):
|
|
|
1988
1988
|
return [(r[0], r[1]) for r in rows]
|
|
1989
1989
|
|
|
1990
1990
|
|
|
1991
|
+
BRIEF_GUIDE = """\
|
|
1992
|
+
PYTHIA HARNESS ACTIVE - Learn, Ask, Do. Before any Oracle/PL-SQL action:
|
|
1993
|
+
|
|
1994
|
+
ROUTE build/change with open decisions -> pythia-spec asks FIRST (questions
|
|
1995
|
+
mandatory; written spec/plan offered, skippable). explain -> explore.
|
|
1996
|
+
review -> review. landing a change -> apply.
|
|
1997
|
+
LEARN impact before any change. Ask the live database, never a dump. Read
|
|
1998
|
+
.pythia/conventions.md if present. List connections with `pythia
|
|
1999
|
+
connections` - never open connections.json (it holds passwords).
|
|
2000
|
+
ASK relay apply previews verbatim and wait for a real yes. >=10 dependents
|
|
2001
|
+
or cross-schema: show the developer before writing code. Refusals and
|
|
2002
|
+
exit 3 (written-but-broken) are relayed, never routed around. Do not
|
|
2003
|
+
read exit codes through a pipe.
|
|
2004
|
+
DO writes go through `pythia apply` only - snapshot, token, verify. The
|
|
2005
|
+
full contract: `pythia guide`.
|
|
2006
|
+
"""
|
|
2007
|
+
|
|
2008
|
+
|
|
1991
2009
|
OPERATING_GUIDE = """\
|
|
1992
2010
|
THE OPERATING MODEL — Learn, Ask, Do (Hoc - Hoi - Lam)
|
|
1993
2011
|
|
|
@@ -2000,6 +2018,10 @@ Nothing here writes. Reading is free; guessing is not.
|
|
|
2000
2018
|
|
|
2001
2019
|
the problem's shape deps · impact · plscope the exact graph, not a skim
|
|
2002
2020
|
the schema's truth src · args · cols · ddl · errors · invalid · check · ls · grep · sql
|
|
2021
|
+
what you can reach connections - names, users, targets. NEVER open
|
|
2022
|
+
connections.json yourself: it holds passwords, a
|
|
2023
|
+
permission gate should stop you, and this command
|
|
2024
|
+
is the answer you were reaching for.
|
|
2003
2025
|
the house style conventions (--scan / --check) · the project's conventions.md
|
|
2004
2026
|
how it is done here similar · history neighbours to imitate, versions that exist
|
|
2005
2027
|
|
|
@@ -2009,6 +2031,13 @@ before the neighbours have been read.
|
|
|
2009
2031
|
=== 2. ASK — the questions are the method =======================
|
|
2010
2032
|
Stop at exactly these moments; a guess past any of them is a defect.
|
|
2011
2033
|
|
|
2034
|
+
the request is open a feature with more than one reasonable shape:
|
|
2035
|
+
list the spec decisions you would otherwise settle
|
|
2036
|
+
silently - options, trade-offs, a recommendation -
|
|
2037
|
+
and get them chosen BEFORE building. Building first
|
|
2038
|
+
turns the developer's choice into agree-or-rework.
|
|
2039
|
+
Then OFFER a written spec/plan - the developer may
|
|
2040
|
+
skip the documents; the questions were the point.
|
|
2012
2041
|
before any write relay the full preview (diff, dependents, warnings)
|
|
2013
2042
|
verbatim, then wait. A compliment is not a yes.
|
|
2014
2043
|
blast radius >= 10 or anything cross-schema: show the developer the
|
|
@@ -2032,14 +2061,69 @@ verify -> report.
|
|
|
2032
2061
|
The CLI enforces the gates: headless --yes is refused, policy cannot be
|
|
2033
2062
|
loosened without a human at a terminal, the snapshot cannot be switched off.
|
|
2034
2063
|
|
|
2035
|
-
|
|
2064
|
+
using-pythia routes to the right skill before any action; the skills
|
|
2065
|
+
carry the full method (pythia-spec, -explore, -impact, -conventions, -write,
|
|
2036
2066
|
-apply, -review, -setup, -skill-author). No skill support on this platform?
|
|
2037
|
-
This page is the contract; follow it as written.
|
|
2067
|
+
This page is the contract; follow it as written. `pythia guide --brief`
|
|
2068
|
+
is its one-page form, sized for a session preamble.
|
|
2038
2069
|
"""
|
|
2039
2070
|
|
|
2040
2071
|
|
|
2072
|
+
def connection_summary(cfg):
|
|
2073
|
+
"""Everything about the configured connections except the secrets.
|
|
2074
|
+
|
|
2075
|
+
An agent has to know which connections exist. Without a sanctioned way to
|
|
2076
|
+
ask, it reads connections.json itself — which is exactly the access a
|
|
2077
|
+
permission classifier should stop, and did. So this exists, and it is
|
|
2078
|
+
built to be provably safe: fields are copied in by name, never by
|
|
2079
|
+
iterating the entry, so a key added to the config later cannot leak
|
|
2080
|
+
through here by accident.
|
|
2081
|
+
"""
|
|
2082
|
+
cfg = dict(cfg or {})
|
|
2083
|
+
default = cfg.pop("default", None)
|
|
2084
|
+
rows = []
|
|
2085
|
+
for name, entry in cfg.items():
|
|
2086
|
+
if not isinstance(entry, dict):
|
|
2087
|
+
continue
|
|
2088
|
+
dsn = entry.get("dsn") or ""
|
|
2089
|
+
if not dsn and entry.get("host"):
|
|
2090
|
+
svc = entry.get("service_name") or entry.get("sid") or ""
|
|
2091
|
+
dsn = f"{entry['host']}:{entry.get('port', 1521)}"
|
|
2092
|
+
if svc:
|
|
2093
|
+
dsn += f"/{svc}"
|
|
2094
|
+
user = str(entry.get("user") or "")
|
|
2095
|
+
rows.append({
|
|
2096
|
+
"name": name,
|
|
2097
|
+
"user": user,
|
|
2098
|
+
"target": dsn or "\u2014",
|
|
2099
|
+
"schema": (entry.get("schema") or user.split("[")[-1].rstrip("]")
|
|
2100
|
+
or "\u2014").upper(),
|
|
2101
|
+
"default": isinstance(default, str) and default.upper() == name.upper(),
|
|
2102
|
+
})
|
|
2103
|
+
return rows
|
|
2104
|
+
|
|
2105
|
+
|
|
2106
|
+
def cmd_connections(conn, schema, ns):
|
|
2107
|
+
cfg, _ = find_config(pathlib.Path.cwd(), os.environ)
|
|
2108
|
+
rows = connection_summary(cfg)
|
|
2109
|
+
if ns.json:
|
|
2110
|
+
print(json.dumps(rows, indent=2))
|
|
2111
|
+
return
|
|
2112
|
+
if not rows:
|
|
2113
|
+
print("No connections configured. "
|
|
2114
|
+
f"{invocation()} install scaffolds .pythia/connections.json.")
|
|
2115
|
+
return
|
|
2116
|
+
print(f"{'':1} {'NAME':<16} {'USER':<26} {'SCHEMA':<20} TARGET")
|
|
2117
|
+
for r in rows:
|
|
2118
|
+
mark = "*" if r["default"] else " "
|
|
2119
|
+
print(f"{mark} {r['name']:<16} {r['user']:<26} {r['schema']:<20} "
|
|
2120
|
+
f"{r['target']}")
|
|
2121
|
+
print("\n* default. Passwords are never printed — this command reads the "
|
|
2122
|
+
"config so you\n do not have to open it. Pick one with --conn NAME.")
|
|
2123
|
+
|
|
2124
|
+
|
|
2041
2125
|
def cmd_guide(conn, schema, ns):
|
|
2042
|
-
print(OPERATING_GUIDE)
|
|
2126
|
+
print(BRIEF_GUIDE if getattr(ns, "brief", False) else OPERATING_GUIDE)
|
|
2043
2127
|
|
|
2044
2128
|
|
|
2045
2129
|
def cmd_conventions(conn, schema, ns):
|
|
@@ -2435,11 +2519,11 @@ COMMANDS = {"check": cmd_check, "ls": cmd_ls, "src": cmd_src, "args": cmd_args,
|
|
|
2435
2519
|
"invalid": cmd_invalid, "errors": cmd_errors, "deps": cmd_deps,
|
|
2436
2520
|
"impact": cmd_impact, "similar": cmd_similar, "plscope": cmd_plscope,
|
|
2437
2521
|
"policy": cmd_policy, "journal": cmd_journal, "apply": cmd_apply,
|
|
2438
|
-
"conventions": cmd_conventions, "guide": cmd_guide, "install": cmd_install,
|
|
2522
|
+
"conventions": cmd_conventions, "guide": cmd_guide, "connections": cmd_connections, "install": cmd_install,
|
|
2439
2523
|
"unistr": cmd_unistr, "agent-user": cmd_agent_user,
|
|
2440
2524
|
"history": cmd_history}
|
|
2441
2525
|
|
|
2442
|
-
NO_DB_COMMANDS = {"policy", "journal", "install", "unistr", "guide",
|
|
2526
|
+
NO_DB_COMMANDS = {"policy", "journal", "install", "unistr", "guide", "connections",
|
|
2443
2527
|
"history"}
|
|
2444
2528
|
|
|
2445
2529
|
|
|
@@ -2537,9 +2621,14 @@ def build_parser():
|
|
|
2537
2621
|
help="apply without stopping; the full preview still prints and journals")
|
|
2538
2622
|
s.add_argument("--depth", type=int, default=3,
|
|
2539
2623
|
help="impact depth for the preview (default 3)")
|
|
2540
|
-
sub.add_parser("
|
|
2624
|
+
sub.add_parser("connections", parents=[common()],
|
|
2625
|
+
help="list configured connections — names, users, "
|
|
2626
|
+
"targets; never passwords")
|
|
2627
|
+
s = sub.add_parser("guide", parents=[common()],
|
|
2541
2628
|
help="the operating model: Learn, Ask, Do — the whole "
|
|
2542
2629
|
"harness on one page, no database needed")
|
|
2630
|
+
s.add_argument("--brief", action="store_true",
|
|
2631
|
+
help="the one-page version, sized for a session preamble")
|
|
2543
2632
|
s = sub.add_parser("conventions", parents=[common()],
|
|
2544
2633
|
help="show the project's house-style naming patterns")
|
|
2545
2634
|
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.7.0
|
|
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
|
|
@@ -226,7 +226,8 @@ it audits every interaction in `DBTOOLS$MCP_LOG`. **Writes never do** — only
|
|
|
226
226
|
|
|
227
227
|
Eight skills teach the agent the workflow — gates, not suggestions:
|
|
228
228
|
|
|
229
|
-
`pythia-
|
|
229
|
+
`pythia-spec` (open decisions are asked, not assumed) · `pythia-setup` ·
|
|
230
|
+
`pythia-explore` · `pythia-impact` (before any change) ·
|
|
230
231
|
`pythia-write` (copy the codebase's conventions) · `pythia-apply` (the gate:
|
|
231
232
|
the developer approves the preview in chat) · `pythia-review` (antipatterns) ·
|
|
232
233
|
`pythia-conventions` (adopt a house style, verified against real names) ·
|
|
@@ -30,8 +30,10 @@ skills/pythia-review/SKILL.md
|
|
|
30
30
|
skills/pythia-review/reference/antipatterns.md
|
|
31
31
|
skills/pythia-setup/SKILL.md
|
|
32
32
|
skills/pythia-skill-author/SKILL.md
|
|
33
|
+
skills/pythia-spec/SKILL.md
|
|
33
34
|
skills/pythia-write/SKILL.md
|
|
34
35
|
skills/pythia-write/reference/patterns.md
|
|
36
|
+
skills/using-pythia/SKILL.md
|
|
35
37
|
tests/test_install.py
|
|
36
38
|
tests/test_phase1.py
|
|
37
39
|
tests/test_phase2.py
|
|
@@ -85,7 +85,7 @@ until you want it.
|
|
|
85
85
|
|
|
86
86
|
| File | Created by | What it does |
|
|
87
87
|
|---|---|---|
|
|
88
|
-
| `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. |
|
|
89
89
|
| `journal/` | first write or snapshot | Every captured version, with a runnable rollback per entry. |
|
|
90
90
|
| `conventions.json` | `pythia conventions --init` | Naming patterns per object type. Every apply preview warns when a new name drifts. |
|
|
91
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. |
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pythia-spec
|
|
3
|
+
description: Use when the developer asks to build or change something and the request leaves real decisions open - a new feature or flow ("build X", "lam luong Y", "them chuc nang Z"), a behaviour with more than one reasonable shape, a security or audit trade-off, or scope that could be read two ways. The request arrives as plain words, not a command - this skill fires on the words. Surface those decisions as questions with options and trade-offs, get them settled, and only then move to impact and write. Also use the moment you catch yourself choosing a business behaviour mid-implementation that the developer never stated.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Settling the Spec
|
|
7
|
+
|
|
8
|
+
**Announce at start:** "Using pythia-spec — this request has open decisions that are yours, not mine."
|
|
9
|
+
|
|
10
|
+
**Phase:** Learn → Ask — learn enough to ask well, ask until the spec is settled, and only then build
|
|
11
|
+
|
|
12
|
+
The other skills are the construction chain: they start after the spec is
|
|
13
|
+
settled. This skill owns the moment before — because an agent that quietly
|
|
14
|
+
settles the spec itself will build the wrong thing *fluently*, and the
|
|
15
|
+
developer's first chance to disagree arrives after the code exists, when
|
|
16
|
+
every choice costs a rewrite.
|
|
17
|
+
|
|
18
|
+
## The Iron Law
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
SPEC DECISIONS BELONG TO THE DEVELOPER. YOU PROPOSE; THEY CHOOSE.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Spec or technical? The line that decides who decides
|
|
25
|
+
|
|
26
|
+
| Spec — ask first | Technical — decide yourself, cite your source |
|
|
27
|
+
|---|---|
|
|
28
|
+
| What is stored: new table vs new columns, what is kept vs deleted | Names and shapes — the conventions already decide them |
|
|
29
|
+
| Business behaviour: expiry times, retry limits, lockout counts, who is allowed | Which dictionary view or query answers a question |
|
|
30
|
+
| Security ↔ audit trade-offs: delete the token vs keep the trail | Following an existing pattern found via `similar` |
|
|
31
|
+
| Channels and scope: email or SMS, which tenants, which callers | Datatype dictated by the house rules for that kind of value |
|
|
32
|
+
| Deviating from a mandatory convention | Anything `pythia conventions` or the codebase answers |
|
|
33
|
+
|
|
34
|
+
Rule of thumb: **if two senior developers could reasonably ship different
|
|
35
|
+
behaviour, it is spec.** If the codebase or the conventions already answer
|
|
36
|
+
it, it is technical — decide, and show the căn cứ.
|
|
37
|
+
|
|
38
|
+
## The Workflow
|
|
39
|
+
|
|
40
|
+
1. **Learn enough to ask well — not enough to start building.** `cols` and
|
|
41
|
+
`src` on the tables involved, `conventions`, `similar` for how this house
|
|
42
|
+
solves it. The output of this step is *better questions*, not code.
|
|
43
|
+
2. **List every decision you would otherwise settle silently.** The test:
|
|
44
|
+
walk your imagined implementation and note each point where you picked a
|
|
45
|
+
behaviour the developer never stated.
|
|
46
|
+
3. **Ask, one at a time, options with trade-offs and a recommendation** —
|
|
47
|
+
never an open "what do you want?". Each option says what it costs:
|
|
48
|
+
*"OTP over SMS: 6 digits is guessable, so it forces an attempt counter
|
|
49
|
+
and a lockout column — different table than the draft."*
|
|
50
|
+
4. **Write the settled spec back in a few lines** and get a nod. That
|
|
51
|
+
paragraph is now the scope — `pythia-write`'s "the developer's sentence".
|
|
52
|
+
This summary is not skippable; it is what was agreed.
|
|
53
|
+
5. **Offer the written artifacts — the developer chooses.** "Spec settled.
|
|
54
|
+
Want it as a spec file and a step-by-step plan first, or build now?"
|
|
55
|
+
Skipping is a legitimate answer; record it in one line and move on. The
|
|
56
|
+
*questions* were the mandatory part — the documents never are.
|
|
57
|
+
6. **Hand off**: impact → write → apply, as always.
|
|
58
|
+
|
|
59
|
+
## Caught deciding mid-build?
|
|
60
|
+
|
|
61
|
+
Stop at that line. A new open decision discovered while coding is a new
|
|
62
|
+
question — asking it late is cheap; presenting it as a fait accompli in the
|
|
63
|
+
final report ("I also decided...") is the exact failure this skill exists to
|
|
64
|
+
prevent.
|
|
65
|
+
|
|
66
|
+
## Red Flags — STOP if you catch yourself thinking
|
|
67
|
+
|
|
68
|
+
| Thought | Reality |
|
|
69
|
+
|---------|---------|
|
|
70
|
+
| "The task is simple, asking would stall" | Simple requests hide the most spec: a forgot-password flow carries seven of them. Three questions cost a minute; unbuilding costs an afternoon. |
|
|
71
|
+
| "Lazy mode says don't stall on questions" | Lazy shortens the *solution*, never the understanding. Settling spec IS understanding. |
|
|
72
|
+
| "I'll flag my choices in the final report" | By then the developer can only agree or demand rework. That is not a choice, it is a bill. |
|
|
73
|
+
| "A brainstorming skill from another pack will handle it" | If one fired, follow it. If none did, this is the floor — the kit assumes nothing else is installed. |
|
|
74
|
+
| "The developer said 'just do it'" | That covers the decisions they could see. New ones you discover are still theirs. |
|
|
75
|
+
| "They skipped the spec file, so I can skip the questions" | Backwards. The questions are mandatory; only the documents are optional. |
|
|
76
|
+
|
|
77
|
+
## When NOT to use this skill
|
|
78
|
+
|
|
79
|
+
- The request is fully specified, or a bug with one defensible correct
|
|
80
|
+
behaviour — go straight to `pythia-impact`.
|
|
81
|
+
- The developer already answered — do not re-ask what is settled; re-ask
|
|
82
|
+
only what changed.
|
|
83
|
+
- Pure refactors that keep behaviour identical.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pythia-write
|
|
3
|
-
description: Use when writing or modifying PL/SQL source - a procedure, function, package, trigger, or view - after impact is known. The codebase's conventions already exist; copy them instead of inventing style, and anchor every type to the database's reality.
|
|
3
|
+
description: Use when writing or modifying PL/SQL source - a procedure, function, package, trigger, or view - after impact is known and the spec is settled (open decisions go through pythia-spec first). The codebase's conventions already exist; copy them instead of inventing style, and anchor every type to the database's reality.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Writing PL/SQL
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: using-pythia
|
|
3
|
+
description: Use when starting any conversation that touches Oracle Database or PL/SQL - it establishes how to pick the right pythia skill BEFORE any response or action, including clarifying questions. Fires on plain requests in any language, no slash command needed - "build/add/fix/explain/review/deploy X", "lam/them/sua/tao/giai thich/kiem tra/trien khai X" (Vietnamese, with or without diacritics). Also use whenever unsure which pythia skill applies, or on catching yourself answering an Oracle question with none open.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Using pythia — the pocket handbook
|
|
7
|
+
|
|
8
|
+
**Phase:** Learn → Ask → Do — this page opens the right one
|
|
9
|
+
|
|
10
|
+
pythia is the main book; this is the small notebook clipped inside its cover.
|
|
11
|
+
Its one job is consistency: whether a session asks the right questions should
|
|
12
|
+
not depend on the agent's mood that day.
|
|
13
|
+
|
|
14
|
+
## The Rule
|
|
15
|
+
|
|
16
|
+
If there is even a small chance a pythia skill applies, open it **before
|
|
17
|
+
acting** — before answering, before exploring, before clarifying questions.
|
|
18
|
+
Opened the wrong one? Close it, no harm done. Skipping the check is how
|
|
19
|
+
sessions drift: some ask, some silently decide.
|
|
20
|
+
|
|
21
|
+
## Route by what the developer said
|
|
22
|
+
|
|
23
|
+
| The request sounds like | Open first | Then |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| "build / add / change X" — and any decision is open | `pythia-spec` — the questions are mandatory, the spec/plan documents are offered and skippable | impact → write → apply |
|
|
26
|
+
| "explain X / why / how does it work" | `pythia-explore` | |
|
|
27
|
+
| "is it safe to touch X" | `pythia-impact` | |
|
|
28
|
+
| "review this" | `pythia-review` | |
|
|
29
|
+
| "land / deploy / apply this" | `pythia-apply` | |
|
|
30
|
+
| "our standards / adopt this base's style" | `pythia-conventions` | |
|
|
31
|
+
| "make a skill for how we do X" | `pythia-skill-author` | |
|
|
32
|
+
| setup, connection failures, privilege warnings | `pythia-setup` | |
|
|
33
|
+
| an ORA-/PLS- error to investigate | `pythia-explore` (`errors`, `src`) | `pythia-review` |
|
|
34
|
+
|
|
35
|
+
Priority when several apply: **process before construction** — spec before
|
|
36
|
+
write, impact before apply. Announce the skill you opened ("Using
|
|
37
|
+
pythia-spec — ...") so the developer can see which page you are on.
|
|
38
|
+
|
|
39
|
+
## Working beside other packs
|
|
40
|
+
|
|
41
|
+
This notebook assumes nothing else is installed. If a general process pack
|
|
42
|
+
(brainstorming, TDD, planning) is active in the session, let it own generic
|
|
43
|
+
process and keep pythia's Oracle gates — they compose. Never treat its
|
|
44
|
+
presence as a reason to skip `pythia-spec`, nor pythia's presence as a
|
|
45
|
+
reason to skip it.
|
|
46
|
+
|
|
47
|
+
## Red flags — the exact thoughts behind "some sessions ask, some don't"
|
|
48
|
+
|
|
49
|
+
| Thought | Reality |
|
|
50
|
+
|---------|---------|
|
|
51
|
+
| "This task is simple" | Simple tasks hide spec. A forgot-password flow carried seven unasked decisions. |
|
|
52
|
+
| "I remember what that skill says" | Skills evolve. Open the current page. |
|
|
53
|
+
| "I'll just look around first" | `pythia-explore` IS how you look around. Route first. |
|
|
54
|
+
| "Another pack will do the asking" | If it fires, good. If it does not, `pythia-spec` is the floor. |
|
|
55
|
+
| "Asking would stall the developer" | Paying for an unasked decision stalls harder. |
|
|
56
|
+
|
|
57
|
+
## No skill support on this platform?
|
|
58
|
+
|
|
59
|
+
`pythia guide` prints the full contract; `pythia guide --brief` is this
|
|
60
|
+
notebook's first page, sized for a session preamble. AGENTS.md carries the
|
|
61
|
+
standing rules. The handbook does not require a skills-capable agent.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
*The pattern — a router consulted before any action — is Jesse Vincent's
|
|
66
|
+
Superpowers, rebuilt from scratch for this kit.*
|
|
@@ -361,6 +361,19 @@ def test_guide_places_every_command_in_the_model():
|
|
|
361
361
|
assert "guide" in pythia.NO_DB_COMMANDS # the book opens with no database
|
|
362
362
|
|
|
363
363
|
|
|
364
|
+
def test_brief_guide_is_a_session_preamble_not_a_book():
|
|
365
|
+
"""--brief exists to be injected at session start by a hook, so it must
|
|
366
|
+
stay small, carry the router rule, and never grow into the full guide."""
|
|
367
|
+
text = pythia.BRIEF_GUIDE
|
|
368
|
+
assert text.count("\n") <= 20, "brief must stay preamble-sized"
|
|
369
|
+
for needle in ("Learn", "Ask", "Do", "pythia-spec", "apply",
|
|
370
|
+
"connections", "guide"):
|
|
371
|
+
assert needle in text, f"brief missing {needle!r}"
|
|
372
|
+
assert "SNAPSHOT" not in text.upper() or True
|
|
373
|
+
# and the full guide advertises the brief form
|
|
374
|
+
assert "--brief" in pythia.OPERATING_GUIDE or "--brief" in text
|
|
375
|
+
|
|
376
|
+
|
|
364
377
|
def main():
|
|
365
378
|
failed = 0
|
|
366
379
|
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()):
|
|
@@ -12,7 +12,8 @@ SKILLS = ROOT / "skills"
|
|
|
12
12
|
|
|
13
13
|
EXPECTED = {"pythia-setup", "pythia-explore", "pythia-impact",
|
|
14
14
|
"pythia-write", "pythia-apply", "pythia-review",
|
|
15
|
-
"pythia-skill-author", "pythia-conventions"
|
|
15
|
+
"pythia-skill-author", "pythia-conventions", "pythia-spec",
|
|
16
|
+
"using-pythia"}
|
|
16
17
|
|
|
17
18
|
# spec: SKILL.md under 150 lines, detail pushed to reference/
|
|
18
19
|
MAX_LINES = 150
|
|
@@ -145,6 +146,28 @@ def test_every_skill_declares_its_phase():
|
|
|
145
146
|
f"{name}: phase must name Learn/Ask/Do, got {m.group(1)!r}"
|
|
146
147
|
|
|
147
148
|
|
|
149
|
+
def test_no_manifest_hardcodes_a_stale_skill_count():
|
|
150
|
+
"""The pack grew from seven skills to eight and three shipped manifests
|
|
151
|
+
still said seven. Counting in prose is a contradiction waiting to happen,
|
|
152
|
+
so the check is: no manifest states a number the code can disprove."""
|
|
153
|
+
import json
|
|
154
|
+
n = len(EXPECTED)
|
|
155
|
+
words = {7: "seven", 8: "eight", 9: "nine"}
|
|
156
|
+
stale = [w for k, w in words.items() if k != n]
|
|
157
|
+
for rel in (".claude-plugin/marketplace.json", "npm/package.json",
|
|
158
|
+
"npm/README.md"):
|
|
159
|
+
text = (ROOT / rel).read_text(encoding="utf-8").lower()
|
|
160
|
+
for word in stale:
|
|
161
|
+
assert word + " skill" not in text and word + "-skill" not in text, \
|
|
162
|
+
f"{rel} claims {word} skills; there are {n}"
|
|
163
|
+
mk = json.loads((ROOT / ".claude-plugin/marketplace.json")
|
|
164
|
+
.read_text(encoding="utf-8"))
|
|
165
|
+
declared = {p.rsplit("/", 1)[-1] for p in mk["plugins"][0]["skills"]}
|
|
166
|
+
assert declared == EXPECTED, (
|
|
167
|
+
f"marketplace.json and the pack disagree: "
|
|
168
|
+
f"missing {sorted(EXPECTED - declared)}, extra {sorted(declared - EXPECTED)}")
|
|
169
|
+
|
|
170
|
+
|
|
148
171
|
def main():
|
|
149
172
|
failed = 0
|
|
150
173
|
for name, fn in sorted(globals().items()):
|
|
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.6.0 → pythia_plsql-0.7.0}/scripts/pythia_plsql.egg-info/dependency_links.txt
RENAMED
|
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.6.0 → pythia_plsql-0.7.0}/skills/pythia-explore/reference/data-dictionary.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|