Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7ac3398
apply dependabot insights
alain-sv May 13, 2026
22d50aa
minor
alain-sv May 13, 2026
2a89660
chore(ci): SHA-pin actions/checkout and actions/setup-python (#43)
alain-sv May 13, 2026
297d98e
docs(changelog): add unreleased dependency security refresh entry (#44)
alain-sv May 13, 2026
1c41f54
chore(ci): add uv cache-suffix per Python version + update AGENTS.md …
alain-sv May 13, 2026
00aad5e
Merge branch 'main' into develop
alain-sv May 13, 2026
1f5c176
supervaizer-v2-mvp-contracts (#47)
alain-sv May 17, 2026
d7c98b9
Minor
alain-sv May 17, 2026
b192229
Merge branch 'main' into develop
alain-sv May 17, 2026
789b0c6
chore: update changelog for Supervaizer v2 enhancements and API key v…
alain-sv May 17, 2026
da4b00d
Merge branch 'main' into develop
alain-sv May 17, 2026
c977b6e
workspace-agent-grants (#50)
alain-sv May 19, 2026
a12b628
minor
alain-sv May 19, 2026
a761421
Merge branch 'main' into develop
alain-sv May 20, 2026
1f20b22
feat(logging): implement structured logging for Cloud Logging compati…
alain-sv May 20, 2026
746a04f
Merge branch 'main' into develop
alain-sv May 24, 2026
75a3a0d
Minor
alain-sv May 24, 2026
612001f
Merge branch 'main' into develop
alain-sv May 26, 2026
3324db5
codex/supervaizer-lifespan-cleanup (#54)
alain-sv May 26, 2026
e7834a2
codex/refactor-server-modules (#55)
alain-sv May 26, 2026
4fed877
minor
alain-sv May 26, 2026
afaf602
codex/agent-interviewer-workspace-jobs-refresh (#56)
alain-sv May 26, 2026
ceede13
Refactor pre-commit configuration and enhance agent validation
alain-sv May 26, 2026
a15f07d
[MINOR] chore: merge develop to main
alain-sv May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ repos:
- id: check-toml
- id: debug-statements

# Add mypy type checking
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.17.1
# Use project mypy (pyproject dev extra) so hook version matches uv.lock
- repo: local
hooks:
- id: mypy
language: python
additional_dependencies: [".[dev]"]
args: []
exclude: ^(tests/|tools/)
name: mypy
entry: uv run mypy src/supervaizer
language: system
pass_filenames: false
types: [python]

# Add copyright headers to files
- repo: https://github.com/Lucas-C/pre-commit-hooks
Expand Down
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This is the canonical agent guide for the Supervaizer controller repo. Supervaiz
## Working Rules

- Prefer simple, typed Python changes that match existing FastAPI/Pydantic patterns.
- Do not import from inside functions, methods, or local scopes unless it is absolutely required to avoid a concrete circular import, optional dependency, or startup-cost problem. Prefer module-level imports by default, and document the reason when a local import is unavoidable.
- **No guessing / no implicit fallbacks:** when protocol versions, workspace identity, action/resource contracts, authentication, or transport configuration are missing or inconsistent, fail with a clear error that names the missing configuration. Do not infer another context, broaden scope, or silently fall back.
- Use `just` recipes from this repo for local commands.
- Use `uv` for Python environment and package operations.
Expand All @@ -31,6 +32,8 @@ Reference specific personas when requesting work:
## Learned User Preferences

- When preparing a merge to `main` or a release, keep `docs/CHANGELOG.md` **Unreleased** accurate; on request, align listed dependency or tooling changes with the delta since the previous git tag (including `pyproject.toml`).
- Prefer `docs/CHANGELOG.md` `Unreleased` entries grouped into `Added` / `Changed` / `Fixed` (instead of custom feature headings).
- Dependabot PRs should target `develop`, not `main` (set `target-branch: "develop"` in `.github/dependabot.yml`).

## Learned Workspace Facts

Expand Down Expand Up @@ -80,7 +83,7 @@ Ask. Refusing to act is always safer than taking an action that bypasses these r
<!-- gitnexus:start -->
# GitNexus — Code Intelligence

This project is indexed by GitNexus as **supervaizer** (6117 symbols, 11434 relationships, 278 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
This project is indexed by GitNexus as **supervaizer** (6225 symbols, 11375 relationships, 276 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.

> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.

Expand Down
71 changes: 70 additions & 1 deletion docs/2026_05_SUPERVAIZER_v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


> **Created:** 2026-05-16
> **Updated:** 2026-05-18
> **Updated:** 2026-05-22

Supervaizer v2 is the new operation contract between an agent controller and Supervaize Studio.

Expand Down Expand Up @@ -431,3 +431,72 @@ New agents should model Studio integration through v2 from the start.
- Use `awaiting` state for HITL.
- Return stable external ids in Job/Case/Step/Artifact snapshots.
- Keep business validation inside agent actions, not inside Studio-specific code paths.

## Implementation Status: Agent Interviewer Reference Agent

As of 2026-05-22, Agent Interviewer is the reference implementation for the
v2 operating model. The current implementation is not just discovery metadata;
Studio can call the agent through A2A JSON-RPC, render A2UI surfaces, and sync
job state back from the agent.

Implemented across the local Runwaize repos:

- Supervaizer SDK exposes the v2 registration builder, A2A Agent Card metadata,
JSON-RPC action dispatch, surface dispatch, resource/dataset/action contracts,
workspace authorization verification, and clear handler-blocking errors.
- Studio ingests v2 registration data, renders generic resources, datasets,
surfaces, HITL forms, artifacts, job analytics, case lanes, and job-state
snapshots, and no longer relies on v1 dynamic job-start choices for v2 agents.
- Agent Interviewer declares campaigns, contacts, prompts, scenarios,
campaign_contacts, campaign datasets, transcript/synthesis artifacts, setup /
work / deliverable lanes, job analytics, workspace binding actions, and
campaign-specific surfaces through the v2 contract.
- Studio-to-agent calls for workspace-scoped actions use Workspace Agent Grants
and Studio-signed workspace authorization tokens. Raw tenant or workspace
slugs are not authority.
- Campaign starts return a top-level `job_state` snapshot so Studio can
materialize setup cases immediately, then converge through `job.sync`.
- Contact enrollment import is modeled as a generic `ResourceImport` surface.
Studio communicates and validates file structure; Agent Interviewer owns the
import format, tenant validation, persistence, and returned job state.
- Agent Interviewer job analytics are Vega-Lite based and currently focus on
the campaign-scoped session-duration-over-time chart for Studio job detail.
- Public interview configuration failures must be caught before live interview
startup. A missing or empty configured campaign prompt is a campaign
configuration error, not a network interruption.

Deliberate decisions:

- v2 does not preserve v1 dynamic-choice, job-poll, or legacy case-update
behavior unless explicitly required. For the current v2 workstream, enforce
v2 workspace operations whenever the Supervaize controller path is active.
- No guessing and no implicit fallback: missing workspace authorization,
missing workspace binding, mismatched server/agent id, missing scopes, and
missing campaign prompt configuration must fail with explicit errors.
- Studio owns generic rendering and acceptance records. Agents own business
vocabulary and must validate every business mutation.
- `server.register.details.server_id` is the authoritative controller identity.
It should survive agent restarts through registration, not by manual user
configuration.
- If `SUPERVAIZER_API_KEY` is set, Supervaizer uses it. If it is not set, the
agent developer may allow generation. Startup must verify Studio persisted
the effective key; mismatches fail startup instead of producing repeated
`/a2a` 401s later.

Current gaps to consider next:

- Make contract-change reacceptance smarter: already accepted grants should be
refreshable automatically when only non-expanding registration metadata
changes; expanded scopes or data access still require explicit acceptance.
- Strengthen e2e coverage for the entire blue-sky flow: share agent, accept
workspace binding, create mission, create campaign job, import contacts, run
setup case, start interview, sync transcript/synthesis, render analytics, and
revoke access.
- Add clearer Studio operator recovery for invalid campaign configuration,
missing workspace binding, missing signing key, wrong server id, and revoked
grants.
- Complete production deployment hardening for split public/controller runtimes,
Cloud Run startup probes, Secret Manager requirements, and dashboarded
registration-handshake health.
- Decide how Studio should present historical jobs when grants are revoked or
when an agent/server is replaced.
48 changes: 47 additions & 1 deletion docs/2026_05_WORKSPACE_AGENT_GRANTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Workspace Agent Grants

> **Created:** 2026-05-18
> **Updated:** 2026-05-18
> **Updated:** 2026-05-22

This document plans the Supervaizer v2 authorization model for shared agents.

Expand Down Expand Up @@ -429,3 +429,49 @@ Studio should surface these failures to operators as configuration or authorizat
- An agent without local persistence can still verify every request.
- Revoked grants stop authorizing requests after token expiry, and immediately for operations that use introspection.
- Studio and agent_interviewer show clear errors for missing grant, missing scope, and missing workspace binding.

## Current Implementation Notes

As of 2026-05-22, the implementation has moved beyond this plan in the local
Runwaize repos:

- Studio stores explicit workspace-agent acceptance and revocation state,
including who accepted the agent and when.
- Studio mints workspace authorization tokens for v2 calls and Supervaizer
verifies them before dispatching workspace-scoped handlers.
- Agent Interviewer requires verified workspace context for v2 resources,
datasets, job start, sync, HITL, and artifacts. It must not resolve access
from raw `workspace_slug` or `tenant_slug`.
- Agent-side workspace binding is generic in the v2 contract. Agent Interviewer
maps the generic `agent_workspace_ref` to its tenant configuration record,
but that tenant terminology is not exposed as a protocol requirement.
- Bootstrap binding actions are allowed before a workspace grant exists, but
only under normal Studio-to-agent transport authentication. Every other
workspace-scoped operation fails closed without a valid workspace token.

Important learning from local restarts and multi-instance concerns:

- A grant must not be bound to an ephemeral process instance id. Use the
registered Studio server identity from `server.register.details.server_id`
and let registration refresh update the server record transparently.
- Agent developers should not have to manually set Studio server ids. If the
effective registered server identity changes, Studio should refresh the
association or offer an explicit reset/refresh action to the operator.
- Registration handshake failures must be startup failures, not latent runtime
failures. The agent should fail to start when Studio did not persist the
effective controller API key or when the handshake response is missing the
data required to verify Studio-to-agent calls.
- Contract fingerprint checks should distinguish expanding changes from
harmless refreshes. Requiring manual reacceptance on every Studio restart is
too strict and creates operational noise.

Open product decisions:

- Which registration changes automatically refresh an accepted grant, and which
require explicit reacceptance?
- Should revocation immediately cancel running jobs, mark them failed in
Studio, or only block new calls while preserving active agent-side work?
- How should Studio present stale accepted grants when a server is replaced by
a new deployment with the same public URL and agent identity?
- Should high-risk operations introspect grant status on every call, or is
short-lived token expiry sufficient for the MVP?
29 changes: 26 additions & 3 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Supervaizer Changelog

> **Created:** 2025-08-05
> **Updated:** 2026-05-20

All notable changes to this project will be documented in this file.

> The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
Expand All @@ -15,6 +12,32 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Changed

- **FastAPI lifespan cleanup** — Controller shutdown now cancels the scheduled-step background loop and waits briefly for it to stop.
- **Server module refactor** — Split server startup configuration, runtime server info persistence, Studio registration handshakes, and scheduled-step loop management out of `server.py` into focused modules while preserving the public `Server` behavior.
- **Supervaizer v2 agent methods** — SDK agents can now declare optional standard actions such as `agent.refresh` plus custom agent actions through the same `AgentMethods` structure used for job methods, and the A2A runtime registers those handlers automatically.

### Tests

- `tests/test_server.py` — scheduler task cancellation and bounded shutdown waiting during FastAPI lifespan shutdown.
- `tests/test_server_refactor_modules.py` — parity coverage for the extracted server configuration, server info, registration, handshake, and scheduled-step helpers.
- `tests/test_a2a.py` — standard and custom agent method dispatch through the v2 A2A controller.
- `tests/test_agent.py` — agent-level v2 method registration and contract validation.
- `tests/test_contracts.py` — typed agent method contract serialization.

### Tests

- `tests/test_common.py` — structured JSON log output for API access-denial records
- `just test`

| Status | Count |
| ---------- | ----- |
| ✅ Passed | 663 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 136s |

## [1.1.1] - 2026-05-20

### Changed
Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies = [
"cryptography>=48.0.0",
"demjson3>=3.0.0",
"deprecated>=1.3.0",
"fastapi>=0.136.1",
"fastapi>=0.136.3",
"httpx>=0.28.1",
"jinja2>=3.1.6",
"loguru>=0.7.3",
Expand All @@ -23,10 +23,10 @@ dependencies = [
"pyyaml>=6.0.0",
"rich>=15.0.0",
"shortuuid>=1.0.0",
"sse-starlette>=3.4.3",
"sse-starlette>=3.4.4",
"tinydb>=4.8.2",
"typer>=0.25.1",
"uvicorn>=0.46.0",
"uvicorn>=0.48.0",
]
license = "MPL-2.0"
classifiers = [
Expand All @@ -50,7 +50,7 @@ supervaizer = "supervaizer.cli:app"

[project.optional-dependencies]
deploy = [
"boto3>=1.43.6",
"boto3>=1.43.14",
"docker>=7.0.0",
"google-cloud-artifact-registry>=1.21.0",
"google-cloud-run>=0.16.0",
Expand All @@ -69,7 +69,7 @@ dev = [
"pytest-sugar>=1.1.1",
"pytest>=9.0.3",
"respx>=0.23.1",
"ruff>=0.15.12",
"ruff>=0.15.14",
"yamllint>=1.38.0",
"types-deprecated>=1.3.1",
"types-PyYAML>=6.0.0",
Expand Down
8 changes: 8 additions & 0 deletions src/supervaizer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@
"supervaizer.contracts",
"SUPERVAIZER_V2_CONTRACT_VERSION",
),
"AGENT_CUSTOM_ACTION_PREFIX": (
"supervaizer.contracts",
"AGENT_CUSTOM_ACTION_PREFIX",
),
"AGENT_REFRESH_ACTION": ("supervaizer.contracts", "AGENT_REFRESH_ACTION"),
"AGENT_REFRESH_EFFECT": ("supervaizer.contracts", "AGENT_REFRESH_EFFECT"),
"WORKSPACE_BINDING_CREATE_ACTION": (
"supervaizer.contracts",
"WORKSPACE_BINDING_CREATE_ACTION",
Expand Down Expand Up @@ -123,6 +129,8 @@
"V2A2UISubmitDefinition": ("supervaizer.contracts", "V2A2UISubmitDefinition"),
"V2AgentCapabilities": ("supervaizer.contracts", "V2AgentCapabilities"),
"V2AgentIdentity": ("supervaizer.contracts", "V2AgentIdentity"),
"V2AgentMethod": ("supervaizer.contracts", "V2AgentMethod"),
"V2AgentMethods": ("supervaizer.contracts", "V2AgentMethods"),
"V2ArtifactRef": ("supervaizer.contracts", "V2ArtifactRef"),
"V2ArtifactTypeDefinition": (
"supervaizer.contracts",
Expand Down
Loading
Loading