All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Tool Result Offloading: Automatically offload industrial-scale tool outputs (>50k chars) to disk.
- Sub-Agent Reasoning (
inspect_result): Use non-autonomous reasoning agents to analyze offloaded data without bloating the main context window. - Deep Dependency Injection: Fully refactored core orchestration (
Conductor,InstructionService,MCPResourceProvider) to use constructor injection, eliminating race conditions in parallel environments.
- Parallel Test Stability: Resolved deep-seated race conditions in global singleton management.
- Schema Compliance: Updated core agents and test configs to match the latest configuration schema.
- Migration to Pearls: Successfully migrated the iteration engine from
pearls(bd) topearls(prl).- Improved data stability with JSONL-only storage (
issues.jsonl). - Simplified CLI interaction by removing daemon dependency and complex sync logic.
- Adopted P0-P4 priority system and native Pearls status flow.
- Native support for Pearls comments and link-based dependencies.
- Improved data stability with JSONL-only storage (
- Improved Performance: Reduced latency in task transitions by moving to direct file-based state management.
- Automatic MCP Resource Injection:
- Implemented
MCPResourceProviderto automatically inject contextual data from MCP servers into agent prompts. - Added support for resource declaration in
citadel.config.ts, workflow formulas (.toml), and dynamic pearl context. - Extended
MCPServicewith full resource reading capabilities including binary content filtering. - Integrated resource injection into the
InstructionServicepipeline.
- Implemented
- Test Suite Stability: Resolved test regressions and flakiness caused by global state leakage in
CoreAgent. - CoreAgent Refactor: Implemented Dependency Injection for
PearlsClientinCoreAgentto isolate tests from the global singleton. - E2E Testing: Fixed
bd doctormock in E2E tests to bypass git working tree checks. - Conductor Tests: Added missing mocks (
getLatestTicket) to fix TypeErrors in Conductor integration tests.
- Critical Crash Fix: Enforced
--no-dbmode for allbdlogic to prevent "Split Stack Overflow" crashes in the underlying Go SQLite driver. This eliminates potential database corruption during high-load state transitions. - Robustness:
bdinteractions now rely exclusively onissues.jsonl(JSONL-only mode), ensuring stability across all environments.
- Token Usage Counting:
CoreAgentnow tracks input, output, and total tokens across all LLM steps in a task execution.- Automatically posts a summary comment to the associated Pearl via the
bdCLI upon task completion.
- Context Management Strategy: Implemented configurable limits for agent history and message sizes to prevent context window overflow and reduce costs.
- Added
contextconfiguration object tocitadel.config.ts. - History Pruning:
CoreAgentnow automatically prunes message history exceedingmaxHistoryMessages(default: 20/30) while intelligently preserving the system prompt and tool-call/result pairs. - Output Truncation: Large tool outputs are now truncated if they exceed
maxToolResponseSize(default: 50k/100k chars), preventing agents from choking on massive file reads or command outputs. - Message Size Safety: Added safeguards against excessively large single messages.
- Added
- Dynamic Tool Injection Architecture:
- Refactored
CoreAgentand role-specific agents to use factory-based tool creation with injectedAgentContext. - Tools now implicitly handle mandatory parameters like
pearlIdandparentPearlId, significantly reducing LLM cognitive load and omission errors. - Implemented async dynamic tool loading to support formula-defined output schemas.
- Refactored
- Project Health Sweep:
- Achieved a perfectly clean Biome lint report across the entire codebase.
- Hardened type safety by eliminating
anyusage inWorkerPoolandCoreAgent. - Standardized modern Node.js imports and role-specific tool consolidation.
- AI SDK v6 Alignment: Migrated all tool definitions and registration logic to the new
inputSchemapattern required by AI SDK 6.0. - Instruction Precision: Audited and updated all system prompts and instruction templates to remove stale requirements for agents to provide
pearlIdmanually.
- Stricter filesystem operations filtering
- Retry on Crash: Added retry logic for `` tool to automatically retry the command if it crashes.
- Pearls and Git Integration:
- Implemented auto-synchronization for the Pearls database to handle staleness after Git operations.
- Added proactive sync in
WorkerAgentandEvaluatorAgentafterrun_commandexecutesgitcommands. - Added automated recovery in
PearlsClientto catch staleness errors and performing auto-sync before retrying.
- Conductor Hook Dependency Injection (Critical): Fixed a bug where
WorkerPoolandGatekeeperPoolhooks were falling back to the global singletonWorkQueueinstead of using the isolated queue instance passed toConductor. This caused test failures (claim is not a function) and prevented proper multi-queue isolation. - Robust Error Handling: Added null checks for
pearlaccess inConductor's error handling block to prevent secondary crashes during failure recovery. - Output Capture: Ensuring
Conductorhooks return the agent's execution result so it gets persisted to the queue ticket output, fixing data flow to Gatekeepers.
- Submit Work Schema Regression: Fixed an issue where agents providing structured output without a top-level summary were failing validation.
submit_worknow robustly extracts summaries fromoutput.summary,output.analysis, or generates a fallback summary from keys.
- Output Persistence Bug: Fixed a critical "double-complete" race condition where agent tools (like
submit_work) would save structured JSON, but the task runner would later overwrite it with a narration string.WorkQueue.complete()andfail()are now idempotent.
- Documentation Update: Fully synchronized
docs/CITADEL-FSM.mdwith the latest FSM implementation, including new rejection transitions, recovery labels, and the v0.1.23 Persistence Guard details.
- Persistence Overwrite Bug (Critical): Fixed a bug in
WorkQueue.complete()where the standard Hook cleanup logic (which callscompletewith no output) was unconditionally overwriting the existing output withnull. Modifiedcomplete()to conditionally update the output field only if a non-null value is provided, ensuring that the WorkerAgent's submission is preserved.
- Gatekeeper Null Context (Critical): Fixed a bug where the Gatekeeper received
nullassubmitted_workbecause it was reading from the active verification ticket instead of the completed worker ticket. The Conductor now explicitly fetches the latest completed output from the Queue, ensuring proper context for verification.
- Submission Feedback: The
submit_worktool now returns an explicit"message": "Work submitted successfully."in its JSON response. This provides clearer feedback to agents (especially after auto-extraction), preventing confusion and unnecessary retries.
- Crash Loop Recovery: Enhanced submission idempotency to handle "Partial Failure" states. If a workspace Ticket is marked completed but the Pearl state update fails (leaving it
in_progress), the Worker now automatically detects this inconsistency, forces the Pearl transition toverify, and returns success instead of crashing with "No active ticket".
- Submission Idempotency: Fixed a regression in v0.1.15 where agents crashed with "No active ticket" when retrying
submit_workafter an auto-extracted submission.submit_worknow idempotently returns success if the pearl is already inverifyordonestates.
- Agent Summary Conflation: Relaxed
submit_workschema to makesummaryoptional and implemented smart extraction logic inWorkerAgent. This fixes a common issue where agents placed thesummaryinside the structuredoutputobject, causing validation failures.
- Evaluator State & Validation Fixes:
- Relaxed FSM to allow
verify->opentransitions, enabling Gatekeepers to reject work back to the pool. - Updated validation logic to skip strict
acceptance_testchecks for tasks markedfailed, enabling Gatekeepers to fail work (terminal failure). - Updated Evaluator system prompt to strictly enforce providing a
reasonwhen rejecting work. - Added new integration tests (
tests/integration/evaluator_state.test.ts) covering these edge cases.
- Relaxed FSM to allow
- Fixed critical race condition in Conductor where dependent tasks were routed before their blockers were complete. Added "Double Check" validation logic to
cycleRouter. - Fixed test leakage in integration tests by replacing global
mock.modulewith prototype patching inconductor_race.test.ts.
- Summary Validation Fix: Addressed an issue where agents (especially in planning mode) misplaced the
summaryfield inside the structuredoutputobject.- Made
summaryoptional insubmit_workschema to prevent immediate validation failure. - Added auto-extraction logic in
WorkerAgentto recover the summary fromoutput.summaryif missing at the top level. - Improves robustness against common agent "envelope conflation" errors.
- Made
- Persistent Schema Validation Fix: Fixed issue where dynamic schema validation in
run()defaulted toz.string()when no formula was present, blocking structured output even with the v0.1.10 fix.- Updated default
outputSchemainWorkerAgent.run()toz.record(z.string(), z.unknown())to explicitly allow structured objects by default. - Ensures backward compatibility for agents not using formula-enforced schemas.
- Updated default
- Planning Workflow Schema Fix: Fixed critical bug where
submit_worktool rejected structured JSON output from planning steps- Updated initial schema to accept both strings and objects:
z.union([z.string(), z.record(z.unknown())]) - Planning workflows can now submit structured output with
affected_files,analysis, andsteps - Preserves backward compatibility with string outputs and dynamic schema enforcement
- Updated initial schema to accept both strings and objects:
- Critical Deadlock Fix: Resolved a system deadlock caused by agent parameter omission and premature state transitions:
handleSubmitWorknow validates ticket existence and saves output before transitioning toverifystatusreject_worknow resets pearl toopen(withrejectedlabel) instead ofin_progress, preventing orphaned pearls- Added stuck pearl recovery to Router: automatically resets
in_progresspearls with no active ticket - Added
REQUIREDhints to mandatory tool parameters to reduce LLM omission
- Updated
docs/CITADEL-FSM.mdto reflect new rejection behavior, stuck pearl recovery, and new labels
- Gatekeeper Awareness: The EvaluatorAgent now receives the Worker's submitted output (
submitted_work) in its context. Updated the Evaluator's system prompt to correctly handle planning tasks, reducing false rejections for non-filesystem work.
- Tool Tolerance: Improved
report_progresstool inWorkerAgentto be more tolerant of missing parameters. It now acceptsreasoningas a fallback formessageand supports extra parameters without failing validation.
- Docker Compatibility: Added
--sandboxflag to all pearls commands to enable direct mode operation without daemon dependency. Fixes Unix socket permission errors in Docker containers that prevented Citadel from running.
- Router Queue Assignment: Removed default value from
queueparameter inenqueue_taskto prevent infinite loops where verify pearls were incorrectly routed to worker queue instead of gatekeeper queue.
- Smart Tool Name Matching: Agents can now call tools by suffix (e.g.,
list_skillsinstead ofmcp_list_skills). Auto-resolves if exactly one match is found and name is >= 5 characters.
- Conductor Resilience: Implemented exponential backoff for the main router loop to prevent log flooding and CPU spikes during infrastructure outages (e.g., database synchronization errors).
- Environment Validation: Added a startup check (
bd doctor) to ensure the Conductor only starts when thepearlsdatabase is in a healthy state.
- Zombie Task Prevention: Added error handling and state recovery to worker and gatekeeper hooks. If an agent exits without calling a terminal tool (
submit_work,approve_work,reject_work), the pearl is automatically returned to an actionable state with appropriate labels (agent-incomplete,agent-error,evaluator-incomplete,evaluator-error) for retry. This prevents tasks from getting permanently stuck inin_progressorverifystates.
- Dependency-Aware Task Routing: The Conductor now uses
pearlsClient.ready()instead oflist('open')to ensure only pearls with satisfied dependencies (all blockers closed) are routed to workers. This prevents wasting resources on tasks that cannot proceed due to missing dependencies. - Recovery Logic: Re-added recovery pearl handling to correctly skip recovery tasks when their dependencies succeed.
- Parameter Auto-Injection: Citadel now automatically injects mandatory parameters like
pearlIdandparentPearlIdfrom the agent's context into tool calls if they are missing. This significantly improves reliability for weaker local models (e.g., 20B class models) that sometimes fail to extract context into tool arguments.
- CRITICAL: Tool Execution Context Shadowing: Fixed a major bug where
AgentContext(includingpearlId) was being ignored during tool execution. This now correctly passes the agent's run-time context to all tools, enablingenqueue_task,submit_work, andreport_progressto function correctly without explicitpearlIdparameters. - WorkerAgent Typo: Fixed a minor syntax typo in the
run_commandhandler.
- Tool Parameter Tolerance: Made tools more forgiving of LLM variations:
run_commandnow accepts bothcommand(string) andcmd(string or array), automatically converting arrays to space-separated stringsrun_commanduses.passthrough()to allow extra parameters liketimeoutthat LLMs might addenqueue_tasknow makespearlIdoptional, falling back to context if not provided- Reduces wasted API calls from agents learning tool schemas through trial and error
- Bug #1 - Invalid State Transition: Fixed the Conductor to properly move pearls to
in_progressstatus when workers start processing tasks, not when they finish. This prevents the invalidopen→verifytransition that was occurring insubmit_work. - Bug #2 - Output Schema Mismatch: Updated
submit_workto accept both string and object types for theoutputparameter, allowing agents to submit structured data naturally without manual stringification. - Bug #3 - Tool Schema Ambiguity: Improved
run_commandtool description to explicitly clarify thatcommandmust be a single string, not an array, reducing agent confusion and wasted API calls.
- JSON Schema Validation Error (Complete Fix): Fixed the root cause in
jsonSchemaToZodfunction that was converting empty JSON Schema objects toz.record(), which generates invalid schemas. Now usesz.object({}).passthrough()for dynamic objects. This resolves production errors when using workflow formulas with output schemas. - RouterAgent Schema: Also fixed
instantiate_formulatool'svariablesparameter (from v0.0.6).
- JSON Schema Validation Error: Fixed RouterAgent's
instantiate_formulatool generating invalid JSON schemas. Replacedz.record()withz.object({}).passthrough()to properly support dynamic variable objects in workflow formulas.
- 100% WorkerAgent Test Coverage: Achieved full line and function coverage for
src/agents/worker.ts. - Agent Dependency Injection: Refactored
CoreAgent,WorkerAgent, andEvaluatorAgentto supportLanguageModelinjection, eliminating reliance on global mocks.
- Test Suite Modernization: Removed all cache-busting hacks (
?t=...) and broad module mocks to unify coverage reporting and improve test reliability. - Lint & Type Safety: Resolved all
anywarnings in agent constructors and optimized import styles (import type).
- Coverage Shadowing: Fixed issues where global mocks were interfering with coverage tracking across different test files.
- LLM Mocking Stability: Implemented role-validated LLM mocks in integration tests to prevent unauthorized API calls during testing.
- 100% Biome Lint Compliance: Achieved full compliance across
src/directory, resolving 18 warnings without ignore comments. - Strict Tool Validation:
CoreAgentnow performs explicit Zod schema validation on all tool inputs. - Improved Test Isolation: Switched to dynamic imports for
WorkerAgentin integration tests to prevent singleton leakage.
- enqueue_task Constraint Failure: Resolved
NOT NULLconstraint errors by providing default values inWorkQueueand markingRouterAgentparameters as optional. - Build Compilation Errors: Fixed several TypeScript "possibly undefined" and type mismatch errors in core logic and tests.
- AI Mocking: Repaired incomplete
aimodule mocks in unit tests.
- Dynamic Data Piping (DDP): Enabled structured data flow between workflow steps using
{{steps.ID.output.KEY}}syntax. - Dynamic Schema Enforcement: Worker Agents now rigidly enforce Formula-defined
output_schemausing Zod validation. - Context Preservation: Pearls now support a structured
contextproperty persisted in description frontmatter. - Data Piper Service: Just-in-time dependency resolution and context injection.
- Configuration State Duplication: Resolved a critical bug where bundled CLI state was duplicated, causing "Config not loaded" errors. Corrected by implementing a global singleton registry using
globalThisandSymbol.for.
- Parallel Multi-Worker Support: Introduced
WorkerPoolfor dynamic scaling. - Workflow Engine: Implemented TOML-based "Formulas".
- Dynamic Task Decomposition: Enabled Worker Agents to delegate subtasks.
- NPM Package Readiness: Configured package metadata and CLI entry points.
- Documentation: Comprehensive update to
USER-GUIDE.mdand technical docs.