Skip to content

feat(mcgregor): v0.2.0 gstack-grade upgrade #27

feat(mcgregor): v0.2.0 gstack-grade upgrade

feat(mcgregor): v0.2.0 gstack-grade upgrade #27

Workflow file for this run

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 .
python -m pip install pytest pytest-cov pyyaml
- name: Run tests (all patterns, with coverage)
run: |
pytest module-1-individual/ module-2-team/ module-3-organization/ \
-v --tb=short \
--cov=agentcity \
--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/
- name: Run ruff format check
run: ruff format --check module-1-individual/ module-2-team/ module-3-organization/
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
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 \
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.
# pip-audit on the installed environment catches transitive issues.
# We use --strict in the primary pass but fall through to a warn-only
# pass so a flaky transitive doesn't false-positive the entire matrix.
run: |
python -m pip install -e ".[all]"
pip-audit --strict --progress-spinner=off || pip-audit --progress-spinner=off
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/agentcity-*-py3-none-any.whl
python -c "
import importlib, os
import agentcity
assert agentcity.__version__, 'top-level __version__ missing'
print(f'agentcity v{agentcity.__version__}')
assert os.path.exists(os.path.join(os.path.dirname(agentcity.__file__), 'py.typed')), 'py.typed marker missing from wheel'
print('py.typed marker present')
namespaces = [
'agentcity.aar',
'agentcity.lencioni',
'agentcity.trust_triangle',
'agentcity.johari',
'agentcity.grpi',
'agentcity.bias_stack',
'agentcity.psych_safety',
'agentcity.thomas_kilmann',
'agentcity.feedback_triggers',
'agentcity.devils_advocate',
'agentcity.lewin',
'agentcity.mcallister_trust',
'agentcity.social_loafing',
'agentcity.debate_pathology',
'agentcity.process_gain_loss',
'agentcity.smart_goal',
'agentcity.mcgregor',
'agentcity.group_decision',
'agentcity.schein_culture',
'agentcity.grant_strengths',
'agentcity.plus_delta',
'agentcity.robbins_culture',
'agentcity.superflocks',
'agentcity.yerkes_dodson',
'agentcity.org_structure',
'agentcity.motivation_traps',
'agentcity.glaser_conversation',
'agentcity.goleman_ei',
'agentcity.sdt_reward',
'agentcity.span_of_control',
'agentcity.danva_emotion',
'agentcity.cognitive_reappraisal',
'agentcity.hexaco',
'agentcity.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