sbxloop 0.7.0__tar.gz → 0.7.2__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.
- {sbxloop-0.7.0 → sbxloop-0.7.2}/PKG-INFO +1 -1
- sbxloop-0.7.0/src/sbxloop/_vendor/sbxloop_worker-0.7.0-py3-none-any.whl → sbxloop-0.7.2/src/sbxloop/_vendor/sbxloop_worker-0.7.2-py3-none-any.whl +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/_version.py +2 -2
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/cli/app.py +2 -2
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/plan.md +8 -1
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/verifylint.py +23 -1
- {sbxloop-0.7.0 → sbxloop-0.7.2}/.gitignore +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/README.md +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/hatch_build.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/pyproject.toml +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/cli/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/cli/doctor.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/cli/models.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/cli/tui.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/config.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/backlog.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/control.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/discord.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/discord_format.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/github.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/loop.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/model.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/paths.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/sources.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/daemon/store.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/deliver.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/engine.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/model.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/phases.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/decompose.md +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/execute.md +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/scrutinize.md +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/steer.md +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/prompts/validate.md +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/engine/store.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/errors.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/events.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/gc.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/gh/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/gh/ops.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/gh/reporter.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/hostgit.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/ids.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/policy.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/py.typed +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/bake.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/cli.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/conformance.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/models.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/pair.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/parse.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/provision.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/prune.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/sandbox.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/sbx/secretstate.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/toolchains.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/worker/__init__.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/worker/client.py +0 -0
- {sbxloop-0.7.0 → sbxloop-0.7.2}/src/sbxloop/worker/wheel.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sbxloop
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Agentic loop orchestration on Docker Sandboxes (sbx) with isolated credential domains
|
|
5
5
|
Project-URL: Homepage, https://github.com/brettbergin/sbxloop
|
|
6
6
|
Project-URL: Repository, https://github.com/brettbergin/sbxloop
|
|
Binary file
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.7.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 7,
|
|
21
|
+
__version__ = version = '0.7.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 7, 2)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -2003,8 +2003,8 @@ mem_abort = 0.0
|
|
|
2003
2003
|
# open a per-run tracking issue. For a design/discussion tracker set both
|
|
2004
2004
|
# false: the source issue gets the summary + delivered_label and stays open
|
|
2005
2005
|
# until a human merges the PR, and no extra tracking issue is opened.
|
|
2006
|
-
# close_on_success = true
|
|
2007
|
-
# tracking_issue = true
|
|
2006
|
+
# close_on_success = true # false leaves the issue open for a human to close on merge
|
|
2007
|
+
# tracking_issue = true # false skips the per-run tracking issue
|
|
2008
2008
|
# max_runs_per_day = 12 # rolling 24h window, persisted across restarts
|
|
2009
2009
|
# max_attempts_per_item = 2
|
|
2010
2010
|
# max_resumes_per_item = 2 # interrupted runs resumed at most this often per item
|
|
@@ -105,7 +105,14 @@ literal text (a grep for an escape code never matches, and nothing says
|
|
|
105
105
|
why), while `[[ ]]`, `source`, `declare`/`local`, `pushd`/`popd` fail as
|
|
106
106
|
unknown commands and here-strings are a syntax error. Write portable shell:
|
|
107
107
|
`[ ]` not `[[ ]]`, `printf` for escape sequences, pipes instead of
|
|
108
|
-
here-strings, `.` instead of `source`. Bashisms are rejected mechanically.
|
|
108
|
+
here-strings, `.` instead of `source`. Bashisms are rejected mechanically.
|
|
109
|
+
Never wrap a check in its own `sh -c "..."` / `bash -c` — each command is
|
|
110
|
+
already run that way, and any dollar expansion (`$$?`, an awk field) inside
|
|
111
|
+
the wrapper's double quotes is consumed by the outer shell before the inner
|
|
112
|
+
one ever sees it — a wrapped `git status | awk` field-print guard printed
|
|
113
|
+
whole lines and failed every revision of a correct change. Write the
|
|
114
|
+
pipeline directly. And
|
|
115
|
+
prefer to verify *behavior* through the project's test
|
|
109
116
|
runner rather than shell pipelines: asserting on bytes, escape sequences,
|
|
110
117
|
exact whitespace, or exit codes is trivial and exact inside a test file
|
|
111
118
|
(`assert "\x1b[31m" in captured.out`) and fragile as a `grep`/`od`
|
|
@@ -177,6 +177,14 @@ def _strip_quoted(command: str, *, keep_ansi_c: bool = False) -> str:
|
|
|
177
177
|
return "".join(out)
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
# `sh -c "..."` / `bash -c '...'` at command position: a shell inside the
|
|
181
|
+
# shell the runner already provides. Matched on the raw command so quoting
|
|
182
|
+
# does not hide it.
|
|
183
|
+
_NESTED_SHELL = re.compile(
|
|
184
|
+
r"(?:^|[|&;(]\s*)(?:/bin/|/usr/bin/)?(?:sh|bash|dash|zsh)\s+-[a-zA-Z]*c\b"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
180
188
|
def bashisms(command: str) -> list[str]:
|
|
181
189
|
"""Portable-shell violations in one verify command (empty = clean)."""
|
|
182
190
|
problems: list[str] = []
|
|
@@ -191,12 +199,26 @@ def bashisms(command: str) -> list[str]:
|
|
|
191
199
|
for token, what, rewrite in _BASHISM_OPERATORS[1:]:
|
|
192
200
|
if token in unquoted:
|
|
193
201
|
problems.append(f"uses {what} — verify commands run under `sh -c`; {rewrite}")
|
|
194
|
-
|
|
202
|
+
heads = command_heads(command)
|
|
203
|
+
for head in heads:
|
|
195
204
|
if head in _BASHISM_COMMANDS:
|
|
196
205
|
what, rewrite = _BASHISM_COMMANDS[head]
|
|
197
206
|
problems.append(
|
|
198
207
|
f"invokes {what}, which fails as an unknown command under `sh -c`; {rewrite}"
|
|
199
208
|
)
|
|
209
|
+
if _NESTED_SHELL.search(command):
|
|
210
|
+
# Field failure r7ef26eht (first sbxloop-on-sbxloop run): the plan
|
|
211
|
+
# wrapped a pipeline as `sh -c "... awk '{print $2}' ..."`. The
|
|
212
|
+
# runner already executes each verify command under `sh -c`, so the
|
|
213
|
+
# OUTER shell expanded the double-quoted `$2` to nothing, awk printed
|
|
214
|
+
# whole lines, the allowlist grep matched none of them, and a correct
|
|
215
|
+
# change failed verification three revisions and a replan in a row.
|
|
216
|
+
problems.append(
|
|
217
|
+
"wraps the check in a nested `sh -c`/`bash -c` string — verify commands "
|
|
218
|
+
"already run under `sh -c`, and `$` expansions inside the wrapper's double "
|
|
219
|
+
"quotes are consumed by the outer shell; write the pipeline directly, "
|
|
220
|
+
"unwrapped"
|
|
221
|
+
)
|
|
200
222
|
return problems
|
|
201
223
|
|
|
202
224
|
|
|
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
|