shell-next 0.1.0__tar.gz → 0.1.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.
- shell_next-0.1.2/.github/workflows/docs.yml +54 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/.gitignore +2 -1
- shell_next-0.1.2/AGENTS.md +321 -0
- shell_next-0.1.2/CHANGELOG.md +41 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/PKG-INFO +30 -3
- {shell_next-0.1.0 → shell_next-0.1.2}/README.md +26 -2
- shell_next-0.1.2/docs/assets/stylesheets/brand.css +105 -0
- shell_next-0.1.2/docs/backends.md +59 -0
- shell_next-0.1.2/docs/development/documentation.md +42 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/docs/development/release.md +5 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/docs/development/specification.md +39 -4
- shell_next-0.1.2/docs/getting-started.md +66 -0
- shell_next-0.1.2/docs/index.md +55 -0
- shell_next-0.1.2/docs/testing.md +67 -0
- shell_next-0.1.2/docs/troubleshooting.md +55 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/docs/usage.md +89 -1
- shell_next-0.1.2/mkdocs.yml +42 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/pyproject.toml +63 -61
- shell_next-0.1.2/scripts/docs/validate.py +77 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/client.py +1 -1
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/github.py +1 -1
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/publish.py +7 -1
- shell_next-0.1.2/shell-next-logo.png +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/mock/scenario.py +132 -131
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/execution.py +200 -199
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/handle.py +243 -228
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/session.py +327 -313
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/capabilities.py +75 -74
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/commands.py +49 -48
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/config.py +175 -174
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/input.py +92 -91
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/privilege.py +81 -80
- shell_next-0.1.2/src/shell_next/models/representation.py +71 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/results.py +194 -167
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_state_integration.py +4 -1
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/contracts/test_execution.py +14 -6
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/contracts/test_queue_cancellation.py +2 -0
- shell_next-0.1.2/tests/docs/test_validation.py +50 -0
- shell_next-0.1.2/tests/frontend/test_representation.py +32 -0
- shell_next-0.1.2/tests/frontend/test_result_content.py +39 -0
- shell_next-0.1.2/tests/models/test_representation.py +134 -0
- shell_next-0.1.2/tests/models/test_results.py +37 -0
- shell_next-0.1.2/wiki/Backend-Support.md +22 -0
- shell_next-0.1.2/wiki/Command-Lifecycle.md +23 -0
- shell_next-0.1.2/wiki/Getting-Started.md +37 -0
- shell_next-0.1.2/wiki/Home.md +24 -0
- shell_next-0.1.2/wiki/README.md +20 -0
- shell_next-0.1.2/wiki/Testing-with-Mocks.md +34 -0
- shell_next-0.1.2/wiki/Troubleshooting.md +16 -0
- shell_next-0.1.2/wiki/_Footer.md +4 -0
- shell_next-0.1.2/wiki/_Sidebar.md +10 -0
- shell_next-0.1.0/CHANGELOG.md +0 -18
- {shell_next-0.1.0 → shell_next-0.1.2}/.gitattributes +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/.github/workflows/ci.yml +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/.github/workflows/publish.yml +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/LICENSE +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2/docs/assets}/shell-next-logo.png +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/docs/development/architecture.md +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/quality/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/quality/check_source.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/quality/rhel8.sh +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/check_wheel.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/verify.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/scripts/release/wheel_probe.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/shell-next Development Specification.md +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/bash/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/bash/authentication.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/bash/containment.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/bash/password_channel.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/bash/syntax.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/cmd/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/cmd/syntax.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/mock/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/mock/driver.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/mock/session.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/mock/state.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/bridge.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/channels.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/containment.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/driver.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/preparation.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/process.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/syntax.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/native/termination.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/powershell/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/powershell/driver.ps1 +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/powershell/syntax.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/protocol.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/windows/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/windows/containment.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/backends/windows/limits.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/errors.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/capture.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/finalization.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/lease.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/observation.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/operations.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/frontend/output.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/models/state.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/src/shell_next/py.typed +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/bash/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/bash/test_authentication.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/bash/test_password_channel.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/bash/test_sudo_integration.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/mock/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/mock/test_input_edges.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/mock/test_privilege.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/mock/test_session.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/mock/test_state.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/mock/test_virtual_observation.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_bridge.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_channels.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_interrupt_integration.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_platform_containment.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_process_failures.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_resources_integration.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_stdin_integration.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_syntax.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/backends/native/test_termination.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/conftest.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/contracts/test_lifecycle.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/test_capture.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/test_capture_failures.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/test_failures.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/test_lease_races.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/test_observation_edges.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/frontend/test_operations.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/models/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/models/test_values.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/support/__init__.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/support/native.py +0 -0
- {shell_next-0.1.0 → shell_next-0.1.2}/tests/support/sessions.py +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: documentation
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
paths:
|
|
6
|
+
- 'docs/**'
|
|
7
|
+
- 'wiki/**'
|
|
8
|
+
- 'scripts/docs/**'
|
|
9
|
+
- 'shell-next-logo.png'
|
|
10
|
+
- 'mkdocs.yml'
|
|
11
|
+
- 'pyproject.toml'
|
|
12
|
+
- '.github/workflows/docs.yml'
|
|
13
|
+
pull_request:
|
|
14
|
+
paths:
|
|
15
|
+
- 'docs/**'
|
|
16
|
+
- 'wiki/**'
|
|
17
|
+
- 'scripts/docs/**'
|
|
18
|
+
- 'shell-next-logo.png'
|
|
19
|
+
- 'mkdocs.yml'
|
|
20
|
+
- 'pyproject.toml'
|
|
21
|
+
- '.github/workflows/docs.yml'
|
|
22
|
+
workflow_dispatch:
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
concurrency:
|
|
26
|
+
group: documentation-${{ github.ref }}
|
|
27
|
+
cancel-in-progress: true
|
|
28
|
+
jobs:
|
|
29
|
+
build:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: '3.14'
|
|
36
|
+
- run: python -m pip install ".[docs]"
|
|
37
|
+
- run: python -m mkdocs build --strict
|
|
38
|
+
- run: python -m scripts.docs.validate
|
|
39
|
+
- uses: actions/upload-pages-artifact@v3
|
|
40
|
+
with:
|
|
41
|
+
path: site
|
|
42
|
+
deploy:
|
|
43
|
+
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
|
44
|
+
needs: build
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
permissions:
|
|
47
|
+
pages: write
|
|
48
|
+
id-token: write
|
|
49
|
+
environment:
|
|
50
|
+
name: github-pages
|
|
51
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/deploy-pages@v4
|
|
54
|
+
id: deployment
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# shell-next engineering requirements
|
|
2
|
+
|
|
3
|
+
## Verified project mappings and adoption status
|
|
4
|
+
|
|
5
|
+
- Distribution: `shell-next`; import: `shell_next`; source: `src/shell_next`.
|
|
6
|
+
- Python: 3.14+; Windows (PowerShell 7 and cmd) and Linux Bash, with RHEL 8
|
|
7
|
+
as the reference Linux platform. License: MIT, recorded in `LICENSE`.
|
|
8
|
+
- Runtime dependencies: Python standard library only. Development/build tools
|
|
9
|
+
are in the `dev` extra and MkDocs is in the `docs` extra in `pyproject.toml`.
|
|
10
|
+
- Version source: `pyproject.toml`; there is no runtime `__version__` copy.
|
|
11
|
+
Published tags use `v<version>`. Default branch: `main`; feature branches:
|
|
12
|
+
`codex/<description>` or `codex/<issue-number>-<description>`.
|
|
13
|
+
- GitHub repository: https://github.com/gokurakujoudo/shell-next, remote `origin`.
|
|
14
|
+
Preserve the established `release/<version>` branches (currently
|
|
15
|
+
`release/0.1.1`), rather than introducing a branch named `release`.
|
|
16
|
+
- Contracts: `docs/development/specification.md`; architecture:
|
|
17
|
+
`docs/development/architecture.md`; guides: `docs/usage.md` and
|
|
18
|
+
`docs/getting-started.md`; implemented inventory: `docs/index.md` and
|
|
19
|
+
`README.md`; change record: `CHANGELOG.md`. The root development
|
|
20
|
+
specification and `wiki/` are earlier reference/draft material; canonical
|
|
21
|
+
published documentation is in `docs/`.
|
|
22
|
+
- Production dependencies flow from backends and frontend to models. Preserve
|
|
23
|
+
the shared lifecycle used by native and mock sessions. Original command
|
|
24
|
+
objects are trusted input, not a hostile-code sandbox. Authentication secrets
|
|
25
|
+
and secret stdin payloads must stay out of results and call history.
|
|
26
|
+
- Tests mirror responsibilities under `tests/`; shared fixtures are in
|
|
27
|
+
`tests/support/`. Mock scenarios remain deterministic and free of real
|
|
28
|
+
subprocesses, filesystem writes, network calls, and sleeps. Keep native
|
|
29
|
+
Bash/sudo/Windows differences explicit.
|
|
30
|
+
|
|
31
|
+
The authoritative complete quality gate is `.github/workflows/ci.yml`:
|
|
32
|
+
Ruff check/format, strict mypy, `python scripts/quality/check_source.py`,
|
|
33
|
+
platform behavioral contracts, installed-wheel probes, combined 100% branch
|
|
34
|
+
coverage across Windows/Linux/RHEL 8, builds, and Twine checks. Per-platform
|
|
35
|
+
coverage collection uses a zero threshold only for combination; acceptance
|
|
36
|
+
still requires the combined 100% gate. Genuine platform skips are reported.
|
|
37
|
+
|
|
38
|
+
Use `venv/Scripts/python.exe` in this Windows checkout, or the selected Python
|
|
39
|
+
3.14+ environment elsewhere. Local handoff runs `git diff --check`,
|
|
40
|
+
`python -m ruff check .`, `python -m ruff format --check .`,
|
|
41
|
+
`python scripts/quality/check_source.py`, `python -m mypy`, documentation
|
|
42
|
+
checks, then `python -m pytest --cov --cov-branch --cov-report=xml`.
|
|
43
|
+
Report any platform-only coverage shortfall; local Windows evidence cannot
|
|
44
|
+
substitute for the combined hosted gate. Installed-wheel/build checks use
|
|
45
|
+
`python -m scripts.release.check_wheel`, `python -m build`, and
|
|
46
|
+
`python -m twine check dist/*`.
|
|
47
|
+
|
|
48
|
+
Documentation checks are `python -m pytest tests/docs`,
|
|
49
|
+
`python -m mkdocs build --strict`, and `python -m scripts.docs.validate`.
|
|
50
|
+
`.github/workflows/docs.yml` builds PR documentation and deploys Pages from
|
|
51
|
+
`main`. It generates `site/` from canonical Markdown; generated files stay ignored.
|
|
52
|
+
|
|
53
|
+
Adoption gaps: `scripts/quality/__init__.py` is empty and no local
|
|
54
|
+
`python -m scripts.quality` entry point exists. A consolidated local entry point,
|
|
55
|
+
automated architecture/capability inventory checks, complete constant/exception
|
|
56
|
+
policy enforcement, and executable marking of legacy examples remain required
|
|
57
|
+
but unimplemented. Existing source-policy checks enforce line counts, names,
|
|
58
|
+
and parameter/return docstrings. Newly marked `python-doc-exec` examples are
|
|
59
|
+
executed by the documentation tests; do not claim legacy examples are covered.
|
|
60
|
+
This policy adoption does not authorize an unrelated mass refactor or release.
|
|
61
|
+
|
|
62
|
+
## Established publication profile and explicit exceptions
|
|
63
|
+
|
|
64
|
+
Preserve `docs/development/release.md`: prepare versions through a PR to `main`,
|
|
65
|
+
squash merge after verification, then create `release/<version>` at that exact
|
|
66
|
+
merged commit. Do not introduce release-only commits or overwrite published tags.
|
|
67
|
+
Use compatibility-aware PEP 440 versions and `v<version>` tags. The dated,
|
|
68
|
+
nonempty release-note requirement below applies to future releases; existing
|
|
69
|
+
undated changelog sections are historical adoption gaps.
|
|
70
|
+
|
|
71
|
+
The requested default publication target is PyPI and matching GitHub Releases.
|
|
72
|
+
`.github/workflows/publish.yml` is manually dispatched and verifies exact-commit
|
|
73
|
+
quality evidence before building and using Trusted Publishing in environment
|
|
74
|
+
`pypi`. It does not currently create the matching GitHub Release. The existing
|
|
75
|
+
explicit alternative, `python -m scripts.release.publish`, uses configured
|
|
76
|
+
local Twine credentials and stages matching GitHub artifacts after the same
|
|
77
|
+
quality evidence. Preserve this authorized local-release option. Automatic
|
|
78
|
+
release-branch triggering and CI creation of matching GitHub Releases remain
|
|
79
|
+
adoption gaps, not completed capabilities. No publication is part of a feature
|
|
80
|
+
request unless the user requests it.
|
|
81
|
+
|
|
82
|
+
## Scope, project facts, and sources of truth
|
|
83
|
+
|
|
84
|
+
These requirements govern engineering quality and delivery. Keep the project's
|
|
85
|
+
business purpose, domain model, public behavior, and specialized architecture
|
|
86
|
+
in their existing sections. Read AGENTS.md, README.md, pyproject.toml, the
|
|
87
|
+
feature/status inventory if present, and relevant reference/development
|
|
88
|
+
documentation before changing code.
|
|
89
|
+
|
|
90
|
+
Record the actual distribution/import names, production source root, supported
|
|
91
|
+
Python versions and platforms, license, dependency policy, version source,
|
|
92
|
+
default branch, release branch, quality command, and documentation entry points.
|
|
93
|
+
Use pyproject.toml for packaging/tool metadata. Resolve license and compatibility
|
|
94
|
+
decisions from the project's choices; do not assume a license, Python minimum,
|
|
95
|
+
fixed version series, or release destination.
|
|
96
|
+
|
|
97
|
+
Reference documentation owns public contracts; executable guides own workflows;
|
|
98
|
+
tests own behavioral evidence; the feature inventory and README describe
|
|
99
|
+
implemented capability. The changelog records user-visible changes. Requirements
|
|
100
|
+
are not evidence of compliance: identify missing enforcement or documentation
|
|
101
|
+
without claiming that it already exists.
|
|
102
|
+
|
|
103
|
+
## Design and public API
|
|
104
|
+
|
|
105
|
+
- Organize production code into small packages by responsibility. Dependencies
|
|
106
|
+
flow toward core types and domain logic; CLI, filesystem, network, and other
|
|
107
|
+
adapters depend on the core. Avoid cyclic imports and cross-layer shortcuts.
|
|
108
|
+
Package __init__.py files curate re-exports without behavioral initialization.
|
|
109
|
+
- Prefer the standard library and existing project mechanisms. Keep runtime
|
|
110
|
+
dependencies minimal and separate development, documentation, build, and
|
|
111
|
+
publishing dependencies. Do not introduce speculative abstractions or new
|
|
112
|
+
backends without a concrete requirement; preserve explicitly chosen native
|
|
113
|
+
integrations or dependencies.
|
|
114
|
+
- Design typed public APIs with explicit input validation, stable result/error
|
|
115
|
+
contracts, and documented compatibility. Use __all__ to curate exports and
|
|
116
|
+
ship py.typed for typed distributions. Distinguish intentional exceptions
|
|
117
|
+
from unexpected failures; preserve causes and useful context.
|
|
118
|
+
- For asynchronous I/O and resource workflows, prefer async public entry points.
|
|
119
|
+
Keep synchronous convenience boundaries explicit and prevent nested event
|
|
120
|
+
loops. Pure calculations need not become async merely for uniformity.
|
|
121
|
+
- Define resource ownership, cleanup order, cancellation behavior, and allowed
|
|
122
|
+
concurrency scope. Close caller-owned resources explicitly or through context
|
|
123
|
+
managers. Document whether objects are task-, thread-, or process-safe.
|
|
124
|
+
Specify cache consistency and recalculation/invalidation rules where caching
|
|
125
|
+
exists; do not import another project's cache semantics by default.
|
|
126
|
+
- State the actual trust boundary. Do not describe trusted configuration or
|
|
127
|
+
static capability checks as a hostile-code sandbox. Dynamic execution,
|
|
128
|
+
reflection, imports, ambient I/O, and connectivity need an explicit role in
|
|
129
|
+
the design rather than appearing accidentally through convenience helpers.
|
|
130
|
+
|
|
131
|
+
## Production source requirements
|
|
132
|
+
|
|
133
|
+
- Each production Python file has at most 200 code-bearing physical lines,
|
|
134
|
+
excluding imports, declaration/attribute docstrings, pure comments, and blank
|
|
135
|
+
lines. Multiline signatures, expressions, and runtime strings count by their
|
|
136
|
+
physical lines. Do not compress statements or embed code in strings to evade
|
|
137
|
+
the limit. Split by responsibility, not arbitrary line count.
|
|
138
|
+
- Production functions and classes use descriptive names without an underscore
|
|
139
|
+
prefix. Only required Python protocol methods use dunder spellings. Do not
|
|
140
|
+
replace meaningful names with generic internal prefixes; curate exports with
|
|
141
|
+
__all__. These declaration rules do not forbid ordinary private state fields.
|
|
142
|
+
- Every production docstring is English rST. Functions and methods, including
|
|
143
|
+
nested helpers, explain how they work, every parameter with :param name:,
|
|
144
|
+
returned values with :returns: unless returning no value, and intentional
|
|
145
|
+
escaping exceptions with :raises Type:. Value classes document constructor
|
|
146
|
+
fields and edge cases. Use notes for useful special behavior, not repetition.
|
|
147
|
+
- Document every named constant and coherent constant group, including enums:
|
|
148
|
+
units or absence of units, actual source, purpose, and choice rationale.
|
|
149
|
+
Never invent external sources or annotate every ordinary control-flow literal.
|
|
150
|
+
- These size, naming, docstring, and constant requirements apply to production
|
|
151
|
+
source. Tests and scripts still pass Ruff and strict mypy. Existing explicit
|
|
152
|
+
project exceptions must be recorded rather than silently broadened.
|
|
153
|
+
|
|
154
|
+
## Behavioral tests and isolation
|
|
155
|
+
|
|
156
|
+
- Mirror production subsystem responsibilities in tests. A test file may cover
|
|
157
|
+
several related implementation modules; each behavior has one obvious owner.
|
|
158
|
+
Keep integration contracts explicit and reusable fixtures in support modules
|
|
159
|
+
when actually shared. Do not require one test file per source file.
|
|
160
|
+
- Assert public behavior, observable state, and meaningful diagnostics rather
|
|
161
|
+
than private method calls or a second implementation of the same algorithm.
|
|
162
|
+
Cover sunny, rainy, boundary, and composite cases where applicable.
|
|
163
|
+
- Unit tests mock external connectivity, clocks, randomness, and other
|
|
164
|
+
nondeterminism as needed. Isolate file I/O and enabled logs in a separate
|
|
165
|
+
TemporaryDirectory per test. CLI test configuration sources are static
|
|
166
|
+
fixtures declared with their cases. No test should depend on a live account.
|
|
167
|
+
- Include deterministic stress, concurrency, cancellation, and lifecycle/leak
|
|
168
|
+
tests for relevant behavior in the ordinary full gate. Use property or
|
|
169
|
+
differential tests where there is a useful invariant or independent oracle.
|
|
170
|
+
Keep performance benchmarks separate from correctness acceptance.
|
|
171
|
+
- Require 100% production branch coverage, with no threshold reductions,
|
|
172
|
+
exclusions, ignores, weakened assertions, or invented skips merely to pass.
|
|
173
|
+
Report genuine platform/dependency skips explicitly and cover supported
|
|
174
|
+
platforms in the appropriate environment. Use strict test markers/config.
|
|
175
|
+
- If filesystem or temporary-directory permissions block a tool or test, stop
|
|
176
|
+
that operation and obtain the required permission. Do not relocate temporary
|
|
177
|
+
files, change temporary environment variables, weaken isolation, skip checks,
|
|
178
|
+
or change paths solely to bypass the restriction. Continue independent work.
|
|
179
|
+
|
|
180
|
+
## Change workflow and quality gate
|
|
181
|
+
|
|
182
|
+
- For a bug: update the relevant English contract; add a behavioral regression
|
|
183
|
+
test and prove the intended failure; implement the smallest correct fix;
|
|
184
|
+
prove the test passes; refactor if needed and run focused/full checks.
|
|
185
|
+
- For a feature: prototypes may precede the settled contract, but acceptance
|
|
186
|
+
requires reference documentation and behavioral tests. Update README,
|
|
187
|
+
changelog, and the feature inventory when public claims change.
|
|
188
|
+
- For a refactor: pass existing tests first, change production code, pass the
|
|
189
|
+
same tests, then reorganize test ownership and verify again.
|
|
190
|
+
- Use one authoritative, reproducible quality entry point, preferably
|
|
191
|
+
python -m scripts.quality if no project equivalent exists. Define its concrete
|
|
192
|
+
command and environment in this file; identify it as required but unimplemented
|
|
193
|
+
if it does not exist yet.
|
|
194
|
+
- The gate fails fast through whitespace validation, Ruff, production-policy
|
|
195
|
+
checks, architecture/capability checks, strict mypy over source/tests/scripts,
|
|
196
|
+
documentation checks without coverage, and full behavioral tests with branch
|
|
197
|
+
coverage, including stress tests. Keep all checks in the same environment.
|
|
198
|
+
- Run affected checks during editing. Each completed code-refactor stage and
|
|
199
|
+
final code handoff runs the full gate. Re-run after new changes, failures, or
|
|
200
|
+
unresolved concerns; do not repeat unchanged successful suites without cause.
|
|
201
|
+
- Pure prose needs relevant structure and link checks. Execute the exact source
|
|
202
|
+
of changed examples. Structural documentation changes run the documentation
|
|
203
|
+
suite once without coverage; avoid chapter/series/full-gate duplication.
|
|
204
|
+
- Produce useful JUnit and machine-readable/browsable coverage reports when
|
|
205
|
+
supported. Keep generated reports ignored. Record actual commands, results,
|
|
206
|
+
skips, and tested revisions; never equate configured checks with passing ones.
|
|
207
|
+
|
|
208
|
+
## Documentation and tutorials
|
|
209
|
+
|
|
210
|
+
- Keep public documentation in English with reference contracts, practical
|
|
211
|
+
guides, an accessible README, and a concise implemented-feature inventory.
|
|
212
|
+
Explain behavior and limitations; never present plans as implemented features.
|
|
213
|
+
- Each tutorial series has a useful standalone introduction and one ordered
|
|
214
|
+
table of contents. Link every published chapter; do not list planned chapters
|
|
215
|
+
as available or duplicate the inventory in other documentation entry points.
|
|
216
|
+
Use stable ordered topic filenames, such as NN-topic-name.md.
|
|
217
|
+
- Mark every complete copyable Python example with a project-specific execution
|
|
218
|
+
marker, using `<!-- python-doc-exec -->` when no marker exists. Documentation
|
|
219
|
+
tests extract and execute that exact Markdown source, not a copied equivalent.
|
|
220
|
+
- Teach the smallest useful operation first, add one concept at a time, and end
|
|
221
|
+
with a realistic composition. Put observable results in inline assertions
|
|
222
|
+
where practical. Explain why each result follows, what resolves or executes,
|
|
223
|
+
and who owns state; do not duplicate assertions in expected-result sections.
|
|
224
|
+
- Examples are deterministic and independent. Mock connectivity, isolate file
|
|
225
|
+
examples in TemporaryDirectory, and close async/resource scopes explicitly.
|
|
226
|
+
Examples must not use production credentials or persistent external effects.
|
|
227
|
+
- Test chapter discovery against the single table of contents and published
|
|
228
|
+
files. Update navigation and changelog when adding, renaming, reordering, or
|
|
229
|
+
retiring chapters. Do not impose word counts, slogans, one test per chapter,
|
|
230
|
+
or arbitrary exact example counts.
|
|
231
|
+
- Check relative links and anchors, CLI/API inventories, and executable snippets.
|
|
232
|
+
If a site/export exists, generate it from canonical Markdown after checks,
|
|
233
|
+
preserve exact examples, and validate navigation/assets. Avoid a competing
|
|
234
|
+
manually maintained copy of the same documentation.
|
|
235
|
+
|
|
236
|
+
## Packaging and release integrity
|
|
237
|
+
|
|
238
|
+
- Declare build metadata, supported Python versions, license, project identity,
|
|
239
|
+
and tool settings in pyproject.toml. Keep a real license file and accurate
|
|
240
|
+
compatibility claims; do not silently change the license or support matrix.
|
|
241
|
+
- Keep one authoritative version source or verify all maintained copies agree,
|
|
242
|
+
including runtime __version__ when present. Respect established version and
|
|
243
|
+
tag conventions; for new projects use a documented PEP 440-compatible policy
|
|
244
|
+
with compatibility-aware version increments, not a fixed release series.
|
|
245
|
+
- Use isolated/reproducible build tooling appropriate to the project. Build a
|
|
246
|
+
wheel and source distribution from the verified release revision; include
|
|
247
|
+
production code, required runtime resources, typing data, packaging metadata,
|
|
248
|
+
license, and README. Keep local secrets, reports, environments, development
|
|
249
|
+
scratch files, and unrelated artifacts out of distributions.
|
|
250
|
+
- A release is a separate requested operation. Prepare a nonempty dated
|
|
251
|
+
changelog section for its version, retaining unreleased work separately.
|
|
252
|
+
Check notes and metadata before promotion. Preserve the selected source SHA
|
|
253
|
+
and artifact identity through the release; never silently replace a version's
|
|
254
|
+
published tag or distribution.
|
|
255
|
+
- Do not publish, push, merge, delete branches, or contact collaborators merely
|
|
256
|
+
because this policy was installed. Follow the authorized task scope, preserve
|
|
257
|
+
unrelated changes, and honor existing approvals without asking again.
|
|
258
|
+
|
|
259
|
+
## GitHub feature delivery
|
|
260
|
+
|
|
261
|
+
Use issue -> feature branch -> pull request -> squash merge -> branch cleanup.
|
|
262
|
+
|
|
263
|
+
1. Create or reuse an issue in the configured GitHub repository for authorized
|
|
264
|
+
feature/bug work. Record scope, public behavior, and acceptance criteria.
|
|
265
|
+
Fetch the configured remote and base a feature branch on the current default
|
|
266
|
+
branch. Prefer codex/<issue-number>-<description> unless the project uses an
|
|
267
|
+
explicit alternative.
|
|
268
|
+
2. Keep implementation, tests, and documentation together. Follow the change
|
|
269
|
+
workflow and full gate, commit, push, and open a PR against the default
|
|
270
|
+
branch. Link the issue with Closes #number. Describe the final behavior,
|
|
271
|
+
material limitations, and actual verification results.
|
|
272
|
+
3. Wait for all applicable checks on the exact latest PR head, including push
|
|
273
|
+
and PR verification/builds. Honor required reviews and branch rules. Fix
|
|
274
|
+
failures and re-check the updated head; earlier green checks do not approve
|
|
275
|
+
new commits. Intentional workflow-condition exclusions are not missing
|
|
276
|
+
checks. Keep PR metadata current.
|
|
277
|
+
4. When merging is within scope, squash merge with an expected-head-SHA guard.
|
|
278
|
+
Preserve draft/review-only requests. Confirm merge and issue closure.
|
|
279
|
+
Synchronize the local default branch and confirm the merged content.
|
|
280
|
+
5. Verify no post-review work remains on the feature branch before deleting
|
|
281
|
+
its remote and local copies. Squash merges lose feature-commit ancestry;
|
|
282
|
+
inspect merged content before a necessary forced local deletion. Finish
|
|
283
|
+
on the default branch without discarding unrelated work.
|
|
284
|
+
|
|
285
|
+
## GitHub version publication
|
|
286
|
+
|
|
287
|
+
Use version update -> verified PR -> squash merge -> release/<version> promotion
|
|
288
|
+
-> CI quality/build -> PyPI -> matching Git tag and GitHub Release.
|
|
289
|
+
|
|
290
|
+
1. On a feature or dedicated release-preparation branch, update the canonical
|
|
291
|
+
version and all maintained copies, including runtime metadata. Finalize a
|
|
292
|
+
dated changelog section. Validate notes, run the full gate, and verify the
|
|
293
|
+
latest PR's CI before squash merging.
|
|
294
|
+
2. Select the verified merged commit on `main`. Create `release/<version>` at
|
|
295
|
+
exactly that commit and push it. Never add release-only commits, force an
|
|
296
|
+
existing release branch, or publish a feature head.
|
|
297
|
+
3. Verify version notes and default-branch ancestry, then require the complete
|
|
298
|
+
exact-commit quality gate. The configured release workflow checks quality
|
|
299
|
+
evidence, builds distributions, and publishes with Trusted Publishing. Use
|
|
300
|
+
least-privilege permissions, environment `pypi`, and serialized uploads.
|
|
301
|
+
4. After PyPI succeeds, create `v<version>` and its GitHub Release at the same
|
|
302
|
+
source commit with changelog notes and the same wheel/source artifacts.
|
|
303
|
+
CI automation of this final stage remains a gap; the established authorized
|
|
304
|
+
local publishing command is the existing alternative. Never run competing
|
|
305
|
+
publication paths for the same immutable version.
|
|
306
|
+
5. Verify completion, not dispatch: latest applicable CI results, successful
|
|
307
|
+
registry publication, tag target, published Release, attached artifacts, and
|
|
308
|
+
any applicable documentation deployment. Fetch the tag and report links.
|
|
309
|
+
If PyPI succeeds and Release creation fails, retry only the failed final
|
|
310
|
+
stage; never repeat a successful immutable-version upload. After uncertain
|
|
311
|
+
publication, inspect remote state before any retry.
|
|
312
|
+
6. Keep the default and release branches. For a combined feature/release task,
|
|
313
|
+
clean up the implementation branch only after publication succeeds and
|
|
314
|
+
verification shows no unmerged work remains.
|
|
315
|
+
|
|
316
|
+
Apply this pipeline only when publication is part of the project and requested
|
|
317
|
+
task. A package deliberately not published to PyPI must state its actual release
|
|
318
|
+
destination instead. Missing credentials, environments, CI workflows, or required
|
|
319
|
+
approvals are concrete blockers to the affected stage; do not bypass branch or
|
|
320
|
+
registry controls or claim a release succeeded.
|
|
321
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
Released 2026-09-11.
|
|
6
|
+
|
|
7
|
+
- Retain the original submitted command in finalized results, including failures
|
|
8
|
+
and commands stopped before execution.
|
|
9
|
+
- Add `CommandResult.stdout_str()` and `stderr_str()` to decode retained tails
|
|
10
|
+
with configurable encoding and error handling (UTF-8 with replacement by default).
|
|
11
|
+
- Document and verify configurable stdout/stderr tail bounds through
|
|
12
|
+
`CaptureConfig.tail_bytes`, including the existing 64 KiB per-stream default.
|
|
13
|
+
- Add readable, bounded representations across public records, mock scenarios,
|
|
14
|
+
sessions, and command handles, preserving secret-field exclusions.
|
|
15
|
+
|
|
16
|
+
## 0.1.1
|
|
17
|
+
|
|
18
|
+
- Add CI, required coverage, PyPI, Python-version, and license badges to the README.
|
|
19
|
+
- Include branded, searchable documentation and review-ready wiki drafts.
|
|
20
|
+
- Deploy GitHub Pages from `main` and keep logo/edit links valid after branch cleanup.
|
|
21
|
+
- Add documentation build tooling and generated-site validation.
|
|
22
|
+
- Make release uploads independent of Windows progress-display encoding.
|
|
23
|
+
|
|
24
|
+
The package runtime API is unchanged from 0.1.0.
|
|
25
|
+
|
|
26
|
+
## 0.1.0
|
|
27
|
+
|
|
28
|
+
- Persistent Bash, PowerShell 7, and cmd sessions for Python 3.14+.
|
|
29
|
+
- Structural process arguments and native scripts with persistent shell state.
|
|
30
|
+
- Managed commands, scoped handles, FIFO queuing, independent observation deadlines,
|
|
31
|
+
and bounded interruption and cleanup.
|
|
32
|
+
- Manual and planned stdin, literal prompt matching, bounded byte capture,
|
|
33
|
+
optional durable files, and independent output subscribers.
|
|
34
|
+
- Interactive/noninteractive Bash sudo with separate authentication channels.
|
|
35
|
+
- Strict deterministic mock scenarios through `SessionConfig._session_cls`.
|
|
36
|
+
- RHEL 8, Linux, and Windows contracts, installed-wheel checks, static analysis,
|
|
37
|
+
and 100% combined branch coverage as publication gates.
|
|
38
|
+
|
|
39
|
+
Active Windows elevation, terminal emulation, and strict cleanup of privileged
|
|
40
|
+
descendants are unsupported. Forced interruption invalidates the persistent
|
|
41
|
+
session; callers create a new session explicitly.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: shell-next
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Persistent asynchronous shell sessions with deterministic test doubles
|
|
5
|
+
Project-URL: Documentation, https://gokurakujoudo.github.io/shell-next/
|
|
5
6
|
Project-URL: Repository, https://github.com/gokurakujoudo/shell-next
|
|
6
7
|
Project-URL: Issues, https://github.com/gokurakujoudo/shell-next/issues
|
|
7
8
|
Author: shell-next contributors
|
|
@@ -22,12 +23,27 @@ Requires-Dist: pytest-cov>=7; extra == 'dev'
|
|
|
22
23
|
Requires-Dist: pytest>=9; extra == 'dev'
|
|
23
24
|
Requires-Dist: ruff>=0.15; extra == 'dev'
|
|
24
25
|
Requires-Dist: twine>=6; extra == 'dev'
|
|
26
|
+
Provides-Extra: docs
|
|
27
|
+
Requires-Dist: mkdocs==1.6.1; extra == 'docs'
|
|
25
28
|
Description-Content-Type: text/markdown
|
|
26
29
|
|
|
30
|
+
<p align="center">
|
|
31
|
+
<img src="https://raw.githubusercontent.com/gokurakujoudo/shell-next/main/shell-next-logo.png" alt="shell-next logo" width="300">
|
|
32
|
+
</p>
|
|
33
|
+
|
|
27
34
|
# shell-next
|
|
28
35
|
|
|
36
|
+
[](https://github.com/gokurakujoudo/shell-next/actions/workflows/ci.yml?query=branch%3Amain)
|
|
37
|
+
[](https://github.com/gokurakujoudo/shell-next/actions/workflows/ci.yml?query=branch%3Amain)
|
|
38
|
+
[](https://pypi.org/project/shell-next/)
|
|
39
|
+
[](https://pypi.org/project/shell-next/)
|
|
40
|
+
[](https://github.com/gokurakujoudo/shell-next/blob/main/LICENSE)
|
|
41
|
+
|
|
29
42
|
Persistent asynchronous Bash, PowerShell, and cmd sessions for Python 3.14+.
|
|
30
43
|
|
|
44
|
+
[Documentation](https://gokurakujoudo.github.io/shell-next/) ·
|
|
45
|
+
[PyPI](https://pypi.org/project/shell-next/) · [Wiki drafts](wiki/README.md)
|
|
46
|
+
|
|
31
47
|
```python
|
|
32
48
|
from shell_next import Backend, ProcessCommand, SessionConfig, use_shell_session
|
|
33
49
|
|
|
@@ -36,7 +52,7 @@ async def inspect_repository(config: SessionConfig):
|
|
|
36
52
|
async with use_shell_session(config) as shell:
|
|
37
53
|
await shell.chdir("/srv/project")
|
|
38
54
|
result = await shell.run(ProcessCommand("git", ("status", "--short")), check=True)
|
|
39
|
-
return result.
|
|
55
|
+
return result.stdout_str()
|
|
40
56
|
```
|
|
41
57
|
|
|
42
58
|
Use `ProcessCommand` for executable arguments that must remain structural. Use
|
|
@@ -92,7 +108,18 @@ and output in memory. Unmatched commands and unconsumed strict expectations fail
|
|
|
92
108
|
|
|
93
109
|
## Capture and capabilities
|
|
94
110
|
|
|
95
|
-
|
|
111
|
+
Results retain the original `ProcessCommand` or `SessionScript` as `result.command`.
|
|
112
|
+
Use `result.stdout_str()` and `result.stderr_str()` for decoded tail text (UTF-8
|
|
113
|
+
with replacement by default), or access raw bytes through `result.stdout.tail`
|
|
114
|
+
and `result.stderr.tail`.
|
|
115
|
+
|
|
116
|
+
Public records have named-field reprs with readable enum names and abbreviated
|
|
117
|
+
large payloads. Sessions and command handles show current lifecycle state and
|
|
118
|
+
counts. Representations preserve hidden secret fields and do not query the shell.
|
|
119
|
+
|
|
120
|
+
Set `SessionConfig(capture=CaptureConfig(tail_bytes=4096))` to retain at most
|
|
121
|
+
4 KiB per stream; the default is 65,536 bytes (64 KiB), and zero retains no tail.
|
|
122
|
+
Each stream retains its own bounded tail, and
|
|
96
123
|
literal prompt matching uses a separate bounded window. Slow event subscribers
|
|
97
124
|
receive an overflow error without blocking primary capture. Opt into full capture
|
|
98
125
|
with `CaptureConfig(directory=existing_directory)`. Results distinguish received
|
|
@@ -1,7 +1,20 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/gokurakujoudo/shell-next/main/shell-next-logo.png" alt="shell-next logo" width="300">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# shell-next
|
|
2
6
|
|
|
7
|
+
[](https://github.com/gokurakujoudo/shell-next/actions/workflows/ci.yml?query=branch%3Amain)
|
|
8
|
+
[](https://github.com/gokurakujoudo/shell-next/actions/workflows/ci.yml?query=branch%3Amain)
|
|
9
|
+
[](https://pypi.org/project/shell-next/)
|
|
10
|
+
[](https://pypi.org/project/shell-next/)
|
|
11
|
+
[](https://github.com/gokurakujoudo/shell-next/blob/main/LICENSE)
|
|
12
|
+
|
|
3
13
|
Persistent asynchronous Bash, PowerShell, and cmd sessions for Python 3.14+.
|
|
4
14
|
|
|
15
|
+
[Documentation](https://gokurakujoudo.github.io/shell-next/) ·
|
|
16
|
+
[PyPI](https://pypi.org/project/shell-next/) · [Wiki drafts](wiki/README.md)
|
|
17
|
+
|
|
5
18
|
```python
|
|
6
19
|
from shell_next import Backend, ProcessCommand, SessionConfig, use_shell_session
|
|
7
20
|
|
|
@@ -10,7 +23,7 @@ async def inspect_repository(config: SessionConfig):
|
|
|
10
23
|
async with use_shell_session(config) as shell:
|
|
11
24
|
await shell.chdir("/srv/project")
|
|
12
25
|
result = await shell.run(ProcessCommand("git", ("status", "--short")), check=True)
|
|
13
|
-
return result.
|
|
26
|
+
return result.stdout_str()
|
|
14
27
|
```
|
|
15
28
|
|
|
16
29
|
Use `ProcessCommand` for executable arguments that must remain structural. Use
|
|
@@ -66,7 +79,18 @@ and output in memory. Unmatched commands and unconsumed strict expectations fail
|
|
|
66
79
|
|
|
67
80
|
## Capture and capabilities
|
|
68
81
|
|
|
69
|
-
|
|
82
|
+
Results retain the original `ProcessCommand` or `SessionScript` as `result.command`.
|
|
83
|
+
Use `result.stdout_str()` and `result.stderr_str()` for decoded tail text (UTF-8
|
|
84
|
+
with replacement by default), or access raw bytes through `result.stdout.tail`
|
|
85
|
+
and `result.stderr.tail`.
|
|
86
|
+
|
|
87
|
+
Public records have named-field reprs with readable enum names and abbreviated
|
|
88
|
+
large payloads. Sessions and command handles show current lifecycle state and
|
|
89
|
+
counts. Representations preserve hidden secret fields and do not query the shell.
|
|
90
|
+
|
|
91
|
+
Set `SessionConfig(capture=CaptureConfig(tail_bytes=4096))` to retain at most
|
|
92
|
+
4 KiB per stream; the default is 65,536 bytes (64 KiB), and zero retains no tail.
|
|
93
|
+
Each stream retains its own bounded tail, and
|
|
70
94
|
literal prompt matching uses a separate bounded window. Slow event subscribers
|
|
71
95
|
receive an overflow error without blocking primary capture. Opt into full capture
|
|
72
96
|
with `CaptureConfig(directory=existing_directory)`. Results distinguish received
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--shell-ink: #20303a;
|
|
3
|
+
--shell-blue: #007caa;
|
|
4
|
+
--shell-accent: #16b8ef;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.wy-side-nav-search,
|
|
8
|
+
.wy-nav-top {
|
|
9
|
+
background: var(--shell-ink);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.wy-side-nav-search > a img.logo {
|
|
13
|
+
width: 200px;
|
|
14
|
+
height: 130px;
|
|
15
|
+
max-width: 100%;
|
|
16
|
+
object-fit: cover;
|
|
17
|
+
border-radius: 12px;
|
|
18
|
+
margin: 4px auto 12px;
|
|
19
|
+
padding: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.wy-side-nav-search input[type="text"] {
|
|
23
|
+
border-color: var(--shell-accent);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.wy-nav-content {
|
|
27
|
+
max-width: 1040px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.wy-menu-vertical header,
|
|
31
|
+
.wy-menu-vertical p.caption {
|
|
32
|
+
color: var(--shell-accent);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.rst-content a {
|
|
36
|
+
color: var(--shell-blue);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.rst-content h1,
|
|
40
|
+
.rst-content h2,
|
|
41
|
+
.rst-content h3 {
|
|
42
|
+
color: var(--shell-ink);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.hero {
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: 220px 1fr;
|
|
48
|
+
align-items: center;
|
|
49
|
+
gap: 32px;
|
|
50
|
+
margin: 0 0 32px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.hero img {
|
|
54
|
+
width: 220px;
|
|
55
|
+
border-radius: 18px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.hero p {
|
|
59
|
+
font-size: 1.15rem;
|
|
60
|
+
line-height: 1.6;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.hero .version {
|
|
64
|
+
color: #52616b;
|
|
65
|
+
font-size: 0.85rem;
|
|
66
|
+
letter-spacing: 0.06em;
|
|
67
|
+
text-transform: uppercase;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.rst-content .button {
|
|
71
|
+
display: inline-block;
|
|
72
|
+
padding: 10px 16px;
|
|
73
|
+
margin: 4px 8px 4px 0;
|
|
74
|
+
border-radius: 6px;
|
|
75
|
+
color: white;
|
|
76
|
+
background: var(--shell-blue);
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.rst-content .button.secondary {
|
|
81
|
+
background: var(--shell-ink);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
a:focus-visible,
|
|
85
|
+
button:focus-visible,
|
|
86
|
+
input:focus-visible {
|
|
87
|
+
outline: 3px solid var(--shell-accent);
|
|
88
|
+
outline-offset: 3px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@media (max-width: 600px) {
|
|
92
|
+
.hero {
|
|
93
|
+
grid-template-columns: 1fr;
|
|
94
|
+
gap: 12px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.hero img {
|
|
98
|
+
width: 170px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.rst-content table.docutils {
|
|
102
|
+
display: block;
|
|
103
|
+
overflow-x: auto;
|
|
104
|
+
}
|
|
105
|
+
}
|