ОРРКЕСТРАЦИЯ - Усилить domain-loop business-first каноном для analyst и orchestrator

This commit is contained in:
2026-04-14 17:33:57 +03:00
parent f6a2c8e0a3
commit cb0eb450d7
19 changed files with 813 additions and 66 deletions
+20 -1
View File
@@ -2120,6 +2120,7 @@ def build_analyst_loop_prompt(
- `.codex/agents/domain_analyst.toml`
- `.codex/skills/domain-case-loop/SKILL.md`
- `.codex/skills/domain-case-loop/references/verdict_template.md`
- `.codex/skills/domain-case-loop/references/business_first_analyst_rubric.md`
Current loop context:
- loop_dir: `{loop_dir}`
@@ -2135,11 +2136,13 @@ def build_analyst_loop_prompt(
Goal:
- evaluate current domain-pack correctness for business meaning, route/capability quality, evidence quality, and absence of silent heuristic masking;
- evaluate business usefulness, direct-answer-first behavior, state continuity, and field truthfulness, not only technical groundedness;
- determine whether the gate `quality_score >= {target_score}` is reached;
- if not, provide the smallest high-value fix targets for the coder.
Rules:
- `accepted` is allowed only if quality_score >= {target_score}, unresolved_p0_count = 0, and regression_detected = false;
- `accepted` also requires `direct_answer_ok = true` and `business_usefulness_ok = true`;
- `partial` means the pack is usable but exactness, routing, or coverage is still insufficient;
- `needs_exact_capability` means the primary blocker is a missing exact route or capability, but the loop should still continue autonomously unless a user decision is required;
- `continue` means there is a clear next patch cycle;
@@ -2152,6 +2155,10 @@ def build_analyst_loop_prompt(
- if `requires_user_decision = true`, fill `user_decision_type` and `user_decision_prompt`;
- if the pack is below {target_score} but there is still safe autonomous implementation work, keep `requires_user_decision = false`;
- do not request user input merely because the score is still below {target_score}; request it only when the loop would otherwise guess, overfit, or risk architecture drift.
- return machine-readable fields for: `user_intent_summary`, `expected_direct_answer`, `actual_direct_answer`, `direct_answer_ok`, `business_usefulness_ok`, `business_utility_score`, `direct_answer_priority_score`, `state_continuity_score`, `answer_shape_score`, `evidence_clarity_score`, `root_cause_layers`, `broken_edge_ids`, `violated_invariants`;
- if the product found the evidence but failed to retain the selected object, provenance bundle, or another reusable resolved object across turns, classify that as `object_memory_gap` or `edge_carryover_gap`, not as a generic route problem;
- if the surfaced business field looks mislabeled, for example supplier vs organization, classify that as `field_mapping_gap`;
- if the answer is technically grounded but still weak for a manager/accountant/operator, classify that as `business_utility_gap`.
Use this UTF-8 evidence bundle as the source of truth for artifact contents. Do not treat shell rendering artifacts as file corruption if the embedded bundle is readable.
@@ -2196,6 +2203,9 @@ def build_coder_loop_prompt(
- do not present heuristic answers as confirmed;
- do not touch unrelated files;
- preserve already successful baseline flows.
- use `root_cause_layers`, `broken_edge_ids`, `violated_invariants`, and business-utility scores from the analyst verdict to choose the smallest fix;
- prioritize state continuity, selected-object persistence, direct-answer-first behavior, and field-truth mapping when those are the blocking layers;
- do not broaden scope when the analyst says the defect is mainly `object_memory_gap`, `field_mapping_gap`, `answer_shape_mismatch`, or `business_utility_gap`.
Required outputs:
- create `{iteration_dir / 'coder_plan.md'}` with a short plan;
@@ -2217,12 +2227,21 @@ def evaluate_analyst_gate(
quality_score = int(verdict.get("quality_score") or 0)
unresolved_p0_count = int(verdict.get("unresolved_p0_count") or 0)
regression_detected = bool(verdict.get("regression_detected"))
direct_answer_ok = bool(verdict.get("direct_answer_ok", True))
business_usefulness_ok = bool(verdict.get("business_usefulness_ok", True))
loop_decision = str(verdict.get("loop_decision") or "").strip() or "continue"
requires_user_decision = bool(verdict.get("requires_user_decision"))
user_decision_type = str(verdict.get("user_decision_type") or "").strip() or "none"
user_decision_prompt_raw = verdict.get("user_decision_prompt")
user_decision_prompt = str(user_decision_prompt_raw).strip() if user_decision_prompt_raw else None
accepted = quality_score >= target_score and unresolved_p0_count == 0 and not regression_detected and loop_decision == "accepted"
accepted = (
quality_score >= target_score
and unresolved_p0_count == 0
and not regression_detected
and direct_answer_ok
and business_usefulness_ok
and loop_decision == "accepted"
)
return accepted, loop_decision, requires_user_decision, user_decision_type, user_decision_prompt