Adopt ADR 0004: stop chasing a single global coverage number and
measure what matters instead.
- Omit the genuinely-interactive `cli/init.py` shell (read_tty_line
prompt loops) alongside the existing `cli/tui.py`, with a rationale
comment in .coveragerc. Subprocess/backend orchestration is NOT
omitted — it stays visible and is scored via the integration suite.
- scripts/coverage.sh runs unit + integration under one coverage
measurement (the policy's yardstick) and can report the critical
security/logic core held to the >=90% target.
- scripts/diff_coverage.py is a stdlib-only gate (no diff-cover dep):
new/changed executable lines must be >=90% covered. This is the
enforced regression guard; the global number is informational.
- CI gains a `coverage` job: combined report + the diff-coverage gate.
- Unit-test `cli/__init__.py` dispatch/exit-code mapping (it's logic,
not I/O, so it earns tests rather than an omit).
Combined unit+integration coverage now reports 83% global / 87% across
the critical modules; per-module ratcheting toward 90% is the ongoing
work this policy frames.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NkwFXLFff9PYPy4wgVBJp9
The update-badges workflow only refreshed pylint and pyright. Add a
coverage step that runs the unit suite under coverage.py, extracts the
TOTAL percentage, and updates a new coverage badge in the README.
Also trigger the workflow on .coveragerc changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NkwFXLFff9PYPy4wgVBJp9
The workflow was silently skipping prd-new-*.md files added in earlier
commits of a multi-commit PR. The final push commit is just the
implementation; the PRD rename to prd-new- happens in an earlier commit
on the branch, so git diff HEAD~1 HEAD never saw it.
Fix: glob the working tree for prd-new-*.md directly. Also switch the
non-PRD-changed check to use GITHUB_EVENT_BEFORE..HEAD so it covers the
full push range rather than just the last commit. Increase fetch-depth
to 0 so the before-SHA is always reachable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements #213: PRDs use prd-new-<slug>.md while a PR is open; a
post-merge workflow on main assigns sequential numbers and renames the
file. A required PR check blocks prd-new-*.md from landing on main
without going through the workflow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The old patterns required a trailing ] that badge markdown doesn't have,
so sed never matched and the README was never updated. Switch to matching
only the /badge/tool-... URL segment, which is stable and unambiguous.
Also encode / as %2F in the pylint score for a valid shields.io URL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Capture full output with || true instead of pipefail-sensitive | tail -1
- Use lookbehind for pylint score to avoid matching "previous run" value
- Use lookahead for pyright error count to search full output not just last line
- Remove hardcoded fallback values that masked parse failures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Badges should reflect the current score even when there are lint/type
errors, not abort the job entirely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Zero-indented lines in the commit message body broke the block scalar,
preventing Gitea from parsing the file at all.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Strip pipelock from all unit and integration test fixtures:
proxy_plan fields removed from DockerBottlePlan/SmolmachinesBottlePlan
constructors; pipelock-specific test classes deleted or renamed
- Update test_sidecar_init: remove test_pipelock_loses_egress_tokens,
rename "pipelock" daemon fixtures to "git-gate" throughout
- Remove test_pipelock_binary_present_and_versioned from integration test
- Remove test_pipelock_answers_on_bundle_ip from smolmachines launch test
- Update _SANDBOX_BLOCK_MARKERS: remove "pipelock" marker (egress blocks)
- Dockerfile.sidecars: remove pipelock build stage and COPY; update layout
comments and port table
- egress_entrypoint.sh: update comments now that egress is sole proxy
- Clean up pipelock references in comments/docstrings across backend,
network, manifest, supervise, git_gate, yaml_subset, agent_provider,
sidecar_bundle, sidecar_init, egress_addon_core modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Runs on push to main when Python files change
- Can be manually triggered via workflow_dispatch
- Executes pylint and pyright to extract quality scores
- Updates README.md badges with current metrics
- Auto-commits changes with [skip ci] to prevent loops
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Standardized lint.yml formatting:
- Changed single quotes to double quotes for consistency
- Updated workflow name to lowercase 'lint'
- No functional changes
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The Gitea Actions runner doesn't have access to pip cache storage,
causing 'reserveCache failed: connect ETIMEDOUT' errors.
Removed cache configuration from both:
- .gitea/workflows/lint.yml
- .gitea/workflows/update-badges.yml
Pip will download dependencies fresh on each run, which is acceptable
for CI workflows and avoids the timeout errors.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Created update-badges.yml Gitea Actions workflow that:
- Runs on push to main when Python files change
- Executes pylint and pyright
- Extracts quality scores from tool output
- Updates README.md badges with current scores
- Auto-commits changes with [skip ci] to avoid loop
This keeps the quality badges in README.md in sync with
actual code quality metrics automatically.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Create requirements-dev.txt with pylint and pyright. The bot-bottle
project itself has no runtime dependencies. Update workflow to use
the requirements file for pip caching.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add Gitea workflow to run pylint and pyright on all Python files
when they are pushed. The workflow triggers on any .py file changes
and enforces a quality threshold.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Replace the hand-maintained INTEGRATION_NAMES classifier (and the
bespoke run_tests.py around it) with a directory-driven split:
tests/unit/ unit tests, always run
tests/integration/ Docker-dependent, skip cleanly without Docker
tests/canaries/ upstream-regression checks, opt-in via
CLAUDE_BOTTLE_RUN_CANARIES=1
The pinned-pipelock-image check moves to the canary suite — it tests
upstream packaging, not our code, so it shouldn't gate every dev push.
A scheduled canaries.yml workflow runs it weekly.
The manifest-runtime tests collapse the four assertRaises cases for
distinct 'runtime' values into one subTest loop and drop the
error-message-wording assertions; the contract is "any value is
rejected", not "the error literally contains 'auto-detect'".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>