substratum-cli 0.2.3__tar.gz → 0.2.4__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.
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/PKG-INFO +1 -1
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/__init__.py +1 -1
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/_vendor/client_gate.py +6 -2
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/apply.py +2 -2
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/failing.py +2 -1
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/pr.py +1 -1
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/gitio.py +10 -3
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/session.py +4 -3
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli.egg-info/PKG-INFO +1 -1
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/README.md +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/pyproject.toml +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/setup.cfg +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/README.md +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/__main__.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/_boot.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/_update.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/_vendor/__init__.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/_vendor/_pro_test_derive.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/_wordmark.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/account.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/build_state.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/cli.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/codes.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/__init__.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/auth.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/commit.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/explain.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/fix.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/history.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/init_cmd.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/replay.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/scaffold.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/show.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/undo.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/verify.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/commands/write.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/config.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/diffs.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/engine.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/langscan.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/product_ops.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/refusals.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/remote.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/render.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/result.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/run_store.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/runid.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli/style.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli.egg-info/SOURCES.txt +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli.egg-info/dependency_links.txt +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli.egg-info/entry_points.txt +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli.egg-info/requires.txt +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/substratum_cli.egg-info/top_level.txt +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_adaptive_prior.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_alias_warrant_trace.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_bidirectional_gate_contracts.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_coherence_evolution.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_coherences.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_connection_web_api.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_cross_entity_scoping.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_data.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_de28_negation_refuse.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_definite_description_handler.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_demo_regression_catalog.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_demo_response_shape.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_e1_e2_field_alignment.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_extraction_class_write_time.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_falsification_predictions.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_gap_d_wh_normalization.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_inference.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_inflection_cvc_rule.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_inflection_irregular.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_intervention.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_invariant.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_legal_citation_handler.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_lens_noop_seam.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_markup_tag_handler.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_nl_parser.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_nl_parser_adversarial.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_noise.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_pass2_contextual.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_perspectives.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_polysemous_token_alias_guard.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_possessive_normalization.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_predicate_canon.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_projection_gate.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_projection_gate_tag_question.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_query_normalizer.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_records_answer_format.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_referent_aboutness_gate.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_referent_quality_gate.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_refuse_message_topic_neutrality.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_relation_detection.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_relaxation.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_residual_content_gate.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_reverse_lookup_subject_filter.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_sec_statement_aliases.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_span_lens.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_span_lens_query_integration.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_substrate.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_synonymy_detector.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_table_ingest.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_triple_ingest.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_two_phase_schema.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_user_asserted_aliases.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_v2_api.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_v2_api_claims.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_v2_claim_determinism.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_word_role.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_word_role_wiring.py +0 -0
- {substratum_cli-0.2.3 → substratum_cli-0.2.4}/tests/test_xbrl_doc_aliases.py +0 -0
|
@@ -5,4 +5,4 @@ Import budget: this package is stdlib-only; the ONLY module reaching into backen
|
|
|
5
5
|
"""
|
|
6
6
|
# SINGLE SOURCE OF TRUTH for the release version. pyproject reads this (dynamic version), the boot shows
|
|
7
7
|
# it, and the update-check compares against it. To cut a release, bump ONLY this line, then publish.
|
|
8
|
-
__version__ = "0.2.
|
|
8
|
+
__version__ = "0.2.4"
|
|
@@ -51,8 +51,11 @@ def _run(cmd: Sequence[str], cwd: str, timeout: int) -> Tuple[Optional[int], str
|
|
|
51
51
|
# SHADOWED by the stale pyc (timestamp validation is second-granular), and the
|
|
52
52
|
# with-patch run silently re-imports the buggy module -- the differential then
|
|
53
53
|
# reports TEST_FAILED for a genuine fix (or worse directions on other shapes).
|
|
54
|
+
# errors="replace": test output is arbitrary user bytes (a test may print binary or a
|
|
55
|
+
# non-UTF-8 traceback); strict decode would raise UnicodeDecodeError and crash the gate.
|
|
56
|
+
# The verdict is the return code, never the decoded text, so replacement is verdict-neutral.
|
|
54
57
|
r = subprocess.run(list(cmd), cwd=cwd, capture_output=True, text=True,
|
|
55
|
-
timeout=timeout,
|
|
58
|
+
errors="replace", timeout=timeout,
|
|
56
59
|
env=dict(os.environ, PYTHONHASHSEED="0", TMPDIR="/tmp",
|
|
57
60
|
PYTHONDONTWRITEBYTECODE="1"))
|
|
58
61
|
return r.returncode, (r.stdout + "\n" + r.stderr)[-4000:]
|
|
@@ -122,7 +125,8 @@ def run_client_gate(repo_dir: str, base_commit: str, edits: Dict[str, str],
|
|
|
122
125
|
wt = tempfile.mkdtemp(prefix="cg_wt_", dir=os.environ.get("TMPDIR") or None)
|
|
123
126
|
try:
|
|
124
127
|
r = subprocess.run(["git", "-C", repo_dir, "worktree", "add", "--detach", "-f",
|
|
125
|
-
wt, base_commit], capture_output=True, text=True,
|
|
128
|
+
wt, base_commit], capture_output=True, text=True,
|
|
129
|
+
errors="replace", timeout=120)
|
|
126
130
|
if r.returncode != 0:
|
|
127
131
|
return ClientGateResult(False, "GATE_WORKTREE_FAILED", r.stderr[-300:])
|
|
128
132
|
cmd = resolve_test_command(wt, test_cmd, test_paths)
|
|
@@ -35,10 +35,10 @@ def cmd_apply(repo: str, run_id: str) -> "_result.SubstratumResult":
|
|
|
35
35
|
patch = fh.name
|
|
36
36
|
try:
|
|
37
37
|
r = subprocess.run(["git", "-C", repo, "apply", "--index", patch],
|
|
38
|
-
capture_output=True, text=True)
|
|
38
|
+
capture_output=True, text=True, errors="replace")
|
|
39
39
|
if r.returncode != 0:
|
|
40
40
|
r2 = subprocess.run(["git", "-C", repo, "apply", "--3way", patch],
|
|
41
|
-
capture_output=True, text=True)
|
|
41
|
+
capture_output=True, text=True, errors="replace")
|
|
42
42
|
if r2.returncode != 0:
|
|
43
43
|
return _result.make(codes.REFUSED, run_id, "apply", code=codes.APPLY_STATE_DRIFT,
|
|
44
44
|
refusal=refusals.build(codes.APPLY_STATE_DRIFT,
|
|
@@ -117,7 +117,8 @@ def cmd_failing(repo: str, path: Optional[str] = None, test_command: Optional[st
|
|
|
117
117
|
if path:
|
|
118
118
|
run_argv.append(path)
|
|
119
119
|
try:
|
|
120
|
-
r = subprocess.run(run_argv, cwd=repo, capture_output=True, text=True,
|
|
120
|
+
r = subprocess.run(run_argv, cwd=repo, capture_output=True, text=True,
|
|
121
|
+
errors="replace", timeout=timeout,
|
|
121
122
|
env={**os.environ, "TMPDIR": "/tmp", "CI": "1", "NO_COLOR": "1"})
|
|
122
123
|
except subprocess.TimeoutExpired:
|
|
123
124
|
return _refuse(rid, codes.GATE_PRECONDITION, f"the test suite did not finish within {timeout}s")
|
|
@@ -66,7 +66,7 @@ def cmd_pr(repo: str, run_id: str = None, title: str = None) -> "_result.Substra
|
|
|
66
66
|
if gh:
|
|
67
67
|
title = title or f"Substratum verified: {res.operation} {target}"[:100]
|
|
68
68
|
r = subprocess.run([gh, "pr", "create", "--title", title, "--body", body],
|
|
69
|
-
cwd=repo, capture_output=True, text=True, timeout=60)
|
|
69
|
+
cwd=repo, capture_output=True, text=True, errors="replace", timeout=60)
|
|
70
70
|
if r.returncode == 0:
|
|
71
71
|
return _result.make(codes.PASS, run_id, "pr",
|
|
72
72
|
data={"url": r.stdout.strip(), "branch": branch, "certified": run_id})
|
|
@@ -7,8 +7,13 @@ from typing import List, Optional
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def _git(repo: str, *args: str, timeout: int = 60) -> subprocess.CompletedProcess:
|
|
10
|
+
# errors="replace": git output carries arbitrary working-tree bytes (a `diff` of a large file
|
|
11
|
+
# git treats as text but that holds a non-UTF-8 byte; a non-ASCII untracked filename). Strict
|
|
12
|
+
# decode would raise UnicodeDecodeError -- this runs on EVERY command via the run-id dirty-hash,
|
|
13
|
+
# so a single binary-ish file in the user's tree would crash the whole CLI. Replacement is
|
|
14
|
+
# deterministic (same bytes -> same text -> same hash), so the run-id story is preserved.
|
|
10
15
|
return subprocess.run(["git", "-C", repo, *args], capture_output=True, text=True,
|
|
11
|
-
timeout=timeout)
|
|
16
|
+
errors="replace", timeout=timeout)
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
def is_git_repo(repo: str) -> bool:
|
|
@@ -23,11 +28,13 @@ def apply_reverse(repo: str, diff_text: str) -> tuple[bool, str]:
|
|
|
23
28
|
if not diff_text.strip():
|
|
24
29
|
return False, "empty diff"
|
|
25
30
|
r = subprocess.run(["git", "-C", repo, "apply", "--reverse", "--3way", "-"],
|
|
26
|
-
input=diff_text, capture_output=True, text=True,
|
|
31
|
+
input=diff_text, capture_output=True, text=True,
|
|
32
|
+
errors="replace", timeout=60)
|
|
27
33
|
if r.returncode == 0:
|
|
28
34
|
return True, "reverted"
|
|
29
35
|
r2 = subprocess.run(["git", "-C", repo, "apply", "--reverse", "-"],
|
|
30
|
-
input=diff_text, capture_output=True, text=True,
|
|
36
|
+
input=diff_text, capture_output=True, text=True,
|
|
37
|
+
errors="replace", timeout=60)
|
|
31
38
|
if r2.returncode == 0:
|
|
32
39
|
return True, "reverted"
|
|
33
40
|
err = (r.stderr or r2.stderr or "").strip().splitlines()
|
|
@@ -592,7 +592,7 @@ class Session:
|
|
|
592
592
|
head("MEMORY & PROOF")
|
|
593
593
|
row("runs", "all you have done, and which refusals became fixes")
|
|
594
594
|
row("show <run>", "see a run; replay <run> re-runs it byte-identical")
|
|
595
|
-
row("history", "
|
|
595
|
+
row("history", "the whole build trail; history <word> searches; run <n> replays a line")
|
|
596
596
|
head("SETUP")
|
|
597
597
|
row("doctor / init", "check the environment / what this repo can gate")
|
|
598
598
|
row("login", "connect the hosted engine for fix and write")
|
|
@@ -638,8 +638,9 @@ class Session:
|
|
|
638
638
|
sys.stdout.write("\n")
|
|
639
639
|
self._say(" cancelled (session still warm)", _CYAN)
|
|
640
640
|
continue
|
|
641
|
-
except Exception as e: # a
|
|
642
|
-
self._say(f" error: {e}", _CYAN)
|
|
641
|
+
except Exception as e: # belt: the ops refuse, never raise -- but a fault must not kill the session
|
|
642
|
+
self._say(f" unexpected internal error: {e}", _CYAN)
|
|
643
|
+
self._say(" the session is still warm; retry or try a different request", _DIM)
|
|
643
644
|
continue
|
|
644
645
|
if not keep:
|
|
645
646
|
_leave()
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|