#define _POSIX_C_SOURCE 200809L /* Multi-round prompt contract: default/solo guidance must stay present so * models stop serializing reads, re-fetching truncations, and busy-waiting * on background jobs. */ #include "cst_agent.h" #include "cst_tools.h" #include "cst_test_util.h" #include "os_compat.h" #include #include #include #include #include static int nfail; #define EXPECT(cond, msg) \ do { \ if (!(cond)) { \ fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, msg); \ nfail++; \ } \ } while (0) static void need(const char *p, const char *needle, const char *why) { EXPECT(p && strstr(p, needle), why); } int main(void) { char dir[2048], cfghome[2048]; assert(!test_tmpdir(dir, sizeof(dir), "prompt-contract")); assert(chdir(dir) == 0); /* Isolate settings / parliament meta so host collaboration cannot leak. */ assert(snprintf(cfghome, sizeof(cfghome), "%s/xdg", dir) < (int)sizeof(cfghome)); assert(os_mkdir_p(cfghome, 0700) == 0); setenv("XDG_CONFIG_HOME", cfghome, 1); setenv("CST_COLLABORATION", "legacy_workers", 1); cst_agent_config_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.tool_profile = CST_TOOLS_DEFAULT; snprintf(cfg.workspace_root, sizeof(cfg.workspace_root), "%s", dir); char *solo = cst_agent_build_prompt(&cfg, CST_PROTO_NATIVE_EOS, NULL); need(solo, "run in parallel", "parallel reads"); need(solo, "[truncated bytes=", "truncation protocol"); need(solo, "evidence_read", "evidence follow-up"); need(solo, "Background jobs finished", "job completion note"); need(solo, "polling job_wait", "no busy wait"); need(solo, "Across turns", "multi-turn reuse"); need(solo, "do not restart exploration from scratch", "continue context"); need(solo, "Task control:", "solo task path"); EXPECT(solo && !strstr(solo, "Parliament control:"), "solo not parliament"); free(solo); snprintf(cfg.mode, sizeof(cfg.mode), "general"); char *gen = cst_agent_build_prompt(&cfg, CST_PROTO_NATIVE_EOS, NULL); need(gen, "general-purpose assistant", "general intro"); need(gen, "Across turns", "general multi-turn"); free(gen); cfg.mode[0] = 0; setenv("CST_COLLABORATION", "parliament", 1); char *parl = cst_agent_build_prompt(&cfg, CST_PROTO_NATIVE_EOS, NULL); need(parl, "Parliament control:", "parliament path"); EXPECT(parl && !strstr(parl, "Task control:"), "parliament hides task ctrl"); free(parl); setenv("CST_COLLABORATION", "legacy_workers", 1); cfg.tool_profile = CST_TOOLS_MINIMAL; char *min = cst_agent_build_prompt(&cfg, CST_PROTO_NATIVE_EOS, NULL); EXPECT(min && !strstr(min, "Background jobs finished"), "minimal omits job guidance"); free(min); test_rmrf(dir); if (nfail) { fprintf(stderr, "%d prompt-contract failure(s)\n", nfail); return 1; } puts("test_prompt_contract: OK"); return 0; }