holoscript-holorepo 0.2.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HoloScript ecosystem (Joseph, founder).
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: holoscript-holorepo
3
+ Version: 0.2.0
4
+ Summary: Python companion for HoloRepo: plug-and-play sovereign DB + HoloScript KS for agent frameworks.
5
+ Author: HoloScript ecosystem
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/brianonbased-dev/ai-ecosystem/tree/main/packages/holorepo-py
8
+ Project-URL: Source, https://github.com/brianonbased-dev/ai-ecosystem
9
+ Project-URL: Doctrine, https://github.com/brianonbased-dev/ai-ecosystem/blob/main/docs/handbooks/holorepo-operating-model.md
10
+ Keywords: holoscript,holorepo,sovereign,postgres,knowledge-store,agent-framework
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Software Development :: Version Control :: Git
15
+ Classifier: Topic :: Database
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # holoscript-holorepo
22
+
23
+ Python companion for HoloRepo: a plug-and-play sovereign GitHub + database +
24
+ HoloScript knowledge store for high-volume agent frameworks.
25
+
26
+ The Python client covers the DB/KS guest surface. It reads any Postgres reachable
27
+ by `psql`, or an explicitly configured owned node over SSH + Docker. No host, IP,
28
+ or container is assumed by default.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install holoscript-holorepo
34
+ ```
35
+
36
+ ## Config
37
+
38
+ Use `holorepo.config.json` or env:
39
+
40
+ ```bash
41
+ export HOLOREPO_DATABASE_URL="postgres://user@host:5432/app"
42
+ export PGPASSWORD="..."
43
+ ```
44
+
45
+ For an owned node over SSH, use the `jetsonExample` profile as an example and
46
+ set `HOLOREPO_SSH`, `HOLOREPO_SSH_KEY`, and `HOLOREPO_POSTGRES_CONTAINER`.
47
+
48
+ ## Use
49
+
50
+ ```bash
51
+ holorepo-py db read knowledge "select count(*) from memory_entries"
52
+ holorepo-py ks query "storage lanes" 8
53
+ ```
54
+
55
+ ```python
56
+ from holoscript_holorepo import query_ks, read_db
57
+
58
+ hits = query_ks("sovereign backbone", limit=5)["rows"]
59
+ ```
60
+
61
+ Reads refuse mutations. Writes are staged by the npm client as
62
+ `holorepo.storage-proof.v1` and admitted by the configured operator route.
63
+
64
+ ## Release Boundary
65
+
66
+ `holoscript-holorepo` is distributed under the MIT license. The compatibility
67
+ label is still `v0-preview`: the Python companion supports config/env-driven
68
+ DB/KS reads for agent frameworks, while write admission remains in the npm
69
+ client and HoloGate/HoloKey operator lane.
@@ -0,0 +1,49 @@
1
+ # holoscript-holorepo
2
+
3
+ Python companion for HoloRepo: a plug-and-play sovereign GitHub + database +
4
+ HoloScript knowledge store for high-volume agent frameworks.
5
+
6
+ The Python client covers the DB/KS guest surface. It reads any Postgres reachable
7
+ by `psql`, or an explicitly configured owned node over SSH + Docker. No host, IP,
8
+ or container is assumed by default.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install holoscript-holorepo
14
+ ```
15
+
16
+ ## Config
17
+
18
+ Use `holorepo.config.json` or env:
19
+
20
+ ```bash
21
+ export HOLOREPO_DATABASE_URL="postgres://user@host:5432/app"
22
+ export PGPASSWORD="..."
23
+ ```
24
+
25
+ For an owned node over SSH, use the `jetsonExample` profile as an example and
26
+ set `HOLOREPO_SSH`, `HOLOREPO_SSH_KEY`, and `HOLOREPO_POSTGRES_CONTAINER`.
27
+
28
+ ## Use
29
+
30
+ ```bash
31
+ holorepo-py db read knowledge "select count(*) from memory_entries"
32
+ holorepo-py ks query "storage lanes" 8
33
+ ```
34
+
35
+ ```python
36
+ from holoscript_holorepo import query_ks, read_db
37
+
38
+ hits = query_ks("sovereign backbone", limit=5)["rows"]
39
+ ```
40
+
41
+ Reads refuse mutations. Writes are staged by the npm client as
42
+ `holorepo.storage-proof.v1` and admitted by the configured operator route.
43
+
44
+ ## Release Boundary
45
+
46
+ `holoscript-holorepo` is distributed under the MIT license. The compatibility
47
+ label is still `v0-preview`: the Python companion supports config/env-driven
48
+ DB/KS reads for agent frameworks, while write admission remains in the npm
49
+ client and HoloGate/HoloKey operator lane.
@@ -0,0 +1,225 @@
1
+ """holoscript-holorepo: Python companion for HoloRepo.
2
+
3
+ The client is config/env driven. It can read any Postgres reachable by `psql`,
4
+ or an explicitly configured owned node over SSH + docker exec. No host, IP, or
5
+ container is assumed by default.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import hashlib
10
+ import json
11
+ import os
12
+ import re
13
+ import subprocess
14
+ from pathlib import Path
15
+ from urllib.parse import urlsplit, urlunsplit
16
+
17
+ __version__ = "0.2.0"
18
+ RELEASE_LANE = "v0-preview"
19
+ CONFIG_SCHEMA = "holorepo.config.v1"
20
+
21
+ _MUTATION = re.compile(r"\b(insert|update|delete|drop|alter|create|truncate|grant|revoke|copy|merge|call)\b", re.I)
22
+ _READ_HEAD = re.compile(r"^(select|with|explain|show|table)\b", re.I)
23
+
24
+
25
+ def default_config() -> dict:
26
+ return {
27
+ "schema": CONFIG_SCHEMA,
28
+ "productName": "HoloRepo",
29
+ "activeProfile": "local",
30
+ "storage": {"kind": "filesystem", "root": ".holorepo/storage"},
31
+ "git": {"backend": "local-bare", "root": ".holorepo/git"},
32
+ "database": {"transport": "direct-psql", "connectionEnv": "HOLOREPO_DATABASE_URL"},
33
+ "knowledgeStore": {"database": "knowledge", "table": "memory_entries"},
34
+ "agents": {"maxConcurrentWriters": 100},
35
+ "profiles": {
36
+ "jetsonExample": {
37
+ "note": "Example only. HoloRepo no longer assumes this host, container, or path.",
38
+ "database": {
39
+ "transport": "ssh-docker-psql",
40
+ "ssh": {"hostEnv": "HOLOREPO_SSH", "keyEnv": "HOLOREPO_SSH_KEY"},
41
+ "docker": {"containerEnv": "HOLOREPO_POSTGRES_CONTAINER"},
42
+ "userEnv": "HOLOREPO_DATABASE_USER",
43
+ },
44
+ }
45
+ },
46
+ }
47
+
48
+
49
+ def _merge(a: dict, b: dict) -> dict:
50
+ out = dict(a)
51
+ for key, value in (b or {}).items():
52
+ if isinstance(value, dict) and isinstance(out.get(key), dict):
53
+ out[key] = _merge(out[key], value)
54
+ else:
55
+ out[key] = value
56
+ return out
57
+
58
+
59
+ def load_config(path: str | None = None, env: dict | None = None) -> dict:
60
+ env = os.environ if env is None else env
61
+ target = Path(path or env.get("HOLOREPO_CONFIG", "holorepo.config.json"))
62
+ cfg = json.loads(target.read_text()) if target.exists() else default_config()
63
+ if "$schema" in cfg and "schema" not in cfg:
64
+ cfg["schema"] = cfg["$schema"]
65
+ profile = env.get("HOLOREPO_CONFIG_PROFILE") or cfg.get("activeProfile") or cfg.get("profile")
66
+ if profile and cfg.get("profiles", {}).get(profile):
67
+ cfg = _merge(cfg, cfg["profiles"][profile])
68
+ cfg["activeProfile"] = profile
69
+ if env.get("HOLOREPO_DATABASE_URL"):
70
+ cfg["database"] = _merge(cfg.get("database", {}), {"transport": "direct-psql", "connectionEnv": "HOLOREPO_DATABASE_URL"})
71
+ elif env.get("DATABASE_URL"):
72
+ cfg["database"] = _merge(cfg.get("database", {}), {"transport": "direct-psql", "connectionEnv": "DATABASE_URL"})
73
+ return cfg
74
+
75
+
76
+ def _sha256(text: str) -> str:
77
+ return "sha256:" + hashlib.sha256(text.encode("utf-8")).hexdigest()
78
+
79
+
80
+ def is_read_only_sql(sql: str) -> bool:
81
+ s = (sql or "").strip().rstrip(";").strip()
82
+ if not s:
83
+ return False
84
+ if ";" in s:
85
+ return False
86
+ if s.startswith("\\"):
87
+ return True
88
+ return bool(_READ_HEAD.match(s)) and not _MUTATION.search(s)
89
+
90
+
91
+ def sanitize_term(term: str) -> str:
92
+ return re.sub(r"\s+", " ", re.sub(r"[%_\\']", " ", term or "")).strip()[:120]
93
+
94
+
95
+ def safe_table(name: str = "memory_entries") -> str:
96
+ if not re.match(r"^[a-z_][a-z0-9_]*$", name or "", re.I):
97
+ raise ValueError(f"unsafe SQL identifier: {name}")
98
+ return name
99
+
100
+
101
+ def build_ks_query(term: str, domain: str | None = None, limit: int = 10, table: str = "memory_entries") -> str:
102
+ t = sanitize_term(term)
103
+ tbl = safe_table(table)
104
+ dom = f" and domain = '{sanitize_term(domain)}'" if domain else ""
105
+ lim = max(1, min(50, int(limit) if str(limit).isdigit() else 10))
106
+ return (
107
+ "select id, domain, type, coalesce(confidence,0), "
108
+ "left(regexp_replace(content, '\\s+', ' ', 'g'), 150) "
109
+ f"from {tbl} where content ILIKE '%{t}%'{dom} and coalesce(is_stale,false)=false "
110
+ f"order by coalesce(reuse_count,0) desc, updated_at desc limit {lim}"
111
+ )
112
+
113
+
114
+ def redact_connection_string(value: str | None) -> str | None:
115
+ if not value:
116
+ return value
117
+ try:
118
+ parts = urlsplit(value)
119
+ host = parts.hostname or "host"
120
+ port = f":{parts.port}" if parts.port else ""
121
+ user = "redacted@" if parts.username else ""
122
+ return urlunsplit((parts.scheme, f"{user}{host}{port}", parts.path, parts.query, parts.fragment))
123
+ except Exception:
124
+ return re.sub(r"//[^:@/\s]+:[^@/\s]+@", "//redacted:redacted@", value)
125
+
126
+
127
+ def _split_password_from_url(value: str):
128
+ if not value:
129
+ return value, None
130
+ try:
131
+ parts = urlsplit(value)
132
+ if not parts.password:
133
+ return value, None
134
+ host = parts.hostname or ""
135
+ port = f":{parts.port}" if parts.port else ""
136
+ netloc = f"{parts.username}@{host}{port}" if parts.username else f"{host}{port}"
137
+ return urlunsplit((parts.scheme, netloc, parts.path, parts.query, parts.fragment)), parts.password
138
+ except Exception:
139
+ return value, None
140
+
141
+
142
+ def redact_db_summary(db: str, config: dict | None = None, env: dict | None = None) -> str:
143
+ env = os.environ if env is None else env
144
+ config = load_config(env=env) if config is None else config
145
+ db_cfg = config.get("database", {})
146
+ transport = db_cfg.get("transport", "direct-psql")
147
+ env_name = db_cfg.get("connectionEnv")
148
+ if env_name and env.get(env_name):
149
+ return f"{redact_connection_string(env[env_name])} db={db} ({transport}, redacted)"
150
+ return f"postgres://<{env_name or 'HOLOREPO_DATABASE_URL'}>/{db} ({transport}, redacted)"
151
+
152
+
153
+ def _run_psql(db: str, sql: str, meta: bool = False, config: dict | None = None, env: dict | None = None):
154
+ env = os.environ if env is None else env
155
+ config = load_config(env=env) if config is None else config
156
+ db_cfg = config.get("database", {})
157
+ transport = db_cfg.get("transport", "direct-psql")
158
+ password = None
159
+ if transport == "direct-psql":
160
+ env_name = db_cfg.get("connectionEnv", "HOLOREPO_DATABASE_URL")
161
+ conn = env.get(env_name)
162
+ if not conn:
163
+ return False, "", f"direct-psql needs {env_name}"
164
+ conn, password = _split_password_from_url(conn)
165
+ args = ["psql", "-X", conn, "-c" if meta else "-tAc", sql]
166
+ elif transport == "ssh-docker-psql":
167
+ ssh = db_cfg.get("ssh", {})
168
+ docker = db_cfg.get("docker", {})
169
+ host = ssh.get("host") or env.get(ssh.get("hostEnv", "HOLOREPO_SSH"))
170
+ key = ssh.get("keyPath") or env.get(ssh.get("keyEnv", "HOLOREPO_SSH_KEY"))
171
+ container = docker.get("container") or env.get(docker.get("containerEnv", "HOLOREPO_POSTGRES_CONTAINER"))
172
+ user = db_cfg.get("user") or env.get(db_cfg.get("userEnv", "HOLOREPO_DATABASE_USER"), "postgres")
173
+ if not host:
174
+ return False, "", "ssh-docker-psql needs database.ssh.host or hostEnv"
175
+ if not container:
176
+ return False, "", "ssh-docker-psql needs database.docker.container or containerEnv"
177
+ esc = sql.replace("'", "'\\''")
178
+ flag = "" if meta else "-tA"
179
+ remote = f"sudo docker exec '{container}' psql -U '{user}' -d '{db}' {flag} -c '{esc}'"
180
+ args = ["ssh", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=15"]
181
+ if key:
182
+ args.extend(["-i", os.path.expanduser(key)])
183
+ args.extend([host, remote])
184
+ else:
185
+ return False, "", f"unsupported database transport: {transport}"
186
+ child_env = dict(os.environ)
187
+ child_env.update(env)
188
+ if transport == "direct-psql" and password and not child_env.get("PGPASSWORD"):
189
+ child_env["PGPASSWORD"] = password
190
+ proc = subprocess.run(args, capture_output=True, text=True, timeout=30, env=child_env)
191
+ return proc.returncode == 0, proc.stdout.strip(), proc.stderr.strip()
192
+
193
+
194
+ def read_db(db: str, sql: str, config: dict | None = None, env: dict | None = None) -> dict:
195
+ if not is_read_only_sql(sql):
196
+ return {"ok": False, "refused": True}
197
+ ok, out, err = _run_psql(db, sql, meta=sql.strip().startswith("\\"), config=config, env=env)
198
+ if not ok:
199
+ return {"ok": False, "err": err}
200
+ rows = out.split("\n") if out else []
201
+ receipt = {
202
+ "schema": "holorepo.db-read-receipt.v1",
203
+ "backend": (config or load_config(env=env)).get("database", {}).get("transport", "direct-psql"),
204
+ "db": db,
205
+ "connection": redact_db_summary(db, config=config, env=env),
206
+ "query_digest": _sha256(sql),
207
+ "result_digest": _sha256(out),
208
+ "row_count": len(rows),
209
+ "read_only": True,
210
+ }
211
+ return {"ok": True, "out": out, "rows": len(rows), "receipt": receipt}
212
+
213
+
214
+ def query_ks(term: str, domain: str | None = None, limit: int = 10, config: dict | None = None, env: dict | None = None) -> dict:
215
+ config = load_config(env=env) if config is None else config
216
+ ks = config.get("knowledgeStore", {})
217
+ ok, out, err = _run_psql(ks.get("database", "knowledge"), build_ks_query(term, domain, limit, ks.get("table", "memory_entries")), config=config, env=env)
218
+ if not ok:
219
+ return {"ok": False, "err": err}
220
+ rows = []
221
+ for line in filter(None, out.split("\n")):
222
+ parts = line.split("|")
223
+ if len(parts) >= 5:
224
+ rows.append({"id": parts[0], "domain": parts[1], "type": parts[2], "confidence": parts[3], "snippet": parts[4]})
225
+ return {"ok": True, "term": sanitize_term(term), "rows": rows}
@@ -0,0 +1,58 @@
1
+ """holorepo-py CLI."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import sys
6
+
7
+ from . import default_config, load_config, query_ks, read_db
8
+
9
+ HELP = """holorepo-py - Python companion for HoloRepo
10
+
11
+ holorepo-py config print resolved config
12
+ holorepo-py db read <db> "<sql>" guest read (SELECT/meta only) + receipt
13
+ holorepo-py ks query "<text>" [limit] configured HoloScript KS read
14
+
15
+ Config: holorepo.config.json + env. No host, IP, or container is assumed.
16
+ """
17
+
18
+
19
+ def main(argv=None) -> int:
20
+ argv = list(sys.argv[1:] if argv is None else argv)
21
+ if not argv or argv[0] in ("-h", "--help"):
22
+ print(HELP)
23
+ return 0
24
+ group = argv[0]
25
+ if group == "config":
26
+ print(json.dumps(load_config(), indent=2))
27
+ return 0
28
+ if group == "sample":
29
+ print(json.dumps(default_config(), indent=2))
30
+ return 0
31
+ if group == "db" and len(argv) >= 4 and argv[1] == "read":
32
+ result = read_db(argv[2], argv[3])
33
+ if result.get("refused"):
34
+ print("[holorepo-py] REFUSED: read accepts SELECT/meta only; mutations go through stage-write.", file=sys.stderr)
35
+ return 3
36
+ if not result["ok"]:
37
+ print(f"[holorepo-py] query failed: {result['err'][:200]}", file=sys.stderr)
38
+ return 1
39
+ print(f"read {argv[2]} ({result['rows']} rows) {result['receipt']['result_digest'][:24]}")
40
+ print(result["out"][:1600])
41
+ return 0
42
+ if group == "ks" and len(argv) >= 3 and argv[1] == "query":
43
+ limit = int(argv[3]) if len(argv) > 3 and argv[3].isdigit() else 10
44
+ result = query_ks(argv[2], limit=limit)
45
+ if not result["ok"]:
46
+ print(f"[holorepo-py] query failed: {result['err'][:200]}", file=sys.stderr)
47
+ return 1
48
+ print(f'"{result["term"]}" - {len(result["rows"])} hit(s)')
49
+ for row in result["rows"]:
50
+ print(f" [{row['domain']}/{row['type']}] {row['snippet']}")
51
+ print(f" {row['id']} conf={row['confidence']}")
52
+ return 0
53
+ print(HELP, file=sys.stderr)
54
+ return 2
55
+
56
+
57
+ if __name__ == "__main__":
58
+ raise SystemExit(main())
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: holoscript-holorepo
3
+ Version: 0.2.0
4
+ Summary: Python companion for HoloRepo: plug-and-play sovereign DB + HoloScript KS for agent frameworks.
5
+ Author: HoloScript ecosystem
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/brianonbased-dev/ai-ecosystem/tree/main/packages/holorepo-py
8
+ Project-URL: Source, https://github.com/brianonbased-dev/ai-ecosystem
9
+ Project-URL: Doctrine, https://github.com/brianonbased-dev/ai-ecosystem/blob/main/docs/handbooks/holorepo-operating-model.md
10
+ Keywords: holoscript,holorepo,sovereign,postgres,knowledge-store,agent-framework
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Software Development :: Version Control :: Git
15
+ Classifier: Topic :: Database
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # holoscript-holorepo
22
+
23
+ Python companion for HoloRepo: a plug-and-play sovereign GitHub + database +
24
+ HoloScript knowledge store for high-volume agent frameworks.
25
+
26
+ The Python client covers the DB/KS guest surface. It reads any Postgres reachable
27
+ by `psql`, or an explicitly configured owned node over SSH + Docker. No host, IP,
28
+ or container is assumed by default.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install holoscript-holorepo
34
+ ```
35
+
36
+ ## Config
37
+
38
+ Use `holorepo.config.json` or env:
39
+
40
+ ```bash
41
+ export HOLOREPO_DATABASE_URL="postgres://user@host:5432/app"
42
+ export PGPASSWORD="..."
43
+ ```
44
+
45
+ For an owned node over SSH, use the `jetsonExample` profile as an example and
46
+ set `HOLOREPO_SSH`, `HOLOREPO_SSH_KEY`, and `HOLOREPO_POSTGRES_CONTAINER`.
47
+
48
+ ## Use
49
+
50
+ ```bash
51
+ holorepo-py db read knowledge "select count(*) from memory_entries"
52
+ holorepo-py ks query "storage lanes" 8
53
+ ```
54
+
55
+ ```python
56
+ from holoscript_holorepo import query_ks, read_db
57
+
58
+ hits = query_ks("sovereign backbone", limit=5)["rows"]
59
+ ```
60
+
61
+ Reads refuse mutations. Writes are staged by the npm client as
62
+ `holorepo.storage-proof.v1` and admitted by the configured operator route.
63
+
64
+ ## Release Boundary
65
+
66
+ `holoscript-holorepo` is distributed under the MIT license. The compatibility
67
+ label is still `v0-preview`: the Python companion supports config/env-driven
68
+ DB/KS reads for agent frameworks, while write admission remains in the npm
69
+ client and HoloGate/HoloKey operator lane.
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ holoscript_holorepo/__init__.py
5
+ holoscript_holorepo/cli.py
6
+ holoscript_holorepo.egg-info/PKG-INFO
7
+ holoscript_holorepo.egg-info/SOURCES.txt
8
+ holoscript_holorepo.egg-info/dependency_links.txt
9
+ holoscript_holorepo.egg-info/entry_points.txt
10
+ holoscript_holorepo.egg-info/top_level.txt
11
+ tests/test_holorepo.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ holorepo-py = holoscript_holorepo.cli:main
@@ -0,0 +1 @@
1
+ holoscript_holorepo
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "holoscript-holorepo"
7
+ version = "0.2.0"
8
+ description = "Python companion for HoloRepo: plug-and-play sovereign DB + HoloScript KS for agent frameworks."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ keywords = ["holoscript", "holorepo", "sovereign", "postgres", "knowledge-store", "agent-framework"]
14
+ authors = [{ name = "HoloScript ecosystem" }]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Programming Language :: Python :: 3",
18
+ "Operating System :: OS Independent",
19
+ "Topic :: Software Development :: Version Control :: Git",
20
+ "Topic :: Database",
21
+ ]
22
+ dependencies = []
23
+
24
+ [project.scripts]
25
+ holorepo-py = "holoscript_holorepo.cli:main"
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/brianonbased-dev/ai-ecosystem/tree/main/packages/holorepo-py"
29
+ Source = "https://github.com/brianonbased-dev/ai-ecosystem"
30
+ Doctrine = "https://github.com/brianonbased-dev/ai-ecosystem/blob/main/docs/handbooks/holorepo-operating-model.md"
31
+
32
+ [tool.holorepo]
33
+ release_lane = "v0-preview"
34
+ npm_companion = "@holoscript/holorepo"
35
+ auth_boundary = "Config/env-driven Postgres or explicit owned-node SSH. Reads + stages proofs; never write authority."
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,66 @@
1
+ """Pure-function guards for holoscript-holorepo."""
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
6
+
7
+ from holoscript_holorepo import (
8
+ build_ks_query,
9
+ default_config,
10
+ is_read_only_sql,
11
+ load_config,
12
+ redact_connection_string,
13
+ redact_db_summary,
14
+ safe_table,
15
+ sanitize_term,
16
+ )
17
+
18
+
19
+ def test_default_config_has_no_private_node_assumption():
20
+ cfg = default_config()
21
+ operational = str({k: cfg[k] for k in ("storage", "git", "database", "knowledgeStore")})
22
+ assert "192.168.0.119" not in operational
23
+ assert "holo-app-pg" not in operational
24
+ assert "JETSON" not in operational
25
+ assert "Example only" in str(cfg["profiles"]["jetsonExample"])
26
+
27
+
28
+ def test_env_load_uses_database_url_without_jetson_aliases():
29
+ cfg = load_config(env={"HOLOREPO_DATABASE_URL": "postgres://u:p@example.test/db"})
30
+ assert cfg["database"]["transport"] == "direct-psql"
31
+ assert cfg["database"]["connectionEnv"] == "HOLOREPO_DATABASE_URL"
32
+
33
+
34
+ def test_read_only_guard():
35
+ for ok in ("select 1", "WITH x as (select 1) select * from x", "explain select 1", "\\dt"):
36
+ assert is_read_only_sql(ok), ok
37
+ for no in ("insert into t values (1)", "update t set a=1", "drop table t", "truncate t",
38
+ "copy t from stdin", "select 1; drop table t", ""):
39
+ assert not is_read_only_sql(no), no
40
+
41
+
42
+ def test_redacted_summary_has_no_credentials():
43
+ redacted = redact_connection_string("postgres://alice:secret@example.test/knowledge")
44
+ assert "secret" not in redacted
45
+ summary = redact_db_summary("knowledge", env={"HOLOREPO_DATABASE_URL": "postgres://alice:secret@example.test/knowledge"})
46
+ assert "secret" not in summary
47
+ assert "knowledge" in summary
48
+
49
+
50
+ def test_ks_query_sanitizes_injection():
51
+ assert "'" not in sanitize_term("a' or '1'='1")
52
+ assert all(c not in sanitize_term("50%_off\\x") for c in "%_\\")
53
+ assert len(sanitize_term("x" * 300)) <= 120
54
+ benign = build_ks_query("x").count("'")
55
+ evil = build_ks_query("'; drop table memory_entries; --").count("'")
56
+ assert evil == benign, "a quote-injection term adds zero quotes"
57
+ assert "limit 50" in build_ks_query("x", limit=9999)
58
+ assert "domain = 'identity'" in build_ks_query("a", domain="identity")
59
+ assert safe_table("memory_entries") == "memory_entries"
60
+
61
+
62
+ if __name__ == "__main__":
63
+ for name, fn in list(globals().items()):
64
+ if name.startswith("test_"):
65
+ fn()
66
+ print("PASS holoscript-holorepo: config + read-only + KS guards")