CopilotOperationKey.java
package com.taxonomy.portfolio.service;
import com.taxonomy.portfolio.model.AnalysisAutomationProfile;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** Compact, parseable metadata stored in the existing analysis-job idempotency key. */
public record CopilotOperationKey(
boolean autopilot,
String operationId,
int pass,
int totalPasses,
AnalysisAutomationProfile profile,
boolean proposeSolutions,
boolean proposeProducts) {
private static final Pattern FORMAT = Pattern.compile(
"^(copilot|autopilot):v1:([0-9a-f]{64}):([1-3])/([1-3]):"
+ "(STANDARD|FULL|EXHAUSTIVE):([01])([01])$");
public CopilotOperationKey {
if (operationId == null || !operationId.matches("[0-9a-f]{64}")) {
throw new IllegalArgumentException("operationId must be a lowercase SHA-256 value");
}
if (pass < 1 || totalPasses < 1 || pass > totalPasses || totalPasses > 3) {
throw new IllegalArgumentException("pass must be within the configured 1-3 pass range");
}
if (profile == null) {
throw new IllegalArgumentException("profile is required");
}
}
public String value() {
return (autopilot ? "autopilot" : "copilot")
+ ":v1:" + operationId
+ ":" + pass + "/" + totalPasses
+ ":" + profile.name()
+ ":" + (proposeSolutions ? "1" : "0")
+ (proposeProducts ? "1" : "0");
}
public CopilotOperationKey forPass(int requestedPass) {
return new CopilotOperationKey(
autopilot,
operationId,
requestedPass,
totalPasses,
profile,
proposeSolutions,
proposeProducts);
}
public static Optional<CopilotOperationKey> parse(String value) {
if (value == null) return Optional.empty();
Matcher matcher = FORMAT.matcher(value.strip());
if (!matcher.matches()) return Optional.empty();
int pass = Integer.parseInt(matcher.group(3));
int total = Integer.parseInt(matcher.group(4));
if (pass > total) return Optional.empty();
return Optional.of(new CopilotOperationKey(
"autopilot".equals(matcher.group(1)),
matcher.group(2),
pass,
total,
AnalysisAutomationProfile.valueOf(matcher.group(5).toUpperCase(Locale.ROOT)),
"1".equals(matcher.group(6)),
"1".equals(matcher.group(7))));
}
}