Skip to content

feat: add exact-cover allocation strategy#663

Open
nash87 wants to merge 13 commits into
mainfrom
t-6405-exact-cover-contract
Open

feat: add exact-cover allocation strategy#663
nash87 wants to merge 13 commits into
mainfrom
t-6405-exact-cover-contract

Conversation

@nash87
Copy link
Copy Markdown
Owner

@nash87 nash87 commented May 21, 2026

Adds the exact-cover allocation strategy lane for recommendation constraints while keeping weighted_v1 as the normal default.

Local Nido evidence:

  • fop/local-ci/pr success posted for 9c8e77d
  • report: /var/home/florian/dev/parkhub-rust.t-6405-exact-cover-contract/.fop/reports/local-ci-pr-9c8e77d88c7c9b31b7a312eadc3a01036fcacf23.json

Copilot AI review requested due to automatic review settings May 21, 2026 20:09
@github-actions github-actions Bot added rust Pull requests that update rust code ci docs labels May 21, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c8e77d88c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +167 to +170
let limits = request
.limits
.unwrap_or_default()
.bounded(DEFAULT_MAX_OPTIONS, DEFAULT_MAX_SEARCH_NODES);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply module-config limits before solving exact-cover

The handler currently derives limits only from request.limits plus hardcoded defaults, so the new module settings (allocation_strategy, exact_cover_max_options, exact_cover_max_search_nodes) loaded in RecommendationEngineConfig::load are never enforced here. In practice, an admin can lower exact_cover_max_options in module config and still receive allocations computed with up to 256 options unless every caller also sends per-request limits, which makes the new config surface effectively a no-op.

Useful? React with 👍 / 👎.

Comment on lines +277 to +283
if let Err(err) = app_state.db.save_audit_log(&entry).await {
tracing::warn!(
%trace_id,
error = ?err,
"failed to persist exact-cover allocation audit trace"
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Return error when allocation trace persistence fails

save_audit_log failures are only logged, so the endpoint can return success with an allocation_trace_id even when no trace was persisted. Under DB write failures (e.g., disk/full or transient storage issues), this silently violates the traceability guarantee for served exact-cover allocations and leaves operators with a response ID that has no immutable audit record.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new admin-only exact_cover_v1 allocation lane for batch/recurring recommendation constraints, while keeping weighted_v1 as the default for the standard recommendation workflow.

Changes:

  • Introduces RecommendationAllocationConfig and module settings for allocation strategy + solver limits.
  • Adds a new /api/v1/recommendations/allocation/exact-cover endpoint with auditing + deterministic Algorithm X solver.
  • Adds shared exact-cover fixtures + contract gate checks and updates contract docs.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
scripts/check-recommendation-contract.sh Extends the contract gate to validate exact-cover fixtures and key contract strings.
parkhub-server/src/api/recommendations.rs Adds allocation config to engine config/stats and loads new module settings.
parkhub-server/src/api/recommendation_allocation.rs New exact-cover solver + admin endpoint + audit trace generation + fixtures-based tests.
parkhub-server/src/api/modules/schemas.rs Extends recommendations module schema with allocation strategy and solver limits.
parkhub-server/src/api/mod.rs Wires the new allocation module and POST route.
docs/recommendation-engine-fixtures/exact_cover_v1.*.json Adds parity fixtures to pin exact-cover semantics across implementations.
docs/recommendation-engine-contract.md Documents exact-cover strategy semantics, config boundary, and audit trace requirements.

Comment on lines +161 to +165
let state_guard = state.read().await;
if let Err((status, msg)) = check_admin(&state_guard, &auth_user).await {
return (status, Json(ApiResponse::error("FORBIDDEN", msg)));
}
drop(state_guard);
Comment on lines +174 to +186
{
let state_guard = state.read().await;
audit_exact_cover_allocation(
&state_guard,
allocation_trace_id,
&auth_user,
&request,
limits,
&result,
)
.await;
}

Comment on lines +82 to +86
pub struct RecommendationAllocationConfig {
pub strategy: String,
pub exact_cover_max_options: usize,
pub exact_cover_max_search_nodes: usize,
}
Comment on lines +215 to +226
cfg.allocation.strategy =
read_module_string(db, "allocation_strategy", "weighted_v1").await;
if !matches!(
cfg.allocation.strategy.as_str(),
"weighted_v1" | "exact_cover_v1"
) {
tracing::warn!(
allocation_strategy = %cfg.allocation.strategy,
"unknown allocation strategy requested; falling back to weighted_v1"
);
cfg.allocation.strategy = "weighted_v1".to_string();
}
Comment on lines +618 to +625
fn status_name(status: ExactCoverStatus) -> &'static str {
match status {
ExactCoverStatus::Solved => "solved",
ExactCoverStatus::FallbackNoSolution => "fallback_no_solution",
ExactCoverStatus::FallbackInputLimited => "fallback_input_limited",
ExactCoverStatus::FallbackSearchLimited => "fallback_search_limited",
}
}
Comment on lines +41 to +42
"human_review_required": true,
"note": "Exact-cover allocation is operational scheduling support, not legal advice or a compliance certification."
@@ -358,7 +393,6 @@ pub struct RecommendationQuery {

#[derive(Debug, Clone, Serialize, utoipa::ToSchema)]
pub struct SlotRecommendation {
@nash87 nash87 enabled auto-merge (squash) May 21, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci docs rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants