Orchestrata Ultimate / Specs / 032-concierge-volk
032-concierge-volk: Concierge Volk (U:Cx)
The Concierge Volk (U:Cx) is the user-facing intake agent in Orchestrata. It receives raw human intent, conducts structured requirements elicitation across up to four Q&A rounds, compiles a complete requirements set, emits Prolog facts for the governance layer, and hands off to the Business Analyst (U:BA) to begin the production pipeline.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/032-concierge-volk/ |
| Status line in the spec | Implemented |
| Requirement IDs defined | 54 |
With a @traces citation in src/ |
48 (88.9%) |
With a @traces citation in tests/ |
4 (7.4%) |
| Tracked files | 6 |
| RTM page | 032-concierge-volk |
Reading this spec
The Concierge Volk (U:Cx) is the user-facing intake agent of Orchestrata. It receives raw human intent, runs a structured requirements elicitation over up to four question-and-answer rounds, compiles a complete requirements set, emits Prolog facts for the governance layer and hands off to the Business Analyst (U:BA) to start the production pipeline. Human intent arrives as informal language that downstream Volks (PM, Architect, CodeDirector) cannot act on directly; the Concierge is the deterministic boundary between human communication and machine-executable specification.
The scope is six priority 1 user stories: human intent intake, iterative clarifying questions, forced finalization after the maximum rounds, requirements compilation and structured parsing, Prolog fact emission, and escalation routing to U:BA. Ten functional requirements cover CXP packet intake, conversation state, LLM invocation with the system prompt, first-round questions, progressive questioning, MAX_QA_ROUNDS enforcement, structured response parsing, Prolog fact emission, UI requirement detection and the U:BA handoff. Requirement IDs use the REQ-032- prefix.
The key decisions are these. ConciergeVolk extends BaseVolk and routes CXP packets by subject: intent starts elicitation and response continues it. The system prompt is a seven-dimension elicitation (functional scope, tech stack, data model, interfaces, quality, deployment, constraints). The first call always asks clarifying questions, with no fast path. Finalization is forced after MAX_QA_ROUNDS of 4 so that elicitation cannot loop forever. The finalization response is parsed for REQUIREMENTS_COMPLETE, PROLOG_FACTS, ESCALATE_TO, TASK_SUMMARY and PROJECT_NAME. UI requirements are detected from keywords in the conversation, and completion routes only to U:BA in the fixed pipeline of BA, PM, Architect, CodeDirector.
In the code, nearly all citations are in orchestrata_ultimate/agents/volks/concierge/volk, with minor ones in orchestrata_ultimate/gateway/handlers/cxp and orchestrata_ultimate/agents/kernel_handler. The per-requirement view is on the RTM page.
The spec's status line reads Implemented. It tracks 6 files and defines 54 requirement IDs. The full text follows below.
Measured coverage is 48 of 54 requirements cited by at least one @traces in src/ (88.9%), spread over 3 modules; the module citing the most of them is orchestrata_ultimate/agents/volks/concierge/volk (46 requirements). In tests/, 4 requirements are cited by a test-side @traces.
Coverage gaps: 6 requirements have no citing symbol. The largest untraced groups are REQ-032-* (6). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (4 against 48).
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-032-001 |
no | ConciergeVolk is defined as a class extending BaseVolk | 1 |
REQ-032-002 |
no | alias is set to the string constant "U:Cx" | 1 |
REQ-032-003 |
no | role is set to the string constant "Concierge (Intake)" | 1 |
REQ-032-004 |
no | ConciergeVolk is registered with the DI container under alias U:Cx | none |
REQ-032-005 |
no | ConciergeVolk exposes MAX_QA_ROUNDS as a class-level integer constant equal to 4 | 1 |
REQ-032-006 |
no | conversation_history is initialised as an empty list on instantiation | 1 |
REQ-032-007 |
no | original_intent is initialised as None or empty string on instantiation | 1 |
REQ-032-008 |
no | prolog_facts is initialised as an empty string on instantiation | 1 |
REQ-032-009 |
no | round_count is initialised to 0 on instantiation | 1 |
REQ-032-010 |
no | All instance state attributes persist for the lifetime of the handling Volk instance | 1 |
REQ-032-011 |
no | process(packet) inspects the CXP packet subject field for routing | 1 |
REQ-032-012 |
no | Packets with subject "intent" are routed to _handle_intent() | 1 |
REQ-032-013 |
no | Packets with subject "response" are routed to _handle_response() | 1 |
REQ-032-014 |
no | Packets with unrecognised subjects are rejected with a logged error | 1 |
REQ-032-015 |
no | Subject matching is case-insensitive or normalised before comparison | none |
REQ-032-016 |
no | _handle_intent() stores the packet body as original_intent on the first call | 1 |
REQ-032-017 |
no | _handle_intent() appends the human intent message to conversation_history | 1 |
REQ-032-018 |
no | _handle_intent() calls the LLM with CONCIERGE_SYSTEM_PROMPT and current conversation_history | 1 |
REQ-032-019 |
no | _handle_intent() routes the LLM response to HUMAN as clarifying questions | 1 |
REQ-032-020 |
no | _handle_intent() never compiles or finalises requirements on the first call (G162-1) | 1 |
REQ-032-021 |
no | round_count increments to 1 after _handle_intent() completes | none |
REQ-032-022 |
no | _handle_response() appends the human answer to conversation_history before the LLM call | 1 |
REQ-032-023 |
no | _handle_response() increments round_count before LLM invocation | 1 |
REQ-032-024 |
no | _handle_response() calls the LLM with the full conversation_history each time | 1 |
REQ-032-025 |
no | _handle_response() checks for REQUIREMENTS_COMPLETE signal in LLM response | 1 |
REQ-032-026 |
no | _handle_response() checks whether round_count >= MAX_QA_ROUNDS (G213) | 1 |
REQ-032-027 |
no | If REQUIREMENTS_COMPLETE is signalled or MAX_QA_ROUNDS is reached, _finalize() is called | 1 |
REQ-032-028 |
no | If neither condition is met, LLM response is sent to HUMAN as follow-up questions | 1 |
REQ-032-029 |
no | MAX_QA_ROUNDS is checked after every response round without exception | none |
REQ-032-030 |
no | When round_count >= MAX_QA_ROUNDS, _finalize() is called unconditionally regardless of LLM signal | 1 |
REQ-032-031 |
no | No additional questions are sent to HUMAN after forced finalization is triggered | 1 |
REQ-032-032 |
no | Forced finalization compiles requirements from all conversation_history accumulated to that point | 1 |
REQ-032-033 |
no | _finalize() calls the LLM with a finalization prompt requesting all structured fields | none |
REQ-032-034 |
no | _finalize() parses REQUIREMENTS_COMPLETE token from LLM response | none |
REQ-032-035 |
no | _finalize() parses PROLOG_FACTS block from LLM response and stores it in prolog_facts | 1 |
REQ-032-036 |
no | _finalize() parses ESCALATE_TO field from LLM response | 1 |
REQ-032-037 |
no | _finalize() parses TASK_SUMMARY paragraph from LLM response | 1 |
REQ-032-038 |
no | _finalize() parses PROJECT_NAME field from LLM response | 1 |
REQ-032-039 |
no | Missing or malformed structured fields are handled without raising an exception | 1 |
REQ-032-040 |
no | All parsed fields are included in the outbound CXP packet to U:BA | 1 |
REQ-032-041 |
no | UI detection scans combined conversation_history text for UI-related keywords | 1 |
REQ-032-042 |
no | Detected UI requirement flag is included in the handoff packet to U:BA | 1 |
REQ-032-043 |
no | UI detection is applied at finalization time, not during elicitation rounds | 1 |
REQ-032-044 |
no | After finalization, a CXP packet is always sent to U:BA | 1 |
REQ-032-045 |
no | The outbound packet to U:BA includes TASK_SUMMARY, PROJECT_NAME, PROLOG_FACTS, conversation_history, and UI flag | 1 |
REQ-032-046 |
no | ESCALATE_TO is parsed and logged but U:BA is the fixed pipeline destination | 1 |
REQ-032-047 |
no | No other Volk receives the requirements packet directly from U:Cx | 1 |
REQ-032-048 |
no | CONCIERGE_SYSTEM_PROMPT is defined as a module-level string constant | 1 |
REQ-032-049 |
no | The prompt instructs the LLM to elicit requirements across seven dimensions (D1-D7) | 1 |
REQ-032-050 |
no | The prompt instructs the LLM to signal REQUIREMENTS_COMPLETE when dimensions are sufficiently covered | 1 |
REQ-032-051 |
no | The prompt instructs the LLM to emit PROLOG_FACTS in valid Prolog syntax | 1 |
REQ-032-052 |
no | The prompt instructs the LLM to emit TASK_SUMMARY, PROJECT_NAME, and ESCALATE_TO on finalization | 1 |
REQ-032-053 |
no | The gateway chat handler (cxp.send to alias U:Cx) MUST dispatch to the real, live ConciergeVolk kernel when it is reachable and MUST NOT fabricate a reply while a live kernel is wired |
4 |
REQ-032-054 |
no | When the live ConciergeVolk kernel is not reachable (unwired, unready within the gRPC readiness window, or dispatch fails), the gateway MUST return an explicit, machine-detectable "assistant unavailable" response instead of a conversational-looking fallback reply | 3 |
Code that traces this spec
| Module | Symbols | Requirements |
|---|---|---|
orchestrata_ultimate/agents/kernel_handler |
2 | 2 |
orchestrata_ultimate/agents/volks/concierge/volk |
7 | 46 |
orchestrata_ultimate/gateway/handlers/cxp |
2 | 2 |
Checklists
checklists/constitutional.md
Concierge Volk Constitutional Checklist
Human Safety and Non-Deception
- [ ] CONST-032-001: Concierge must never fabricate requirements that were not expressed or implied by the human
- [ ] CONST-032-002: All clarifying questions must be neutral — the Concierge must not lead the human toward a predetermined answer
- [ ] CONST-032-003: The Concierge must not claim requirements are complete until either REQUIREMENTS_COMPLETE is signalled or MAX_QA_ROUNDS is exhausted
- [ ] CONST-032-004: Prolog facts emitted must faithfully represent the requirements gathered; no facts may be invented
Governance and Prolog Integrity
- [ ] CONST-032-005: Emitted PROLOG_FACTS must be syntactically valid Prolog; malformed facts must be caught, logged, and excluded rather than silently propagated
- [ ] CONST-032-006: PROLOG_FACTS must only assert claims that are grounded in the conversation_history
- [ ] CONST-032-007: PAM++ governance must be applied to the handoff packet before it is sent to U:BA
- [ ] CONST-032-008: The Concierge must not bypass constitutional articles on intake even when the human provides an apparently complete specification
Pipeline Integrity
- [ ] CONST-032-009: The fixed pipeline entry point (U:BA) must never be bypassed; the Concierge cannot route directly to PM, Architect, or CodeDirector
- [ ] CONST-032-010: The G162-1 constraint (no fast-path on first call) must be enforced unconditionally — it cannot be disabled by configuration
- [ ] CONST-032-011: The G213 constraint (MAX_QA_ROUNDS = 4) must be enforced unconditionally — it cannot be overridden at runtime
Data Retention and Privacy
- [ ] CONST-032-012: conversation_history must not be persisted beyond the session unless explicitly requested and authorised
- [ ] CONST-032-013: original_intent must be treated as potentially sensitive; it must not be logged at INFO level in production configurations
- [ ] CONST-032-014: The Concierge must not retain state from a previous session when instantiated for a new session
Auditability
- [ ] CONST-032-015: Every finalization event must be logged with round_count, trigger reason (REQUIREMENTS_COMPLETE or forced), and timestamp to the audit trail
checklists/requirements.md
The requirement list above comes from this file; 0 of 54 checkbox items are ticked.
checklists/testing.md
Concierge Volk Testing Checklist
Instantiation and State
- [ ] TEST-032-001: Verify ConciergeVolk instantiates with alias "U:Cx" and role "Concierge (Intake)"
- [ ] TEST-032-002: Verify conversation_history is an empty list on a fresh instance
- [ ] TEST-032-003: Verify original_intent is empty/None on a fresh instance
- [ ] TEST-032-004: Verify prolog_facts is an empty string on a fresh instance
- [ ] TEST-032-005: Verify round_count is 0 on a fresh instance
- [ ] TEST-032-006: Verify MAX_QA_ROUNDS equals 4 as a class-level constant
CXP Subject Routing
- [ ] TEST-032-007: Send a CXP packet with subject "intent" and verify _handle_intent() is called
- [ ] TEST-032-008: Send a CXP packet with subject "response" and verify _handle_response() is called
- [ ] TEST-032-009: Send a CXP packet with an unrecognised subject and verify a logged error is produced without crashing
- [ ] TEST-032-010: Verify subject routing is case-insensitive (e.g., "INTENT", "Intent", "intent" all route correctly)
Intent Handling — G162-1
- [ ] TEST-032-011: Send a first "intent" packet and verify original_intent is stored from the packet body
- [ ] TEST-032-012: Send a first "intent" packet and verify the human message is appended to conversation_history
- [ ] TEST-032-013: Send a first "intent" packet and verify the response is routed to HUMAN (not U:BA)
- [ ] TEST-032-014: Send a first "intent" packet and verify no finalization is triggered (G162-1)
- [ ] TEST-032-015: Send a first "intent" packet and verify round_count is 1 after the call
- [ ] TEST-032-016: Send two consecutive "intent" packets and verify original_intent is set from the first and not overwritten by the second
Response Handling
- [ ] TEST-032-017: Send a "response" packet and verify the human answer is appended to conversation_history before the LLM call
- [ ] TEST-032-018: Send a "response" packet and verify round_count increments
- [ ] TEST-032-019: Send a "response" packet where the LLM signals REQUIREMENTS_COMPLETE and verify _finalize() is called
- [ ] TEST-032-020: Send a "response" packet where the LLM does not signal REQUIREMENTS_COMPLETE and verify follow-up questions are routed to HUMAN
- [ ] TEST-032-021: Verify the full conversation_history is passed to the LLM on every response call (not just the latest exchange)
Forced Finalization — G213
- [ ] TEST-032-022: Simulate 4 full Q&A rounds and verify _finalize() is called on the 4th round regardless of LLM signal
- [ ] TEST-032-023: Verify no additional questions are sent to HUMAN after forced finalization
- [ ] TEST-032-024: Verify forced finalization compiles requirements from all accumulated conversation_history
- [ ] TEST-032-025: Simulate 3 rounds without REQUIREMENTS_COMPLETE and verify _finalize() is NOT called prematurely
- [ ] TEST-032-026: Verify MAX_QA_ROUNDS is compared using >= (not ==) so that any count at or above the limit triggers finalization
Structured Parsing in _finalize()
- [ ] TEST-032-027: Provide an LLM finalization response with all five fields and verify each is correctly parsed
- [ ] TEST-032-028: Provide a finalization response missing PROLOG_FACTS and verify no exception is raised
- [ ] TEST-032-029: Provide a finalization response missing PROJECT_NAME and verify a fallback or empty value is used
- [ ] TEST-032-030: Provide a finalization response missing TASK_SUMMARY and verify a fallback or empty value is used
- [ ] TEST-032-031: Provide a finalization response with a malformed PROLOG_FACTS block and verify the block is excluded and an error is logged
- [ ] TEST-032-032: Verify prolog_facts attribute is set after _finalize() parses a valid PROLOG_FACTS block
UI Detection
- [ ] TEST-032-033: Provide a conversation_history containing UI keywords (e.g., "dashboard", "UI", "frontend", "screen") and verify the UI flag is set to True
- [ ] TEST-032-034: Provide a conversation_history with no UI keywords and verify the UI flag is False
- [ ] TEST-032-035: Verify UI detection runs on the combined text of all conversation_history entries, not only the last message
- [ ] TEST-032-036: Verify UI detection is performed at finalization time, not during Q&A rounds
Escalation Routing
- [ ] TEST-032-037: After finalization, verify a CXP packet is sent to U:BA
- [ ] TEST-032-038: Verify the outbound packet to U:BA contains TASK_SUMMARY
- [ ] TEST-032-039: Verify the outbound packet to U:BA contains PROJECT_NAME
- [ ] TEST-032-040: Verify the outbound packet to U:BA contains PROLOG_FACTS
- [ ] TEST-032-041: Verify the outbound packet to U:BA contains the UI requirements flag
- [ ] TEST-032-042: Verify ESCALATE_TO is parsed and logged but does not override the fixed U:BA destination
- [ ] TEST-032-043: Verify no other Volk receives the requirements packet directly from U:Cx
System Prompt Verification
- [ ] TEST-032-044: Verify CONCIERGE_SYSTEM_PROMPT is a non-empty string constant defined at module level
- [ ] TEST-032-045: Verify CONCIERGE_SYSTEM_PROMPT references all seven dimensions (D1 through D7)
- [ ] TEST-032-046: Verify CONCIERGE_SYSTEM_PROMPT instructs the LLM to emit REQUIREMENTS_COMPLETE
- [ ] TEST-032-047: Verify CONCIERGE_SYSTEM_PROMPT instructs the LLM to emit PROLOG_FACTS
End-to-End Integration
- [ ] TEST-032-048: Run a full 2-round elicitation (intent + 1 response with REQUIREMENTS_COMPLETE) against a real LLM and verify U:BA receives a complete handoff packet
- [ ] TEST-032-049: Run a full 4-round elicitation that reaches MAX_QA_ROUNDS and verify forced finalization produces a valid handoff packet
- [ ] TEST-032-050: Verify ConciergeVolk state is isolated between two separate instantiations handling different sessions
Other tracked files
specs/032-concierge-volk/README.mdspecs/032-concierge-volk/compliance-audit.md
Full spec text
Verbatim from specs/032-concierge-volk/spec.md; headings are pushed down two levels.
SPEC-032: Concierge Volk (U:Cx)
Metadata
- Spec ID: 032-concierge-volk
- Title: Concierge Volk — User Intake Agent
- Version: 1.0.1
- Author: Mohamed
- Status: Implemented
- Created: 2026-04-04
- Last Updated: 2026-04-09
- Priority: P1
- Alias: U:Cx
- Components: ConciergeVolk, CONCIERGE_SYSTEM_PROMPT
- Package: orchestrata-concierge
- LOC: ~275 (2 source files)
- Dependencies: orchestrata-core, orchestrata-agents, orchestrata-cxp, orchestrata-governance
Overview
What
The Concierge Volk (U:Cx) is the user-facing intake agent in Orchestrata. It receives raw human intent, conducts structured requirements elicitation across up to four Q&A rounds, compiles a complete requirements set, emits Prolog facts for the governance layer, and hands off to the Business Analyst (U:BA) to begin the production pipeline.
Why
- Human intent arrives as informal natural language and is rarely actionable directly
- Downstream Volks (PM, Architect, CodeDirector) require structured, unambiguous requirements
- Without a governed intake stage, ambiguity propagates through the entire pipeline
- The Concierge provides a deterministic boundary between human communication and machine-executable specification
- Forced finalization after MAX_QA_ROUNDS (4) prevents infinite elicitation loops (G213)
How
- Extends BaseVolk with alias U:Cx and role "Concierge (Intake)"
- Routes incoming CXP packets by subject: "intent" triggers elicitation, "response" continues the Q&A cycle
- Calls the LLM with CONCIERGE_SYSTEM_PROMPT — a structured 7-dimension requirements elicitation prompt (D1-D7)
- Maintains conversation_history, original_intent, and prolog_facts across rounds
- Always asks clarifying questions on the first call (G162-1 — no fast-path on first call)
- Forces finalization after MAX_QA_ROUNDS = 4 regardless of completion signal
- Parses structured fields from LLM finalization response: REQUIREMENTS_COMPLETE, PROLOG_FACTS, ESCALATE_TO, TASK_SUMMARY, PROJECT_NAME
- Detects UI requirements from keywords in combined conversation text
- Routes exclusively to U:BA on completion (fixed pipeline: BA → PM → Ar → Cd)
Terminology
| Term | Definition |
|---|---|
| Intake | The process of receiving, clarifying, and formalising raw human intent before pipeline entry |
| Q&A Round | One cycle of: Concierge sends questions → human provides answers → round count increments |
| MAX_QA_ROUNDS | Hard cap of 4 Q&A rounds; finalization is forced on the 4th round regardless of LLM signal |
| Forced Finalization | Finalization triggered by MAX_QA_ROUNDS exhaustion, not by LLM REQUIREMENTS_COMPLETE signal |
| D1-D7 Dimensions | Seven structured elicitation dimensions: Functional Scope, Tech Stack, Data Model, Interfaces, Quality, Deployment, Constraints |
| REQUIREMENTS_COMPLETE | Structured token in LLM response signalling that sufficient requirements have been gathered |
| PROLOG_FACTS | Structured token in LLM response containing Prolog-syntax facts for the governance layer |
| ESCALATE_TO | Structured token specifying the next Volk to receive the compiled requirements |
| TASK_SUMMARY | Structured token containing a one-paragraph description of the task |
| PROJECT_NAME | Structured token containing the canonical name of the project being scoped |
| UI Detection | Keyword scan over combined conversation text for terms implying a user interface requirement |
| G162-1 | Gap fix: Concierge must always elicit on first call — never fast-path requirements on first intent |
| G213 | Gap fix: MAX_QA_ROUNDS cap prevents unbounded elicitation loops |
| Fixed Pipeline | The deterministic handoff sequence: U:Cx → U:BA → U:PM → U:Ar → U:Cd |
| conversation_history | Ordered list of all message exchanges between Concierge and the human in the current session |
| CXP Subject | The routing key in a CXP packet; "intent" and "response" are the two subjects U:Cx handles |
User Scenarios and Stories
US-001: Human Intent Intake (P1)
As a human user
I want to express my intent in plain language to the Orchestrata system
So that the system understands what I want to build before starting work
Scenario: The user sends a CXP packet with subject "intent" and a free-form description of a project idea. The Concierge receives it, invokes the LLM with CONCIERGE_SYSTEM_PROMPT, and returns a set of clarifying questions covering the relevant D1-D7 dimensions.
Acceptance Criteria:
- [ ] ConciergeVolk accepts CXP packets with subject "intent"
- [ ] original_intent is stored on first call and preserved across all rounds
- [ ] LLM is called with CONCIERGE_SYSTEM_PROMPT on every round
- [ ] Response is routed to HUMAN (not to a downstream Volk) as clarifying questions
- [ ] No requirements are compiled on the first call (G162-1 enforced)
- [ ] round_count increments to 1 after the first call
US-002: Iterative Clarifying Questions (P1)
As a human user
I want to answer questions progressively and receive follow-up questions as needed
So that the system can narrow scope without overwhelming me with every question at once
Scenario: After answering the first set of questions, the user sends a CXP packet with subject "response". The Concierge appends the answer to conversation_history, calls the LLM again with full conversation context, and returns the next set of questions or initiates finalization.
Acceptance Criteria:
- [ ] ConciergeVolk accepts CXP packets with subject "response"
- [ ] Human answers are appended to conversation_history before the next LLM call
- [ ] Each LLM call receives the complete conversation_history as context
- [ ] round_count increments on each "response" packet
- [ ] Questions are progressively focused based on prior answers
- [ ] Finalization is NOT triggered unless LLM signals REQUIREMENTS_COMPLETE or MAX_QA_ROUNDS is reached
US-003: Forced Finalization After MAX_QA_ROUNDS (P1)
As the system
I want to force requirements compilation after 4 Q&A rounds
So that the intake stage cannot loop indefinitely (G213 gap fix)
Scenario: The user and Concierge have exchanged 4 rounds without the LLM signalling REQUIREMENTS_COMPLETE. On the 4th round, the Concierge calls _finalize() regardless of the LLM response content, compiling whatever requirements have been gathered.
Acceptance Criteria:
- [ ] MAX_QA_ROUNDS is defined as the integer constant 4
- [ ] round_count is compared to MAX_QA_ROUNDS after each response round
- [ ] When round_count >= MAX_QA_ROUNDS, _finalize() is called unconditionally
- [ ] Forced finalization compiles requirements from conversation_history to date
- [ ] Forced finalization emits PROLOG_FACTS with whatever facts have been established
- [ ] No additional questions are sent to HUMAN after forced finalization
US-004: Requirements Compilation and Structured Parsing (P1)
As the pipeline
I want to receive a structured, machine-readable requirements package
So that downstream Volks (PM, Architect, CodeDirector) can execute deterministically
Scenario: After the LLM signals REQUIREMENTS_COMPLETE, the Concierge calls _finalize(), which parses the LLM response for five structured fields and assembles the requirements package.
Acceptance Criteria:
- [ ] _finalize() parses REQUIREMENTS_COMPLETE from LLM response
- [ ] _finalize() parses PROLOG_FACTS block from LLM response
- [ ] _finalize() parses ESCALATE_TO field from LLM response
- [ ] _finalize() parses TASK_SUMMARY paragraph from LLM response
- [ ] _finalize() parses PROJECT_NAME field from LLM response
- [ ] Parsed fields are included in the outbound CXP packet to U:BA
- [ ] UI requirements flag is set when UI-related keywords are detected in conversation_history
US-005: Prolog Fact Emission (P1)
As the governance layer
I want to receive Prolog facts derived from the requirements elicitation
So that PAM++ can enforce constitutional policies on the compiled requirements
Scenario: When finalization completes, the Concierge emits the PROLOG_FACTS block extracted from the LLM response. These facts are stored in prolog_facts and included in the handoff packet.
Acceptance Criteria:
- [ ] PROLOG_FACTS block is extracted from the LLM finalization response
- [ ] Extracted facts are stored in the ConciergeVolk prolog_facts attribute
- [ ] Facts are syntactically valid Prolog (predicate/arity form)
- [ ] Facts are included in the CXP packet sent to U:BA
- [ ] prolog_facts persists across rounds once set
- [ ] Absent PROLOG_FACTS block does not cause a parsing error
US-006: Escalation Routing to U:BA (P1)
As the Orchestrata pipeline
I want to receive completed requirements at U:BA as the first downstream Volk
So that the fixed pipeline (BA → PM → Ar → Cd) begins from a consistent entry point
Scenario: After finalization, the Concierge sends a CXP packet addressed to U:BA containing the full requirements package. U:BA is always the next recipient regardless of the ESCALATE_TO field value, unless ESCALATE_TO specifies a human escalation.
Acceptance Criteria:
- [ ] Completed requirements are always sent to U:BA after finalization
- [ ] CXP packet to U:BA includes TASK_SUMMARY, PROJECT_NAME, PROLOG_FACTS, and conversation_history
- [ ] ESCALATE_TO field is parsed and logged but U:BA is the fixed pipeline entry point
- [ ] UI requirements flag is propagated to U:BA in the handoff packet
- [ ] Handoff packet uses the correct CXP subject for BA intake
- [ ] No other Volk receives the requirements packet directly from U:Cx
System Prompt: Seven-Dimension Elicitation (D1-D7)
CONCIERGE_SYSTEM_PROMPT is a structured LLM prompt that directs the Concierge to elicit requirements across seven dimensions before finalizing. Each dimension targets a distinct requirement class:
| Dimension | Label | Scope |
|---|---|---|
| D1 | Functional Scope | What features and capabilities the system must provide |
| D2 | Tech Stack | Languages, frameworks, platforms, and infrastructure constraints |
| D3 | Data Model | Entities, relationships, persistence, and data flow |
| D4 | Interfaces | APIs, UIs, CLIs, webhooks, and integration points |
| D5 | Quality | Performance, reliability, scalability, and security targets |
| D6 | Deployment | Hosting, containerisation, CI/CD, and operational requirements |
| D7 | Constraints | Budget, timeline, team size, compliance, and hard limits |
The prompt instructs the LLM to:
- Ask clarifying questions grouped by dimension
- Signal REQUIREMENTS_COMPLETE when all critical dimensions are sufficiently covered
- Emit PROLOG_FACTS in valid Prolog syntax
- Emit TASK_SUMMARY, PROJECT_NAME, and ESCALATE_TO on finalization
Data Models
ConciergeVolk Attributes
| Attribute | Type | Description |
|---|---|---|
| alias | str | "U:Cx" — fixed Volk identifier |
| role | str | "Concierge (Intake)" — fixed role label |
| conversation_history | list[dict] | Ordered list of all exchanges in the current elicitation session |
| original_intent | str | The first human intent message; preserved across all rounds |
| prolog_facts | str | Prolog-syntax facts parsed from LLM finalization response |
| round_count | int | Number of completed Q&A rounds; compared to MAX_QA_ROUNDS |
| MAX_QA_ROUNDS | int | Class constant = 4; forces finalization when round_count reaches this value |
Inbound CXP Packet (subject: "intent")
| Field | Value |
|---|---|
| from | HUMAN |
| to | U:Cx |
| subject | "intent" |
| body | Free-form human intent description |
Inbound CXP Packet (subject: "response")
| Field | Value |
|---|---|
| from | HUMAN |
| to | U:Cx |
| subject | "response" |
| body | Human answers to prior clarifying questions |
Outbound CXP Packet (questions to human)
| Field | Value |
|---|---|
| from | U:Cx |
| to | HUMAN |
| subject | "questions" |
| body | Clarifying questions formatted for human readability |
Outbound CXP Packet (handoff to U:BA)
| Field | Value |
|---|---|
| from | U:Cx |
| to | U:BA |
| subject | "requirements" |
| body | Structured requirements package including all parsed fields |
JSON Schemas
ConciergeVolk Attributes Schema
{
"type": "object",
"properties": {
"alias": {
"type": "string",
"const": "U:Cx",
"description": "Fixed Volk identifier"
},
"role": {
"type": "string",
"const": "Concierge (Intake)",
"description": "Fixed role label"
},
"conversation_history": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {"type": "string", "enum": ["user", "assistant"]},
"content": {"type": "string"}
}
},
"description": "Ordered list of all exchanges in the current elicitation session"
},
"original_intent": {
"type": "string",
"description": "The first human intent message; preserved across all rounds"
},
"prolog_facts": {
"type": "string",
"description": "Prolog-syntax facts parsed from LLM finalization response"
},
"round_count": {
"type": "integer",
"minimum": 0,
"description": "Number of completed Q&A rounds"
},
"MAX_QA_ROUNDS": {
"type": "integer",
"const": 4,
"description": "Class constant - forces finalization when round_count reaches this value"
}
},
"required": ["alias", "role", "conversation_history", "original_intent", "round_count"]
}
Inbound CXP Packet (intent) Schema
{
"type": "object",
"properties": {
"from": {"type": "string", "const": "HUMAN"},
"to": {"type": "string", "const": "U:Cx"},
"subject": {"type": "string", "const": "intent"},
"body": {"type": "string", "minLength": 1}
},
"required": ["from", "to", "subject", "body"]
}
Inbound CXP Packet (response) Schema
{
"type": "object",
"properties": {
"from": {"type": "string", "const": "HUMAN"},
"to": {"type": "string", "const": "U:Cx"},
"subject": {"type": "string", "const": "response"},
"body": {"type": "string", "minLength": 1}
},
"required": ["from", "to", "subject", "body"]
}
Outbound CXP Packet (questions to human) Schema
{
"type": "object",
"properties": {
"from": {"type": "string", "const": "U:Cx"},
"to": {"type": "string", "const": "HUMAN"},
"subject": {"type": "string", "const": "questions"},
"body": {"type": "string", "minLength": 1}
},
"required": ["from", "to", "subject", "body"]
}
Outbound CXP Packet (handoff to U:BA) Schema
{
"type": "object",
"properties": {
"from": {"type": "string", "const": "U:Cx"},
"to": {"type": "string", "const": "U:BA"},
"subject": {"type": "string", "const": "requirements"},
"body": {
"type": "object",
"properties": {
"TASK_SUMMARY": {"type": "string"},
"PROJECT_NAME": {"type": "string"},
"PROLOG_FACTS": {"type": "string"},
"UI_REQUIREMENTS": {"type": "boolean"},
"CONVERSATION_HISTORY": {"type": "array"}
},
"required": ["TASK_SUMMARY", "PROJECT_NAME"]
}
},
"required": ["from", "to", "subject", "body"]
}
Gap Fixes Encoded in This Spec
| Gap ID | Description | Resolution |
|---|---|---|
| G162-1 | Concierge fast-pathed on first call, skipping elicitation | Always call LLM and ask questions on first "intent" packet; never compile requirements on round 0 |
| G213 | Elicitation could loop indefinitely when LLM never signalled REQUIREMENTS_COMPLETE | MAX_QA_ROUNDS = 4 hard cap; _finalize() called unconditionally when round_count >= MAX_QA_ROUNDS |
| G243 | Gateway chat handler silently faked a Concierge reply (a canned "Received: ..." echo) whenever the out-of-process volk kernel wasn't reachable inside the ~3s gRPC readiness window, giving users a fake assistant with no indication | Gateway routes to the real ConciergeVolk when the live kernel is reachable; otherwise it returns an explicit, machine-detectable "assistant unavailable" response — never a fabricated conversational reply (REQ-032-053/054) |
Functional Requirements
FR-001: CXP Packet Intake
The ConciergeVolk MUST accept and process CXP packets with subjects "intent" and "response".
FR-002: Conversation State Management
The ConciergeVolk MUST maintain conversation_history, original_intent, round_count, and prolog_facts across all Q&A rounds.
FR-003: LLM Invocation with System Prompt
The ConciergeVolk MUST call the LLM with CONCIERGE_SYSTEM_PROMPT on every round, including the first.
FR-004: First-Round Question Elicitation
The ConciergeVolk MUST ask clarifying questions on the first round and MUST NOT compile requirements on round 0 (G162-1).
FR-005: Progressive Questioning
The ConciergeVolk MUST append human responses to conversation_history before each subsequent LLM call.
FR-006: MAX_QA_ROUNDS Enforcement
The ConciergeVolk MUST call _finalize() unconditionally when round_count >= MAX_QA_ROUNDS (4).
FR-007: Structured Response Parsing
The ConciergeVolk MUST parse REQUIREMENTS_COMPLETE, PROLOG_FACTS, ESCALATE_TO, TASK_SUMMARY, and PROJECT_NAME from LLM finalization responses.
FR-008: Prolog Fact Emission
The ConciergeVolk MUST emit syntactically valid Prolog facts in the PROLOG_FACTS block to the governance layer.
FR-009: UI Requirements Detection
The ConciergeVolk MUST detect UI-related keywords in conversation_history and set the UI requirements flag accordingly.
FR-010: U:BA Handoff
The ConciergeVolk MUST route completed requirements to U:BA as the fixed pipeline entry point after finalization.
FR-011: Seven-Dimension Elicitation
The ConciergeVolk MUST conduct requirements elicitation across D1-D7 dimensions: Functional Scope, Tech Stack, Data Model, Interfaces, Quality, Deployment, and Constraints.
FR-012: CXP Packet Construction
The ConciergeVolk MUST construct properly formatted CXP packets for all outbound messages with correct from/to/subject fields.
FR-013: Gateway Routing Availability (G243)
The gateway chat handler MUST dispatch cxp.send chat intents addressed to U:Cx to the real, live ConciergeVolk kernel when it is reachable. When the live kernel is not reachable (unwired, unready within the gRPC readiness window, or dispatch fails), the gateway MUST return an explicit, machine-detectable "assistant unavailable" response and MUST NOT fabricate a conversational-looking reply.
Error Conditions
| ID | Condition | Handling |
|---|---|---|
| ERR-001 | Invalid CXP packet structure | Reject packet and log error with packet ID |
| ERR-002 | Missing required CXP fields (from, to, subject, body) | Return error response with field specification |
| ERR-003 | Unsupported CXP subject (not "intent" or "response") | Reject with supported subjects list |
| ERR-004 | LLM API call timeout | Retry with exponential backoff (max 3 attempts) |
| ERR-005 | LLM response parsing failure | Log malformed response and trigger fallback finalization |
| ERR-006 | Missing original_intent on first call | Reject with intent required error message |
| ERR-007 | Invalid PROLOG_FACTS syntax | Log syntax error, emit absent facts block, continue |
| ERR-009 | Missing required parsed field | Use absent string fallback and log warning |
| ERR-010 | Conversation history corruption | Rebuild from CXP packet trail or restart session |
| ERR-011 | U:BA unreachable | Queue packet for retry with dead letter queue |
| ERR-012 | CONCIERGE_SYSTEM_PROMPT not found | Use default prompt and log configuration error |
| ERR-013 | MAX_QA_ROUNDS constant missing | Use default value of 4 and log configuration error |
| ERR-014 | Duplicate CXP packet detected | Discard duplicate and log with packet hash |
| ERR-015 | Invalid UI keyword detection result | Set UI flag to false and continue processing |
API Contracts
process_cxp_packet(packet: dict) -> dict
Processes incoming CXP packets and returns appropriate response.
Parameters:
- packet (dict): CXP packet with from, to, subject, body fields
Returns:
- dict: Response packet with appropriate structure
Raises:
- ValueError: Invalid packet structure
- RuntimeError: Processing failure
Example:
packet = {
"from": "HUMAN",
"to": "U:Cx",
"subject": "intent",
"body": "I want to build a task management app"
}
response = concierge.process_cxp_packet(packet)
finalize_requirements() -> dict
Forces finalization of requirements regardless of LLM signal.
Returns:
- dict: Structured requirements package with all parsed fields
Raises:
- RuntimeError: Finalization failure
detect_ui_requirements(history: list[str]) -> bool
Detects UI-related keywords in conversation history.
Parameters:
- history (list[str]): Combined conversation text
Returns:
- bool: True if UI requirements detected, False otherwise
Non-Functional Requirements
Performance
- Response time: < 5 seconds for LLM calls with 10-second timeout
- Throughput: Handle 100 concurrent intake sessions
- Memory: < 256MB per session for conversation_history storage
Scalability
- Support up to 1000 Q&A rounds per session
- Scale horizontally across multiple ConciergeVolk instances
- Maintain session state independently per instance
Reliability
- 99.9% uptime for intake operations
- Graceful degradation on LLM API failures
- Automatic recovery from conversation state corruption
Maintainability
- Clear separation between elicitation logic and CXP handling
- Comprehensive logging for all state transitions
- Modular prompt management for D1-D7 dimensions
Technical Design
Architecture
The ConciergeVolk extends BaseVolk with specialized intake logic:
- CXP Router: Routes packets by subject ("intent" vs "response")
- Conversation Manager: Maintains state across Q&A rounds
- LLM Interface: Invokes CONCIERGE_SYSTEM_PROMPT consistently
- Finalizer: Parses structured fields and compiles requirements
- UI Detector: Keyword scanning for interface requirements
State Machine
IDLE → INTENT_RECEIVED → QUESTIONING → (RESPONSE_RECEIVED)*
→ (MAX_ROUNDS_CHECK) → FINALIZING → HANDOVER → COMPLETE
States:
- IDLE: Waiting for intent
- INTENT_RECEIVED: Initial intent stored, round_count = 1
- QUESTIONING: Awaiting human response to questions
- RESPONSE_RECEIVED: Answer appended, history updated
- FINALIZING: Parsing LLM response for structured fields
- HANDOVER: Sending requirements to U:BA
- COMPLETE: Session finished
Data Flow
- Human intent → CXP packet → ConciergeVolk
- ConciergeVolk → LLM call with system prompt → Clarifying questions
- Human answers → CXP packet → ConciergeVolk
- Repeat steps 2-3 until finalization trigger
- Finalization → Structured requirements → CXP packet → U:BA
Examples
Example 1: Complete Intake Session
Intent Packet:
{
"from": "HUMAN",
"to": "U:Cx",
"subject": "intent",
"body": "I need an e-commerce platform for selling handmade jewelry"
}
First Response:
{
"from": "U:Cx",
"to": "HUMAN",
"subject": "questions",
"body": "D1: What product categories besides jewelry? Do you need inventory management?\nD2: Preferred hosting platform? Any budget constraints?"
}
Third Round Finalization:
{
"from": "U:Cx",
"to": "U:BA",
"subject": "requirements",
"body": {
"TASK_SUMMARY": "Build e-commerce platform for handmade jewelry with inventory",
"PROJECT_NAME": "jewelry_marketplace",
"PROLOG_FACTS": "has_feature(inventory). requires_ui(true). has_payment(credit_card).",
"UI_REQUIREMENTS": true,
"CONVERSATION_HISTORY": [...]
}
}
Example 2: Forced Finalization
After 4 rounds without REQUIREMENTS_COMPLETE signal:
- Concierge calls _finalize() regardless of LLM response
- Compiles partial requirements from conversation_history
- Emits PROLOG_FACTS with established facts only
- Proceeds to U:BA handoff
Security
Authentication
- All CXP packets must include valid source authentication
- Internal pipeline communication uses service-to-service auth
- Human users authenticated via Orchestrata gateway
Authorization
- U:Cx can only receive from HUMAN or gateway
- U:Cx can only send to HUMAN, U:BA, or governance layer
- Prolog facts emission requires governance layer authorization
Input Validation
- CXP packet structure validated against schema
- Human input sanitized before LLM prompt injection
- Conversation history encrypted at rest
Audit Logging
- All CXP packets logged with timestamps
- LLM API calls recorded with prompts and responses
- Finalization events logged with parsed requirements summary
- Prolog facts emission logged for governance traceability
Governance
Constitutional Compliance
- Prolog facts feed into PAM++ constitutional enforcement
- Requirements compilation follows governance policies
- Escalation paths governed by pipeline regulations
Quality Gates
- No requirements compiled without elicitation (G162-1)
- Maximum Q&A rounds enforced (G213)
- Structured field completeness validated
- UI requirements properly flagged
Audit Requirements
- Complete conversation_history preserved
- Original intent immutable throughout session
- Prolog facts validated for syntactic correctness
- Finalization triggers logged with rationale
Visual Architecture
Class Diagram
Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 15:).
classDiagram-direction LR
class ArchitectAgent {
$agent_type: ClassVar[str] = 'U:Ar'
---
+__init__(model: str = 'claude-3-5-haiku', agent_name: str = '')
+async analyze_impact(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async design_solution(requirements: dict[str, Any]): dict[str, Any]
+async review_architecture(architecture: dict[str, Any]): dict[str, Any]
}
class BaseAgent <<pydantic>> {
-model: str = Field(default='claude-3-5-haiku', description='Model identifier for the agent', min_length=1, strict=True)
-agent_id: str = Field(default='', description='Unique agent identifier', strict=True)
-agent_name: str = Field(default='', description='Human-readable agent name', strict=True)
$agent_type: ClassVar[str] = 'U:Base'
$_instance_counters: ClassVar[dict[str, int]] = {}
---
{@classmethod} +validate_model(v: str): str
+__init__(**data: Any): None
#_generate_unique_id(): str
+model_post_init(__context: Any): None
+async receive_message(message: Any, sender: str | None = None): Any
}
class CodeDirectorAgent {
$agent_type: ClassVar[str] = 'U:Cd'
---
+__init__(model: str = 'claude-3-5-sonnet', agent_name: str = '')
+async execute_edit(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async review_code(code: str, requirements: dict[str, Any]): dict[str, Any]
+async implement_feature(spec: dict[str, Any]): dict[str, Any]
}
class QualityAssuranceAgent {
$agent_type: ClassVar[str] = 'U:Qa'
---
+__init__(model: str = 'claude-3-5-sonnet', agent_name: str = '')
+async review_edit(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async run_tests(test_suite: str): dict[str, Any]
+async audit_security(code: str): dict[str, Any]
}
class UserExperienceAgent {
$agent_type: ClassVar[str] = 'U:Ux'
---
+__init__(model: str = 'claude-3-5-haiku', agent_name: str = '')
+async review_ux(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async design_ui(requirements: dict[str, Any]): dict[str, Any]
+async evaluate_accessibility(ui: dict[str, Any]): dict[str, Any]
}
BaseAgent <|-- ArchitectAgent
BaseModel <|-- BaseAgent
BaseAgent <|-- CodeDirectorAgent
BaseAgent <|-- QualityAssuranceAgent
BaseAgent <|-- UserExperienceAgent
Dependencies
| Dependency | Version | Purpose |
|---|---|---|
| orchestrata-core | >=1.0.0 | Base Volk infrastructure and CXP handling |
| orchestrata-agents | >=1.0.0 | Base agent abstractions |
| orchestrata-cxp | >=1.0.0 | CXP packet definitions and routing |
| orchestrata-governance | >=1.0.0 | Prolog fact handling and constitutional enforcement |
Testing
Unit Tests
- Test CXP packet acceptance for valid subjects
- Test conversation_history append and retrieval
- Test MAX_QA_ROUNDS enforcement logic
- Test structured field parsing from LLM responses
- Test UI keyword detection accuracy
Integration Tests
- Test complete intake sessions with mock LLM
- Test forced finalization on MAX_QA_ROUNDS
- Test U:BA handoff with structured requirements
- Test Prolog facts emission and validation
End-to-End Tests
- Test multi-round Q&A with human simulator
- Test error conditions and recovery
- Test concurrent session handling
- Test state persistence across restarts
Coverage Targets
- Line coverage: > 95%
- Branch coverage: > 90%
- Functional requirements: 100% coverage
- Error conditions: 100% test cases
Integration Points
Upstream
- Human Users: Send intent and response packets via CXP
- Gateway: Authenticates and routes external messages
Downstream
- U:BA (Business Analyst): Receives compiled requirements
- Governance Layer: Receives Prolog facts for policy enforcement
- LLM API: Provides requirements elicitation intelligence
Internal
- BaseVolk: Provides CXP handling infrastructure
- CXP Router: Routes packets by subject
- Prompt Manager: Manages CONCIERGE_SYSTEM_PROMPT template
External Systems
- Logging System: Receives audit logs and error events
- Metrics System: Reports performance and usage metrics
- Monitoring System: Alerts on failures and SLA breaches
Success Criteria
Functional Success
- [ ] All 6 user scenarios pass acceptance criteria
- [ ] All 12 functional requirements implemented and tested
- [ ] All 15 error conditions handled gracefully
- [ ] G162-1 and G213 gap fixes enforced
Quality Success
- [ ] 95%+ test coverage achieved
- [ ] < 5 second response time for 90% of operations
- [ ] 99.9% uptime for intake services
- [ ] Zero unhandled exceptions in production
Pipeline Success
- [ ] Smooth handoff to U:BA without data loss
- [ ] Complete conversation_history transmitted
- [ ] Syntactically valid Prolog facts emitted
- [ ] UI requirements correctly flagged
Compliance Success
- [ ] Constitutional governance policies enforced
- [ ] Audit logging complete for all operations
- [ ] Security requirements validated
- [ ] No data corruption or state loss
Observability
Logging Requirements
- Component Logging
- Log all major operations with appropriate log levels
- Include correlation IDs for request tracing
- Log performance metrics for critical operations
- Log errors with full context for debugging
Metrics Requirements
- Performance Metrics
- Operation duration histograms
- Request/error rate counters
- Resource utilization gauges
- Business metrics relevant to domain
Tracing Requirements
- Distributed Tracing
- Trace propagation across component boundaries
- Span attributes for domain-specific context
- Trace sampling based on operational needs
Alerting Requirements
- Critical Alerts
- Error rate spikes
- Performance degradation
- Resource exhaustion
- Business metric anomalies
Dashboard Requirements
- Operational Dashboard
- Real-time system health
- Performance trends
- Error analysis
- Resource monitoring
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0 | 2026-04-04 | Mohamed | Initial specification of Concierge Volk intake agent |
| 1.0.1 | 2026-04-09 | Mohamed | Added missing sections per SPEC_STANDARD: Functional Requirements (FR-001-012), Error Conditions (ERR-001-015), API Contracts, Non-Functional Requirements, Technical Design, Examples, Security, Governance, Dependencies, Testing, Integration Points, Success Criteria, Revision History. Fixed gap G162-1 and G213 documentation. |
Design Constraints
- No fast-path — The Concierge must never bypass the Q&A cycle, regardless of how complete the initial intent appears (G162-1)
- Fixed pipeline entry — After finalization, U:BA is always the next recipient; routing to other Volks directly is prohibited
- Conversation history completeness — All rounds of conversation must be passed to the LLM on every subsequent call; no truncation without explicit token-budget logic
- Prolog syntax validity — Emitted PROLOG_FACTS must be syntactically valid Prolog; malformed facts must be caught and logged without crashing
- Stateful within session — conversation_history, original_intent, prolog_facts, and round_count are instance state; they persist for the lifetime of the Volk instance handling the session