Skip to main content

winx_code_agent/utils/
orchestration.rs

1use std::fmt::Write as _;
2
3const DEFAULT_INSTRUCTIONS: &str = concat!(
4    "Initialize Winx once for the intended workspace. Treat structuredContent.status as ",
5    "authoritative. Never repeat a failed tool call unchanged: execute next_action and every ",
6    "required_read first. Keep the exact thread_id/workspace_root pair for the user's current ",
7    "project; never borrow one from another chat. workspace_root identifies the session, not a ",
8    "path sandbox: allowed absolute targets outside it do not require rebinding. After a SEARCH ",
9    "conflict, only ReadFiles refreshes the edit guard: execute its exact next_action, then use the ",
10    "returned revision and visible lines in one corrected EditFiles line_patch. Never fall back to ",
11    "shell, sed, or Python for an ordinary source edit. If ",
12    "edit_applied=true or status=completed_with_issues, never repeat the original edit: diagnose ",
13    "verification and make only corrective changes. If Initialize ",
14    "reports initialize_workspace_already_bound or workspace_change_requires_new_session, do not ",
15    "call Initialize again in that conversation. If a reset or mode change follows adapter state ",
16    "loss, accept the recovered first_call result and continue with its returned pair. Request ",
17    "reset_shell only after BashCommand returns a shell-runtime failure; if Winx reports ",
18    "reset_skipped_healthy, continue with the preserved PTY instead of retrying. Use CodeMap ",
19    "with a concise query to locate code, ",
20    "then batch ReadFiles for exact text. Read existing targets before editing; use one EditFiles ",
21    "call for a single change or an atomic cross-file batch. For an existing file read by ReadFiles, ",
22    "default to revision-bound line_patch; reserve search_replace for intentional text anchoring ",
23    "copied exactly from the current read, replace for new files or intentional whole-file rewrites, ",
24    "and undo only with the returned undo_id. Combine related ",
25    "finite checks with && or EditFiles verify_command. For ",
26    "BashCommand, follow next_action only while status is running and never auto-approve a prompt ",
27    "that changes permissions, data, or system state. Use ReadFiles for unsupported CodeMap ",
28    "languages; never transform source solely to make CodeMap parse it. Put useful derived helpers ",
29    "only in the temporary_artifact_dir returned by Initialize (exported as WINX_TEMP_DIR). Keep ",
30    "a small stable set: overwrite or reuse the same descriptive helper per purpose, retain ",
31    "source-path/line provenance, remove obsolete files, and treat helpers as non-canonical. Never turn ",
32    "TTL-expired helpers into durable state: Winx may reclaim them near the session quota. ",
33    "command, lint, test, or search output into a parseable carrier merely to call CodeMap. CodeMap ",
34    "on helpers accepts only an existing single file and has a smaller aggregate session budget; ",
35    "canonical source maps remain available. Never encode payload in names or create .winx-* or ",
36    ".winx_tmp artifacts at the project root."
37);
38
39const DISALLOW_INSTRUCTION: &str = "As soon as you encounter \"The user has chosen to disallow the tool call.\", immediately stop doing everything and ask the user for the reason.";
40
41/// Instructions advertised in the MCP handshake. The stable defaults come
42/// first so clients that truncate this field still receive the orchestration
43/// contract; operator-provided rules are appended without requiring a rebuild.
44pub fn server_instructions() -> String {
45    let mut instructions = format!("{DEFAULT_INSTRUCTIONS}\n\n{DISALLOW_INSTRUCTION}");
46    if let Some(extra) = crate::config::env_text("WINX_SERVER_INSTRUCTIONS") {
47        let _ = write!(instructions, "\n\nOperator instructions:\n{extra}");
48    }
49    instructions
50}
51
52/// Mirror the handshake contract in Initialize output for older clients that
53/// do not surface ServerInfo.instructions to the model.
54pub fn append_initialize_instructions(response: &mut String) {
55    let _ = write!(response, "\n# Winx orchestration contract\n{}\n", server_instructions());
56}
57
58#[cfg(test)]
59mod tests {
60    use super::server_instructions;
61
62    #[test]
63    fn default_contract_names_structured_recovery_before_optional_operator_text() {
64        let instructions = server_instructions();
65        let prefix = instructions.chars().take(512).collect::<String>();
66        assert!(prefix.contains("structuredContent.status"));
67        assert!(prefix.contains("Never repeat a failed tool call unchanged"));
68        assert!(prefix.contains("required_read"));
69        assert!(prefix.contains("thread_id/workspace_root pair"));
70        assert!(prefix.contains("user's current project"));
71        assert!(prefix.contains("not a path sandbox"));
72    }
73
74    #[test]
75    fn default_contract_keeps_agent_artifacts_coherent() {
76        let instructions = server_instructions();
77        assert!(instructions.contains("never transform source solely"));
78        assert!(instructions.contains("Use ReadFiles"));
79        assert!(instructions.contains("temporary_artifact_dir returned by Initialize"));
80        assert!(instructions.contains("exported as WINX_TEMP_DIR"));
81        assert!(instructions.contains("helpers as non-canonical"));
82        assert!(instructions.contains("overwrite or reuse the same descriptive helper"));
83        assert!(instructions.contains("merely to call CodeMap"));
84        assert!(instructions.contains("existing single file"));
85        assert!(instructions.contains("Never encode payload in names"));
86        assert!(instructions.contains(".winx-* or .winx_tmp artifacts"));
87        assert!(instructions.contains("Winx may reclaim them near the session quota"));
88    }
89
90    #[test]
91    fn default_contract_stops_terminal_initialize_retries() {
92        let instructions = server_instructions();
93        assert!(instructions.contains("initialize_workspace_already_bound"));
94        assert!(instructions.contains("workspace_change_requires_new_session"));
95        assert!(instructions.contains("do not call Initialize again"));
96        assert!(instructions.contains("allowed absolute targets outside it"));
97        assert!(instructions.contains("reset_shell only after BashCommand"));
98        assert!(instructions.contains("reset_skipped_healthy"));
99    }
100
101    #[test]
102    fn default_contract_distinguishes_edit_conflicts_from_verification_follow_up() {
103        let instructions = server_instructions();
104        assert!(instructions.contains("only ReadFiles refreshes the edit guard"));
105        assert!(instructions.contains("one corrected EditFiles line_patch"));
106        assert!(instructions.contains("Never fall back to shell, sed, or Python"));
107        assert!(instructions.contains("default to revision-bound line_patch"));
108        assert!(instructions.contains("edit_applied=true"));
109        assert!(instructions.contains("status=completed_with_issues"));
110        assert!(instructions.contains("never repeat the original edit"));
111    }
112}