Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,21 @@ coval reports create \
--run-ids run1,run2 \
--compare-by test_case

# Pin a report to specific simulations from a human-review project
coval reports create \
--name "Reviewed Subset" \
--run-ids run1,run2 \
--simulation-output-ids sim1,sim2 \
--source-human-review-project-id 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Unpin it again (a flag can only set a value, so clearing needs an explicit null)
coval reports update <report_id> --input-json '{"simulation_output_ids":null}'

# Add and remove review-project simulations without re-sending the whole set
coval review-projects update <project_id> \
--add-simulation-ids sim3,sim4 \
--remove-simulation-ids sim1

# Merge existing reports into one report with a group per source report
coval reports merge \
--name "Q3 Scorecard" \
Expand Down
20 changes: 3 additions & 17 deletions api-coverage-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ only when coverage actually changes.
| Reviewed gaps | 62 |
| Client operations | 143 |
| Published request fields on covered operations | 363 |
| Request fields modeled by the CLI | 329 |
| Reviewed request-field gaps | 31 |
| Request fields modeled by the CLI | 343 |
| Reviewed request-field gaps | 17 |

Catalog: https://api.coval.dev/v1/openapi

Expand Down Expand Up @@ -50,7 +50,7 @@ Catalog: https://api.coval.dev/v1/openapi
## Coverage snapshot mismatches

- `published_request_fields: recorded 360, current 363`
- `cli_modeled_request_fields: recorded 313, current 329`
- `cli_modeled_request_fields: recorded 313, current 343`

## Client-only operations

Expand Down Expand Up @@ -148,27 +148,13 @@ Catalog: https://api.coval.dev/v1/openapi
- `PATCH /agents/{id} workflows`
- `PATCH /conversations/uploaded/{id} metadata`
- `PATCH /metrics/{id} ivr_flow`
- `PATCH /reports/{id} simulation_output_ids`
- `PATCH /reports/{id} source_human_review_project_id`
- `PATCH /reports/{id} view_config`
- `PATCH /review-projects/{id} add_linked_simulation_ids`
- `PATCH /review-projects/{id} blind_labeling_shown_metric_ids`
- `PATCH /review-projects/{id} enforced_collaboration`
- `PATCH /review-projects/{id} metric_addition_completion_action`
- `PATCH /review-projects/{id} project_rules`
- `PATCH /review-projects/{id} remove_linked_simulation_ids`
- `PATCH /run-templates/{id} agent_id`
- `PATCH /run-templates/{id} persona_id`
- `PATCH /run-templates/{id} tags`
- `PATCH /run-templates/{id} test_set_id`
- `PATCH /test-sets/{id} tags`
- `POST /conversations/uploaded:submit tags`
- `POST /metrics ivr_flow`
- `POST /reports simulation_output_ids`
- `POST /reports source_human_review_project_id`
- `POST /review-projects blind_labeling_shown_metric_ids`
- `POST /review-projects enforced_collaboration`
- `POST /review-projects project_rules`
- `POST /run-templates agent_id`
- `POST /run-templates persona_id`
- `POST /run-templates tags`
Expand Down
70 changes: 0 additions & 70 deletions api-coverage.toml
Original file line number Diff line number Diff line change
Expand Up @@ -421,51 +421,6 @@ operation = "PATCH /conversations/uploaded/{conversation_id}"
field = "metadata"
reason = "The additive customer-metadata patch path is served but unmodeled; tracked under COVAL-5823."

[[known_field_gap]]
operation = "PATCH /reports/{report_id}"
field = "simulation_output_ids"
reason = "Report fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /reports/{report_id}"
field = "source_human_review_project_id"
reason = "Report fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /reports/{report_id}"
field = "view_config"
reason = "Report fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /review-projects/{project_id}"
field = "add_linked_simulation_ids"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /review-projects/{project_id}"
field = "blind_labeling_shown_metric_ids"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /review-projects/{project_id}"
field = "enforced_collaboration"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /review-projects/{project_id}"
field = "metric_addition_completion_action"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /review-projects/{project_id}"
field = "project_rules"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /review-projects/{project_id}"
field = "remove_linked_simulation_ids"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "PATCH /run-templates/{run_template_id}"
field = "agent_id"
Expand Down Expand Up @@ -496,31 +451,6 @@ operation = "POST /conversations/uploaded:submit"
field = "tags"
reason = "Resource tagging on write is served but unmodeled; tracked under COVAL-5823."

[[known_field_gap]]
operation = "POST /reports"
field = "simulation_output_ids"
reason = "Report fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "POST /reports"
field = "source_human_review_project_id"
reason = "Report fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "POST /review-projects"
field = "blind_labeling_shown_metric_ids"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "POST /review-projects"
field = "enforced_collaboration"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "POST /review-projects"
field = "project_rules"
reason = "Review-project fields are served but unmodeled; tracked under COVAL-5822."

[[known_field_gap]]
operation = "POST /run-templates"
field = "agent_id"
Expand Down
24 changes: 24 additions & 0 deletions src/client/models/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ pub enum ReportPermission {
pub struct CreateReportRequest {
pub name: String,
pub run_ids: Vec<String>,
/// Pins the report to a subset of the runs' simulations.
#[serde(skip_serializing_if = "Option::is_none")]
pub simulation_output_ids: Option<Vec<String>>,
/// Human-review project the pinned simulations came from.
#[serde(skip_serializing_if = "Option::is_none")]
pub source_human_review_project_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub compare_by: Option<CompareBy>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -109,10 +115,28 @@ pub struct UpdateReportRequest {
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub run_ids: Option<Vec<String>>,
// The API applies these through `model_fields_set`, so an explicit null unpins
// the report rather than leaving it as it was.
#[serde(
default,
deserialize_with = "super::explicit_option",
skip_serializing_if = "Option::is_none"
)]
pub simulation_output_ids: Option<Option<Vec<String>>>,
#[serde(
default,
deserialize_with = "super::explicit_option",
skip_serializing_if = "Option::is_none"
)]
pub source_human_review_project_id: Option<Option<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub compare_by: Option<CompareBy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata_key: Option<String>,
/// Partial update to the saved view configuration. Its members are validated by
/// the API, and it must never be sent as null.
#[serde(skip_serializing_if = "Option::is_none")]
pub view_config: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permissions: Option<ReportPermission>,
}
Expand Down
27 changes: 27 additions & 0 deletions src/client/models/review_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ pub struct CreateReviewProjectRequest {
pub project_type: Option<ProjectType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub notifications: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project_rules: Option<Vec<String>>,
/// Must be a subset of `linked_metric_ids`.
#[serde(skip_serializing_if = "Option::is_none")]
pub blind_labeling_shown_metric_ids: Option<Vec<String>>,
/// Only takes effect on a collaborative project.
#[serde(skip_serializing_if = "Option::is_none")]
pub enforced_collaboration: Option<bool>,
}

#[derive(Debug, Default, Serialize, Deserialize)]
Expand All @@ -75,6 +83,25 @@ pub struct UpdateReviewProjectRequest {
pub notifications: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub opted_out_assignees: Option<Vec<String>>,
/// Adds to the linked simulations instead of replacing them; cannot be combined
/// with `linked_simulation_ids`.
#[serde(skip_serializing_if = "Option::is_none")]
pub add_linked_simulation_ids: Option<Vec<String>>,
/// Removes from the linked simulations instead of replacing them; cannot be
/// combined with `linked_simulation_ids`.
#[serde(skip_serializing_if = "Option::is_none")]
pub remove_linked_simulation_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project_rules: Option<Vec<String>>,
/// Must be a subset of `linked_metric_ids`.
#[serde(skip_serializing_if = "Option::is_none")]
pub blind_labeling_shown_metric_ids: Option<Vec<String>>,
/// What to do with already-completed assignments when linking a new metric.
#[serde(skip_serializing_if = "Option::is_none")]
pub metric_addition_completion_action: Option<String>,
/// Only takes effect on a collaborative project.
#[serde(skip_serializing_if = "Option::is_none")]
pub enforced_collaboration: Option<bool>,
}

#[derive(Debug, Deserialize)]
Expand Down
43 changes: 43 additions & 0 deletions src/commands/reports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ pub struct CreateArgs {
/// Report layout (default rows)
#[arg(long, value_enum)]
view_mode: Option<ReportViewMode>,
/// Comma-separated simulation IDs pinning the report to a subset of the runs
#[arg(long, value_delimiter = ',')]
simulation_output_ids: Option<Vec<String>>,
/// Human-review project the pinned simulations came from (26-character ULID)
#[arg(long)]
source_human_review_project_id: Option<String>,
/// Report visibility (default PRIVATE)
#[arg(long, value_enum)]
permissions: Option<ReportPermission>,
Expand Down Expand Up @@ -145,6 +151,15 @@ pub struct UpdateArgs {
/// Updated metadata key (only valid when compare-by is metadata)
#[arg(long)]
metadata_key: Option<String>,
/// Updated comma-separated simulation IDs (replaces existing)
#[arg(long, value_delimiter = ',')]
simulation_output_ids: Option<Vec<String>>,
/// Updated human-review project the pinned simulations came from
#[arg(long)]
source_human_review_project_id: Option<String>,
/// JSON partial update to the saved view configuration
#[arg(long)]
view_config: Option<String>,
/// Updated visibility
#[arg(long, value_enum)]
permissions: Option<ReportPermission>,
Expand Down Expand Up @@ -214,6 +229,16 @@ pub async fn execute(cmd: ReportCommands, client: &CovalClient, ctx: &OutputCont
input_json::insert(&mut input, "compare_by", args.compare_by)?;
input_json::insert(&mut input, "metadata_key", args.metadata_key)?;
input_json::insert(&mut input, "view_mode", args.view_mode)?;
input_json::insert(
&mut input,
"simulation_output_ids",
args.simulation_output_ids,
)?;
input_json::insert(
&mut input,
"source_human_review_project_id",
args.source_human_review_project_id,
)?;
input_json::insert(&mut input, "permissions", args.permissions)?;
validate_metadata_key(&input)?;
validate_custom_dimensions(&input)?;
Expand Down Expand Up @@ -246,6 +271,22 @@ pub async fn execute(cmd: ReportCommands, client: &CovalClient, ctx: &OutputCont
input_json::insert(&mut input, "run_ids", args.run_ids)?;
input_json::insert(&mut input, "compare_by", args.compare_by)?;
input_json::insert(&mut input, "metadata_key", args.metadata_key)?;
input_json::insert(
&mut input,
"simulation_output_ids",
args.simulation_output_ids,
)?;
input_json::insert(
&mut input,
"source_human_review_project_id",
args.source_human_review_project_id,
)?;
let view_config: Option<serde_json::Value> = args
.view_config
.map(|raw| serde_json::from_str(&raw))
.transpose()
.map_err(|e| anyhow::anyhow!("Invalid JSON for --view-config: {e}"))?;
input_json::insert(&mut input, "view_config", view_config)?;
input_json::insert(&mut input, "permissions", args.permissions)?;
validate_metadata_key(&input)?;
let req: UpdateReportRequest = input_json::finish(input)?;
Expand Down Expand Up @@ -378,6 +419,8 @@ async fn merge_reports(
let request = CreateReportRequest {
name: args.name,
run_ids,
simulation_output_ids: None,
source_human_review_project_id: None,
compare_by: Some(CompareBy::Custom),
metadata_key: None,
custom_dimensions: Some(vec![ReportCustomDimension {
Expand Down
Loading
Loading