qwenloop 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. qwenloop-0.1.0/.githooks/commit-msg +49 -0
  2. qwenloop-0.1.0/.githooks/pre-push +69 -0
  3. qwenloop-0.1.0/.github/CODEOWNERS +1 -0
  4. qwenloop-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +23 -0
  5. qwenloop-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  6. qwenloop-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
  7. qwenloop-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  8. qwenloop-0.1.0/.github/dependabot.yml +21 -0
  9. qwenloop-0.1.0/.github/workflows/ci.yml +68 -0
  10. qwenloop-0.1.0/.github/workflows/merge-train.yml +78 -0
  11. qwenloop-0.1.0/.github/workflows/promote-to-main.yml +78 -0
  12. qwenloop-0.1.0/.github/workflows/provenance.yml +67 -0
  13. qwenloop-0.1.0/.github/workflows/release.yml +110 -0
  14. qwenloop-0.1.0/.gitignore +11 -0
  15. qwenloop-0.1.0/.vibey-gh.toml +22 -0
  16. qwenloop-0.1.0/AGENTS.md +7 -0
  17. qwenloop-0.1.0/CODE_OF_CONDUCT.md +8 -0
  18. qwenloop-0.1.0/CONTRIBUTING.md +27 -0
  19. qwenloop-0.1.0/LICENSE +22 -0
  20. qwenloop-0.1.0/PKG-INFO +111 -0
  21. qwenloop-0.1.0/README.md +76 -0
  22. qwenloop-0.1.0/SECURITY.md +17 -0
  23. qwenloop-0.1.0/deploy/docker/Dockerfile +12 -0
  24. qwenloop-0.1.0/docs/architecture/decisions/0001-local-inference.md +7 -0
  25. qwenloop-0.1.0/docs/architecture/decisions/0002-tool-security.md +7 -0
  26. qwenloop-0.1.0/docs/capability-matrix.md +9 -0
  27. qwenloop-0.1.0/pyproject.toml +75 -0
  28. qwenloop-0.1.0/scripts/evaluate_quantizations.py +172 -0
  29. qwenloop-0.1.0/src/qwenloop/__init__.py +4 -0
  30. qwenloop-0.1.0/src/qwenloop/application/__init__.py +2 -0
  31. qwenloop-0.1.0/src/qwenloop/application/backend_selection.py +28 -0
  32. qwenloop-0.1.0/src/qwenloop/application/interfaces.py +30 -0
  33. qwenloop-0.1.0/src/qwenloop/application/runner.py +115 -0
  34. qwenloop-0.1.0/src/qwenloop/cli/__init__.py +2 -0
  35. qwenloop-0.1.0/src/qwenloop/cli/app.py +343 -0
  36. qwenloop-0.1.0/src/qwenloop/domain/__init__.py +2 -0
  37. qwenloop-0.1.0/src/qwenloop/domain/config.py +37 -0
  38. qwenloop-0.1.0/src/qwenloop/domain/model.py +84 -0
  39. qwenloop-0.1.0/src/qwenloop/infrastructure/__init__.py +2 -0
  40. qwenloop-0.1.0/src/qwenloop/infrastructure/inference.py +315 -0
  41. qwenloop-0.1.0/src/qwenloop/infrastructure/model_cache.py +96 -0
  42. qwenloop-0.1.0/src/qwenloop/infrastructure/profiles.py +31 -0
  43. qwenloop-0.1.0/src/qwenloop/infrastructure/run_store.py +52 -0
  44. qwenloop-0.1.0/src/qwenloop/infrastructure/tools.py +61 -0
  45. qwenloop-0.1.0/src/qwenloop/py.typed +1 -0
  46. qwenloop-0.1.0/tests/test_cli.py +305 -0
  47. qwenloop-0.1.0/tests/test_domain.py +38 -0
  48. qwenloop-0.1.0/tests/test_inference.py +277 -0
  49. qwenloop-0.1.0/tests/test_model_cache.py +88 -0
  50. qwenloop-0.1.0/tests/test_runner.py +173 -0
  51. qwenloop-0.1.0/uv.lock +736 -0
@@ -0,0 +1,49 @@
1
+ #!/bin/sh
2
+ # Installed by `vibey-gh install` — do not edit; edit the template in vibey-gh.
3
+ #
4
+ # Appends the provenance trailer to any commit message that lacks it, so the rule holds
5
+ # locally without anyone having to remember it. CI enforces the same trailer, so a commit
6
+ # made without this hook fails the pull request rather than slipping through.
7
+
8
+
9
+ # Resolve the CLI. `vibey-gh` on PATH is the normal case, but a project virtualenv that
10
+ # has not been activated is just as normal — and a gate that reports "not installed"
11
+ # when the tool IS installed is a gate people learn to bypass. Look where it actually
12
+ # lives before giving up. Hooks run from the top of the working tree.
13
+ vibey_gh() {
14
+ if command -v vibey-gh >/dev/null 2>&1; then
15
+ vibey-gh "$@"
16
+ elif [ -n "${VIRTUAL_ENV:-}" ] && [ -x "${VIRTUAL_ENV}/bin/vibey-gh" ]; then
17
+ "${VIRTUAL_ENV}/bin/vibey-gh" "$@"
18
+ elif [ -x ".venv/bin/vibey-gh" ]; then
19
+ ./.venv/bin/vibey-gh "$@"
20
+ elif [ -x "venv/bin/vibey-gh" ]; then
21
+ ./venv/bin/vibey-gh "$@"
22
+ elif python3 -c "import vibey_gh.cli" >/dev/null 2>&1; then
23
+ python3 -m vibey_gh.cli "$@"
24
+ elif python3 -c "import vibey_bootstrap.gh.cli" >/dev/null 2>&1; then
25
+ python3 -m vibey_bootstrap.gh.cli "$@" # pre-split layout
26
+ else
27
+ return 127
28
+ fi
29
+ }
30
+
31
+
32
+ msg_file="$1"
33
+ key=$(vibey_gh trailer-key 2>/dev/null || echo "Made-With")
34
+ trailer=$(vibey_gh trailer 2>/dev/null || echo "Made-With: Vibey, the auto-vibecoding machine by Adam Matthew Steinberger")
35
+
36
+ # A pre-existing project hook runs first and may do its own thing.
37
+ [ -x "$(dirname "$0")/commit-msg.local" ] && "$(dirname "$0")/commit-msg.local" "$@"
38
+
39
+ # Already present in any case — nothing to do.
40
+ if grep -qiE "^${key}:[[:space:]]*[^[:space:]]" "$msg_file"; then
41
+ exit 0
42
+ fi
43
+
44
+ # A comment-only or empty message means an aborted commit; leave it alone.
45
+ if ! grep -qvE '^\s*(#.*)?$' "$msg_file"; then
46
+ exit 0
47
+ fi
48
+
49
+ printf '\n%s\n' "$trailer" >> "$msg_file"
@@ -0,0 +1,69 @@
1
+ #!/bin/sh
2
+ # Installed by `vibey-gh install` — do not edit; edit the template in vibey-gh.
3
+ #
4
+ # THE GATE. A repository that has adopted the vibey GitHub automation must keep it
5
+ # installed and working. If the tooling is missing, or the fingerprints it enforces are
6
+ # not intact, the push is refused — to any branch, local or remote.
7
+ #
8
+ # The point is not ceremony. Provenance that can be skipped whenever it is inconvenient
9
+ # is provenance nobody can rely on, so the check has to sit on the last action before
10
+ # code leaves the machine.
11
+ #
12
+ # Escape hatch: `git push --no-verify` still works, because a hook that cannot be
13
+ # bypassed in an emergency gets uninstalled instead. CI applies the same rule server-side,
14
+ # so skipping here only defers the failure rather than avoiding it.
15
+
16
+ set -e
17
+
18
+ red() { printf '\033[0;31m%s\033[0m\n' "$1"; }
19
+
20
+
21
+ # Resolve the CLI. `vibey-gh` on PATH is the normal case, but a project virtualenv that
22
+ # has not been activated is just as normal — and a gate that reports "not installed"
23
+ # when the tool IS installed is a gate people learn to bypass. Look where it actually
24
+ # lives before giving up. Hooks run from the top of the working tree.
25
+ vibey_gh() {
26
+ if command -v vibey-gh >/dev/null 2>&1; then
27
+ vibey-gh "$@"
28
+ elif [ -n "${VIRTUAL_ENV:-}" ] && [ -x "${VIRTUAL_ENV}/bin/vibey-gh" ]; then
29
+ "${VIRTUAL_ENV}/bin/vibey-gh" "$@"
30
+ elif [ -x ".venv/bin/vibey-gh" ]; then
31
+ ./.venv/bin/vibey-gh "$@"
32
+ elif [ -x "venv/bin/vibey-gh" ]; then
33
+ ./venv/bin/vibey-gh "$@"
34
+ elif python3 -c "import vibey_gh.cli" >/dev/null 2>&1; then
35
+ python3 -m vibey_gh.cli "$@"
36
+ elif python3 -c "import vibey_bootstrap.gh.cli" >/dev/null 2>&1; then
37
+ python3 -m vibey_bootstrap.gh.cli "$@" # pre-split layout
38
+ else
39
+ return 127
40
+ fi
41
+ }
42
+
43
+ if ! vibey_gh trailer-key >/dev/null 2>&1; then
44
+ red "✖ push refused: the vibey GitHub automation is not installed."
45
+ echo
46
+ echo " This repository requires it for provenance and release automation."
47
+ echo
48
+ echo " pip install vibey-gh"
49
+ echo " vibey-gh install"
50
+ echo
51
+ echo " Then push again. To bypass once: git push --no-verify"
52
+ exit 1
53
+ fi
54
+
55
+ if ! vibey_gh check --quiet; then
56
+ red "✖ push refused: the provenance fingerprints are not intact."
57
+ echo
58
+ echo " vibey-gh check # see what is missing"
59
+ echo " vibey-gh check --apply # add the missing file headers"
60
+ echo
61
+ echo " Commit trailers are added automatically by the commit-msg hook."
62
+ echo " To bypass once: git push --no-verify"
63
+ exit 1
64
+ fi
65
+
66
+ # Chain to a pre-existing project hook, so adopting this does not discard local checks.
67
+ if [ -x "$(dirname "$0")/pre-push.local" ]; then
68
+ "$(dirname "$0")/pre-push.local" "$@"
69
+ fi
@@ -0,0 +1 @@
1
+ * @adammatthewsteinberger
@@ -0,0 +1,23 @@
1
+ name: Bug report
2
+ description: Report reproducible qwenloop behavior.
3
+ title: "bug: "
4
+ labels: [bug]
5
+ body:
6
+ - type: textarea
7
+ attributes:
8
+ label: What happened?
9
+ description: Include the command, expected result, and actual result.
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ attributes:
14
+ label: Environment
15
+ description: OS, hardware, Python, backend, runtime version, and model profile. Never include secrets.
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ attributes:
20
+ label: Reproduction
21
+ description: Provide the smallest safe reproduction and relevant redacted events.
22
+ validations:
23
+ required: true
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Security vulnerability
4
+ url: https://github.com/adammatthewsteinberger/qwenloop/security/advisories/new
5
+ about: Report security issues privately.
@@ -0,0 +1,23 @@
1
+ name: Feature request
2
+ description: Propose a qwenloop capability or integration.
3
+ title: "feat: "
4
+ labels: [enhancement]
5
+ body:
6
+ - type: textarea
7
+ attributes:
8
+ label: Problem
9
+ description: What operator or agent problem should this solve?
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ attributes:
14
+ label: Proposed contract
15
+ description: Describe CLI, persisted-state, security-policy, and compatibility implications.
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ attributes:
20
+ label: Acceptance criteria
21
+ description: List observable, testable outcomes.
22
+ validations:
23
+ required: true
@@ -0,0 +1,15 @@
1
+ ## Summary
2
+
3
+ <!-- What changes, and why? -->
4
+
5
+ ## Verification
6
+
7
+ - [ ] Ruff and formatting pass
8
+ - [ ] Strict mypy passes
9
+ - [ ] Onion-boundary checks pass
10
+ - [ ] Tests retain 100% line and branch coverage
11
+ - [ ] No model weights, caches, credentials, or generated artifacts are committed
12
+
13
+ ## Runtime impact
14
+
15
+ <!-- Note model/backend, security-policy, run-contract, or Vibey boundary changes. -->
@@ -0,0 +1,21 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ python-dependencies:
9
+ patterns: ["*"]
10
+ - package-ecosystem: github-actions
11
+ directory: /
12
+ schedule:
13
+ interval: weekly
14
+ # vibey-gh owns the versions used by its generated workflows. Upgrade these
15
+ # through vibey-gh so Dependabot cannot make the canonical templates drift.
16
+ ignore:
17
+ - dependency-name: actions/checkout
18
+ - dependency-name: actions/setup-python
19
+ groups:
20
+ github-actions:
21
+ patterns: ["*"]
@@ -0,0 +1,68 @@
1
+ # Made with love by Vibey, the auto-vibecoding machine by Adam Matthew Steinberger.
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [main, develop]
7
+ pull_request:
8
+ branches: [main, develop]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: ci-${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ quality:
19
+ name: Quality and architecture
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v7
23
+ - uses: astral-sh/setup-uv@v7
24
+ with:
25
+ enable-cache: true
26
+ - run: uv sync --frozen --extra dev
27
+ - run: uv run ruff check .
28
+ - run: uv run ruff format --check .
29
+ - run: uv run mypy --strict src/qwenloop
30
+ - run: uv run lint-imports
31
+ - run: uv run bandit -q -r src/qwenloop
32
+
33
+ test:
34
+ name: Tests (Python ${{ matrix.python-version }})
35
+ runs-on: ubuntu-latest
36
+ strategy:
37
+ fail-fast: false
38
+ matrix:
39
+ python-version: ["3.12", "3.13", "3.14"]
40
+ steps:
41
+ - uses: actions/checkout@v7
42
+ - uses: astral-sh/setup-uv@v7
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+ enable-cache: true
46
+ - run: uv sync --frozen --extra dev
47
+ - run: uv run pytest -q
48
+
49
+ lock:
50
+ name: Lockfile is current
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - uses: actions/checkout@v7
54
+ - uses: astral-sh/setup-uv@v7
55
+ - run: uv lock --check
56
+
57
+ build:
58
+ name: Build and install distributions
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@v7
62
+ - uses: astral-sh/setup-uv@v7
63
+ - run: uv build
64
+ - run: uvx twine check --strict dist/*
65
+ - run: uv venv /tmp/qwenloop-wheel
66
+ - run: uv pip install --python /tmp/qwenloop-wheel/bin/python dist/*.whl
67
+ - run: /tmp/qwenloop-wheel/bin/qwenloop --version
68
+ - run: /tmp/qwenloop-wheel/bin/qwenloop --help
@@ -0,0 +1,78 @@
1
+ # Made with love by Vibey, the auto-vibecoding machine by Adam Matthew Steinberger.
2
+ name: Merge train
3
+
4
+ # Weekly: merge every pull request into the integration branch that is READY.
5
+ #
6
+ # Readiness is mechanical and is decided by `vibey-gh merge-train` — not a draft, no
7
+ # conflicts, checks green, no changes requested — plus the trust rule: work from the owner
8
+ # or their own bots merges on a green build, work from anyone else additionally needs an
9
+ # approving review. The logic lives in the library, where it is unit-tested, rather than
10
+ # in this file where it would not be.
11
+ #
12
+ # A pull request held ONLY on that approval is labelled `needs-human-review` and the owner
13
+ # is mentioned on it, once — because otherwise the contribution just sits there and nobody
14
+ # finds out. Repeating the mention weekly would train the owner to ignore it, so an
15
+ # existing notification is detected before another is posted. A draft or a red build gets
16
+ # neither: that is the contributor's to fix, and paging anyone about it is noise.
17
+ #
18
+ # The run also writes a markdown table to the job summary, so a week that merged nothing
19
+ # still says what it looked at.
20
+ #
21
+ # PERMISSIONS. A branch ruleset that requires an approving review cannot be satisfied by
22
+ # the default GITHUB_TOKEN, and GitHub Actions is usually not a bypass actor. Supply a
23
+ # repository secret `AUTOMERGE_TOKEN` belonging to someone with the admin role. Without
24
+ # one this job reports every pull request as blocked rather than merging anything.
25
+ #
26
+ # Use a real token rather than adding GitHub Actions to the bypass list: a push made with
27
+ # GITHUB_TOKEN does not trigger further workflows, so a release chain downstream of this
28
+ # would silently stop.
29
+
30
+ on:
31
+ schedule:
32
+ - cron: "17 7 * * 1"
33
+ workflow_dispatch:
34
+ inputs:
35
+ dry_run:
36
+ description: "Report what would be merged without merging it"
37
+ required: false
38
+ default: false
39
+ type: boolean
40
+
41
+ permissions:
42
+ contents: write
43
+ pull-requests: write
44
+
45
+ concurrency:
46
+ group: merge-train
47
+ cancel-in-progress: false
48
+
49
+ jobs:
50
+ merge:
51
+ name: Merge train
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+
56
+ - name: Set up Python
57
+ uses: actions/setup-python@v5
58
+ with:
59
+ python-version: "3.12"
60
+
61
+ - name: Install the tooling
62
+ run: |
63
+ set -euo pipefail
64
+ if grep -qE '^name = "vibey-(gh|bootstrap)"' pyproject.toml 2>/dev/null; then
65
+ python -m pip install --quiet -e .
66
+ else
67
+ python -m pip install --quiet vibey-gh
68
+ fi
69
+
70
+ - name: Merge what is ready
71
+ env:
72
+ GH_TOKEN: ${{ secrets.AUTOMERGE_TOKEN || github.token }}
73
+ run: |
74
+ set -euo pipefail
75
+ # No `tee` into the job summary: the command writes its own markdown table
76
+ # there. Piping stdout in as well would append the plain log lines too, which
77
+ # are not markdown and render as one run-on paragraph above the table.
78
+ vibey-gh merge-train ${{ inputs.dry_run && '--dry-run' || '' }}
@@ -0,0 +1,78 @@
1
+ # Made with love by Vibey, the auto-vibecoding machine by Adam Matthew Steinberger.
2
+ name: Promote
3
+
4
+ # The other half of the flow. The merge train fills the integration branch; this moves it
5
+ # to the release branch, which is what publishes.
6
+ #
7
+ # It follows the merge train's SUCCESS rather than a clock, so a week's work is promoted
8
+ # as soon as it is all in. The cron is a backstop for the weeks the train has nothing to
9
+ # merge and so never completes, and for anything that arrives by another route.
10
+ #
11
+ # The decisions live in `vibey-gh promote`, where they are unit-tested: compare the
12
+ # branches by CONTENT rather than commit count, derive the version before opening
13
+ # anything, wait for the checks, then merge. A hand-written version of this workflow gets
14
+ # at least one of those wrong.
15
+ #
16
+ # PERMISSIONS. A ruleset requiring an approving review cannot be satisfied by the default
17
+ # GITHUB_TOKEN. Supply `AUTOMERGE_TOKEN` (a token belonging to someone with the admin
18
+ # role) or the job will open the pull request and report that it could not merge it —
19
+ # which is a safe place to stop.
20
+
21
+ on:
22
+ workflow_run:
23
+ workflows: ["Merge train"]
24
+ types: [completed]
25
+ schedule:
26
+ - cron: "17 8 * * 1"
27
+ workflow_dispatch:
28
+ inputs:
29
+ dry_run:
30
+ description: "Report what would be promoted without opening or merging anything"
31
+ required: false
32
+ default: false
33
+ type: boolean
34
+
35
+ permissions:
36
+ contents: write
37
+ pull-requests: write
38
+
39
+ concurrency:
40
+ group: promote
41
+ cancel-in-progress: false
42
+
43
+ jobs:
44
+ promote:
45
+ name: Promote
46
+ # A merge train that failed leaves the integration branch in an unknown state.
47
+ if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success'
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ with:
52
+ fetch-depth: 0
53
+ # checkout's extraheader beats a remote URL, so the push of the version bump
54
+ # needs the token HERE or it authenticates as the default bot and is refused.
55
+ token: ${{ secrets.AUTOMERGE_TOKEN || github.token }}
56
+
57
+ - name: Set up Python
58
+ uses: actions/setup-python@v5
59
+ with:
60
+ python-version: "3.12"
61
+
62
+ - name: Install the tooling
63
+ run: |
64
+ set -euo pipefail
65
+ if grep -qE '^name = "vibey-(gh|bootstrap)"' pyproject.toml 2>/dev/null; then
66
+ python -m pip install --quiet -e .
67
+ else
68
+ python -m pip install --quiet vibey-gh
69
+ fi
70
+
71
+ - name: Promote
72
+ env:
73
+ GH_TOKEN: ${{ secrets.AUTOMERGE_TOKEN || github.token }}
74
+ run: |
75
+ set -euo pipefail
76
+ git config user.name "vibey[bot]"
77
+ git config user.email "adam@matthewsteinberger.com"
78
+ vibey-gh promote ${{ inputs.dry_run && '--dry-run' || '' }}
@@ -0,0 +1,67 @@
1
+ # Made with love by Vibey, the auto-vibecoding machine by Adam Matthew Steinberger.
2
+ name: Provenance
3
+
4
+ # Server-side half of the provenance rule. The pre-push hook is the fast, local half, but
5
+ # a hook lives in a clone: it can be skipped with --no-verify, and a fresh clone that
6
+ # never ran `vibey-gh install` has no hook at all. This job is what makes the rule hold
7
+ # for everyone, so make it a REQUIRED status check on every protected branch.
8
+ #
9
+ # It runs on every branch, not just pull requests, so an unfingerprinted commit is caught
10
+ # where it is pushed rather than at merge time.
11
+ #
12
+ # The job name below — "Provenance" — is the context you add to the branch ruleset.
13
+
14
+ on:
15
+ push:
16
+ branches: ["**"]
17
+ pull_request:
18
+
19
+ permissions:
20
+ contents: read
21
+
22
+ concurrency:
23
+ group: provenance-${{ github.ref }}
24
+ cancel-in-progress: true
25
+
26
+ jobs:
27
+ provenance:
28
+ name: Provenance
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ with:
33
+ # Needed to walk the commits a pull request adds.
34
+ fetch-depth: 0
35
+
36
+ - name: Set up Python
37
+ uses: actions/setup-python@v5
38
+ with:
39
+ python-version: "3.12"
40
+
41
+ # A repository that IS the tooling installs itself; everyone else takes the
42
+ # published package. Self-describing, so the same template works in both places.
43
+ - name: Install the tooling
44
+ run: |
45
+ set -euo pipefail
46
+ if grep -qE '^name = "vibey-(gh|bootstrap)"' pyproject.toml 2>/dev/null; then
47
+ echo "this repository provides the tooling — installing from source"
48
+ python -m pip install --quiet -e .
49
+ else
50
+ python -m pip install --quiet vibey-gh
51
+ fi
52
+
53
+ # --ci skips the core.hooksPath assertion, which is per-clone local git config that
54
+ # no runner can satisfy. The hook FILES are repository state and are still checked.
55
+ # The base SHA goes through env: rather than into the shell, so there is no
56
+ # injection surface even though it comes from github.event.
57
+ - name: Check provenance
58
+ env:
59
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
60
+ run: |
61
+ set -euo pipefail
62
+ if [ -n "${BASE_SHA:-}" ]; then
63
+ git fetch --quiet --depth=50 origin "${BASE_SHA}" 2>/dev/null || true
64
+ vibey-gh check --ci --commits "${BASE_SHA}..HEAD"
65
+ else
66
+ vibey-gh check --ci
67
+ fi
@@ -0,0 +1,110 @@
1
+ # Made with love by Vibey, the auto-vibecoding machine by Adam Matthew Steinberger.
2
+ name: Release
3
+
4
+ on:
5
+ push:
6
+ branches: [main, develop]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ name: Build distributions
14
+ runs-on: ubuntu-latest
15
+ outputs:
16
+ version: ${{ steps.version.outputs.version }}
17
+ steps:
18
+ - uses: actions/checkout@v7
19
+ - uses: astral-sh/setup-uv@v7
20
+ - name: Stamp development version
21
+ if: github.ref == 'refs/heads/develop'
22
+ run: |
23
+ uvx vibey-gh version --dev "${GITHUB_RUN_NUMBER}" --apply
24
+ - id: version
25
+ run: |
26
+ python - <<'PY' >> "$GITHUB_OUTPUT"
27
+ import pathlib
28
+ import tomllib
29
+ data = tomllib.loads(pathlib.Path("pyproject.toml").read_text())
30
+ print("version=" + data["project"]["version"])
31
+ PY
32
+ - run: uv build
33
+ - uses: actions/upload-artifact@v7
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+
38
+ testpypi:
39
+ name: Publish to TestPyPI
40
+ if: github.ref == 'refs/heads/develop'
41
+ needs: build
42
+ runs-on: ubuntu-latest
43
+ environment: testpypi
44
+ permissions:
45
+ id-token: write
46
+ steps:
47
+ - uses: actions/download-artifact@v8
48
+ with: {name: dist, path: dist}
49
+ - uses: pypa/gh-action-pypi-publish@release/v1
50
+ with:
51
+ repository-url: https://test.pypi.org/legacy/
52
+ skip-existing: true
53
+
54
+ verify-testpypi:
55
+ name: Verify TestPyPI artifact
56
+ needs: [build, testpypi]
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: astral-sh/setup-uv@v7
60
+ - name: Install exact TestPyPI version
61
+ env:
62
+ VERSION: ${{ needs.build.outputs.version }}
63
+ run: |
64
+ for attempt in $(seq 1 20); do
65
+ if uv tool install --refresh \
66
+ --index https://test.pypi.org/simple/ \
67
+ --index https://pypi.org/simple/ \
68
+ "qwenloop==${VERSION}"; then
69
+ break
70
+ fi
71
+ sleep 30
72
+ done
73
+ qwenloop --version
74
+ qwenloop --help
75
+
76
+ pypi:
77
+ name: Publish to PyPI
78
+ if: github.ref == 'refs/heads/main'
79
+ needs: build
80
+ runs-on: ubuntu-latest
81
+ environment: pypi
82
+ permissions:
83
+ id-token: write
84
+ steps:
85
+ - uses: actions/download-artifact@v8
86
+ with: {name: dist, path: dist}
87
+ - uses: pypa/gh-action-pypi-publish@release/v1
88
+ with:
89
+ skip-existing: true
90
+
91
+ verify-pypi:
92
+ name: Verify PyPI artifact
93
+ needs: [build, pypi]
94
+ runs-on: ubuntu-latest
95
+ steps:
96
+ - uses: astral-sh/setup-uv@v7
97
+ - name: Install exact PyPI version
98
+ env:
99
+ VERSION: ${{ needs.build.outputs.version }}
100
+ run: |
101
+ for attempt in $(seq 1 20); do
102
+ if uv tool install --refresh \
103
+ --index https://pypi.org/simple/ \
104
+ "qwenloop==${VERSION}"; then
105
+ break
106
+ fi
107
+ sleep 30
108
+ done
109
+ qwenloop --version
110
+ qwenloop --help
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ .pytest_cache/
3
+ .coverage
4
+ htmlcov/
5
+ dist/
6
+ *.egg-info/
7
+ __pycache__/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+ .qwenloop/
11
+
@@ -0,0 +1,22 @@
1
+ # vibey-gh owns provenance and release automation for this repository.
2
+
3
+ [fingerprint]
4
+ sources = [
5
+ "src/**/*.py",
6
+ "tests/**/*.py",
7
+ "scripts/**/*.py",
8
+ ".github/workflows/*.yml",
9
+ ]
10
+
11
+ [version]
12
+ files = ["pyproject.toml", "src/qwenloop/__init__.py"]
13
+ content_paths = ["src/qwenloop/"]
14
+ code_paths = ["src/qwenloop/"]
15
+
16
+ [branches]
17
+ integration = "develop"
18
+ release = "main"
19
+
20
+ [merge_train]
21
+ owner = "adammatthewsteinberger"
22
+ trusted_authors = ["adammatthewsteinberger", "claude[bot]", "github-actions[bot]", "vibey[bot]"]
@@ -0,0 +1,7 @@
1
+ # qwenloop
2
+
3
+ An onion-architected autonomous local Qwen runner. Domain code is pure. The
4
+ runner never blocks on a human, capacity rejection outranks completion, and
5
+ model downloads are explicit only. Use Conventional Commits and never develop
6
+ on `main`.
7
+
@@ -0,0 +1,8 @@
1
+ # Code of conduct
2
+
3
+ Be respectful, constructive, and specific. Harassment, discrimination,
4
+ threats, and disclosure of another person's private information are not
5
+ accepted in this project.
6
+
7
+ Report conduct concerns privately to the repository owner. Reports will be
8
+ reviewed promptly and handled as confidentially as practical.