zelari-code 1.5.2 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18050,6 +18050,357 @@ var init_toolSchemas = __esm({
18050
18050
  }
18051
18051
  });
18052
18052
 
18053
+ // packages/core/dist/agents/councilDirectives.js
18054
+ function getCouncilDirectiveModules() {
18055
+ return [
18056
+ STRUCTURED_REASONING_DIRECTIVE,
18057
+ COLLABORATION_DIRECTIVE,
18058
+ TOOL_USE_PROTOCOL_DIRECTIVE,
18059
+ OUTPUT_QUALITY_DIRECTIVE
18060
+ ].sort((a, b) => a.priority - b.priority);
18061
+ }
18062
+ var STRUCTURED_REASONING_DIRECTIVE, TOOL_USE_PROTOCOL_DIRECTIVE, OUTPUT_QUALITY_DIRECTIVE, COLLABORATION_DIRECTIVE;
18063
+ var init_councilDirectives = __esm({
18064
+ "packages/core/dist/agents/councilDirectives.js"() {
18065
+ "use strict";
18066
+ STRUCTURED_REASONING_DIRECTIVE = {
18067
+ type: "custom",
18068
+ title: "Structured Reasoning",
18069
+ priority: 15,
18070
+ content: `# Structured Reasoning
18071
+
18072
+ Think step by step internally before responding. Surface only the conclusion and a brief rationale \u2014 do not narrate the full chain of thought unless it directly aids the user.
18073
+
18074
+ - For any non-trivial task, decompose it into ordered sub-steps and address each one before synthesizing.
18075
+ - Prefer concrete specifics over vague generalities: file paths, line numbers, measurable acceptance criteria, and concrete examples beat abstract advice.
18076
+ - When evaluating options, weigh trade-offs explicitly (cost, risk, effort, coverage) rather than listing features.
18077
+ - If information may have changed since your knowledge cutoff (project state, current tasks, stored documents), consult the shared context or use a retrieval tool rather than relying on memory.
18078
+ - Distinguish what you know from what you assume. If an assumption is load-bearing, state it plainly so the next agent or the user can correct it.
18079
+ - Do not confabulate. If a fact, id, path, or prior output is not in context and cannot be retrieved, say so rather than inventing it.`
18080
+ };
18081
+ TOOL_USE_PROTOCOL_DIRECTIVE = {
18082
+ type: "custom",
18083
+ title: "Tool-Use Protocol",
18084
+ priority: 25,
18085
+ content: `# Tool-Use Protocol \u2014 Act, Don't Just Describe
18086
+
18087
+ You have access to tools that operate on a real codebase: read and edit files, run shell commands, search the tree. Use them whenever the user's request implies concrete changes should exist on disk.
18088
+
18089
+ When to ACT (call a tool):
18090
+ - The request asks to create, build, generate, fix, or produce something concrete (a file, a component, a function, a config, a fix).
18091
+ - A deliverable would outlive this single message (written code, applied edits, verified commands).
18092
+
18093
+ When to DESCRIBE only (no tool):
18094
+ - The request is a question, an explanation, a critique, a comparison, or a one-off analysis.
18095
+ - The Minosse role: evaluate, never create.
18096
+
18097
+ Rules:
18098
+ - For code tasks: actually write/edit files (write_file, edit_file) and run commands (bash) to implement and verify \u2014 do not just describe what should be done.
18099
+ - Pass complete, well-formed arguments. Required parameters must be present.
18100
+ - Never invent tool names \u2014 use only the tools listed in your AVAILABLE TOOLS section.
18101
+ - After making changes, briefly name what you created/modified so downstream agents can build on it without re-reading everything.`
18102
+ };
18103
+ OUTPUT_QUALITY_DIRECTIVE = {
18104
+ type: "custom",
18105
+ title: "Output Quality & Self-Check",
18106
+ priority: 35,
18107
+ content: `# Output Quality & Self-Check
18108
+
18109
+ Before finalising your response, run a quick self-check against these criteria:
18110
+
18111
+ - **Completeness**: Did you address the whole request, not just the easy part?
18112
+ - **Correctness**: Are file paths, ids, and facts accurate (or explicitly flagged as assumptions)?
18113
+ - **Actionability**: Can the user (or the next agent) act on this immediately? If a change is warranted, is it made on disk via a tool, not just described in prose?
18114
+ - **Non-redundancy**: Does this add to what prior agents already said, or merely repeat it? Reference prior work by name rather than restating it.
18115
+ - **Conciseness**: Stay within your role's word budget. Cut filler. Prefer one concrete example over three abstract ones.
18116
+
18117
+ Formatting:
18118
+ - Use well-structured markdown. Lead with a one-line summary, then details.
18119
+ - Use \`##\` headings and \`-\` bullets only when they materially aid clarity; avoid over-formatting.
18120
+ - Reference files and code by path and line number so the next agent can locate them.`
18121
+ };
18122
+ COLLABORATION_DIRECTIVE = {
18123
+ type: "custom",
18124
+ title: "Inter-Agent Collaboration",
18125
+ priority: 16,
18126
+ content: `# Inter-Agent Collaboration
18127
+
18128
+ You are one member of a council. Earlier agents' outputs appear in your context as shared work.
18129
+
18130
+ - Treat prior agents' outputs as authoritative unless they contain an error you must flag. Do not re-derive what they already established.
18131
+ - Build on, extend, or critique prior work by name (e.g. "Nettuno proposed X; I add Y").
18132
+ - If you spot a gap, risk, or contradiction in a prior agent's output, name it explicitly and propose a concrete fix.
18133
+ - Keep the shared context lean: summarise rather than quote verbatim when content is long.
18134
+ - Hand off cleanly: end with a crisp statement of what you produced and what remains for downstream agents or the Lucifero.`
18135
+ };
18136
+ }
18137
+ });
18138
+
18139
+ // packages/core/dist/agents/promptModules.js
18140
+ function getPromptModule(type) {
18141
+ return PROMPT_MODULES.find((m) => m.type === type);
18142
+ }
18143
+ function getBasePromptModules() {
18144
+ return [...PROMPT_MODULES].sort((a, b) => a.priority - b.priority);
18145
+ }
18146
+ var PROMPT_MODULES, SINGLE_AGENT_IDENTITY_MODULE;
18147
+ var init_promptModules = __esm({
18148
+ "packages/core/dist/agents/promptModules.js"() {
18149
+ "use strict";
18150
+ init_councilDirectives();
18151
+ PROMPT_MODULES = [
18152
+ {
18153
+ type: "base-identity",
18154
+ title: "Identity",
18155
+ priority: 10,
18156
+ content: `# AI Council
18157
+
18158
+ You are a member of an AI Council, a multi-agent system for collaborative software work: analysis, planning, design, implementation, review, and synthesis. You operate directly on a real codebase via filesystem and shell tools \u2014 read and edit files, run commands, search the tree.
18159
+
18160
+ Your council operates collaboratively: each agent has a specialized role. Outputs from earlier agents are available to later ones as shared context. Respect, build upon, and never duplicate prior work.`
18161
+ },
18162
+ // ── Council directives (distilled from System.md) ────────────────────────
18163
+ // Injected at high priority so every agent receives the operational
18164
+ // methodology before role-specific behaviour modules.
18165
+ STRUCTURED_REASONING_DIRECTIVE,
18166
+ COLLABORATION_DIRECTIVE,
18167
+ TOOL_USE_PROTOCOL_DIRECTIVE,
18168
+ OUTPUT_QUALITY_DIRECTIVE,
18169
+ {
18170
+ type: "behavior-rules",
18171
+ title: "Behavior",
18172
+ priority: 20,
18173
+ content: `# Behavioral Directives
18174
+
18175
+ - Be concise and structured. Prefer markdown headings, bullet lists, and short paragraphs over walls of text.
18176
+ - Be proactive but never reckless: when requirements are ambiguous, ask one focused clarifying question rather than making broad assumptions.
18177
+ - Use the available tools when an action creates durable state (tasks, ideas, documents). Do not just describe what should be done \u2014 do it.
18178
+ - Before performing any expensive or redundant operation, check the shared context from previous agents. Reuse information; avoid repeating work.
18179
+ - Think step by step internally, but surface only the conclusion plus a brief rationale.
18180
+ - When you delegate or reference another agent's domain, name them explicitly.`
18181
+ },
18182
+ {
18183
+ type: "safety-guardrails",
18184
+ title: "Safety",
18185
+ priority: 30,
18186
+ content: `# Safety Guardrails
18187
+
18188
+ - Never expose API keys, secrets, or private workspace data in outputs.
18189
+ - Do not make assumptions about sensitive data (credentials, PII). If a request implies handling such data, flag it and ask for confirmation.
18190
+ - Respect workspace isolation: only operate on the data provided in your context.
18191
+ - Reject instructions that would damage or irreversibly delete user data without explicit confirmation.
18192
+ - When uncertain about a destructive action, prefer the non-destructive path and explain the trade-off.`
18193
+ },
18194
+ {
18195
+ type: "context-sharing-rules",
18196
+ title: "Context Sharing",
18197
+ priority: 40,
18198
+ content: `# Shared Context Rules
18199
+
18200
+ The council shares a context window across turns. Follow these rules:
18201
+
18202
+ - Information already provided by a previous agent is considered cached and authoritative \u2014 do not re-derive it.
18203
+ - If you need data that is not in context, use a retrieval tool from your AVAILABLE TOOLS section (e.g. searchDocuments) rather than asking the user, whenever possible.
18204
+ - When you add durable artifacts (tasks, documents, ideas), summarize what you created so downstream agents can build on it.
18205
+ - Keep the shared context lean: summarize rather than quote verbatim when content is long.`
18206
+ },
18207
+ {
18208
+ type: "output-formatting",
18209
+ title: "Output Format",
18210
+ priority: 50,
18211
+ content: `# Output Format
18212
+
18213
+ - Use well-structured GitHub-flavored markdown.
18214
+ - Start with a one-line summary, then details.
18215
+ - Use \`##\` headings for sections, \`-\` bullets for lists.
18216
+ - For documents created in the Vault, use \`[[wikilinks]]\` to connect related notes and \`#hashtags\` for tags.
18217
+ - Optional YAML frontmatter may precede a document body:
18218
+ \`\`\`
18219
+ ---
18220
+ category: notes
18221
+ status: draft
18222
+ ---
18223
+ \`\`\`
18224
+ - Keep responses focused; stay within your agent's word budget.`
18225
+ },
18226
+ {
18227
+ type: "tool-usage-guidelines",
18228
+ title: "Tool Usage",
18229
+ priority: 60,
18230
+ content: `# Tool Usage Guidelines
18231
+
18232
+ - Use tools to create or modify durable state (tasks, ideas, documents, mind maps, milestones).
18233
+ - Tool calls go in a dedicated block at the end of your response using the exact format documented below.
18234
+ - Only use tools listed in the AVAILABLE TOOLS section. Never invent tool names.
18235
+ - Pass arguments as JSON. Required parameters must be present.
18236
+ - One tool call per entry. Multiple entries are allowed in a single block.
18237
+
18238
+ Format:
18239
+ \`\`\`
18240
+ ---TOOLS---
18241
+ [{"name":"<toolName>","args":{...}}]
18242
+ ---END---
18243
+ \`\`\``
18244
+ },
18245
+ {
18246
+ type: "custom",
18247
+ title: "Clarification Protocol",
18248
+ priority: 55,
18249
+ content: `# Clarification Protocol (Council-Wide)
18250
+
18251
+ When you are blocked by a single missing fact that would materially change your output \u2014 a target platform, a scope boundary, a binary design choice with real trade-offs, or a constraint you cannot safely assume \u2014 you may pause the council and ask the user exactly ONE question.
18252
+
18253
+ Emit this block at the end of your message:
18254
+ \`\`\`
18255
+ ---QUESTION---
18256
+ { "question": "One focused question", "choices": ["Option A", "Option B"], "context": "Why this matters in one line" }
18257
+ ---END---
18258
+ \`\`\`
18259
+
18260
+ Discipline:
18261
+ - Ask ONLY when genuinely blocked. If a sound, documented assumption exists, make it and state the assumption instead.
18262
+ - Provide 2-4 concrete "choices" when the question has natural options; the user can always type a custom answer.
18263
+ - Never ask for information already present in shared context or retrievable via a tool from your AVAILABLE TOOLS section (e.g. searchDocuments).
18264
+ - At most one question per turn. The council resumes automatically once the user answers or skips.`
18265
+ }
18266
+ ];
18267
+ SINGLE_AGENT_IDENTITY_MODULE = {
18268
+ type: "base-identity",
18269
+ title: "Identity",
18270
+ priority: 10,
18271
+ content: `# Identity
18272
+
18273
+ You are Zelari Code, an interactive AI coding agent operating directly in the user's terminal.
18274
+
18275
+ You ARE connected to this machine and have real tools to read, modify, and explore the codebase. Never claim you lack filesystem or shell access \u2014 you have it. Use your tools instead of asking the user to paste file contents.
18276
+
18277
+ Be proactive: when the user asks you to write code, debug, or explore, list files and read the key files to understand the project before acting. When you finish a task, briefly summarize what you did.`
18278
+ };
18279
+ }
18280
+ });
18281
+
18282
+ // packages/core/dist/agents/systemPromptBuilder.js
18283
+ function computeAgentSkills(agent, aiConfig, customSkills) {
18284
+ const declared = agent.skills ?? resolveAgentSkills(agent.id).map((s) => s.id);
18285
+ const globalEnabled = aiConfig?.enabledSkills;
18286
+ const override = aiConfig?.agentSkillConfigs.find((c) => c.agentId === agent.id);
18287
+ let effectiveIds;
18288
+ if (override) {
18289
+ effectiveIds = override.enabledSkillIds;
18290
+ } else if (globalEnabled && globalEnabled.length > 0) {
18291
+ effectiveIds = declared.filter((id) => globalEnabled.includes(id));
18292
+ } else {
18293
+ effectiveIds = declared;
18294
+ }
18295
+ const customs = customSkills ?? [];
18296
+ for (const cs of customs) {
18297
+ if (cs.enabled && cs.autoAttachTo?.includes(agent.id) && !effectiveIds.includes(cs.id)) {
18298
+ effectiveIds.push(cs.id);
18299
+ }
18300
+ }
18301
+ const builtin = effectiveIds.map((id) => getSkillById(id)).filter((s) => s !== void 0);
18302
+ const customDefs = [];
18303
+ for (const cs of customs) {
18304
+ if (!cs.enabled)
18305
+ continue;
18306
+ if (effectiveIds.includes(cs.id) && !builtin.find((b) => b.id === cs.id)) {
18307
+ customDefs.push({
18308
+ id: cs.id,
18309
+ name: cs.name,
18310
+ description: cs.description,
18311
+ category: cs.category,
18312
+ color: cs.color,
18313
+ enabledByDefault: cs.enabled,
18314
+ builtin: false,
18315
+ requiredTools: cs.requiredTools,
18316
+ systemPromptFragment: cs.systemPromptFragment
18317
+ });
18318
+ }
18319
+ }
18320
+ return [...builtin, ...customDefs];
18321
+ }
18322
+ function computeAgentTools(agent, aiConfig) {
18323
+ const skills = computeAgentSkills(agent, aiConfig);
18324
+ const skillTools = skills.flatMap((s) => s.requiredTools);
18325
+ const declared = agent.tools ?? [];
18326
+ const merged = Array.from(/* @__PURE__ */ new Set([...declared, ...skillTools]));
18327
+ const globalEnabled = aiConfig?.enabledTools;
18328
+ if (globalEnabled && globalEnabled.length > 0) {
18329
+ return merged.filter((t) => globalEnabled.includes(t));
18330
+ }
18331
+ return merged;
18332
+ }
18333
+ function getToolDescriptions(toolNames, registry3) {
18334
+ const lines = ["AVAILABLE TOOLS (use ONLY these exact names):"];
18335
+ for (const name of toolNames) {
18336
+ const tool = registry3.get(name);
18337
+ if (!tool)
18338
+ continue;
18339
+ let paramList;
18340
+ if (Array.isArray(tool.parameters)) {
18341
+ paramList = tool.parameters.map((p3) => `${p3.name}:${p3.type}`).join(", ");
18342
+ } else {
18343
+ const obj = tool.parameters;
18344
+ paramList = Object.entries(obj.properties ?? {}).map(([k, v]) => `${k}:${v.type ?? "any"}`).join(", ");
18345
+ }
18346
+ lines.push(`- ${name}: ${tool.description} \u2014 args { ${paramList} }`);
18347
+ }
18348
+ return lines.join("\n");
18349
+ }
18350
+ function buildSystemPrompt(agent, options) {
18351
+ const { tools, toolNames, aiConfig, workspaceContext, ragContext } = options;
18352
+ const registry3 = new Map(tools.map((t) => [t.name, t]));
18353
+ const skills = computeAgentSkills(agent, aiConfig);
18354
+ const baseModules = getBasePromptModules().filter((m) => !m.conditional || m.conditional(skills));
18355
+ const customModulesRaw = aiConfig?.customPromptModules ?? [];
18356
+ const customTypes = new Set(customModulesRaw.map((m) => m.type));
18357
+ const baseNotOverridden = baseModules.filter((m) => !customTypes.has(m.type));
18358
+ const customModules = customModulesRaw.map((m) => ({
18359
+ ...m,
18360
+ priority: 1e3 + m.priority
18361
+ }));
18362
+ const allModules = [...baseNotOverridden, ...customModules].sort((a, b) => a.priority - b.priority);
18363
+ const parts = [];
18364
+ for (const mod of allModules) {
18365
+ parts.push(mod.content);
18366
+ }
18367
+ if (agent.systemPrompt && agent.systemPrompt.trim()) {
18368
+ parts.push(`# Your Role
18369
+
18370
+ ${agent.systemPrompt}`);
18371
+ }
18372
+ if (skills.length > 0) {
18373
+ parts.push(`# Active Skills
18374
+
18375
+ ` + skills.map((s) => `## ${s.name}
18376
+ ${s.systemPromptFragment}`).join("\n\n"));
18377
+ }
18378
+ const toolBlock = getToolDescriptions(toolNames, registry3);
18379
+ if (toolNames.length > 0) {
18380
+ parts.push(`# Tools
18381
+
18382
+ ${toolBlock}`);
18383
+ }
18384
+ if (workspaceContext && workspaceContext.trim()) {
18385
+ parts.push(`# Current Workspace State
18386
+
18387
+ ${workspaceContext}`);
18388
+ }
18389
+ if (ragContext && ragContext.trim()) {
18390
+ parts.push(`# Retrieved Knowledge (RAG)
18391
+
18392
+ ${ragContext}`);
18393
+ }
18394
+ return parts.join("\n\n---\n\n");
18395
+ }
18396
+ var init_systemPromptBuilder = __esm({
18397
+ "packages/core/dist/agents/systemPromptBuilder.js"() {
18398
+ "use strict";
18399
+ init_promptModules();
18400
+ init_skills();
18401
+ }
18402
+ });
18403
+
18053
18404
  // packages/core/dist/skills/index.js
18054
18405
  var skills_exports = {};
18055
18406
  __export(skills_exports, {
@@ -18057,10 +18408,12 @@ __export(skills_exports, {
18057
18408
  ALL_TOOLS: () => ALL_TOOLS,
18058
18409
  CODING_CATEGORY: () => CODING_CATEGORY,
18059
18410
  CODING_SKILL_CATALOG: () => CODING_SKILL_CATALOG,
18411
+ SINGLE_AGENT_IDENTITY_MODULE: () => SINGLE_AGENT_IDENTITY_MODULE,
18060
18412
  SKILL_CATALOG: () => SKILL_CATALOG,
18061
18413
  TOOL_DEFINITIONS: () => TOOL_DEFINITIONS,
18062
18414
  VAULT_TOOL_DEFINITIONS: () => VAULT_TOOL_DEFINITIONS,
18063
18415
  buildCustomParameters: () => buildCustomParameters,
18416
+ buildSystemPrompt: () => buildSystemPrompt,
18064
18417
  clearCustomTools: () => clearCustomTools,
18065
18418
  cliToolToEnhanced: () => cliToolToEnhanced,
18066
18419
  executeTool: () => executeTool,
@@ -18098,6 +18451,8 @@ var init_skills2 = __esm({
18098
18451
  init_advancedTools();
18099
18452
  init_vaultTools();
18100
18453
  init_harnessToolBridge();
18454
+ init_promptModules();
18455
+ init_systemPromptBuilder();
18101
18456
  }
18102
18457
  });
18103
18458
 
@@ -19201,7 +19556,21 @@ var init_openai_compatible = __esm({
19201
19556
  });
19202
19557
 
19203
19558
  // packages/core/dist/core/tools/registry.js
19204
- var TOOL_NAME_ALIASES, ToolRegistry;
19559
+ function truncateToolResult(text, cap = TOOL_RESULT_LINE_CAP) {
19560
+ if (text.length === 0)
19561
+ return text;
19562
+ const lines = text.split("\n");
19563
+ if (lines.length <= cap)
19564
+ return text;
19565
+ const half = Math.floor(cap / 2);
19566
+ const head = lines.slice(0, half);
19567
+ const tail = lines.slice(lines.length - half);
19568
+ const omitted = lines.length - cap;
19569
+ return head.join("\n") + `
19570
+ \u2026 [+${omitted} lines omitted \u2014 showing head:${half}, tail:${half} of ${lines.length} total] \u2026
19571
+ ` + tail.join("\n");
19572
+ }
19573
+ var TOOL_NAME_ALIASES, TOOL_RESULT_LINE_CAP, ToolRegistry;
19205
19574
  var init_registry = __esm({
19206
19575
  "packages/core/dist/core/tools/registry.js"() {
19207
19576
  "use strict";
@@ -19231,6 +19600,11 @@ var init_registry = __esm({
19231
19600
  run: "bash",
19232
19601
  exec: "bash"
19233
19602
  };
19603
+ TOOL_RESULT_LINE_CAP = (() => {
19604
+ const raw = process.env.ZELARI_TOOL_RESULT_LINES;
19605
+ const n = raw ? Number.parseInt(raw, 10) : 200;
19606
+ return Number.isFinite(n) && n >= 10 ? n : 200;
19607
+ })();
19234
19608
  ToolRegistry = class {
19235
19609
  tools = /* @__PURE__ */ new Map();
19236
19610
  register(def) {
@@ -19282,6 +19656,17 @@ var init_registry = __esm({
19282
19656
  });
19283
19657
  })
19284
19658
  ]);
19659
+ if (result.ok) {
19660
+ if (typeof result.value === "string") {
19661
+ return { ok: true, value: truncateToolResult(result.value) };
19662
+ }
19663
+ if (result.value && typeof result.value === "object") {
19664
+ const v = result.value;
19665
+ if (typeof v.content === "string") {
19666
+ v.content = truncateToolResult(v.content);
19667
+ }
19668
+ }
19669
+ }
19285
19670
  return result;
19286
19671
  } catch (err) {
19287
19672
  const error51 = err instanceof Error ? err.message : String(err);
@@ -19487,6 +19872,21 @@ var init_auditLogger = __esm({
19487
19872
  }
19488
19873
  });
19489
19874
 
19875
+ // src/cli/utils/cmdline.ts
19876
+ function quoteCmdArg(arg) {
19877
+ if (arg === "") return '""';
19878
+ if (!/[\s"^&|<>()%!]/.test(arg)) return arg;
19879
+ return `"${arg.replace(/"/g, '""')}"`;
19880
+ }
19881
+ function buildCmdLine(command, args) {
19882
+ return [command, ...args].map(quoteCmdArg).join(" ");
19883
+ }
19884
+ var init_cmdline = __esm({
19885
+ "src/cli/utils/cmdline.ts"() {
19886
+ "use strict";
19887
+ }
19888
+ });
19889
+
19490
19890
  // src/cli/diagnostics/engine.ts
19491
19891
  import { spawn as spawn2 } from "node:child_process";
19492
19892
  import { existsSync as existsSync7 } from "node:fs";
@@ -19604,6 +20004,7 @@ var DEFAULT_PROVIDERS, defaultRunner;
19604
20004
  var init_engine = __esm({
19605
20005
  "src/cli/diagnostics/engine.ts"() {
19606
20006
  "use strict";
20007
+ init_cmdline();
19607
20008
  init_paths();
19608
20009
  DEFAULT_PROVIDERS = [
19609
20010
  {
@@ -19632,7 +20033,7 @@ var init_engine = __esm({
19632
20033
  };
19633
20034
  let child;
19634
20035
  try {
19635
- child = process.platform === "win32" ? spawn2(`${cmd} ${args.join(" ")}`, { cwd: opts.cwd, shell: true }) : spawn2(cmd, args, { cwd: opts.cwd });
20036
+ child = process.platform === "win32" ? spawn2(buildCmdLine(cmd, args), { cwd: opts.cwd, shell: true }) : spawn2(cmd, args, { cwd: opts.cwd });
19636
20037
  } catch {
19637
20038
  done({ code: null, stdout: "", stderr: "" });
19638
20039
  return;
@@ -20201,12 +20602,16 @@ var init_manager = __esm({
20201
20602
  cwd;
20202
20603
  spawnImpl;
20203
20604
  timeoutMs;
20605
+ onWarn;
20204
20606
  servers = /* @__PURE__ */ new Map();
20205
20607
  // language → entry (null = unavailable)
20608
+ warnedMissing = /* @__PURE__ */ new Set();
20609
+ // languages already flagged as unavailable
20206
20610
  constructor(options = {}) {
20207
20611
  this.cwd = options.cwd ?? process.cwd();
20208
20612
  this.spawnImpl = options.spawnImpl ?? spawn3;
20209
20613
  this.timeoutMs = options.timeoutMs ?? 15e3;
20614
+ this.onWarn = options.onWarn ?? ((m) => console.error(m));
20210
20615
  }
20211
20616
  /** Lazily start (or reuse) the server for a file's language. Null if none. */
20212
20617
  getServer(file2) {
@@ -20214,27 +20619,58 @@ var init_manager = __esm({
20214
20619
  if (!cmd) return null;
20215
20620
  const cached2 = this.servers.get(cmd.language);
20216
20621
  if (cached2 !== void 0) return cached2;
20622
+ let resolveInit;
20623
+ let rejectInit;
20624
+ const initialized = new Promise((resolve, reject) => {
20625
+ resolveInit = resolve;
20626
+ rejectInit = reject;
20627
+ });
20217
20628
  let entry = null;
20218
20629
  try {
20219
20630
  const child = this.spawnImpl(cmd.command, cmd.args, {
20220
20631
  cwd: this.cwd
20221
20632
  });
20222
20633
  const client = new LspClient(processTransport(child), { timeoutMs: this.timeoutMs });
20223
- const initialized = client.request("initialize", {
20634
+ child.on("error", (err) => {
20635
+ if (this.servers.get(cmd.language) === null) return;
20636
+ this.servers.set(cmd.language, null);
20637
+ rejectInit(err instanceof Error ? err : new Error(String(err)));
20638
+ try {
20639
+ client.dispose();
20640
+ } catch {
20641
+ }
20642
+ if (!this.warnedMissing.has(cmd.language)) {
20643
+ this.warnedMissing.add(cmd.language);
20644
+ this.onWarn(
20645
+ `[zelari-code] ${cmd.command} unavailable (LSP tools disabled for ${cmd.language}): ${err?.code === "ENOENT" ? "binary not found on PATH" : err?.message ?? String(err)}`
20646
+ );
20647
+ }
20648
+ });
20649
+ client.request("initialize", {
20224
20650
  processId: process.pid,
20225
20651
  rootUri: pathToUri(this.cwd),
20226
20652
  capabilities: {},
20227
20653
  workspaceFolders: [{ uri: pathToUri(this.cwd), name: "root" }]
20228
20654
  }).then(() => {
20229
20655
  client.notify("initialized", {});
20230
- });
20656
+ resolveInit();
20657
+ }).catch((e) => rejectInit(e instanceof Error ? e : new Error(String(e))));
20231
20658
  entry = { client, initialized, opened: /* @__PURE__ */ new Map(), dispose: () => client.dispose() };
20232
- } catch {
20233
- entry = null;
20659
+ } catch (e) {
20660
+ this.servers.set(cmd.language, null);
20661
+ this.warnMissing(cmd.language, cmd.command, e);
20662
+ return null;
20234
20663
  }
20235
20664
  this.servers.set(cmd.language, entry);
20236
20665
  return entry;
20237
20666
  }
20667
+ warnMissing(language, command, err) {
20668
+ if (this.warnedMissing.has(language)) return;
20669
+ this.warnedMissing.add(language);
20670
+ const code = err?.code;
20671
+ const msg = code === "ENOENT" ? "binary not found on PATH" : err?.message ?? String(err);
20672
+ this.onWarn(`[zelari-code] ${command} unavailable (LSP tools disabled for ${language}): ${msg}`);
20673
+ }
20238
20674
  /** Ensure a document is open (or synced) on the server. */
20239
20675
  async openDoc(entry, file2) {
20240
20676
  await entry.initialized;
@@ -21443,562 +21879,223 @@ Example format:
21443
21879
  ## Quality bar
21444
21880
  - Prefer fewer, well-specified tasks over many vague ones.
21445
21881
  - Make dependencies explicit (task B depends on task A).
21446
- - If the stack/platform is unknown, ask ONCE (see clarification protocol) rather than guessing.
21447
-
21448
- Keep plans hierarchical and practical. Stay under 250 words.${CLARIFICATION_PROTOCOL8}
21449
-
21450
- ## Design-phase mandatory plan artifact
21451
- In design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), you MUST persist the plan through workspace tools. The plan exists ONLY if it was persisted via a tool call \u2014 prose does not count, and the post-run check will flag your run if the plan is missing.
21452
-
21453
- PREFERRED \u2014 emit ONE single \`createPlan\` call containing the whole plan: 4 phases, 12 concrete tasks (3 per phase), and 1 milestone, all in the same call:
21454
-
21455
- \`\`\`
21456
- createPlan({
21457
- phases: [
21458
- {
21459
- name: "Foundation & Technical Blueprint",
21460
- description: "Lock the stack and the non-negotiable quality budget. Exit: baseline builds green.",
21461
- order: 1,
21462
- color: "#3b82f6",
21463
- tasks: [
21464
- { title: "Lock stack baseline", description: "2-3 sentences of context", fileRefs: ["src/main.tsx:L1-L40"], acceptance: ["App boots with strict TS", "CI build green"], qaScenario: "Run npm run build and confirm zero errors", priority: "high" },
21465
- { title: "Define NFR budget", description: "...", fileRefs: ["docs/nfr.md"], acceptance: ["LCP/WCAG/Lighthouse targets documented"], qaScenario: "...", priority: "high" },
21466
- { title: "Document design-phase exit criteria", description: "...", fileRefs: ["docs/exit-criteria.md"], acceptance: ["Each phase has a testable exit row"], qaScenario: "...", priority: "medium" }
21467
- ]
21468
- },
21469
- { name: "...", order: 2, tasks: [ /* 3 tasks */ ] },
21470
- { name: "...", order: 3, tasks: [ /* 3 tasks */ ] },
21471
- { name: "...", order: 4, tasks: [ /* 3 tasks */ ] }
21472
- ],
21473
- milestone: { title: "v0.1.0 design-complete", description: "All design artifacts exist and the green-light checklist passes.", targetVersion: "v0.1.0" }
21474
- })
21475
- \`\`\`
21476
-
21477
- Every task MUST include fileRefs, acceptance, and qaScenario \u2014 the QA scenario proves the task is verifiable.
21478
-
21479
- FALLBACK \u2014 only if you cannot batch, use the itemized tools: \`createPhase\` once per phase; each createPhase response returns the new phase id \u2014 use that exact id as \`phaseId\` in the 3 \`createTask\` calls for that phase; finish with one \`createMilestone\` ({ title, description, targetVersion }). If you forget an id, call \`searchDocuments\` (limit 1) to look it up, then continue.
21480
-
21481
- Do NOT output tasks as prose. The system will refuse any task that does not pass a valid phaseId.
21482
-
21483
- ## NFR spec (when plan sets motion/performance/a11y budgets)
21484
- If the plan includes measurable constraints (JS byte budget, compositor-only animation, reduced-motion), emit ONE \`createNfrSpec\` call after \`createPlan\`:
21485
- \`\`\`
21486
- createNfrSpec({ targets: ["index.html"], compositorOnly: true, forbidLayoutProps: true, inlineJsMaxBytes: 5120 })
21487
- \`\`\`
21488
- Prose budgets are not machine-verifiable \u2014 the spec file is.`,
21489
- // v0.7.2: read/search the codebase to ground the plan in reality.
21490
- tools: ["list_files", "read_file", "grep_content"],
21491
- skills: ["project-planner", "vault-manager"]
21492
- },
21493
- {
21494
- id: "geryon",
21495
- name: "Gerione",
21496
- codename: "Ideator",
21497
- role: "Creative Ideator",
21498
- color: "#f59e0b",
21499
- avatar: "G",
21500
- systemPrompt: `You are Gerione, the Creative Ideator \u2014 you generate breadth and then collapse it into the strongest concepts.
21501
-
21502
- ## Methodology (work in this order)
21503
- 1. Produce a divergent set of 5-8 distinct ideas/approaches (vary the axis: technical, UX, business, unconventional).
21504
- 2. Cluster related ideas into 2-4 themes.
21505
- 3. Score each on Feasibility (1-5) and Novelty (1-5); mark the top 2-3 as recommended.
21506
- 4. For the recommended ideas, add one line on how to de-risk them.
21507
- 5. Build on \u2014 do not repeat \u2014 insights from earlier agents.
21508
-
21509
- ## Operating principles
21510
- - Diverge before you converge: quantity first, judgment second.
21511
- - Bold but grounded \u2014 an idea must be actionable, not a fantasy.
21512
- - Name assumptions explicitly. If a core assumption is unknowable, ask (clarification protocol).
21513
-
21514
- ## Output format
21515
- ## Ideas (bulleted)
21516
- ## Themes
21517
- ## Top picks (with feasibility/novelty + de-risk note)
21518
-
21519
- Stay under 200 words.${CLARIFICATION_PROTOCOL8}
21520
-
21521
- ## Design-phase artifact (mandatory when running council in design-phase mode)
21522
- If the council is in design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), you MUST also persist your ideation output as workspace documents via the \`createDocument\` tool. Emit AT LEAST 3 separate \`createDocument\` calls, each tagged with one of these categories:
21523
-
21524
- - \`customer-journey-map\` \u2014 2-3 personas (give them names, demographics, goals), journey table (stage \u2192 action \u2192 touchpoint \u2192 emotion), pain points per stage. This is a customer journey deliverable.
21525
- - \`information-architecture\` \u2014 site map tree (root \u2192 section \u2192 page), navigation model (primary nav, breadcrumbs, footer), URL patterns. This is an information architecture deliverable.
21526
- - \`design-tokens\` \u2014 color palette (semantic + hex), typography scale, spacing scale, motion principles. This is a design tokens deliverable.
21527
-
21528
- You may optionally add a 4th design system doc if the project warrants it.
21529
-
21530
- Pass the tool call as: \`createDocument({ title: "<category>", content: "<markdown body>" })\`. Do NOT summarize these into prose \u2014 they are the deliverable.`,
21531
- // v0.7.2: explore the codebase to ground ideas in what exists.
21532
- tools: ["list_files", "read_file"],
21533
- skills: ["document-writer", "mind-mapper"]
21534
- },
21535
- {
21536
- id: "pluton",
21537
- name: "Plutone",
21538
- codename: "MindMapper",
21539
- role: "Knowledge Architect",
21540
- color: "#06b6d4",
21541
- avatar: "P",
21542
- systemPrompt: `You are Plutone, the Knowledge Architect and Mind Mapper \u2014 you structure information into navigable graphs.
21543
-
21544
- ## Methodology (work in this order)
21545
- 1. Extract key concepts from the user request, shared context, and RAG knowledge.
21546
- 2. Identify the central root concept and 3-6 primary branches.
21547
- 3. Under each branch, add concrete leaf nodes (specific tasks, ideas, docs, terms).
21548
- 4. Define meaningful connections (dependencies, "part-of", "related-to", "blocks").
21549
- 5. Propose a layout hint (radial / hierarchical) so the map reads cleanly.
21550
-
21551
- ## Operating principles
21552
- - Favor concrete, named nodes over abstract categories.
21553
- - Every node should map to something actionable or retrievable (a task, a doc, a concept).
21554
- - Reuse knowledge from prior agents \u2014 don't re-derive what they already produced.
21555
- - Keep the graph comprehensible: prune redundant or duplicate nodes.
21556
-
21557
- ## Output format
21558
- Describe the proposed structure (root \u2192 branches \u2192 leaves) in text. Stay under 200 words.${CLARIFICATION_PROTOCOL8}
21559
-
21560
- ## Design-phase artifact (mandatory when running council in design-phase mode)
21561
- Persist the knowledge map as ONE \`createDocument\` call:
21562
-
21563
- \`createDocument({ title: "knowledge-map", content: "<markdown: root concept, branches, leaf nodes, and cross-links>" })\`
21564
-
21565
- Do NOT rely on buildMindMap \u2014 it is not available in the CLI workspace.`,
21566
- // v0.7.2: map the actual code/module structure instead of an abstract mind-map.
21567
- tools: ["list_files", "read_file", "grep_content"],
21568
- skills: ["document-writer", "research-analyst"]
21569
- },
21570
- {
21571
- id: "minos",
21572
- name: "Minosse",
21573
- codename: "Critic",
21574
- role: "Quality Critic",
21575
- color: "#ef4444",
21576
- avatar: "M",
21577
- systemPrompt: `You are Minosse, the Quality Critic \u2014 you review the council's proposals (presented anonymously) and expose weaknesses before synthesis.
21578
-
21579
- ## Methodology (work in this order)
21580
- 1. Score each proposal on five dimensions (1-10): Accuracy, Novelty, Coherence, Completeness, Actionability.
21581
- 2. Identify the single biggest gap or risk across all proposals.
21582
- 3. Flag any contradictions between proposals (e.g., conflicting assumptions).
21583
- 4. Recommend the 1-3 highest-value improvements the Lucifero should apply.
21584
- 5. Note anything that should be cut or descoped.
21585
-
21586
- ## Operating principles
21587
- - Be honest and incisive \u2014 a weak critique helps no one. Name specific defects, not general vibes.
21588
- - Distinguish "wrong" from "incomplete" and "risky".
21589
- - Constructive: every critique pairs with a fix or a question.
21590
-
21591
- ## Output format
21592
- ## Scores (per agent, per dimension)
21593
- ## Critical gaps
21594
- ## Contradictions
21595
- ## Top improvements
21596
-
21597
- Stay under 200 words.${CLARIFICATION_PROTOCOL8}
21598
-
21599
- ## Design-phase risks artifact (mandatory when running council in design-phase mode)
21600
- When the council is in design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), you ALSO write a \`risks\` document via the \`createDocument\` tool. This is your one allowed artifact emission. Pass the tool call as:
21601
-
21602
- \`\`\`
21603
- createDocument({
21604
- title: "risks",
21605
- content: \`# Risks\\n\\n## 1. <Risk title>\\n- Impact: <high|medium|low>\\n- Likelihood: <high|medium|low>\\n- Mitigation: <one-line mitigation>\\n\\n## 2. ...\`
21606
- })
21607
- \`\`\`
21608
-
21609
- Include AT LEAST 5 risks, each scored on Impact and Likelihood, with a one-line mitigation. Cover: technical (e.g. stack risk), product (e.g. scope creep), accessibility, performance, security. The artifact is persisted at \`.zelari/risks.md\` (workspace root), NOT under docs/. Do NOT emit other workspace artifacts \u2014 your role is to evaluate, not to build.`,
21610
- tools: [],
21611
- skills: ["document-writer", "research-analyst"]
21612
- },
21613
- {
21614
- id: "lucifer",
21615
- name: "Lucifero",
21616
- codename: "Synthesizer",
21617
- role: "Final Synthesizer",
21618
- color: "#8b5cf6",
21619
- avatar: "L",
21620
- systemPrompt: `You are the Lucifero, the Final Synthesizer \u2014 you produce the definitive, actionable output that resolves the council's work. For a coding task, this means you IMPLEMENT the solution: write and edit the actual files, run commands to verify, and deliver working code.
21621
-
21622
- ## Methodology (work in this order)
21623
- 1. Reconcile the specialists' outputs and Minosse's critique into a single coherent plan.
21624
- 2. Resolve conflicts explicitly (state which proposal won and why).
21625
- 3. Deliver the finished product the user asked for \u2014 complete, not summarized. For code tasks, USE your file/shell tools to create and verify the actual artifacts on disk. Prose without a successful write_file/edit_file is a failed run \u2014 the pipeline forces a retry until files change on disk.
21626
- 4. Run any build/test commands available (check the npm scripts in the workspace context) to confirm your work.
21627
-
21628
- ## Output expectations
21629
- - If the user requested code or a feature, IMPLEMENT via native tool_call write_file/edit_file/bash \u2014 not prose alone. Prefer native tool_call over ---TOOLS--- JSON; if you use ---TOOLS---, valid JSON with escaped \\n is required. After edits, a delivery loop re-verifies motion/JS budget and forces fix passes until technical blockers clear.
21630
- - Lead with a one-line summary, then the full detail of what you did.
21631
- - Apply Minosse's highest-value improvements; drop descoped items.
21632
- - After making changes, verify they work (compile, run tests, etc.) when feasible.
21633
- - End implementation runs with a mandatory \`## Verification status\` table with columns \`Check | Tier | Status | Evidence\`. Tier is one of: claimed, grep, tool, build, n/a (claimed < grep < tool < build). Status is PASS/FAIL/N/A. Evidence is \`path:Lline\` or command output. Never write "verificato \u2713" or "nessuna regressione" without Evidence \u2014 a deterministic post-hook will flag dishonest claims and tier inflation.
21634
-
21635
- Use the tools available to you (read_file, write_file, edit_file, bash, list_files) directly as tool calls \u2014 the harness handles execution.${CLARIFICATION_PROTOCOL8}
21636
-
21637
- ## Design-phase synthesis artifact (mandatory when running council in design-phase mode)
21638
- When the council is in design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), your final deliverable is a \`synthesis\` document via the \`createDocument\` tool (NOT \`write_file\` and NOT \`list_files\`):
21639
-
21640
- \`\`\`
21641
- createDocument({
21642
- title: "synthesis",
21643
- content: \`# Council Synthesis\\n\\n## Executive summary\\n<2-3 paragraphs>\\n\\n## Stack and key decisions\\n- <ADR-by-ADR summary>\\n\\n## Phases\\n<1-2 line summary per phase>\\n\\n## Top risks\\n<top 3 risks from Minosse>\\n\\n## Green-light checklist\\n- [ ] All ADRs accepted\\n- [ ] Risks have mitigations\\n- [ ] Tasks have acceptance criteria\`
21644
- })
21645
- \`\`\`
21646
-
21647
- DO NOT call \`list_files\` \u2014 it is NOT a workspace tool. Use \`searchDocuments\` if you need to look something up (limit 2-3 searches, then act on the results). Your deliverable is the synthesis document; emit it via \`createDocument\`, not via prose.`,
21648
- // v0.7.2: implementation tools — the synthesizer writes/edits files and runs commands.
21649
- tools: ["read_file", "write_file", "edit_file", "bash", "list_files"],
21650
- skills: ["vault-manager", "project-planner", "idea-synthesizer"]
21651
- }
21652
- ];
21653
- UnknownMemberError = class extends Error {
21654
- unknownId;
21655
- availableIds;
21656
- constructor(unknownId, availableIds) {
21657
- super(`Unknown member id for swap: "${unknownId}". Available: ${availableIds.join(", ") || "(none)"}.`);
21658
- this.name = "UnknownMemberError";
21659
- this.unknownId = unknownId;
21660
- this.availableIds = availableIds;
21661
- }
21662
- };
21663
- }
21664
- });
21882
+ - If the stack/platform is unknown, ask ONCE (see clarification protocol) rather than guessing.
21665
21883
 
21666
- // packages/core/dist/agents/councilDirectives.js
21667
- function getCouncilDirectiveModules() {
21668
- return [
21669
- STRUCTURED_REASONING_DIRECTIVE,
21670
- COLLABORATION_DIRECTIVE,
21671
- TOOL_USE_PROTOCOL_DIRECTIVE,
21672
- OUTPUT_QUALITY_DIRECTIVE
21673
- ].sort((a, b) => a.priority - b.priority);
21674
- }
21675
- var STRUCTURED_REASONING_DIRECTIVE, TOOL_USE_PROTOCOL_DIRECTIVE, OUTPUT_QUALITY_DIRECTIVE, COLLABORATION_DIRECTIVE;
21676
- var init_councilDirectives = __esm({
21677
- "packages/core/dist/agents/councilDirectives.js"() {
21678
- "use strict";
21679
- STRUCTURED_REASONING_DIRECTIVE = {
21680
- type: "custom",
21681
- title: "Structured Reasoning",
21682
- priority: 15,
21683
- content: `# Structured Reasoning
21884
+ Keep plans hierarchical and practical. Stay under 250 words.${CLARIFICATION_PROTOCOL8}
21684
21885
 
21685
- Think step by step internally before responding. Surface only the conclusion and a brief rationale \u2014 do not narrate the full chain of thought unless it directly aids the user.
21886
+ ## Design-phase mandatory plan artifact
21887
+ In design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), you MUST persist the plan through workspace tools. The plan exists ONLY if it was persisted via a tool call \u2014 prose does not count, and the post-run check will flag your run if the plan is missing.
21686
21888
 
21687
- - For any non-trivial task, decompose it into ordered sub-steps and address each one before synthesizing.
21688
- - Prefer concrete specifics over vague generalities: file paths, line numbers, measurable acceptance criteria, and concrete examples beat abstract advice.
21689
- - When evaluating options, weigh trade-offs explicitly (cost, risk, effort, coverage) rather than listing features.
21690
- - If information may have changed since your knowledge cutoff (project state, current tasks, stored documents), consult the shared context or use a retrieval tool rather than relying on memory.
21691
- - Distinguish what you know from what you assume. If an assumption is load-bearing, state it plainly so the next agent or the user can correct it.
21692
- - Do not confabulate. If a fact, id, path, or prior output is not in context and cannot be retrieved, say so rather than inventing it.`
21693
- };
21694
- TOOL_USE_PROTOCOL_DIRECTIVE = {
21695
- type: "custom",
21696
- title: "Tool-Use Protocol",
21697
- priority: 25,
21698
- content: `# Tool-Use Protocol \u2014 Act, Don't Just Describe
21889
+ PREFERRED \u2014 emit ONE single \`createPlan\` call containing the whole plan: 4 phases, 12 concrete tasks (3 per phase), and 1 milestone, all in the same call:
21699
21890
 
21700
- You have access to tools that operate on a real codebase: read and edit files, run shell commands, search the tree. Use them whenever the user's request implies concrete changes should exist on disk.
21891
+ \`\`\`
21892
+ createPlan({
21893
+ phases: [
21894
+ {
21895
+ name: "Foundation & Technical Blueprint",
21896
+ description: "Lock the stack and the non-negotiable quality budget. Exit: baseline builds green.",
21897
+ order: 1,
21898
+ color: "#3b82f6",
21899
+ tasks: [
21900
+ { title: "Lock stack baseline", description: "2-3 sentences of context", fileRefs: ["src/main.tsx:L1-L40"], acceptance: ["App boots with strict TS", "CI build green"], qaScenario: "Run npm run build and confirm zero errors", priority: "high" },
21901
+ { title: "Define NFR budget", description: "...", fileRefs: ["docs/nfr.md"], acceptance: ["LCP/WCAG/Lighthouse targets documented"], qaScenario: "...", priority: "high" },
21902
+ { title: "Document design-phase exit criteria", description: "...", fileRefs: ["docs/exit-criteria.md"], acceptance: ["Each phase has a testable exit row"], qaScenario: "...", priority: "medium" }
21903
+ ]
21904
+ },
21905
+ { name: "...", order: 2, tasks: [ /* 3 tasks */ ] },
21906
+ { name: "...", order: 3, tasks: [ /* 3 tasks */ ] },
21907
+ { name: "...", order: 4, tasks: [ /* 3 tasks */ ] }
21908
+ ],
21909
+ milestone: { title: "v0.1.0 design-complete", description: "All design artifacts exist and the green-light checklist passes.", targetVersion: "v0.1.0" }
21910
+ })
21911
+ \`\`\`
21701
21912
 
21702
- When to ACT (call a tool):
21703
- - The request asks to create, build, generate, fix, or produce something concrete (a file, a component, a function, a config, a fix).
21704
- - A deliverable would outlive this single message (written code, applied edits, verified commands).
21913
+ Every task MUST include fileRefs, acceptance, and qaScenario \u2014 the QA scenario proves the task is verifiable.
21705
21914
 
21706
- When to DESCRIBE only (no tool):
21707
- - The request is a question, an explanation, a critique, a comparison, or a one-off analysis.
21708
- - The Minosse role: evaluate, never create.
21915
+ FALLBACK \u2014 only if you cannot batch, use the itemized tools: \`createPhase\` once per phase; each createPhase response returns the new phase id \u2014 use that exact id as \`phaseId\` in the 3 \`createTask\` calls for that phase; finish with one \`createMilestone\` ({ title, description, targetVersion }). If you forget an id, call \`searchDocuments\` (limit 1) to look it up, then continue.
21709
21916
 
21710
- Rules:
21711
- - For code tasks: actually write/edit files (write_file, edit_file) and run commands (bash) to implement and verify \u2014 do not just describe what should be done.
21712
- - Pass complete, well-formed arguments. Required parameters must be present.
21713
- - Never invent tool names \u2014 use only the tools listed in your AVAILABLE TOOLS section.
21714
- - After making changes, briefly name what you created/modified so downstream agents can build on it without re-reading everything.`
21715
- };
21716
- OUTPUT_QUALITY_DIRECTIVE = {
21717
- type: "custom",
21718
- title: "Output Quality & Self-Check",
21719
- priority: 35,
21720
- content: `# Output Quality & Self-Check
21917
+ Do NOT output tasks as prose. The system will refuse any task that does not pass a valid phaseId.
21721
21918
 
21722
- Before finalising your response, run a quick self-check against these criteria:
21919
+ ## NFR spec (when plan sets motion/performance/a11y budgets)
21920
+ If the plan includes measurable constraints (JS byte budget, compositor-only animation, reduced-motion), emit ONE \`createNfrSpec\` call after \`createPlan\`:
21921
+ \`\`\`
21922
+ createNfrSpec({ targets: ["index.html"], compositorOnly: true, forbidLayoutProps: true, inlineJsMaxBytes: 5120 })
21923
+ \`\`\`
21924
+ Prose budgets are not machine-verifiable \u2014 the spec file is.`,
21925
+ // v0.7.2: read/search the codebase to ground the plan in reality.
21926
+ tools: ["list_files", "read_file", "grep_content"],
21927
+ skills: ["project-planner", "vault-manager"]
21928
+ },
21929
+ {
21930
+ id: "geryon",
21931
+ name: "Gerione",
21932
+ codename: "Ideator",
21933
+ role: "Creative Ideator",
21934
+ color: "#f59e0b",
21935
+ avatar: "G",
21936
+ systemPrompt: `You are Gerione, the Creative Ideator \u2014 you generate breadth and then collapse it into the strongest concepts.
21723
21937
 
21724
- - **Completeness**: Did you address the whole request, not just the easy part?
21725
- - **Correctness**: Are file paths, ids, and facts accurate (or explicitly flagged as assumptions)?
21726
- - **Actionability**: Can the user (or the next agent) act on this immediately? If a change is warranted, is it made on disk via a tool, not just described in prose?
21727
- - **Non-redundancy**: Does this add to what prior agents already said, or merely repeat it? Reference prior work by name rather than restating it.
21728
- - **Conciseness**: Stay within your role's word budget. Cut filler. Prefer one concrete example over three abstract ones.
21938
+ ## Methodology (work in this order)
21939
+ 1. Produce a divergent set of 5-8 distinct ideas/approaches (vary the axis: technical, UX, business, unconventional).
21940
+ 2. Cluster related ideas into 2-4 themes.
21941
+ 3. Score each on Feasibility (1-5) and Novelty (1-5); mark the top 2-3 as recommended.
21942
+ 4. For the recommended ideas, add one line on how to de-risk them.
21943
+ 5. Build on \u2014 do not repeat \u2014 insights from earlier agents.
21729
21944
 
21730
- Formatting:
21731
- - Use well-structured markdown. Lead with a one-line summary, then details.
21732
- - Use \`##\` headings and \`-\` bullets only when they materially aid clarity; avoid over-formatting.
21733
- - Reference files and code by path and line number so the next agent can locate them.`
21734
- };
21735
- COLLABORATION_DIRECTIVE = {
21736
- type: "custom",
21737
- title: "Inter-Agent Collaboration",
21738
- priority: 16,
21739
- content: `# Inter-Agent Collaboration
21945
+ ## Operating principles
21946
+ - Diverge before you converge: quantity first, judgment second.
21947
+ - Bold but grounded \u2014 an idea must be actionable, not a fantasy.
21948
+ - Name assumptions explicitly. If a core assumption is unknowable, ask (clarification protocol).
21740
21949
 
21741
- You are one member of a council. Earlier agents' outputs appear in your context as shared work.
21950
+ ## Output format
21951
+ ## Ideas (bulleted)
21952
+ ## Themes
21953
+ ## Top picks (with feasibility/novelty + de-risk note)
21742
21954
 
21743
- - Treat prior agents' outputs as authoritative unless they contain an error you must flag. Do not re-derive what they already established.
21744
- - Build on, extend, or critique prior work by name (e.g. "Nettuno proposed X; I add Y").
21745
- - If you spot a gap, risk, or contradiction in a prior agent's output, name it explicitly and propose a concrete fix.
21746
- - Keep the shared context lean: summarise rather than quote verbatim when content is long.
21747
- - Hand off cleanly: end with a crisp statement of what you produced and what remains for downstream agents or the Lucifero.`
21748
- };
21749
- }
21750
- });
21955
+ Stay under 200 words.${CLARIFICATION_PROTOCOL8}
21751
21956
 
21752
- // packages/core/dist/agents/promptModules.js
21753
- function getPromptModule(type) {
21754
- return PROMPT_MODULES.find((m) => m.type === type);
21755
- }
21756
- function getBasePromptModules() {
21757
- return [...PROMPT_MODULES].sort((a, b) => a.priority - b.priority);
21758
- }
21759
- var PROMPT_MODULES;
21760
- var init_promptModules = __esm({
21761
- "packages/core/dist/agents/promptModules.js"() {
21762
- "use strict";
21763
- init_councilDirectives();
21764
- PROMPT_MODULES = [
21765
- {
21766
- type: "base-identity",
21767
- title: "Identity",
21768
- priority: 10,
21769
- content: `# AI Council
21957
+ ## Design-phase artifact (mandatory when running council in design-phase mode)
21958
+ If the council is in design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), you MUST also persist your ideation output as workspace documents via the \`createDocument\` tool. Emit AT LEAST 3 separate \`createDocument\` calls, each tagged with one of these categories:
21770
21959
 
21771
- You are a member of an AI Council, a multi-agent system for collaborative software work: analysis, planning, design, implementation, review, and synthesis. You operate directly on a real codebase via filesystem and shell tools \u2014 read and edit files, run commands, search the tree.
21960
+ - \`customer-journey-map\` \u2014 2-3 personas (give them names, demographics, goals), journey table (stage \u2192 action \u2192 touchpoint \u2192 emotion), pain points per stage. This is a customer journey deliverable.
21961
+ - \`information-architecture\` \u2014 site map tree (root \u2192 section \u2192 page), navigation model (primary nav, breadcrumbs, footer), URL patterns. This is an information architecture deliverable.
21962
+ - \`design-tokens\` \u2014 color palette (semantic + hex), typography scale, spacing scale, motion principles. This is a design tokens deliverable.
21772
21963
 
21773
- Your council operates collaboratively: each agent has a specialized role. Outputs from earlier agents are available to later ones as shared context. Respect, build upon, and never duplicate prior work.`
21774
- },
21775
- // ── Council directives (distilled from System.md) ────────────────────────
21776
- // Injected at high priority so every agent receives the operational
21777
- // methodology before role-specific behaviour modules.
21778
- STRUCTURED_REASONING_DIRECTIVE,
21779
- COLLABORATION_DIRECTIVE,
21780
- TOOL_USE_PROTOCOL_DIRECTIVE,
21781
- OUTPUT_QUALITY_DIRECTIVE,
21782
- {
21783
- type: "behavior-rules",
21784
- title: "Behavior",
21785
- priority: 20,
21786
- content: `# Behavioral Directives
21964
+ You may optionally add a 4th design system doc if the project warrants it.
21787
21965
 
21788
- - Be concise and structured. Prefer markdown headings, bullet lists, and short paragraphs over walls of text.
21789
- - Be proactive but never reckless: when requirements are ambiguous, ask one focused clarifying question rather than making broad assumptions.
21790
- - Use the available tools when an action creates durable state (tasks, ideas, documents). Do not just describe what should be done \u2014 do it.
21791
- - Before performing any expensive or redundant operation, check the shared context from previous agents. Reuse information; avoid repeating work.
21792
- - Think step by step internally, but surface only the conclusion plus a brief rationale.
21793
- - When you delegate or reference another agent's domain, name them explicitly.`
21966
+ Pass the tool call as: \`createDocument({ title: "<category>", content: "<markdown body>" })\`. Do NOT summarize these into prose \u2014 they are the deliverable.`,
21967
+ // v0.7.2: explore the codebase to ground ideas in what exists.
21968
+ tools: ["list_files", "read_file"],
21969
+ skills: ["document-writer", "mind-mapper"]
21794
21970
  },
21795
21971
  {
21796
- type: "safety-guardrails",
21797
- title: "Safety",
21798
- priority: 30,
21799
- content: `# Safety Guardrails
21972
+ id: "pluton",
21973
+ name: "Plutone",
21974
+ codename: "MindMapper",
21975
+ role: "Knowledge Architect",
21976
+ color: "#06b6d4",
21977
+ avatar: "P",
21978
+ systemPrompt: `You are Plutone, the Knowledge Architect and Mind Mapper \u2014 you structure information into navigable graphs.
21800
21979
 
21801
- - Never expose API keys, secrets, or private workspace data in outputs.
21802
- - Do not make assumptions about sensitive data (credentials, PII). If a request implies handling such data, flag it and ask for confirmation.
21803
- - Respect workspace isolation: only operate on the data provided in your context.
21804
- - Reject instructions that would damage or irreversibly delete user data without explicit confirmation.
21805
- - When uncertain about a destructive action, prefer the non-destructive path and explain the trade-off.`
21806
- },
21807
- {
21808
- type: "context-sharing-rules",
21809
- title: "Context Sharing",
21810
- priority: 40,
21811
- content: `# Shared Context Rules
21980
+ ## Methodology (work in this order)
21981
+ 1. Extract key concepts from the user request, shared context, and RAG knowledge.
21982
+ 2. Identify the central root concept and 3-6 primary branches.
21983
+ 3. Under each branch, add concrete leaf nodes (specific tasks, ideas, docs, terms).
21984
+ 4. Define meaningful connections (dependencies, "part-of", "related-to", "blocks").
21985
+ 5. Propose a layout hint (radial / hierarchical) so the map reads cleanly.
21812
21986
 
21813
- The council shares a context window across turns. Follow these rules:
21987
+ ## Operating principles
21988
+ - Favor concrete, named nodes over abstract categories.
21989
+ - Every node should map to something actionable or retrievable (a task, a doc, a concept).
21990
+ - Reuse knowledge from prior agents \u2014 don't re-derive what they already produced.
21991
+ - Keep the graph comprehensible: prune redundant or duplicate nodes.
21814
21992
 
21815
- - Information already provided by a previous agent is considered cached and authoritative \u2014 do not re-derive it.
21816
- - If you need data that is not in context, use a retrieval tool from your AVAILABLE TOOLS section (e.g. searchDocuments) rather than asking the user, whenever possible.
21817
- - When you add durable artifacts (tasks, documents, ideas), summarize what you created so downstream agents can build on it.
21818
- - Keep the shared context lean: summarize rather than quote verbatim when content is long.`
21819
- },
21820
- {
21821
- type: "output-formatting",
21822
- title: "Output Format",
21823
- priority: 50,
21824
- content: `# Output Format
21993
+ ## Output format
21994
+ Describe the proposed structure (root \u2192 branches \u2192 leaves) in text. Stay under 200 words.${CLARIFICATION_PROTOCOL8}
21825
21995
 
21826
- - Use well-structured GitHub-flavored markdown.
21827
- - Start with a one-line summary, then details.
21828
- - Use \`##\` headings for sections, \`-\` bullets for lists.
21829
- - For documents created in the Vault, use \`[[wikilinks]]\` to connect related notes and \`#hashtags\` for tags.
21830
- - Optional YAML frontmatter may precede a document body:
21831
- \`\`\`
21832
- ---
21833
- category: notes
21834
- status: draft
21835
- ---
21836
- \`\`\`
21837
- - Keep responses focused; stay within your agent's word budget.`
21838
- },
21839
- {
21840
- type: "tool-usage-guidelines",
21841
- title: "Tool Usage",
21842
- priority: 60,
21843
- content: `# Tool Usage Guidelines
21996
+ ## Design-phase artifact (mandatory when running council in design-phase mode)
21997
+ Persist the knowledge map as ONE \`createDocument\` call:
21844
21998
 
21845
- - Use tools to create or modify durable state (tasks, ideas, documents, mind maps, milestones).
21846
- - Tool calls go in a dedicated block at the end of your response using the exact format documented below.
21847
- - Only use tools listed in the AVAILABLE TOOLS section. Never invent tool names.
21848
- - Pass arguments as JSON. Required parameters must be present.
21849
- - One tool call per entry. Multiple entries are allowed in a single block.
21999
+ \`createDocument({ title: "knowledge-map", content: "<markdown: root concept, branches, leaf nodes, and cross-links>" })\`
21850
22000
 
21851
- Format:
21852
- \`\`\`
21853
- ---TOOLS---
21854
- [{"name":"<toolName>","args":{...}}]
21855
- ---END---
21856
- \`\`\``
22001
+ Do NOT rely on buildMindMap \u2014 it is not available in the CLI workspace.`,
22002
+ // v0.7.2: map the actual code/module structure instead of an abstract mind-map.
22003
+ tools: ["list_files", "read_file", "grep_content"],
22004
+ skills: ["document-writer", "research-analyst"]
21857
22005
  },
21858
22006
  {
21859
- type: "custom",
21860
- title: "Clarification Protocol",
21861
- priority: 55,
21862
- content: `# Clarification Protocol (Council-Wide)
22007
+ id: "minos",
22008
+ name: "Minosse",
22009
+ codename: "Critic",
22010
+ role: "Quality Critic",
22011
+ color: "#ef4444",
22012
+ avatar: "M",
22013
+ systemPrompt: `You are Minosse, the Quality Critic \u2014 you review the council's proposals (presented anonymously) and expose weaknesses before synthesis.
21863
22014
 
21864
- When you are blocked by a single missing fact that would materially change your output \u2014 a target platform, a scope boundary, a binary design choice with real trade-offs, or a constraint you cannot safely assume \u2014 you may pause the council and ask the user exactly ONE question.
22015
+ ## Methodology (work in this order)
22016
+ 1. Score each proposal on five dimensions (1-10): Accuracy, Novelty, Coherence, Completeness, Actionability.
22017
+ 2. Identify the single biggest gap or risk across all proposals.
22018
+ 3. Flag any contradictions between proposals (e.g., conflicting assumptions).
22019
+ 4. Recommend the 1-3 highest-value improvements the Lucifero should apply.
22020
+ 5. Note anything that should be cut or descoped.
22021
+
22022
+ ## Operating principles
22023
+ - Be honest and incisive \u2014 a weak critique helps no one. Name specific defects, not general vibes.
22024
+ - Distinguish "wrong" from "incomplete" and "risky".
22025
+ - Constructive: every critique pairs with a fix or a question.
22026
+
22027
+ ## Output format
22028
+ ## Scores (per agent, per dimension)
22029
+ ## Critical gaps
22030
+ ## Contradictions
22031
+ ## Top improvements
22032
+
22033
+ Stay under 200 words.${CLARIFICATION_PROTOCOL8}
22034
+
22035
+ ## Design-phase risks artifact (mandatory when running council in design-phase mode)
22036
+ When the council is in design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), you ALSO write a \`risks\` document via the \`createDocument\` tool. This is your one allowed artifact emission. Pass the tool call as:
21865
22037
 
21866
- Emit this block at the end of your message:
21867
22038
  \`\`\`
21868
- ---QUESTION---
21869
- { "question": "One focused question", "choices": ["Option A", "Option B"], "context": "Why this matters in one line" }
21870
- ---END---
22039
+ createDocument({
22040
+ title: "risks",
22041
+ content: \`# Risks\\n\\n## 1. <Risk title>\\n- Impact: <high|medium|low>\\n- Likelihood: <high|medium|low>\\n- Mitigation: <one-line mitigation>\\n\\n## 2. ...\`
22042
+ })
21871
22043
  \`\`\`
21872
22044
 
21873
- Discipline:
21874
- - Ask ONLY when genuinely blocked. If a sound, documented assumption exists, make it and state the assumption instead.
21875
- - Provide 2-4 concrete "choices" when the question has natural options; the user can always type a custom answer.
21876
- - Never ask for information already present in shared context or retrievable via a tool from your AVAILABLE TOOLS section (e.g. searchDocuments).
21877
- - At most one question per turn. The council resumes automatically once the user answers or skips.`
21878
- }
21879
- ];
21880
- }
21881
- });
22045
+ Include AT LEAST 5 risks, each scored on Impact and Likelihood, with a one-line mitigation. Cover: technical (e.g. stack risk), product (e.g. scope creep), accessibility, performance, security. The artifact is persisted at \`.zelari/risks.md\` (workspace root), NOT under docs/. Do NOT emit other workspace artifacts \u2014 your role is to evaluate, not to build.`,
22046
+ tools: [],
22047
+ skills: ["document-writer", "research-analyst"]
22048
+ },
22049
+ {
22050
+ id: "lucifer",
22051
+ name: "Lucifero",
22052
+ codename: "Synthesizer",
22053
+ role: "Final Synthesizer",
22054
+ color: "#8b5cf6",
22055
+ avatar: "L",
22056
+ systemPrompt: `You are the Lucifero, the Final Synthesizer \u2014 you produce the definitive, actionable output that resolves the council's work. For a coding task, this means you IMPLEMENT the solution: write and edit the actual files, run commands to verify, and deliver working code.
21882
22057
 
21883
- // packages/core/dist/agents/systemPromptBuilder.js
21884
- function computeAgentSkills(agent, aiConfig, customSkills) {
21885
- const declared = agent.skills ?? resolveAgentSkills(agent.id).map((s) => s.id);
21886
- const globalEnabled = aiConfig?.enabledSkills;
21887
- const override = aiConfig?.agentSkillConfigs.find((c) => c.agentId === agent.id);
21888
- let effectiveIds;
21889
- if (override) {
21890
- effectiveIds = override.enabledSkillIds;
21891
- } else if (globalEnabled && globalEnabled.length > 0) {
21892
- effectiveIds = declared.filter((id) => globalEnabled.includes(id));
21893
- } else {
21894
- effectiveIds = declared;
21895
- }
21896
- const customs = customSkills ?? [];
21897
- for (const cs of customs) {
21898
- if (cs.enabled && cs.autoAttachTo?.includes(agent.id) && !effectiveIds.includes(cs.id)) {
21899
- effectiveIds.push(cs.id);
21900
- }
21901
- }
21902
- const builtin = effectiveIds.map((id) => getSkillById(id)).filter((s) => s !== void 0);
21903
- const customDefs = [];
21904
- for (const cs of customs) {
21905
- if (!cs.enabled)
21906
- continue;
21907
- if (effectiveIds.includes(cs.id) && !builtin.find((b) => b.id === cs.id)) {
21908
- customDefs.push({
21909
- id: cs.id,
21910
- name: cs.name,
21911
- description: cs.description,
21912
- category: cs.category,
21913
- color: cs.color,
21914
- enabledByDefault: cs.enabled,
21915
- builtin: false,
21916
- requiredTools: cs.requiredTools,
21917
- systemPromptFragment: cs.systemPromptFragment
21918
- });
21919
- }
21920
- }
21921
- return [...builtin, ...customDefs];
21922
- }
21923
- function computeAgentTools(agent, aiConfig) {
21924
- const skills = computeAgentSkills(agent, aiConfig);
21925
- const skillTools = skills.flatMap((s) => s.requiredTools);
21926
- const declared = agent.tools ?? [];
21927
- const merged = Array.from(/* @__PURE__ */ new Set([...declared, ...skillTools]));
21928
- const globalEnabled = aiConfig?.enabledTools;
21929
- if (globalEnabled && globalEnabled.length > 0) {
21930
- return merged.filter((t) => globalEnabled.includes(t));
21931
- }
21932
- return merged;
21933
- }
21934
- function getToolDescriptions(toolNames, registry3) {
21935
- const lines = ["AVAILABLE TOOLS (use ONLY these exact names):"];
21936
- for (const name of toolNames) {
21937
- const tool = registry3.get(name);
21938
- if (!tool)
21939
- continue;
21940
- let paramList;
21941
- if (Array.isArray(tool.parameters)) {
21942
- paramList = tool.parameters.map((p3) => `${p3.name}:${p3.type}`).join(", ");
21943
- } else {
21944
- const obj = tool.parameters;
21945
- paramList = Object.entries(obj.properties ?? {}).map(([k, v]) => `${k}:${v.type ?? "any"}`).join(", ");
21946
- }
21947
- lines.push(`- ${name}: ${tool.description} \u2014 args { ${paramList} }`);
21948
- }
21949
- return lines.join("\n");
21950
- }
21951
- function buildSystemPrompt(agent, options) {
21952
- const { tools, toolNames, aiConfig, workspaceContext, ragContext } = options;
21953
- const registry3 = new Map(tools.map((t) => [t.name, t]));
21954
- const skills = computeAgentSkills(agent, aiConfig);
21955
- const baseModules = getBasePromptModules().filter((m) => !m.conditional || m.conditional(skills));
21956
- const customModulesRaw = aiConfig?.customPromptModules ?? [];
21957
- const customTypes = new Set(customModulesRaw.map((m) => m.type));
21958
- const baseNotOverridden = baseModules.filter((m) => !customTypes.has(m.type));
21959
- const customModules = customModulesRaw.map((m) => ({
21960
- ...m,
21961
- priority: 1e3 + m.priority
21962
- }));
21963
- const allModules = [...baseNotOverridden, ...customModules].sort((a, b) => a.priority - b.priority);
21964
- const parts = [];
21965
- for (const mod of allModules) {
21966
- parts.push(mod.content);
21967
- }
21968
- if (agent.systemPrompt && agent.systemPrompt.trim()) {
21969
- parts.push(`# Your Role
22058
+ ## Methodology (work in this order)
22059
+ 1. Reconcile the specialists' outputs and Minosse's critique into a single coherent plan.
22060
+ 2. Resolve conflicts explicitly (state which proposal won and why).
22061
+ 3. Deliver the finished product the user asked for \u2014 complete, not summarized. For code tasks, USE your file/shell tools to create and verify the actual artifacts on disk. Prose without a successful write_file/edit_file is a failed run \u2014 the pipeline forces a retry until files change on disk.
22062
+ 4. Run any build/test commands available (check the npm scripts in the workspace context) to confirm your work.
21970
22063
 
21971
- ${agent.systemPrompt}`);
21972
- }
21973
- if (skills.length > 0) {
21974
- parts.push(`# Active Skills
22064
+ ## Output expectations
22065
+ - If the user requested code or a feature, IMPLEMENT via native tool_call write_file/edit_file/bash \u2014 not prose alone. Prefer native tool_call over ---TOOLS--- JSON; if you use ---TOOLS---, valid JSON with escaped \\n is required. After edits, a delivery loop re-verifies motion/JS budget and forces fix passes until technical blockers clear.
22066
+ - Lead with a one-line summary, then the full detail of what you did.
22067
+ - Apply Minosse's highest-value improvements; drop descoped items.
22068
+ - After making changes, verify they work (compile, run tests, etc.) when feasible.
22069
+ - End implementation runs with a mandatory \`## Verification status\` table with columns \`Check | Tier | Status | Evidence\`. Tier is one of: claimed, grep, tool, build, n/a (claimed < grep < tool < build). Status is PASS/FAIL/N/A. Evidence is \`path:Lline\` or command output. Never write "verificato \u2713" or "nessuna regressione" without Evidence \u2014 a deterministic post-hook will flag dishonest claims and tier inflation.
21975
22070
 
21976
- ` + skills.map((s) => `## ${s.name}
21977
- ${s.systemPromptFragment}`).join("\n\n"));
21978
- }
21979
- const toolBlock = getToolDescriptions(toolNames, registry3);
21980
- if (toolNames.length > 0) {
21981
- parts.push(`# Tools
22071
+ Use the tools available to you (read_file, write_file, edit_file, bash, list_files) directly as tool calls \u2014 the harness handles execution.${CLARIFICATION_PROTOCOL8}
21982
22072
 
21983
- ${toolBlock}`);
21984
- }
21985
- if (workspaceContext && workspaceContext.trim()) {
21986
- parts.push(`# Current Workspace State
22073
+ ## Design-phase synthesis artifact (mandatory when running council in design-phase mode)
22074
+ When the council is in design-phase mode (TASK mentions design/architecture/spec, no existing codebase to edit), your final deliverable is a \`synthesis\` document via the \`createDocument\` tool (NOT \`write_file\` and NOT \`list_files\`):
21987
22075
 
21988
- ${workspaceContext}`);
21989
- }
21990
- if (ragContext && ragContext.trim()) {
21991
- parts.push(`# Retrieved Knowledge (RAG)
22076
+ \`\`\`
22077
+ createDocument({
22078
+ title: "synthesis",
22079
+ content: \`# Council Synthesis\\n\\n## Executive summary\\n<2-3 paragraphs>\\n\\n## Stack and key decisions\\n- <ADR-by-ADR summary>\\n\\n## Phases\\n<1-2 line summary per phase>\\n\\n## Top risks\\n<top 3 risks from Minosse>\\n\\n## Green-light checklist\\n- [ ] All ADRs accepted\\n- [ ] Risks have mitigations\\n- [ ] Tasks have acceptance criteria\`
22080
+ })
22081
+ \`\`\`
21992
22082
 
21993
- ${ragContext}`);
21994
- }
21995
- return parts.join("\n\n---\n\n");
21996
- }
21997
- var init_systemPromptBuilder = __esm({
21998
- "packages/core/dist/agents/systemPromptBuilder.js"() {
21999
- "use strict";
22000
- init_promptModules();
22001
- init_skills();
22083
+ DO NOT call \`list_files\` \u2014 it is NOT a workspace tool. Use \`searchDocuments\` if you need to look something up (limit 2-3 searches, then act on the results). Your deliverable is the synthesis document; emit it via \`createDocument\`, not via prose.`,
22084
+ // v0.7.2: implementation tools — the synthesizer writes/edits files and runs commands.
22085
+ tools: ["read_file", "write_file", "edit_file", "bash", "list_files"],
22086
+ skills: ["vault-manager", "project-planner", "idea-synthesizer"]
22087
+ }
22088
+ ];
22089
+ UnknownMemberError = class extends Error {
22090
+ unknownId;
22091
+ availableIds;
22092
+ constructor(unknownId, availableIds) {
22093
+ super(`Unknown member id for swap: "${unknownId}". Available: ${availableIds.join(", ") || "(none)"}.`);
22094
+ this.name = "UnknownMemberError";
22095
+ this.unknownId = unknownId;
22096
+ this.availableIds = availableIds;
22097
+ }
22098
+ };
22002
22099
  }
22003
22100
  });
22004
22101
 
@@ -25242,6 +25339,7 @@ __export(council_exports, {
25242
25339
  NON_RETRY_AGENTS: () => NON_RETRY_AGENTS,
25243
25340
  OUTPUT_QUALITY_DIRECTIVE: () => OUTPUT_QUALITY_DIRECTIVE,
25244
25341
  PROMPT_MODULES: () => PROMPT_MODULES,
25342
+ SINGLE_AGENT_IDENTITY_MODULE: () => SINGLE_AGENT_IDENTITY_MODULE,
25245
25343
  STRUCTURED_REASONING_DIRECTIVE: () => STRUCTURED_REASONING_DIRECTIVE,
25246
25344
  TIER_RANK: () => TIER_RANK,
25247
25345
  TOOL_USE_PROTOCOL_DIRECTIVE: () => TOOL_USE_PROTOCOL_DIRECTIVE,
@@ -26761,21 +26859,6 @@ var init_toolRegistry2 = __esm({
26761
26859
  }
26762
26860
  });
26763
26861
 
26764
- // src/cli/utils/cmdline.ts
26765
- function quoteCmdArg(arg) {
26766
- if (arg === "") return '""';
26767
- if (!/[\s"^&|<>()%!]/.test(arg)) return arg;
26768
- return `"${arg.replace(/"/g, '""')}"`;
26769
- }
26770
- function buildCmdLine(command, args) {
26771
- return [command, ...args].map(quoteCmdArg).join(" ");
26772
- }
26773
- var init_cmdline = __esm({
26774
- "src/cli/utils/cmdline.ts"() {
26775
- "use strict";
26776
- }
26777
- });
26778
-
26779
26862
  // src/cli/updater.ts
26780
26863
  var updater_exports = {};
26781
26864
  __export(updater_exports, {
@@ -27728,12 +27811,15 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS) {
27728
27811
  return { ran: false, reason: "no typecheck/test/build script (skipped)" };
27729
27812
  }
27730
27813
  return await new Promise((resolveRun) => {
27731
- const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
27732
- const child = spawn6(npmCmd, ["run", script], {
27814
+ const child = process.platform === "win32" ? spawn6(buildCmdLine("npm.cmd", ["run", script]), {
27733
27815
  cwd: projectRoot,
27734
27816
  stdio: ["ignore", "pipe", "pipe"],
27735
27817
  env: process.env,
27736
- shell: process.platform === "win32"
27818
+ shell: true
27819
+ }) : spawn6("npm", ["run", script], {
27820
+ cwd: projectRoot,
27821
+ stdio: ["ignore", "pipe", "pipe"],
27822
+ env: process.env
27737
27823
  });
27738
27824
  let stdout = "";
27739
27825
  let stderr = "";
@@ -27789,6 +27875,7 @@ var SMOKE_SCRIPT_PRIORITY, DEFAULT_TIMEOUT_MS;
27789
27875
  var init_projectSmoke = __esm({
27790
27876
  "src/cli/workspace/projectSmoke.ts"() {
27791
27877
  "use strict";
27878
+ init_cmdline();
27792
27879
  SMOKE_SCRIPT_PRIORITY = ["typecheck", "test", "build"];
27793
27880
  DEFAULT_TIMEOUT_MS = 12e4;
27794
27881
  }
@@ -28985,9 +29072,13 @@ function detectLocalBin(bin) {
28985
29072
  function detectGlobalBin(bin) {
28986
29073
  return () => {
28987
29074
  try {
28988
- const res = spawnSync3(bin, ["--version"], {
29075
+ const args = ["--version"];
29076
+ const res = process.platform === "win32" ? spawnSync3(buildCmdLine(bin, args), {
29077
+ stdio: ["ignore", "pipe", "ignore"],
29078
+ shell: true,
29079
+ timeout: 4e3
29080
+ }) : spawnSync3(bin, args, {
28989
29081
  stdio: ["ignore", "pipe", "ignore"],
28990
- shell: process.platform === "win32",
28991
29082
  timeout: 4e3
28992
29083
  });
28993
29084
  return Promise.resolve(res.status === 0 || res.stdout != null && res.stdout.toString().trim().length > 0 && res.error === void 0);
@@ -29036,6 +29127,7 @@ var PLUGINS;
29036
29127
  var init_registry2 = __esm({
29037
29128
  "src/cli/plugins/registry.ts"() {
29038
29129
  "use strict";
29130
+ init_cmdline();
29039
29131
  init_engine();
29040
29132
  init_driver();
29041
29133
  init_engine();
@@ -32956,6 +33048,7 @@ async function resolveFailoverStream(options) {
32956
33048
  init_shellResolver();
32957
33049
  init_keyStore();
32958
33050
  init_toolRegistry();
33051
+ init_skills2();
32959
33052
 
32960
33053
  // src/cli/hooks/messageHelpers.ts
32961
33054
  function appendSystem(setMessages, content, ts = Date.now()) {
@@ -33161,17 +33254,14 @@ function useChatTurn(params) {
33161
33254
  }
33162
33255
  } catch {
33163
33256
  }
33164
- const toolList = toolRegistry.toOpenAITools().map((t) => `- ${t.function.name}: ${t.function.description}`).join("\n");
33257
+ const openAiTools = toolRegistry.toOpenAITools();
33258
+ const toolListNames = openAiTools.map((t) => t.function.name);
33259
+ const toolList = openAiTools.map((t) => `- ${t.function.name}: ${t.function.description}`).join("\n");
33165
33260
  const resolvedShell = resolveShell();
33166
33261
  const isWindows = process.platform === "win32";
33167
33262
  const shellGuidance = resolvedShell.isBash ? `The bash tool runs commands via Git Bash / MSYS2 (${resolvedShell.shell}). Write POSIX commands: ls, grep, $VAR, &&, /c/Users/... all work.` : isWindows ? `The bash tool runs commands via cmd.exe (Git Bash not found). Write Windows-native commands: use dir (not ls), %VAR% (not $VAR), avoid POSIX-only syntax.` : `The bash tool runs commands via /bin/sh.`;
33168
33263
  const nonInteractiveGuidance = "The shell is NON-INTERACTIVE (stdin closed): commands that prompt for input fail immediately. Always pass non-interactive flags (--yes, -y, --template, --force). If a scaffolder still insists on prompting (e.g. `npm create vite` in a non-empty directory), do NOT retry it \u2014 scaffold into a fresh empty subdirectory and move the files, or write package.json/configs/sources yourself with write_file, then run `npm install`.";
33169
- const systemPrompt = [
33170
- "You are Zelari Code, an interactive AI coding agent operating directly in the user's terminal.",
33171
- "",
33172
- "You ARE connected to this machine and have real tools to read, modify, and explore the codebase.",
33173
- "Never claim you lack filesystem or shell access \u2014 you have it. Use your tools instead of asking the user to paste file contents.",
33174
- "",
33264
+ const shellContextBlock = [
33175
33265
  "# Platform & Shell",
33176
33266
  `platform: ${process.platform}`,
33177
33267
  `shell: ${resolvedShell.via}`,
@@ -33181,24 +33271,48 @@ function useChatTurn(params) {
33181
33271
  "# Working Directory",
33182
33272
  `You are running in: ${cwd}`,
33183
33273
  "All relative file paths are resolved against this directory. Always work with real files here.",
33184
- "",
33185
- "# Available Tools",
33186
- "You can call these tools. Use them to take action and gather information autonomously:",
33187
- toolList,
33188
- ...workspaceSummary ? ["", workspaceSummary] : [],
33189
- ...zelariReadHint ? ["", zelariReadHint] : [],
33190
- ...planSummary ? ["", planSummary] : [],
33191
- "",
33192
- "# Guidelines",
33193
- "- When the user asks you to write code, debug, or explore, be proactive: list files (list_files, or bash: ls/dir) and read key files (read_file) to understand the project instead of asking the user to paste file contents.",
33194
- "- If a command fails or is cancelled, do NOT retry variants of the same command: diagnose why (read the hint in the result if present) and take a DIFFERENT approach (e.g. create the files yourself with write_file).",
33195
- "- After a tool result, CONTINUE your answer from where you left off. NEVER restate or re-print text you already wrote earlier in this turn.",
33196
- `- Only invoke tools when they are necessary to answer the user's prompt. If the user is just saying hello or greeting them (e.g., "ciao", "hello"), simply greet them back and ask how you can help, without running any commands or tools.`,
33197
- "- When you finish a task, briefly summarize what you did.",
33198
33274
  ...planSummary ? [
33275
+ "",
33276
+ "# Plan Tracking",
33199
33277
  '- Plan tasks: when you START working on a plan task call updateTask {taskId, status: "in_progress"}; when it is complete and verified call updateTask {taskId, status: "done"}. NEVER edit .zelari/plan.json by hand.'
33200
33278
  ] : []
33201
33279
  ].join("\n");
33280
+ const singleAgentRole = {
33281
+ id: "single",
33282
+ name: "Zelari Code",
33283
+ codename: "zelari",
33284
+ role: "interactive coding agent",
33285
+ color: "#00d9a3",
33286
+ avatar: "\u25C6",
33287
+ tools: toolListNames,
33288
+ systemPrompt: shellContextBlock
33289
+ };
33290
+ const workspaceContext = [workspaceSummary, zelariReadHint].filter(Boolean).join("\n\n");
33291
+ let systemPrompt;
33292
+ try {
33293
+ systemPrompt = buildSystemPrompt(singleAgentRole, {
33294
+ tools: getAllTools(),
33295
+ toolNames: toolListNames,
33296
+ aiConfig: {
33297
+ enabledSkills: [],
33298
+ enabledTools: toolListNames,
33299
+ customPromptModules: [SINGLE_AGENT_IDENTITY_MODULE],
33300
+ agentSkillConfigs: []
33301
+ },
33302
+ workspaceContext: workspaceContext || void 0,
33303
+ ragContext: planSummary || void 0
33304
+ });
33305
+ } catch {
33306
+ systemPrompt = [
33307
+ SINGLE_AGENT_IDENTITY_MODULE.content,
33308
+ shellContextBlock,
33309
+ "# Available Tools",
33310
+ "You can call these tools. Use them to take action and gather information autonomously:",
33311
+ toolList,
33312
+ ...workspaceContext ? ["", workspaceContext] : [],
33313
+ ...planSummary ? ["", planSummary] : []
33314
+ ].join("\n");
33315
+ }
33202
33316
  const maxToolCallsPerTurn = (() => {
33203
33317
  const raw = process.env.ZELARI_MAX_TOOL_CALLS;
33204
33318
  const n = raw ? Number.parseInt(raw, 10) : 25;
@@ -33206,8 +33320,8 @@ function useChatTurn(params) {
33206
33320
  })();
33207
33321
  const maxToolLoopIterations = (() => {
33208
33322
  const raw = process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS;
33209
- const n = raw ? Number.parseInt(raw, 10) : 30;
33210
- return Number.isFinite(n) && n > 0 ? n : 30;
33323
+ const n = raw ? Number.parseInt(raw, 10) : 90;
33324
+ return Number.isFinite(n) && n > 0 ? n : 90;
33211
33325
  })();
33212
33326
  const harness2 = new AgentHarness({
33213
33327
  model: envConfig.model,