unvibecode 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. shipreadyv2/SOURCE_MANIFEST.json +27 -0
  2. shipreadyv2/__init__.py +3 -0
  3. shipreadyv2/__main__.py +5 -0
  4. shipreadyv2/cli.py +204 -0
  5. shipreadyv2/credentials.py +178 -0
  6. shipreadyv2/customer_runner.py +2457 -0
  7. shipreadyv2/engine_sources/00a_shipreadyv2_fast_lane_v11_api_context_bundle.py +5862 -0
  8. shipreadyv2/engine_sources/01_shipreadyv2_merged_graph_pipeline_5chunks.py +4703 -0
  9. shipreadyv2/engine_sources/02_shipreadyv2_prepare_pass1_inputs.py +996 -0
  10. shipreadyv2/engine_sources/03_shipreadyv2_pass1_full_runner.py +1666 -0
  11. shipreadyv2/engine_sources/04_shipreadyv2_business_path_compiler.py +3444 -0
  12. shipreadyv2/engine_sources/05_shipreadyv2_critical_business_insight_selector_v4.py +1756 -0
  13. shipreadyv2/engine_sources/06_shipreadyv2_step4_v2_with_v4_inputs.py +2155 -0
  14. shipreadyv2/engine_sources/__init__.py +2 -0
  15. shipreadyv2/engine_sources/agent_knowledge_graph.db +0 -0
  16. shipreadyv2/engine_sources/archetype_taxonomy.yaml +2127 -0
  17. shipreadyv2/engine_sources/archetype_taxonomy_pass1_compact.yaml +1922 -0
  18. shipreadyv2/engine_sources/build_pass1_compact_taxonomy.py +330 -0
  19. shipreadyv2/engine_sources/generate_combinedjson.py +184 -0
  20. shipreadyv2/engine_sources/normalized_business_path.schema.json +840 -0
  21. shipreadyv2/engine_sources/shipready_business_insight_implementation_plan_v2.md +1006 -0
  22. shipreadyv2/engine_sources/universal_insight_rules.yaml +875 -0
  23. unvibecode-0.3.0.dist-info/METADATA +133 -0
  24. unvibecode-0.3.0.dist-info/RECORD +27 -0
  25. unvibecode-0.3.0.dist-info/WHEEL +5 -0
  26. unvibecode-0.3.0.dist-info/entry_points.txt +2 -0
  27. unvibecode-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,27 @@
1
+ {
2
+ "schema_version": "shipreadyv2.exact_source_manifest.v2",
3
+ "package_version": "0.3.0",
4
+ "engine_baseline_version": "0.2.1",
5
+ "engine_changes_from_baseline": [],
6
+ "hash_mode": "LF-normalized SHA-256 for text; raw SHA-256 for binary",
7
+ "customer_runner_source": "shipreadyv2_customer_mvp_runner_v9.py",
8
+ "engine_source": "shipreadyv2_fresh_source.zip plus universal_insight_rules.yaml",
9
+ "source_files": {
10
+ "customer_runner.py": "6a0593de05be1a460c0375a431331fb115d6426c507a185a087c801a78055c1d",
11
+ "engine_sources/00a_shipreadyv2_fast_lane_v11_api_context_bundle.py": "1eac10db5403bb470929da4b52eaafb88dbce6b5919492016754e227680e7c3e",
12
+ "engine_sources/01_shipreadyv2_merged_graph_pipeline_5chunks.py": "697f7dda0a65a582939bae75b16d601342fd547adeda1a209778f60903a494a2",
13
+ "engine_sources/02_shipreadyv2_prepare_pass1_inputs.py": "cb5bb27a6d923341e55b2b121e128bcce66edf04937cc3b18e31d5f3989fe891",
14
+ "engine_sources/03_shipreadyv2_pass1_full_runner.py": "40e5a0afd70e55110c1784f5e29332a910fad3b03fe3030492633277ff93caba",
15
+ "engine_sources/04_shipreadyv2_business_path_compiler.py": "7ed142e07cb37b1f90084837b7cb45f63f2718826f121b834c5e1a5a57ffab94",
16
+ "engine_sources/05_shipreadyv2_critical_business_insight_selector_v4.py": "e770c8cd21a06a7a02d8e8f9e8c6f7bedb1a5b7be96fdb6ba646e740f006a011",
17
+ "engine_sources/06_shipreadyv2_step4_v2_with_v4_inputs.py": "6dbc77b72e0066f9fcfb7e5d92026bb6b54b77a8eed687a94971c4d9ab6160c2",
18
+ "engine_sources/agent_knowledge_graph.db": "db362f684eb4d9e43827400f4e11f1dfd7cbfffa5fd481c105cd9d3f14d9f8b2",
19
+ "engine_sources/archetype_taxonomy.yaml": "55e98bdace2af1a1dbe6a73315e651383f9f2ca265a3ad5ca262dbd8acbf1f5f",
20
+ "engine_sources/archetype_taxonomy_pass1_compact.yaml": "93452175b35bd74bc9043766324c8442607e920a70548115c32a0b09a33673e3",
21
+ "engine_sources/build_pass1_compact_taxonomy.py": "5d8692214509c80dddeb2e2eee0d6f80f172d8150b9640db27dbeb07dec69769",
22
+ "engine_sources/generate_combinedjson.py": "1c2ffbb4ec9d40b9b4304abc2848943a69424d3087125993733a1b57064f5267",
23
+ "engine_sources/normalized_business_path.schema.json": "5d408b2cce353ab6ef4b37a0686330ff5610c6d7aaf4bc37fdf9b0aa1fc665cd",
24
+ "engine_sources/shipready_business_insight_implementation_plan_v2.md": "210cc34f9a28c7e4acc4ba39a164f8d78ce5c97b99fb9f9beff308db2bda7eac",
25
+ "engine_sources/universal_insight_rules.yaml": "4aa10f8c581100190c24365fa4188862c49738403db36c6c298ba15c54067ab7"
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ """ShipReadyV2 customer package."""
2
+
3
+ __version__ = "0.3.0"
@@ -0,0 +1,5 @@
1
+ from .cli import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())
shipreadyv2/cli.py ADDED
@@ -0,0 +1,204 @@
1
+ """Customer-facing command adapter for the preserved ShipReadyV2 workflow."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import contextlib
7
+ import getpass
8
+ import os
9
+ import shutil
10
+ import tempfile
11
+ from pathlib import Path
12
+ from typing import Iterator, Optional, Sequence
13
+
14
+ from . import __version__
15
+ from . import customer_runner
16
+ from . import credentials
17
+
18
+
19
+ def bundled_engine_root() -> Path:
20
+ """Return the installed directory containing the preserved engine files."""
21
+ return Path(__file__).resolve().parent / "engine_sources"
22
+
23
+
24
+ def default_runs_root() -> Path:
25
+ """Keep customer runs outside the installed Python package."""
26
+ return Path.cwd() / "shipready_results"
27
+
28
+
29
+ @contextlib.contextmanager
30
+ def prepared_runtime_engine(access_key: str) -> Iterator[Path]:
31
+ """Provide the preserved scripts with a private hosted-service environment.
32
+
33
+ Steps 03 and 06 require an engine-root .env file before they read the
34
+ SDK credential. The value supplied here is a ShipReady customer credential,
35
+ and OPENAI_BASE_URL directs the unmodified OpenAI SDK calls to ShipReady's
36
+ hosted gateway. The customer never supplies an OpenAI API key.
37
+
38
+ Installed package directories may be read-only, so the adapter copies the
39
+ preserved engine into a private temporary directory for the duration of the
40
+ review. The directory and its temporary .env file are removed afterward.
41
+ """
42
+ access_key = credentials.normalize_access_key(access_key)
43
+ if "\r" in access_key or "\n" in access_key:
44
+ raise customer_runner.CustomerRunError(
45
+ "The ShipReady access key contains an invalid line break"
46
+ )
47
+
48
+ hosted_environment = {
49
+ "OPENAI_API_KEY": access_key,
50
+ "OPENAI_BASE_URL": credentials.api_base_url(),
51
+ }
52
+ previous_environment = {
53
+ name: os.environ.get(name)
54
+ for name in hosted_environment
55
+ }
56
+
57
+ with tempfile.TemporaryDirectory(prefix="shipreadyv2-engine-") as temporary:
58
+ runtime_root = Path(temporary) / "engine"
59
+ shutil.copytree(
60
+ bundled_engine_root(),
61
+ runtime_root,
62
+ ignore=shutil.ignore_patterns("__pycache__", "*.pyc"),
63
+ )
64
+ (runtime_root / ".env").write_text(
65
+ (
66
+ f"OPENAI_API_KEY={access_key}\n"
67
+ f"OPENAI_BASE_URL={credentials.api_base_url()}\n"
68
+ ),
69
+ encoding="utf-8",
70
+ )
71
+ try:
72
+ os.environ.update(hosted_environment)
73
+ yield runtime_root
74
+ finally:
75
+ for name, previous_value in previous_environment.items():
76
+ if previous_value is None:
77
+ os.environ.pop(name, None)
78
+ else:
79
+ os.environ[name] = previous_value
80
+
81
+
82
+ def build_parser() -> argparse.ArgumentParser:
83
+ parser = argparse.ArgumentParser(
84
+ prog="shipready",
85
+ description=(
86
+ "Prepare a Connected Code Map for LLMs and, when repository size "
87
+ "permits, a Business Workflow & Risk Review."
88
+ ),
89
+ )
90
+ parser.add_argument(
91
+ "--version",
92
+ action="version",
93
+ version=f"%(prog)s {__version__}",
94
+ )
95
+ subparsers = parser.add_subparsers(dest="command", required=True)
96
+
97
+ subparsers.add_parser(
98
+ "activate",
99
+ help="Securely activate ShipReady on this computer",
100
+ )
101
+ subparsers.add_parser(
102
+ "deactivate",
103
+ help="Remove the stored ShipReady access key",
104
+ )
105
+
106
+ review = subparsers.add_parser("review", help="Review a source repository")
107
+ review.add_argument("--repository", required=True)
108
+ review.add_argument(
109
+ "--runs-root",
110
+ default=str(default_runs_root()),
111
+ help=(
112
+ "Folder for repository-review runs "
113
+ "(default: ./shipready_results)"
114
+ ),
115
+ )
116
+ review.add_argument(
117
+ "--large-repo-token-limit",
118
+ type=int,
119
+ default=customer_runner.DEFAULT_LARGE_REPOSITORY_TOKEN_LIMIT,
120
+ help=(
121
+ "Prepare only the Connected Code Map above this approximate token "
122
+ "count (default: 2000000)"
123
+ ),
124
+ )
125
+ review.add_argument(
126
+ "--no-open-browser",
127
+ action="store_true",
128
+ help="Create customer HTML reports without opening browser tabs",
129
+ )
130
+ return parser
131
+
132
+
133
+ def main(argv: Optional[Sequence[str]] = None) -> int:
134
+ parser = build_parser()
135
+ args = parser.parse_args(argv)
136
+
137
+ if args.command == "activate":
138
+ try:
139
+ access_key = credentials.normalize_access_key(
140
+ getpass.getpass("Paste your ShipReady access key: ")
141
+ )
142
+ verification = credentials.verify_access_key(access_key)
143
+ if not verification.valid:
144
+ print(f"[STOPPED] {verification.message}")
145
+ return 2
146
+ credentials.store_access_key(access_key)
147
+ except (credentials.CredentialError, KeyboardInterrupt, EOFError) as exc:
148
+ message = str(exc) or "Activation was cancelled."
149
+ print(f"[STOPPED] {message}")
150
+ return 2
151
+ print("ShipReady access is ready on this computer.")
152
+ return 0
153
+
154
+ if args.command == "deactivate":
155
+ try:
156
+ removed = credentials.delete_access_key()
157
+ except credentials.CredentialError as exc:
158
+ print(f"[STOPPED] {exc}")
159
+ return 2
160
+ if removed:
161
+ print("ShipReady access was removed from this computer.")
162
+ else:
163
+ print("ShipReady was not activated on this computer.")
164
+ return 0
165
+
166
+ if args.command != "review":
167
+ parser.error("A supported command is required")
168
+ if args.large_repo_token_limit <= 0:
169
+ parser.error("--large-repo-token-limit must be greater than zero")
170
+
171
+ try:
172
+ access_key = credentials.load_access_key()
173
+ if not access_key:
174
+ raise credentials.CredentialError(
175
+ "ShipReady is not activated. Run: shipready activate"
176
+ )
177
+ except credentials.CredentialError as exc:
178
+ print(f"[STOPPED] {exc}")
179
+ return 2
180
+
181
+ try:
182
+ with prepared_runtime_engine(access_key) as engine_root:
183
+ runner_args = [
184
+ "start",
185
+ "--repository",
186
+ str(Path(args.repository).expanduser()),
187
+ "--engine-root",
188
+ str(engine_root),
189
+ "--runs-root",
190
+ str(Path(args.runs_root).expanduser()),
191
+ "--large-repo-token-limit",
192
+ str(args.large_repo_token_limit),
193
+ ]
194
+ if args.no_open_browser:
195
+ runner_args.append("--no-open-browser")
196
+
197
+ return customer_runner.main(runner_args)
198
+ except customer_runner.CustomerRunError as exc:
199
+ print(f"[STOPPED] {exc}")
200
+ return 2
201
+
202
+
203
+ if __name__ == "__main__":
204
+ raise SystemExit(main())
@@ -0,0 +1,178 @@
1
+ """ShipReady hosted-service credential storage and verification."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import urllib.error
8
+ import urllib.request
9
+ from dataclasses import dataclass
10
+ from typing import Optional
11
+
12
+
13
+ DEFAULT_API_BASE_URL = "https://shipready-api.alphashots.ai/v1"
14
+ KEYRING_SERVICE = "ShipReady"
15
+ KEYRING_USERNAME = "customer-access-key"
16
+
17
+
18
+ class CredentialError(RuntimeError):
19
+ """Raised when a ShipReady access credential cannot be used safely."""
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class VerificationResult:
24
+ valid: bool
25
+ message: str
26
+
27
+
28
+ def api_base_url() -> str:
29
+ """Return the fixed production URL, with a test-only environment override."""
30
+
31
+ value = (
32
+ os.getenv("SHIPREADY_API_BASE_URL")
33
+ or DEFAULT_API_BASE_URL
34
+ ).strip().rstrip("/")
35
+ if not value.startswith("https://"):
36
+ raise CredentialError("The ShipReady service URL must use HTTPS.")
37
+ return value
38
+
39
+
40
+ def normalize_access_key(value: str) -> str:
41
+ """Validate a customer key without exposing it in an error."""
42
+
43
+ key = value.strip().strip("\"'").strip()
44
+ if not key:
45
+ raise CredentialError("A ShipReady access key is required.")
46
+ if "\r" in key or "\n" in key or any(character.isspace() for character in key):
47
+ raise CredentialError("The ShipReady access key contains invalid whitespace.")
48
+ try:
49
+ key.encode("ascii")
50
+ except UnicodeEncodeError as exc:
51
+ raise CredentialError(
52
+ "The ShipReady access key contains an invalid character."
53
+ ) from exc
54
+ if len(key) < 24:
55
+ raise CredentialError("The ShipReady access key is not valid.")
56
+ return key
57
+
58
+
59
+ def _keyring_module():
60
+ try:
61
+ import keyring # type: ignore
62
+ except ImportError as exc:
63
+ raise CredentialError(
64
+ "Secure credential storage is unavailable. Reinstall ShipReady."
65
+ ) from exc
66
+ return keyring
67
+
68
+
69
+ def store_access_key(value: str) -> None:
70
+ """Store the key in the operating system credential manager."""
71
+
72
+ key = normalize_access_key(value)
73
+ try:
74
+ _keyring_module().set_password(KEYRING_SERVICE, KEYRING_USERNAME, key)
75
+ except Exception as exc:
76
+ raise CredentialError(
77
+ "The operating system credential manager could not store the "
78
+ "ShipReady access key."
79
+ ) from exc
80
+
81
+
82
+ def delete_access_key() -> bool:
83
+ """Delete the stored key, returning False when no stored key exists."""
84
+
85
+ keyring = _keyring_module()
86
+ try:
87
+ existing = keyring.get_password(KEYRING_SERVICE, KEYRING_USERNAME)
88
+ if not existing:
89
+ return False
90
+ keyring.delete_password(KEYRING_SERVICE, KEYRING_USERNAME)
91
+ except Exception as exc:
92
+ raise CredentialError(
93
+ "The operating system credential manager could not remove the "
94
+ "ShipReady access key."
95
+ ) from exc
96
+ return True
97
+
98
+
99
+ def load_access_key() -> Optional[str]:
100
+ """Prefer an automation environment variable, then secure local storage."""
101
+
102
+ environment_key = (os.getenv("SHIPREADY_ACCESS_KEY") or "").strip()
103
+ if environment_key:
104
+ return normalize_access_key(environment_key)
105
+
106
+ try:
107
+ stored = _keyring_module().get_password(
108
+ KEYRING_SERVICE,
109
+ KEYRING_USERNAME,
110
+ )
111
+ except CredentialError:
112
+ raise
113
+ except Exception as exc:
114
+ raise CredentialError(
115
+ "The operating system credential manager could not read the "
116
+ "ShipReady access key."
117
+ ) from exc
118
+ if not stored:
119
+ return None
120
+ return normalize_access_key(stored)
121
+
122
+
123
+ def verify_access_key(value: str, timeout_seconds: float = 20.0) -> VerificationResult:
124
+ """Verify authentication without sending repository code or invoking a model.
125
+
126
+ The gateway authenticates before validating the request body. Therefore an
127
+ empty JSON request returns 400 for a valid key and 401/403 for an invalid key.
128
+ """
129
+
130
+ key = normalize_access_key(value)
131
+ request = urllib.request.Request(
132
+ f"{api_base_url()}/responses",
133
+ data=b"{}",
134
+ headers={
135
+ "Authorization": f"Bearer {key}",
136
+ "Content-Type": "application/json",
137
+ "User-Agent": "ShipReady-Activation/0.3",
138
+ },
139
+ method="POST",
140
+ )
141
+
142
+ try:
143
+ with urllib.request.urlopen(request, timeout=timeout_seconds) as response:
144
+ status = int(response.status)
145
+ except urllib.error.HTTPError as exc:
146
+ status = int(exc.code)
147
+ try:
148
+ payload = json.loads(exc.read().decode("utf-8", errors="replace"))
149
+ except Exception:
150
+ payload = {}
151
+ if status in {401, 403}:
152
+ message = (
153
+ payload.get("error", {}).get("message")
154
+ if isinstance(payload, dict)
155
+ else None
156
+ )
157
+ return VerificationResult(
158
+ False,
159
+ str(message or "The ShipReady access key was rejected."),
160
+ )
161
+ if status == 400:
162
+ return VerificationResult(True, "ShipReady access verified.")
163
+ return VerificationResult(
164
+ False,
165
+ f"The ShipReady service returned HTTP {status}.",
166
+ )
167
+ except (urllib.error.URLError, TimeoutError) as exc:
168
+ raise CredentialError(
169
+ "The ShipReady service could not be reached. Check the internet "
170
+ "connection and try again."
171
+ ) from exc
172
+
173
+ if 200 <= status < 300:
174
+ return VerificationResult(True, "ShipReady access verified.")
175
+ return VerificationResult(
176
+ False,
177
+ f"The ShipReady service returned HTTP {status}.",
178
+ )