Improves Captain V1 → V2 migration for complex legacy instructions so mandatory triggers, workflows, language rules, and escalation behavior remain active while query-dependent product knowledge is prepared as pending FAQ candidates. ## What changed - Added explicit preservation rules for mandatory triggers, verification steps, escalation conditions, exceptions, and language behavior. - Added an auditor that checks the draft and fixes any issues before manual review. - Kept the existing migration application contract and schema limits unchanged - Added focused regression coverage for the complex-prompt classifier contract. ## How to reproduce Generate a migration draft for an assistant with dense legacy instructions containing mandatory handoff triggers, verification rules, product facts, and multi-step workflows. The resulting draft should keep actions active, place query-dependent facts in FAQ candidates, and avoid silently dropping or reversing source requirements. Focused Captain migration specs and RuboCop checks pass locally.
90 lines
4.9 KiB
Ruby
90 lines
4.9 KiB
Ruby
class Captain::AssistantMigration::InstructionClassifierSchema < RubyLLM::Schema
|
|
DESCRIPTION_LENGTH_LIMIT = 500
|
|
|
|
def self.instruction_items(field_name, description:, max_items: 20)
|
|
array field_name,
|
|
description: "#{description} Return plain standalone sentences without numbering, bullets, or section labels.",
|
|
max_items: max_items,
|
|
of: :string
|
|
end
|
|
|
|
array :business_product_context,
|
|
description: "Single compact root assistant description for the root orchestrator prompt, maximum #{DESCRIPTION_LENGTH_LIMIT} characters: " \
|
|
'preserve the existing assistant description and enrich it only with relevant business/product context from the ' \
|
|
'custom instructions. Include assistant identity, product scope, high-level mission, and high-level source/routing ' \
|
|
'priorities only. Do not include workflows, procedures, attribute glossaries, policy details, or long inventories. ' \
|
|
'Return complete plain prose without numbering, bullets, section labels, or a truncated final sentence.',
|
|
min_items: 1,
|
|
max_items: 1 do
|
|
string max_length: DESCRIPTION_LENGTH_LIMIT
|
|
end
|
|
|
|
instruction_items :response_guidelines,
|
|
description: 'Tone, language, answer length, formatting, and clarification behavior.',
|
|
max_items: 20
|
|
|
|
instruction_items :guardrails,
|
|
description: 'Refusal rules, escalation boundaries, source boundaries, safety limits, and things the assistant must not do.',
|
|
max_items: 20
|
|
|
|
array :scenario_candidates,
|
|
description: 'Review-stage specialized-agent candidates. These are also temporarily flattened into response guidelines.',
|
|
max_items: 15 do
|
|
object do
|
|
string :title,
|
|
description: 'Short scenario agent title for a distinct user-intent workflow.',
|
|
max_length: 80
|
|
string :description,
|
|
description: 'When this specialized scenario should be used. This is shown to the orchestrator for routing.',
|
|
max_length: 500
|
|
string :instruction,
|
|
description: 'How the specialized agent should handle the workflow. Include only evidence-backed markdown tool links. ' \
|
|
'Do not include confidence labels or review notes.',
|
|
max_length: 2000
|
|
string :response_guideline,
|
|
description: 'Same-language, customer-visible response guideline that preserves this scenario behavior when flattened. ' \
|
|
'Do not include tool syntax, tool names, labels, private-note instructions, or internal implementation details.',
|
|
max_length: 1000
|
|
array :tool_ids,
|
|
description: 'Available tool IDs explicitly referenced in instruction using markdown links. Empty when no tools are required.',
|
|
max_items: 10,
|
|
of: :string
|
|
end
|
|
end
|
|
|
|
object :conversation_messages, description: 'Exact globally reusable customer-facing message copy found in instructions. ' \
|
|
'Leave empty for conditional, placeholder, or workflow-specific copy.' do
|
|
string :welcome_message, description: 'Exact globally reusable initial greeting copy from instructions, or empty string. ' \
|
|
'Do not convert an instruction about greeting into message copy.',
|
|
max_length: 1000
|
|
string :handoff_message,
|
|
description: 'Exact globally reusable human-handoff message copy from instructions, or empty string. ' \
|
|
'Do not use scenario-specific, team-specific, placeholder, or conditional handoff copy.',
|
|
max_length: 1000
|
|
string :resolution_message,
|
|
description: 'Exact globally reusable resolution/closing message copy from instructions, or empty string. ' \
|
|
'Do not use conditional or placeholder closing copy.',
|
|
max_length: 1000
|
|
end
|
|
|
|
array :faq_document_candidates,
|
|
description: 'FAQ candidates for reusable query-dependent facts such as pricing, policy, setup, troubleshooting, ' \
|
|
'or operational details.',
|
|
max_items: 25 do
|
|
object do
|
|
string :question,
|
|
description: 'Natural, standalone customer question about factual product or business knowledge.',
|
|
max_length: 255
|
|
string :answer,
|
|
description: 'Self-contained factual answer using only the existing instructions. Do not include assistant behavior, ' \
|
|
'tool use, or message copy. Preserve exact values, conditions, and exceptions.',
|
|
max_length: 2000
|
|
end
|
|
end
|
|
|
|
instruction_items :needs_review,
|
|
description: 'Unclear, conflicting, risky, duplicated, or uncertain content that needs human review. ' \
|
|
'Include the reason in the item text.',
|
|
max_items: 20
|
|
end
|