fix: unblock MR follow-up and simplify orchestration guidance
This commit is contained in:
@@ -1108,7 +1108,7 @@ pub fn description(n: &str) -> Option<&'static str> {
|
||||
"Open one repository-scoped Merge Request linked to the Ticket; reuse an existing Merge Request for that repository and advance only its selector_from with a normal non-force push.",
|
||||
),
|
||||
"CompleteMergeRequest" => Some(
|
||||
"Record Orchestrator-owned integration for the explicitly addressed Merge Request using current trusted exact-source approval and provider evidence. This records an already-applied integration, not a Ticket conclusion or assignment release; a review-not-required Ticket request does not bypass MR integration guards.",
|
||||
"Record an exact-source MR integration receipt using current trusted exact-source approval and provider evidence. This optional recording workflow describes an already-applied integration; it does not update a branch, select which Coder changes to adopt, conclude a Ticket, or release an assignment. Do not record partial or adapted adoption as full integration of the reviewed source.",
|
||||
),
|
||||
"ReviewMergeRequest" => Some(
|
||||
"Submit the injected trusted Reviewer capability result for its captured exact source ref; source movement cancels it, while target-only movement does not. The capability authenticates the attempt, not the verdict: independent natural-language judgment and validation remain the Reviewer's responsibility.",
|
||||
|
||||
@@ -791,58 +791,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn orchestrator_prompt_uses_normal_branch_integration_before_escalation() {
|
||||
fn merge_request_prompts_keep_recording_and_reviewer_contracts() {
|
||||
let catalog = PromptCatalog::builtins_only().unwrap();
|
||||
let prompt = &catalog.projection.templates["role.orchestrator"];
|
||||
|
||||
assert!(prompt.contains("`merge_from`"));
|
||||
assert!(prompt.contains("`merge_to`"));
|
||||
assert!(prompt.contains("normal source-control operations"));
|
||||
assert!(prompt.contains("switch to `merge_to`"));
|
||||
assert!(prompt.contains("concrete source-control or provider failure"));
|
||||
assert!(prompt.contains("does not update the branch itself"));
|
||||
assert!(!prompt.contains("use the Ticket repository `origin` transport"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_request_prompts_use_selector_refs_and_verb_first_operations() {
|
||||
let catalog = PromptCatalog::builtins_only().unwrap();
|
||||
let templates = &catalog.projection.templates;
|
||||
let common = &templates["common.merge_request"];
|
||||
let coder = &templates["role.coder"];
|
||||
let orchestrator = &templates["role.orchestrator"];
|
||||
let reviewer = &templates["role.reviewer"];
|
||||
let combined = format!("{common}\n{coder}\n{orchestrator}\n{reviewer}");
|
||||
|
||||
for operation in [
|
||||
"OpenMergeRequest",
|
||||
"ShowMergeRequest",
|
||||
"ReviewMergeRequest",
|
||||
"CheckMergeRequestReadiness",
|
||||
"CompleteMergeRequest",
|
||||
"TicketCaseUpdate",
|
||||
] {
|
||||
assert!(combined.contains(operation), "missing {operation}");
|
||||
}
|
||||
for stale_operation in [
|
||||
"MergeRequestOpen",
|
||||
"MergeRequestShow",
|
||||
"MergeRequestReview",
|
||||
"MergeRequestReadinessCheck",
|
||||
"MergeRequestComplete",
|
||||
] {
|
||||
assert!(
|
||||
!combined.contains(stale_operation),
|
||||
"stale operation {stale_operation} remains in prompt authority"
|
||||
);
|
||||
}
|
||||
let common = &catalog.projection.templates["common.merge_request"];
|
||||
let reviewer = &catalog.projection.templates["role.reviewer"];
|
||||
assert!(common.contains("selector_from"));
|
||||
assert!(common.contains("selector_to"));
|
||||
assert!(common.contains("normal non-force push"));
|
||||
assert!(common.contains("Moving only the target ref does not invalidate approval"));
|
||||
assert!(common.contains("take precedence over stale Memory"));
|
||||
assert!(coder.contains("Never invent an operation to append another source candidate"));
|
||||
assert!(orchestrator.contains("Target-only movement preserves source approval"));
|
||||
assert!(reviewer.contains("target-only movement does not invalidate approval"));
|
||||
assert!(common.contains("target-only movement preserves approval"));
|
||||
assert!(reviewer.contains("complete linked MR/result snapshot"));
|
||||
assert!(reviewer.contains("Submit `ReviewMergeRequest` once"));
|
||||
assert!(reviewer.contains("without modifying implementation files"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1076,28 +1035,12 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(rendered.contains("This policy governs naming only"));
|
||||
assert!(rendered.contains("Worker cleanup is a separate lifecycle decision"));
|
||||
assert!(rendered.contains("not an automatic consequence of a Ticket state"));
|
||||
assert!(rendered.contains("perform one cleanup pass before ending the orchestration turn"));
|
||||
assert!(rendered.contains("Never predeclare `delete_on_completion`"));
|
||||
assert!(rendered.contains("call `WorkerStop`"));
|
||||
assert!(rendered.contains("call `WorkerRemove`"));
|
||||
assert!(rendered.contains("only then call `WorkdirDelete`"));
|
||||
assert!(rendered.contains("must have no unfinished Ticket work"));
|
||||
assert!(rendered.contains("does not require unassignment before cleanup"));
|
||||
assert!(rendered.contains("`UnfinishedWork` (`unfinished_work` on the wire)"));
|
||||
assert!(rendered.contains("requires explicit work end or reassignment"));
|
||||
assert!(rendered.contains("stop the Worker, remove it, then delete the Workdir"));
|
||||
assert!(rendered.contains("releases attachments but preserves the Workdir"));
|
||||
assert!(
|
||||
rendered.contains("Retained terminal responsibility does not require unassignment")
|
||||
);
|
||||
assert!(rendered.contains("idle or stopped status does not end unfinished work"));
|
||||
for stale_policy in [
|
||||
"no current Ticket assignment",
|
||||
"unassign it through the available orchestration authority",
|
||||
"`CurrentAssignment`",
|
||||
] {
|
||||
assert!(
|
||||
!rendered.contains(stale_policy),
|
||||
"stale cleanup policy: {stale_policy}"
|
||||
);
|
||||
}
|
||||
assert!(!rendered.contains("{% include"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +409,19 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn effective_code_instructions_preserve_independent_review_before_merge() {
|
||||
fn effective_orchestrator_instructions_separate_adoption_from_optional_mr_receipts() {
|
||||
let (without_mr, without_mr_tools) =
|
||||
ticket_workflow_fixture("role.orchestrator", MergeRequestFeatureConfig::default());
|
||||
assert!(without_mr.contains("Select, adapt, or reject Coder changes"));
|
||||
assert!(
|
||||
without_mr.contains("Use Tickets and Merge Requests by default, adapting the workflow when the request calls for a different approach.")
|
||||
);
|
||||
assert!(
|
||||
!without_mr_tools
|
||||
.iter()
|
||||
.any(|meta| meta.name == "CompleteMergeRequest")
|
||||
);
|
||||
|
||||
let (prompt, tools) = ticket_workflow_fixture(
|
||||
"role.orchestrator",
|
||||
MergeRequestFeatureConfig {
|
||||
@@ -419,16 +431,15 @@ mod tests {
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
assert!(prompt.contains("Trusted Reviewer authority"));
|
||||
assert!(
|
||||
prompt.contains(
|
||||
"Target integration and `CompleteMergeRequest` are Orchestrator authority"
|
||||
)
|
||||
);
|
||||
assert!(
|
||||
prompt.contains("does not bypass the guarded review requirements for MR integration")
|
||||
);
|
||||
assert!(prompt.contains("not a universal Ticket pipeline"));
|
||||
for policy in [
|
||||
"Select, adapt, or reject Coder changes",
|
||||
"validate the combined result",
|
||||
"Use Tickets and Merge Requests by default, adapting the workflow when the request calls for a different approach.",
|
||||
"its approval requirement is not a general Git adoption gate",
|
||||
"Partial or adapted adoption is not full MR integration",
|
||||
] {
|
||||
assert!(prompt.contains(policy), "missing {policy}");
|
||||
}
|
||||
assert!(!tools.iter().any(|meta| meta.name == "ReviewMergeRequest"));
|
||||
let complete = tools
|
||||
.iter()
|
||||
@@ -453,7 +464,10 @@ mod tests {
|
||||
for role in ["role.ticket_worker", "role.coder", "role.orchestrator"] {
|
||||
let (prompt, tools) =
|
||||
ticket_workflow_fixture(role, MergeRequestFeatureConfig::default());
|
||||
assert!(prompt.contains("return without conclusion"), "{role}");
|
||||
assert!(
|
||||
prompt.contains("return without concluding the Ticket"),
|
||||
"{role}"
|
||||
);
|
||||
assert!(
|
||||
prompt.contains(
|
||||
"a turn ending or a result report is not itself a completion decision"
|
||||
@@ -534,9 +548,8 @@ mod tests {
|
||||
| "TicketClose"
|
||||
)));
|
||||
if role == "role.orchestrator" {
|
||||
assert!(prompt.contains("observed current `orchestrator_assignment_id`"));
|
||||
assert!(prompt.contains(
|
||||
"generic `WorkerSpawn` Ticket starts and existing-Worker assignment"
|
||||
"`SpawnTicketWorker` using the current `orchestrator_assignment_id`"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user