mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-03 12:18:39 +00:00
Selectively port 5 PR #25 commits into ouroboros (clipboard image paste, autocorrect-off on chat textarea, integration-test CI tier, optional macOS code signing & notarization, secrets→env fix for step-level if-conditions in GitHub Actions. Plus chat bottom gradient migration from #chat-input-area's background to a dedicated .chat-bottom-fade sibling layer (z-index 4, pointer-events:none) so the textarea no longer optically sinks into the dense end of the gradient. Plus retire ouroboros-three-layer as a dev branch — ouroboros is now the single dev branch. (1) Clipboard image paste: web/modules/chat.js registers a paste listener on #chat-input that scans e.clipboardData.items for image/*, calls getAsFile(), wraps as File(clipboard-<unix-ts>.<ext>), and stages via the same pendingAttachment slot the paperclip uses (no inline upload — uploads when Send/Enter fires). Non-image paste falls through natively. The paperclip change handler was extracted into a shared stagePendingFile() helper so both entry points are identical. The textarea gains autocorrect=off autocapitalize=off spellcheck=false so code/identifiers/slash-commands are not silently rewritten by the browser. (2) Chat bottom-fade layer: web/style.css strips the linear-gradient background and mask-image from #chat-input-area (which keeps z-index 5), and adds a new dedicated sibling .chat-bottom-fade (position:absolute; bottom:0; pointer-events:none; z-index:4; height:200px) below the input dock. Mobile @media (max-width: 640px) uses calc(200px + env(safe-area-inset-bottom, 0px)) so the fade fully covers the iOS-home-indicator safe area at the worst-case input-area state (attachment + fully-expanded textarea). (3) Integration tier in CI (Tier 2.5): new integration-test job runs pytest tests/test_provider_integration.py -m integration on ubuntu-latest with OPENROUTER_API_KEY/OPENAI_API_KEY/ANTHROPIC_API_KEY in repo secrets. Triggered on push to main / ouroboros / ouroboros-stable, on workflow_dispatch, and on tag v*. Locally the pytest marker plus addopts -m 'not integration' in pyproject.toml exclude the tests from default runs. (4) Optional macOS code signing & notarization (Build tier): when BUILD_CERTIFICATE_BASE64 / P12_PASSWORD / KEYCHAIN_PASSWORD / APPLE_TEAM_ID are configured as repo secrets, the build job creates a temporary keychain, imports the Developer ID certificate, and runs bash build.sh (which signs .app and .dmg via env-overridable SIGN_IDENTITY). With APPLE_ID + APPLE_APP_SPECIFIC_PASSWORD also present, build.sh runs xcrun notarytool submit --wait followed by xcrun stapler staple. Stapler/notarytool failures are wrapped in if/else (set -e exempt) so transient Apple-CDN flakes become warnings instead of dropping the macOS DMG from the release. A NOTARIZE_OUTCOME enum drives a 4-case summary cascade (success / staple_failed / submit_failed / unconfigured) plus a defensive *) arm. With no Apple secrets the build falls back to OUROBOROS_SIGN=0 bash build.sh (identical to v5.0.0). Cleanup keychain step runs with if: always() && matrix.os == 'macos-latest' && env.BUILD_CERTIFICATE_BASE64 != '' so signing material never persists across runs and the bash-only security delete-keychain invocation never fires on Linux/Windows shards. The Import step sets trap 'rm -f "$CERTIFICATE_PATH"' EXIT so the temporary .p12 is removed on every exit, including a set -e abort mid-import. (5) secrets→env fix for step-level if (v4.47.1 lesson): GitHub Actions rejects secrets.* references inside step-level if expressions (Unrecognized named-value: secrets). All Apple signing secrets are mapped at the build job's env: block with a ${{ matrix.os == 'macos-latest' && secrets.X || '' }} guard so non-macOS shards receive empty strings — Linux/Windows never see the signing material. Step-level if reads env.* instead. New docs/DEVELOPMENT.md section GitHub Actions: secrets in step-level if conditions formalizes the rule with worked examples. (6) Tests: tests/test_chat_logs_ui.py gains 3 new tests (test_chat_input_disables_autocorrect, test_clipboard_paste_handler_exists, test_chat_bottom_fade_is_separate_layer); tests/test_build_scripts.py gains a new TestMacOSSigning class with 7 contract tests (job-level secrets env mapping with matrix.os guard, no secrets.* in any if-block, Import step gates on full secret set, Cleanup keychain always() + matrix.os + env guard, build.sh SIGN_IDENTITY env override, notarytool + stapler optional gate, stapler-failure-as-soft-warning regression); tests/test_provider_integration.py is added new with 6 tuple-aware tests (OpenRouter / OpenAI / Anthropic × {basic, isolation}) handling the post-v4.44.0 LLMClient.chat() (msg, usage) tuple plus Anthropic's list-of-blocks content. The existing test_chat_floating_overlays_have_readable_glass_backing was updated for the migrated bottom-fade contract (asserts no backdrop-filter on .chat-bottom-fade across base + mobile @media rules). (7) Branch consolidation: ouroboros-three-layer is retired as a dev branch. ouroboros is now the single dev branch. .github/workflows/ci.yml (Tier 1 quick-test trigger + path-filter branches list + build job's OUROBOROS_MANAGED_SOURCE_BRANCH default), build.sh / build_linux.sh / build_windows.ps1 (each script's ${OUROBOROS_MANAGED_SOURCE_BRANCH:-...} default), and four test files (test_release_workflow.py, test_launcher_sync.py, test_git_ops_recovery.py, test_build_repo_bundle.py — 21 occurrences total) all switch from ouroboros-three-layer to ouroboros. Historical references in older changelog rows (v4.50.0-rc.7) and in ouroboros/* module comments about the Phase 2/3 three-layer architecture refactor are intentionally preserved — those describe the architectural refactor, not the dev branch name. The remote managed/ouroboros-three-layer branch is deleted in the same release. Adversarial multimodel review (gemini-2.5/gpt-5.5/claude-opus-4.7 critics in parallel, full-context, 4 rounds): 32 findings total → 18 fixed, 14 rejected/deferred with explicit per-finding reasoning. All three critics independently reach SAFE TO COMMIT after round 4. Ouroboros triad+scope review (production code path parallel_review.run_parallel_review with full-repo pack, 2 rounds): 4 findings (2 scope-critical + 1 scope-advisory + 1 triad-advisory) → all 4 fixed. Round 1 caught matrix-shard secret leak; round 2 caught documentation/runtime command mismatch + cert-file cleanup gap on set -e failure. VERSION 5.0.0 → 5.1.0 (MINOR: additive features + UX/CI polish, no breaking change). Release invariant synchronised: VERSION, pyproject.toml [project].version, README badge, docs/ARCHITECTURE.md header — all 5.1.0. Note on changelog rolloff: the v4.50.0-rc.2 minor entry is rolled off proactively to keep one slot below the P7 5-minor-row cap. Its full body remains at git tag v4.50.0-rc.2. EOF )
65 lines
2.1 KiB
Bash
65 lines
2.1 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
VERSION=$(tr -d '[:space:]' < VERSION)
|
|
ARCHIVE_NAME="Ouroboros-${VERSION}-linux-$(uname -m).tar.gz"
|
|
MANAGED_SOURCE_BRANCH="${OUROBOROS_MANAGED_SOURCE_BRANCH:-ouroboros}"
|
|
RELEASE_TAG="v${VERSION}"
|
|
|
|
PYTHON_CMD="${PYTHON_CMD:-python3}"
|
|
if ! command -v "$PYTHON_CMD" >/dev/null 2>&1; then
|
|
PYTHON_CMD=python
|
|
fi
|
|
|
|
echo "=== Building Ouroboros for Linux (v${VERSION}) ==="
|
|
|
|
if [ ! -f "python-standalone/bin/python3" ]; then
|
|
echo "ERROR: python-standalone/ not found."
|
|
echo "Run first: bash scripts/download_python_standalone.sh"
|
|
exit 1
|
|
fi
|
|
|
|
echo "--- Installing launcher dependencies ---"
|
|
"$PYTHON_CMD" -m pip install -q -r requirements-launcher.txt
|
|
|
|
echo "--- Installing agent dependencies into python-standalone ---"
|
|
python-standalone/bin/pip3 install -q -r requirements.txt
|
|
|
|
rm -rf build dist
|
|
|
|
export PYINSTALLER_CONFIG_DIR="$PWD/.pyinstaller-cache"
|
|
mkdir -p "$PYINSTALLER_CONFIG_DIR"
|
|
|
|
echo "--- Installing Chromium for browser tools (bundled into python-standalone) ---"
|
|
PLAYWRIGHT_BROWSERS_PATH=0 python-standalone/bin/python3 -m playwright install chromium
|
|
|
|
echo "--- Building embedded managed repo bundle ---"
|
|
if ! git rev-parse -q --verify "refs/tags/$RELEASE_TAG" >/dev/null 2>&1; then
|
|
echo "ERROR: packaging requires git tag $RELEASE_TAG to exist."
|
|
exit 1
|
|
fi
|
|
TAG_TYPE="$(git cat-file -t "refs/tags/$RELEASE_TAG" 2>/dev/null || true)"
|
|
if [ "$TAG_TYPE" != "tag" ]; then
|
|
echo "ERROR: packaging requires annotated git tag $RELEASE_TAG (got '$TAG_TYPE'). Recreate with: git tag -a $RELEASE_TAG -m 'Release $RELEASE_TAG'"
|
|
exit 1
|
|
fi
|
|
if ! git tag --points-at HEAD | grep -Fx "$RELEASE_TAG" >/dev/null 2>&1; then
|
|
echo "ERROR: packaging requires HEAD to be tagged with $RELEASE_TAG."
|
|
exit 1
|
|
fi
|
|
"$PYTHON_CMD" scripts/build_repo_bundle.py --source-branch "$MANAGED_SOURCE_BRANCH"
|
|
|
|
echo "--- Running PyInstaller ---"
|
|
"$PYTHON_CMD" -m PyInstaller Ouroboros.spec --clean --noconfirm
|
|
|
|
echo ""
|
|
echo "=== Creating archive ==="
|
|
cd dist
|
|
tar -czf "$ARCHIVE_NAME" Ouroboros/
|
|
cd ..
|
|
|
|
echo ""
|
|
echo "=== Done ==="
|
|
echo "Archive: dist/$ARCHIVE_NAME"
|
|
echo ""
|
|
echo "To run: extract and execute ./Ouroboros/Ouroboros"
|