Metadata-Version: 2.4
Name: ob-project-utils
Version: 0.2.35rc1
Summary: Utilities for building, validating, deploying, and scoring Outerbounds projects
Author: Outerbounds
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: requests
Provides-Extra: lint
Requires-Dist: pyyaml>=6.0; extra == "lint"
Provides-Extra: ci
Requires-Dist: jinja2>=3.1; extra == "ci"
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Requires-Dist: pytest-xdist; extra == "test"
Requires-Dist: pyyaml>=6.0; extra == "test"
Requires-Dist: jinja2>=3.1; extra == "test"


# ob-project-utils

Utilities for building, validating, deploying, and scoring Outerbounds projects.

## Install

```bash
pip install ob-project-utils              # core (deploy, lint)
pip install ob-project-utils[ci]          # + CI module generation (jinja2)
pip install ob-project-utils[lint]        # + deployment config validation (pyyaml)
pip install ob-project-utils[test]        # + test dependencies (pytest, pyyaml, jinja2)
```

## Commands

### `obproject-deploy` — Deploy projects to Outerbounds

The existing deployment script. Discovers flows, deployments, and assets in a project and deploys them to the Outerbounds platform via CI or manually.

### `obproject-lint` — Validate project structure

Four validators in one pass:

```bash
obproject-lint                          # lint current directory
obproject-lint --project-dir ../my-proj  # lint specific project
obproject-lint --format json            # machine-readable output
```

| Check | What it validates |
|-------|-------------------|
| **toml** | obproject.toml parses, required fields (platform, project, title), naming conventions, known sections |
| **flow** | `python flow.py check` (Metaflow's 21-rule DAG linter) + anti-pattern detection (e.g., `Parameter(default=None)`) |
| **deployment** | config.yml/config.yaml parses, required fields (requires pyyaml) |
| **ci** | Config exists, uses `--from-obproject-toml`, no yq, OIDC permissions |

### `obproject-ci` — Generate CI workflows from config

Declare CI modules in obproject.toml, generate the workflow file:

```toml
[ci]
platform = "github-actions"
modules = ["auth", "lint", "deploy", "teardown"]
```

```bash
obproject-ci generate              # writes .github/workflows/deploy.yml
obproject-ci generate --dry-run    # preview without writing
```

Available modules:

| Module | What it does | Separate job? |
|--------|-------------|---------------|
| `auth` | `service-principal-configure --from-obproject-toml` | No (step in deploy) |
| `lint` | `obproject-lint` validation | No (step in deploy) |
| `deploy` | `obproject-deploy` with git context | No (step in deploy) |
| `teardown` | `teardown-branch` on PR merge/branch delete | Yes |
| `promote` | `promote_assets` on PR merge, then teardown | Yes (replaces teardown) |

### `obproject-score` — Project health scoring

Score a project across 5 categories:

```bash
obproject-score --project-dir .                           # single project
obproject-score --registry registry.toml --format dashboard  # fleet dashboard
```

| Category | What it checks |
|----------|---------------|
| **structure** | toml valid, has flows, flows parse, has deployments, has src/, has assets |
| **documentation** | README, CLAUDE.md with schema sections (Architecture, Verification, etc.) |
| **ci** | Has config, uses `--from-obproject-toml`, has teardown |
| **testing** | Test directory, test files, Verification section in CLAUDE.md |
| **agent_context** | Has agent instructions (CLAUDE.md/AGENTS.md/.cursor), runtime config |

## Agent skills

Platform knowledge for coding agents, in `.claude/skills/`:

```
.claude/skills/
  metaflow/           8 files — flows, decorators, data, client-api, scaling, cards, environments
  outerbounds/       12 files — platform, projects, assets, CI, testing, inference, compute, security, workstations, cost
```

Skills are lazy-loaded by Claude Code — only descriptions consume context at startup, full content loads on demand. They're navigation guides with doc links, not standalone references.

## How the tools chain together

### Agent sets up a new project

```
read CLAUDE.md → activates outerbounds skill
  → write obproject.toml (guided by project-structure skill)
  → scaffold flows (guided by metaflow-flows skill)
  → obproject-lint → fix issues
  → add [ci] to toml → obproject-ci generate
  → obproject-score → read suggestions → improve → re-score
```

### Agent migrates an existing project

```
obproject-score → see 36%, read suggestions
  → "Missing CLAUDE.md" → write it
  → "CI uses yq" → migrate to --from-obproject-toml
  → obproject-lint → fix remaining issues
  → re-score → 70%
```

### Nightly fleet health scan

```
obproject-score --registry registry.toml --format dashboard
  → score all registered projects
  → flag regressions from previous run
  → generate issues for projects below threshold
```

### The improvement loop

```
Agent hits edge case → fixes it
  → pattern is cross-project?
    → add to skill gotchas + lint rule if regex-expressible
    → re-score → score improves
    → nightly scan catches same issue in other projects
```

## Package structure

```
obproject/
  __init__.py          — public API: ProjectFlow, project_trigger, project_schedule, etc.
  projectbase.py       — ProjectFlow base class (wraps Metaflow FlowSpec)
  assets.py            — Asset API client (register, consume, promote)
  project_events.py    — Branch-scoped event publishing
  project_schedule.py  — Branch-aware scheduling (@project_schedule wraps @schedule)
  lint.py              — obproject-lint
  ci.py                — obproject-ci
  score.py             — obproject-score
  ci_modules/          — Jinja2 templates for CI generation
  evals_logger.py      — Evaluation metric logging

deploy/
  deploy_obproject.py  — obproject-deploy

.claude/skills/        — Agent platform knowledge (20 files)
highlight_card/        — @highlight decorator
metaflow_extensions/   — Metaflow plugin: highlight card backend
src-html/              — Svelte source for highlight and table cards
```
