v0.34.0: vstack.timeline + vstack.cost_sim + vstack.findings_router m… #171
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Test (Python ${{ matrix.python-version }} on ${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| python-version: ["3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: pip | |
| - name: Install package + test deps | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[mcp,api]" | |
| python -m pip install pytest pytest-cov pyyaml httpx | |
| # Framework-gated adapter tests skip when their framework is | |
| # missing; install the lightweight ones so CI actually runs | |
| # them. CrewAI's dep tree is heavier and slower; we leave it | |
| # gated unless someone needs that signal locally. | |
| python -m pip install langchain-core langgraph llama-index-core 'pydantic-ai>=0.0.20' | |
| - name: Run tests (all patterns + surfaces, with coverage) | |
| run: | | |
| pytest module-1-individual/ module-2-team/ module-3-organization/ \ | |
| _mcp/ _memory/ _upgrade/ _api/ \ | |
| _adapters/ _learnings/ _analytics/ \ | |
| _browser/ _gbrain/ _benchmarks/ \ | |
| _security/ _cache/ _observability/ _doctor/ \ | |
| _hello/ \ | |
| -v --tb=short \ | |
| --cov=vstack \ | |
| --cov-report=term-missing \ | |
| --cov-report=xml | |
| - name: Upload coverage artifact | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-xml | |
| path: coverage.xml | |
| retention-days: 14 | |
| lint: | |
| name: Lint (ruff) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| cache: pip | |
| - name: Install ruff | |
| run: python -m pip install ruff | |
| - name: Run ruff check | |
| run: | | |
| ruff check module-1-individual/ module-2-team/ module-3-organization/ \ | |
| _mcp/ _memory/ _upgrade/ _api/ _adapters/ _learnings/ _analytics/ \ | |
| _browser/ _gbrain/ _benchmarks/ examples/ _baselines/scripts/ \ | |
| _security/ _cache/ _observability/ _doctor/ _hello/ | |
| - name: Run ruff format check | |
| run: | | |
| ruff format --check module-1-individual/ module-2-team/ module-3-organization/ \ | |
| _mcp/ _memory/ _upgrade/ _api/ _adapters/ _learnings/ _analytics/ \ | |
| _browser/ _gbrain/ _benchmarks/ examples/ _baselines/scripts/ \ | |
| _security/ _cache/ _observability/ _doctor/ _hello/ | |
| typecheck: | |
| name: Typecheck (mypy) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| cache: pip | |
| - name: Install mypy and dependencies | |
| run: | | |
| python -m pip install mypy pydantic mcp fastapi 'uvicorn[standard]' httpx \ | |
| langchain-core langgraph llama-index-core 'pydantic-ai>=0.0.20' | |
| python -m pip install -e . | |
| - name: Run mypy per-pattern | |
| # Each pattern's lib is its own logical package (via pyproject's | |
| # force-include mapping). Running mypy across all patterns at once | |
| # produces a 'Duplicate module named "lib"' error; running each | |
| # pattern's lib separately avoids that and gives clearer per-pattern | |
| # output. New patterns add another line here. | |
| run: | | |
| set -e | |
| for pattern in \ | |
| _mcp \ | |
| _memory \ | |
| _upgrade \ | |
| _api \ | |
| _adapters \ | |
| _learnings \ | |
| _analytics \ | |
| _browser \ | |
| _gbrain \ | |
| _benchmarks \ | |
| _security \ | |
| _cache \ | |
| _observability \ | |
| _doctor \ | |
| _hello \ | |
| module-2-team/30-aar-generator \ | |
| module-2-team/17-lencioni-diagnostic \ | |
| module-2-team/18-trust-triangle-audit \ | |
| module-1-individual/03-johari-window \ | |
| module-2-team/13-grpi-working-agreement \ | |
| module-2-team/27-bias-stack-detector \ | |
| module-2-team/20-edmondson-psych-safety \ | |
| module-2-team/29-thomas-kilmann-selector \ | |
| module-2-team/22-stone-heen-feedback-triggers \ | |
| module-2-team/28-devils-advocate-separator \ | |
| module-1-individual/01-lewin-formula \ | |
| module-2-team/19-mcallister-trust-dimensions \ | |
| module-2-team/15-social-loafing-detector \ | |
| module-2-team/26-groupthink-polarization-contagion \ | |
| module-2-team/14-process-gain-loss-detector \ | |
| module-2-team/24-smart-goal-generator \ | |
| module-1-individual/11-mcgregor-orchestrator-mode \ | |
| module-2-team/25-group-decision-models \ | |
| module-3-organization/31-schein-iceberg-culture \ | |
| module-1-individual/08-grant-strengths-as-weaknesses \ | |
| module-2-team/23-plus-delta-feedback-format \ | |
| module-3-organization/32-robbins-judge-7-culture \ | |
| module-2-team/16-heffernan-superflocks-detector \ | |
| module-1-individual/06-yerkes-dodson-workload \ | |
| module-3-organization/33-org-structure-matrix \ | |
| module-1-individual/09-motivation-traps \ | |
| module-2-team/21-glaser-conversation-steering \ | |
| module-1-individual/02-goleman-ei-audit \ | |
| module-1-individual/10-sdt-intrinsic-reward \ | |
| module-3-organization/34-span-of-control \ | |
| module-1-individual/04-danva-emotion-reader \ | |
| module-1-individual/05-cognitive-reappraisal \ | |
| module-1-individual/07-hexaco-personality \ | |
| module-1-individual/12-vroom-expectancy; do | |
| echo "=== mypy: $pattern ===" | |
| mypy "$pattern/lib" --strict --ignore-missing-imports | |
| done | |
| security: | |
| name: Security (bandit + pip-audit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| cache: pip | |
| - name: Install security tools | |
| run: python -m pip install "bandit[toml]" pip-audit | |
| - name: Run bandit (library code only) | |
| # Tests and demos exercise the library deliberately, so they may | |
| # trip rules that flag exec / subprocess / hardcoded "secrets" in | |
| # canned fixtures. Scan only the shipping library code. | |
| run: | | |
| bandit -r \ | |
| module-1-individual/*/lib \ | |
| module-2-team/*/lib \ | |
| module-3-organization/*/lib \ | |
| -ll -ii -f txt | |
| - name: Run pip-audit (declared deps) | |
| # The library itself only pins pydantic + (optional) anthropic / | |
| # openai / mcp / fastapi / framework adapters. pip-audit on the | |
| # installed environment surfaces both first-party and transitive | |
| # issues. The framework adapter dep trees (langchain / langgraph | |
| # / llama-index / pydantic-ai / crewai) pull in dozens of | |
| # transitives we can't pin, so we treat the audit as informational: | |
| # the report is logged, and bandit (above) is the security gate. | |
| run: | | |
| python -m pip install -e ".[all]" | |
| pip-audit --strict --progress-spinner=off \ | |
| || pip-audit --progress-spinner=off \ | |
| || echo "pip-audit found advisories; see report above (warn-only)." | |
| build: | |
| name: Build wheel + sdist | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| cache: pip | |
| - name: Install build | |
| run: python -m pip install build | |
| - name: Build | |
| run: python -m build | |
| - name: Verify wheel ships all 34 namespaces + py.typed marker | |
| run: | | |
| python -m pip install dist/valanistack-*-py3-none-any.whl | |
| python -c " | |
| import importlib, os | |
| import vstack | |
| assert vstack.__version__, 'top-level __version__ missing' | |
| print(f'vstack v{vstack.__version__}') | |
| assert os.path.exists(os.path.join(os.path.dirname(vstack.__file__), 'py.typed')), 'py.typed marker missing from wheel' | |
| print('py.typed marker present') | |
| namespaces = [ | |
| 'vstack.aar', | |
| 'vstack.lencioni', | |
| 'vstack.trust_triangle', | |
| 'vstack.johari', | |
| 'vstack.grpi', | |
| 'vstack.bias_stack', | |
| 'vstack.psych_safety', | |
| 'vstack.thomas_kilmann', | |
| 'vstack.feedback_triggers', | |
| 'vstack.devils_advocate', | |
| 'vstack.lewin', | |
| 'vstack.mcallister_trust', | |
| 'vstack.social_loafing', | |
| 'vstack.debate_pathology', | |
| 'vstack.process_gain_loss', | |
| 'vstack.smart_goal', | |
| 'vstack.mcgregor', | |
| 'vstack.group_decision', | |
| 'vstack.schein_culture', | |
| 'vstack.grant_strengths', | |
| 'vstack.plus_delta', | |
| 'vstack.robbins_culture', | |
| 'vstack.superflocks', | |
| 'vstack.yerkes_dodson', | |
| 'vstack.org_structure', | |
| 'vstack.motivation_traps', | |
| 'vstack.glaser_conversation', | |
| 'vstack.goleman_ei', | |
| 'vstack.sdt_reward', | |
| 'vstack.span_of_control', | |
| 'vstack.danva_emotion', | |
| 'vstack.cognitive_reappraisal', | |
| 'vstack.hexaco', | |
| 'vstack.vroom_expectancy', | |
| ] | |
| for ns in namespaces: | |
| mod = importlib.import_module(ns) | |
| assert hasattr(mod, '__all__'), f'{ns} missing __all__' | |
| print(f'All {len(namespaces)} pattern namespaces import cleanly') | |
| " | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist-${{ github.sha }} | |
| path: dist/ | |
| retention-days: 14 |