/** Pure checks for world settings, Markdown definitions, overlays, and skill frontmatter. */ import assert from 'node:assert/strict' import {readFileSync,readdirSync} from 'node:fs' import {parseConfig,parseDefinition,parseFrontmatter,definitionRuns,toolsFor} from './agents.ts' let count=0 function test(name:string,run:()=>void){run();console.log(`ok ${++count} - ${name}`)} const config=parseConfig(readFileSync('config/config.yaml','utf8')) const definitions=readdirSync('config/roster').sort().map(name=>parseDefinition(readFileSync(`config/roster/${name}`,'utf8'),`config/roster/${name}`)) test('exactly eight built-in Markdown definitions and no inline roster',()=>{ assert.deepEqual(definitions.map(d=>d.name),['coordinator','designer','dream-pass','reviewer','sausage','scout','watcher','worker']) assert.equal(config.roster,undefined);assert.equal(config.main_agent_name,'sausage') for(const d of definitions){ const model=['coordinator','designer','sausage'].includes(d.name)?'anthropic/claude-opus-5-5':d.name==='reviewer'?'openai/gpt-6-astra':['scout','watcher'].includes(d.name)?'openai/gpt-6-luna':'openai/gpt-6.1-sol' assert.equal(d.model,model) assert.equal(d.thinking,['scout','watcher'].includes(d.name)?'low':['worker','dream-pass'].includes(d.name)?'medium':'high') } }) test('shared prompt contains state inspection and current world paths',()=>{ for(const text of ['http://host.sausage/harness/','whoami','conversations/ID/entries?after=N','events?after=N','credential-requests','/proc/processes','/proc/extensions','jaq','/etc/sausage/config.yaml'])assert(config.prompt.includes(text),text) }) test('main role describes direct self-change and state inspection',()=>{ const role=definitions.find(d=>d.name===config.main_agent_name)! assert(role.instructions.includes('Act directly'));assert(role.instructions.includes('instead of guessing')) }) test('filename defines the name and model IDs preserve slashes',()=>{ const d=parseDefinition('---\ndescription: Example\nmodel: local/org/model\n---\nRole','/roster/new-name.md') assert.equal(d.name,'new-name');assert.deepEqual(definitionRuns(d).model,{provider:'local',modelId:'org/model'}) }) test('an additive project overlay retains base settings and appends instructions',()=>{ const base=parseDefinition('---\ndescription: Base\nmodel: local/model\ntools: [read]\n---\nBase instructions','/roster/worker.md') const overlay=parseDefinition('---\naddTools: [bash]\ndenyTools: [read]\n---\nProject instructions','/project/.sausage/roster/worker.md',base) assert.equal(overlay.model,'local/model');assert.deepEqual(toolsFor(overlay,[]),['bash']) assert(overlay.instructions.includes('Base instructions'));assert(overlay.instructions.includes('Project instructions')) }) test('a complete project definition replaces the body',()=>{ const base=definitions.find(d=>d.name==='worker')! const next=parseDefinition('---\ndescription: Project worker\nmodel: local/model\n---\nReplacement','/project/.sausage/roster/worker.md',base) assert.equal(next.instructions,'Replacement') }) test('missing settings and malformed definition fields fail with a path',()=>{ assert.throws(()=>parseConfig('main_agent_name: sausage'),/prompt/) assert.throws(()=>parseConfig('prompt: text'),/main_agent_name/) assert.throws(()=>parseDefinition('---\nmodel: local/model\n---\nRole','/roster/example.md'),/description/) assert.throws(()=>parseDefinition('---\ndescription: Example\nmodel: invalid\n---\nRole','/roster/example.md'),/example.md/) assert.throws(()=>parseDefinition('---\ndescription: Example\nmodel: local/model\nthinking: invalid\n---\nRole','/roster/example.md'),/thinking/) }) test('tool denials do not mutate inherited tools',()=>{ const inherited=['read','bash'];assert.deepEqual(toolsFor({...definitions[0],denyTools:['bash']},inherited),['read']);assert.deepEqual(inherited,['read','bash']) }) test('all built-in skills contain valid YAML frontmatter',()=>{ for(const name of readdirSync('skills',{withFileTypes:true}).filter(e=>e.isDirectory()).map(e=>e.name)){ const skill=parseFrontmatter(readFileSync(`skills/${name}/SKILL.md`,'utf8')) assert.equal(skill.frontmatter.name,name);assert.equal(typeof skill.frontmatter.description,'string');assert(skill.body.length>0) } }) console.log(`${count} tests passed`)