Orchestrata Ultimate / Specs / 012-pm-volk
012-pm-volk: PM Volk (Project Manager)
U:PM is the Project Manager volk — responsible for scope validation, effort estimation, progress tracking, and process enforcement. It sits between Concierge (requirements) and Architect (design), ensuring the project scope is achievable before design begins.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/012-pm-volk/ |
| Status line in the spec | Draft |
| Requirement IDs defined | 59 |
With a @traces citation in src/ |
52 (88.1%) |
With a @traces citation in tests/ |
1 (1.7%) |
| Tracked files | 6 |
| RTM page | 012-pm-volk |
Reading this spec
U:PM is the Project Manager Volk. It is responsible for scope validation, effort estimation, progress tracking and process enforcement. It sits between the Concierge, which supplies requirements, and the Architect, which produces design, and makes sure the project scope is achievable before design begins.
The scope is five user stories: scope validation and effort estimation (critical), and progress monitoring, budget enforcement and iteration summary (high). The goals are to prevent scope creep before it reaches architecture, give iterations realistic estimates, track fix and review cycles, enforce process (design before code, review before test) and flag when an iteration exceeds its budget of time, LLM calls or cycles. Requirement IDs use the REQ-012- prefix.
The overview describes how it works. The PM Volk receives requirements from U:Cx and validates scope, estimates effort from file count, complexity and expected test count, monitors CXP packet flow for cycle counts and escalations, emits warnings when thresholds are exceeded, and produces an iteration summary with metrics.
In the code, the Volk lives at orchestrata_ultimate/agents/volks/pm/volk, with goal handling in orchestrata_ultimate/agents/volks/pm/goal_registry and orchestrata_ultimate/agents/volks/pm/goal_report, and budget tracking in orchestrata_ultimate/agents/volks/pm/budget. The per-requirement view is on the RTM page.
The spec's status line reads Draft. It tracks 6 files and defines 59 requirement IDs. The full text follows below.
Measured coverage is 52 of 59 requirements cited by at least one @traces in src/ (88.1%), spread over 6 modules; the module citing the most of them is orchestrata_ultimate/agents/volks/pm/volk (28 requirements). In tests/, 1 requirement is cited by a test-side @traces.
Coverage gaps: 7 requirements have no citing symbol. The largest untraced groups are REQ-012-* (4), REQ-012-NFR (3). 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 (1 against 52).
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-012-001 |
no | PMVolk class extends BaseVolk with alias U:PM and role "Project Manager". | 1 |
REQ-012-002 |
no | PMVolk registers with the volk registry at import time so the kernel can discover it. | none |
REQ-012-003 |
no | process() accepts a CXPPacket and dispatches on the subject field. | 1 |
REQ-012-004 |
no | process() handles subjects: "implement", "scope_review", "progress_update". | 2 |
REQ-012-005 |
no | Unrecognised subjects are returned as an error CXPPacket without raising an exception. | 1 |
REQ-012-006 |
no | PM_SYSTEM_PROMPT instructs the LLM to count FEATURES, DATA ENTITIES, INTERFACES, and DEPLOYMENT targets in the task description. | none |
REQ-012-007 |
no | PM_SYSTEM_PROMPT specifies WARNING thresholds: >10 files, >8 features, >5 integrations, >20 LLM calls. | none |
REQ-012-008 |
no | _handle_scope_review() calls the LLM with PM_SYSTEM_PROMPT and the inbound packet body as user content. |
2 |
REQ-012-009 |
no | LLM response must include a SCOPE_RESULT token of either VALIDATED or WARNING. | 1 |
REQ-012-010 |
no | LLM response must include an ESTIMATE block containing a JSON object with keys: files, tests, llm_calls, duration_minutes, features, entities, interfaces. | 1 |
REQ-012-011 |
no | LLM response may include a WARNINGS block; absence of the block is treated as an empty warning list. | 1 |
REQ-012-012 |
no | LLM response must include a TASK_SUMMARY block summarising the work in plain language. | 1 |
REQ-012-013 |
no | Scope validation operates in advisory mode: a WARNING result does not halt the pipeline. | 1 |
REQ-012-014 |
no | The parsed SCOPE_RESULT, ESTIMATE, and WARNINGS are attached to the outbound packet payload under structured keys. | 2 |
REQ-012-015 |
no | When the LLM returns an unparseable response, _handle_scope_review() logs the raw text and returns a packet with SCOPE_RESULT=WARNING and a parse-error warning entry. |
none |
REQ-012-016 |
no | _detect_has_ui() scans the task description for UI-indicator keywords (web app, dashboard, frontend, UI, React, Vue, Angular, interface, browser, SPA, PWA, portal). |
1 |
REQ-012-017 |
no | Keyword matching is case-insensitive. | 1 |
REQ-012-018 |
no | _detect_has_ui() returns True if at least one keyword matches, False otherwise. |
1 |
REQ-012-019 |
no | The has_ui boolean is stored in the outbound packet payload. | 1 |
REQ-012-020 |
no | _detect_has_ui() is called once per scope-review cycle and the result is not re-computed during routing. |
1 |
REQ-012-021 |
no | After scope review, _handle_scope_review() routes to alias U:Ux when has_ui is True. |
1 |
REQ-012-022 |
no | After scope review, _handle_scope_review() routes to alias U:Ar when has_ui is False. |
1 |
REQ-012-023 |
no | All structured fields from the inbound packet (thread_id, correlation_id, context) are preserved in the forwarded packet. | 1 |
REQ-012-024 |
no | The ESTIMATE JSON is forwarded verbatim in the payload so downstream volks can use it. | 1 |
REQ-012-025 |
no | Routing destination is logged at DEBUG level before forwarding. | 1 |
REQ-012-026 |
no | GoalRegistry.create() accepts name, description, priority (GoalPriority), and optional SuccessCriteria; returns a new Goal with a unique ID. | 1 |
REQ-012-027 |
no | GoalRegistry.activate() transitions a Goal from its current state to ACTIVE; raises GoalTransitionError for illegal transitions. | 2 |
REQ-012-028 |
no | GoalRegistry.update() accepts a Goal ID and a partial dict of fields; merges changes without replacing unspecified fields. | 1 |
REQ-012-029 |
no | GoalRegistry.complete() transitions a Goal to COMPLETED and records a completed_at timestamp. | 1 |
REQ-012-030 |
no | GoalRegistry.block() transitions a Goal to BLOCKED and records a reason string. | 1 |
REQ-012-031 |
no | GoalRegistry.defer() transitions a Goal to DEFERRED and records a reason string. | 1 |
REQ-012-032 |
no | GoalRegistry.cancel() transitions a Goal to CANCELLED and records a reason string. | 1 |
REQ-012-033 |
no | GoalRegistry.get() returns a Goal by ID; raises GoalNotFoundError when the ID does not exist. | 2 |
REQ-012-034 |
no | GoalRegistry.list() returns all Goals; accepts an optional status filter. | 1 |
REQ-012-035 |
no | GoalRegistry persists all state changes to context.json under the "goals" key atomically (write-then-rename). | 11 |
REQ-012-036 |
no | GoalStatus enum defines: ACTIVE, RUNNING, COMPLETED, BLOCKED, DEFERRED, CANCELLED. | 1 |
REQ-012-037 |
no | GoalPriority enum defines P0 (critical), P1 (high), P2 (medium), P3 (low). | 1 |
REQ-012-038 |
no | SuccessCriteria dataclass exposes: tests_pass (bool), min_coverage_pct (float), min_spec_coverage_pct (float), max_iterations (int), custom (list[str]). | 1 |
REQ-012-039 |
no | Goals serialise to and deserialise from JSON without data loss (all fields round-trip). | 1 |
REQ-012-040 |
no | GoalRegistry loads existing goals from context.json on construction so state survives process restarts. | 3 |
REQ-012-041 |
no | GoalReportGenerator.generate() accepts a Goal and iteration results dict; returns a structured GoalReport object. | 5 |
REQ-012-042 |
no | Report includes a summary section stating whether success criteria were met. | 2 |
REQ-012-043 |
no | Report includes a test results section comparing actual vs required test pass status. | 4 |
REQ-012-044 |
no | Report includes a coverage section comparing actual coverage pct against min_coverage_pct. | 2 |
REQ-012-045 |
no | Report includes a spec coverage section comparing actual spec coverage pct against min_spec_coverage_pct. | 2 |
REQ-012-046 |
no | Report includes a trend analysis section using iteration history to identify improving or degrading metrics. | 2 |
REQ-012-047 |
no | Gap analysis identifies every criterion that was not met and states the delta (e.g., "coverage 78% vs required 90%"). | 2 |
REQ-012-048 |
no | Recommendations section lists concrete next actions derived from identified gaps. | 3 |
REQ-012-049 |
no | Overall progress is calculated as (criteria met / total criteria) * 100, rounded to one decimal place. | 3 |
REQ-012-050 |
no | GoalReportGenerator.generate() is a pure function — it does not mutate the Goal or write to context.json. | 2 |
REQ-012-051 |
yes | PM monitors CXP packet flow for progress tracking and emits iteration_stalled when no progress arrives for 5 minutes (US-003). Implemented: PMVolk._emit_stall_if_due + budget.is_stalled; tested in tests/agents/volks/pm/test_budget_tracking.py. |
4 |
REQ-012-052 |
yes | PM emits progress_update at each stage transition (US-003). Implemented: PMVolk._emit_stage_progress + PipelineRunner._notify_pm (per-stage + end-of-run feed); tested in tests/agents/volks/pm/test_budget_tracking.py, tests/orchestrator/test_pipeline_runner_pm_notify.py. |
1 |
REQ-012-053 |
yes | PM emits budget_warning when 80% of any budget (LLM calls, duration, fix cycles) is consumed (US-004). Implemented: budget.BudgetTracker + PMVolk._emit_budget_events; tested in tests/agents/volks/pm/test_budget_tracking.py. |
2 |
REQ-012-054 |
yes | PM emits budget_exceeded when 100% of any budget is consumed; advisory only — never kills the iteration (US-004, SPEC-012 NFR-002). Implemented: budget.BudgetTracker + guarded _emit_guarded; tested in tests/agents/volks/pm/test_budget_tracking.py. |
2 |
REQ-012-055 |
yes | PM produces a structured iteration_summary dict (files, tests passed/failed, pass rate, LLM calls, duration, design/fix cycles), emitted as an event and persisted to the iteration conversation.md (US-005). Implemented: budget.build_iteration_summary + PMVolk.finalize_iteration; tested in tests/agents/volks/pm/test_budget_tracking.py. |
2 |
REQ-012-056 |
yes | PMConfig (SPEC-012 § Configuration) governs budgets and scope thresholds; defaults max_llm_calls=20, max_duration_minutes=30, max_fix_cycles=3, scope_file_threshold=10, scope_feature_threshold=8 (US-004). Implemented: budget.PMConfig; tested in tests/agents/volks/pm/test_budget_tracking.py. |
1 |
REQ-012-NFR-001 |
- | PM processing adds < 1s latency to pipeline | none |
REQ-012-NFR-002 |
- | PM is advisory only — never blocks pipeline | none |
REQ-012-NFR-003 |
- | PM state survives process restart (Redis-backed) | none |
Code that traces this spec
Checklists
checklists/constitutional.md
SPEC-012 PM Volk — Constitutional Checklist
Trace to: spec.md Constitutional articles referenced: CAI-1 (advisory), CAI-3 (data integrity), CAI-5 (governance compatibility), CAI-7 (performance), CAI-9 (no code modification)
Advisory Constraint
- [ ] CONST-012-001: PMVolk never blocks the pipeline; scope review results are advisory regardless of WARNING or VALIDATED status.
- [ ] CONST-012-002: PMVolk does not raise exceptions that propagate to the kernel; all internal errors are caught and surfaced as structured warning fields in the response packet.
- [ ] CONST-012-003: PMVolk does not set or override any downstream volk's decision — routing is deterministic based on has_ui and does not condition on SCOPE_RESULT.
No Code Modification
- [ ] CONST-012-004: PMVolk does not read, write, or modify any source code file. Its inputs and outputs are CXPPackets and context.json only.
- [ ] CONST-012-005: GoalRegistry writes exclusively to the "goals" key in context.json and does not modify any other key.
Prolog Governance Compatibility
- [ ] CONST-012-006: PMVolk exposes a Prolog-compatible fact signature pm_scope_result(ThreadId, ScopeResult, EstimateJson) for PAM++ fact integration.
- [ ] CONST-012-007: GoalRegistry exposes goal_status(GoalId, Status) Prolog facts so governance rules can query goal lifecycle state.
- [ ] CONST-012-008: PMVolk does not bypass PAM++ persona checks; all outbound packets are issued with the U:PM persona header.
Data Integrity
- [ ] CONST-012-009: GoalRegistry writes to context.json atomically using write-then-rename; partial writes must not corrupt existing goal state.
- [ ] CONST-012-010: GoalRegistry does not overwrite the full context.json — it merges only the "goals" key, leaving all other keys intact.
- [ ] CONST-012-011: Goal IDs are globally unique (UUID4); no two goals may share the same ID within a session or across sessions.
Immutability of Completed Goals
- [ ] CONST-012-012: A Goal in COMPLETED or CANCELLED state cannot be transitioned to any other state; GoalTransitionError is raised on any such attempt.
Performance
- [ ] CONST-012-013: _handle_scope_review() must complete (excluding LLM latency) within 200 ms on commodity hardware.
- [ ] CONST-012-014: GoalRegistry CRUD operations (excluding I/O) complete within 10 ms.
- [ ] CONST-012-015: GoalReportGenerator.generate() completes within 50 ms for a goal with up to 50 iteration history entries.
checklists/requirements.md
The requirement list above comes from this file; 6 of 56 checkbox items are ticked.
checklists/testing.md
SPEC-012 PM Volk — Testing Checklist
One test item per requirement. Trace to: requirements.md All tests use real implementations — no mocking.
Volk Identity and Routing
- [ ] TEST-012-001: Instantiate PMVolk and assert alias == "U:PM" and role == "Project Manager".
- [ ] TEST-012-002: Import orchestrata.pm; assert "U:PM" is present in the volk registry.
- [ ] TEST-012-003: Call process() with a CXPPacket for each handled subject; assert no AttributeError is raised.
- [ ] TEST-012-004: Call process() with subject "implement", "scope_review", "progress_update"; assert a CXPPacket is returned in each case.
- [ ] TEST-012-005: Call process() with subject "unknown_subject"; assert returned packet has status=error and contains the unknown subject in the error message.
Scope Validation — PM_SYSTEM_PROMPT
- [ ] TEST-012-006: Assert PM_SYSTEM_PROMPT contains the strings "FEATURES", "DATA ENTITIES", "INTERFACES", "DEPLOYMENT".
- [ ] TEST-012-007: Assert PM_SYSTEM_PROMPT contains threshold values 10, 8, 5, 20 in context of files, features, integrations, LLM calls respectively.
- [ ] TEST-012-008: Call
_handle_scope_review()with a real LLM stub that returns a minimal valid response; assert the LLM was called with PM_SYSTEM_PROMPT as system message. - [ ] TEST-012-009: Provide a synthetic LLM response containing "SCOPE_RESULT: VALIDATED"; assert
_parse_scope_result()returns scope_result=="VALIDATED". - [ ] TEST-012-010: Provide a synthetic LLM response with a valid ESTIMATE JSON block; assert
_parse_scope_result()returns a dict with all 7 required keys. - [ ] TEST-012-011: Provide a response without a WARNINGS block; assert parsed warnings list is empty (not None).
- [ ] TEST-012-012: Provide a response with a TASK_SUMMARY block; assert
_parse_scope_result()extracts the summary text. - [ ] TEST-012-013: Set SCOPE_RESULT=WARNING and call process(); assert the outbound packet is still forwarded (not dropped or held).
- [ ] TEST-012-014: Assert outbound packet payload contains keys scope_result, estimate, and warnings after
_handle_scope_review(). - [ ] TEST-012-015: Provide a response with invalid JSON in ESTIMATE; assert returned packet has SCOPE_RESULT=WARNING and warnings list contains a parse-error entry.
UI Detection
- [ ] TEST-012-016: Pass descriptions containing each keyword ("web app", "dashboard", "frontend", "UI", "React", "Vue", "Angular", "interface", "browser", "SPA", "PWA", "portal") to
_detect_has_ui(); assert True for each. - [ ] TEST-012-017: Pass "WEB APP" and "Dashboard" (mixed case) to
_detect_has_ui(); assert True for both. - [ ] TEST-012-018: Pass a description with no UI keywords to
_detect_has_ui(); assert False. - [ ] TEST-012-019: After
_handle_scope_review()on a UI task, assert outbound packet payload["has_ui"] is True. - [ ] TEST-012-020: Spy on
_detect_has_ui()call count per scope-review cycle; assert it is called exactly once.
Routing Logic
- [ ] TEST-012-021: Call
_handle_scope_review()with a UI task; assert outbound packet to_agent == "U:Ux". - [ ] TEST-012-022: Call
_handle_scope_review()with a non-UI task; assert outbound packet to_agent == "U:Ar". - [ ] TEST-012-023: Compare inbound and outbound packets; assert thread_id, correlation_id, and context are identical.
- [ ] TEST-012-024: Assert outbound packet payload["estimate"] equals the dict returned by
_parse_scope_result(). - [ ] TEST-012-025: Capture log output during
_handle_scope_review(); assert a DEBUG entry containing the routing destination is present.
GoalRegistry — CRUD and Lifecycle
- [ ] TEST-012-026: Call GoalRegistry.create() with all required fields; assert returned Goal has a non-empty UUID id and status==ACTIVE (default).
- [ ] TEST-012-027: Create a Goal then call activate(); assert status transitions correctly. Attempt activate() on a CANCELLED goal; assert GoalTransitionError.
- [ ] TEST-012-028: Create a Goal, call update() with a partial dict; assert specified fields changed and unspecified fields are unchanged.
- [ ] TEST-012-029: Call complete() on an ACTIVE Goal; assert status==COMPLETED and completed_at is a recent ISO timestamp.
- [ ] TEST-012-030: Call block() with a reason; assert status==BLOCKED and reason is stored.
- [ ] TEST-012-031: Call defer() with a reason; assert status==DEFERRED and reason is stored.
- [ ] TEST-012-032: Call cancel() with a reason; assert status==CANCELLED and reason is stored.
- [ ] TEST-012-033: Call get() with a valid ID; assert correct Goal returned. Call get() with a fake ID; assert GoalNotFoundError.
- [ ] TEST-012-034: Create 3 Goals with different statuses; assert list() returns all 3 unfiltered, and list(status=ACTIVE) returns only ACTIVE ones.
- [ ] TEST-012-035: After create(), read context.json; assert "goals" key contains the new goal. Simulate a partial write failure (truncated file); assert existing goals are intact.
- [ ] TEST-012-036: Assert GoalStatus.ACTIVE, RUNNING, COMPLETED, BLOCKED, DEFERRED, CANCELLED all exist in the enum.
- [ ] TEST-012-037: Assert GoalPriority.P0, P1, P2, P3 all exist and P0 > P1 > P2 > P3 in sort order.
- [ ] TEST-012-038: Construct a SuccessCriteria with all fields; assert each field is accessible and has the correct type.
- [ ] TEST-012-039: Create a Goal, serialise to dict, deserialise back; assert all fields are equal to the original.
- [ ] TEST-012-040: Write goals to context.json, create a second GoalRegistry instance; assert it loads the same goals on construction.
GoalReportGenerator
- [ ] TEST-012-041: Call generate() with a completed Goal and a passing results dict; assert a GoalReport object is returned.
- [ ] TEST-012-042: Assert report.summary states criteria were met when all criteria pass; states not met when any criterion fails.
- [ ] TEST-012-043: Pass results with tests_pass=False when SuccessCriteria.tests_pass=True; assert test results section reflects the failure.
- [ ] TEST-012-044: Pass coverage=78.0 against min_coverage_pct=90.0; assert coverage section reports the shortfall.
- [ ] TEST-012-045: Pass spec_coverage=65.0 against min_spec_coverage_pct=80.0; assert spec coverage section reports the shortfall.
- [ ] TEST-012-046: Pass iteration history with improving coverage over 3 iterations; assert trend analysis section notes improvement.
- [ ] TEST-012-047: Pass results that miss 2 criteria; assert gap analysis section contains exactly 2 entries each with a delta.
- [ ] TEST-012-048: Pass results that miss coverage and spec coverage; assert recommendations section contains at least 2 entries.
- [ ] TEST-012-049: Create a SuccessCriteria with 4 criteria; pass results where 3 pass; assert report.progress_pct == 75.0.
- [ ] TEST-012-050: Call generate() twice with the same inputs; assert the Goal object is identical before and after each call (no mutation).
Other tracked files
specs/012-pm-volk/README.mdspecs/012-pm-volk/compliance-audit.md
Full spec text
Verbatim from specs/012-pm-volk/spec.md; headings are pushed down two levels.
SPEC-012: PM Volk (Project Manager)
Metadata
- Spec ID: 012-pm-volk
- Title: PM Volk — Project Management Agent
- Author: Mohamed
- Status: Draft
- Created: 2026-03-16
- Priority: P1
- Components: PM Volk, Scope Validator, Effort Estimator
Overview
What
U:PM is the Project Manager volk — responsible for scope validation, effort estimation, progress tracking, and process enforcement. It sits between Concierge (requirements) and Architect (design), ensuring the project scope is achievable before design begins.
Why
- Prevent scope creep before it reaches architecture
- Estimate effort so iterations have realistic expectations
- Track progress across fix cycles and review cycles
- Enforce process (design before code, review before test)
- Flag when an iteration exceeds budget (time, LLM calls, cycles)
How
- Receives requirements from U:Cx, validates scope
- Estimates effort (file count, complexity, expected test count)
- Monitors CXP packet flow for cycle counts and escalations
- Emits warnings when thresholds exceeded
- Produces iteration summary with metrics
User Scenarios & Stories
US-001: Scope Validation (Critical)
As a system operator I want the PM to validate project scope before architecture begins So that overly ambitious intents are flagged early
Acceptance Criteria:
- PM receives requirements from Concierge
- Validates against complexity heuristics (file count, feature count)
- Emits
scope_validatedorscope_warningevent - Scope warnings include specific concern (e.g., "10+ files estimated, consider splitting")
- Does NOT block — warns only, Architect proceeds regardless
US-002: Effort Estimation (Critical)
As a system operator I want effort estimates before implementation begins So that I can set expectations for iteration duration
Acceptance Criteria:
- PM estimates: expected file count, expected test count, estimated LLM calls, estimated duration
- Estimates based on requirements dimensions (features, data model, interfaces, deployment)
- Estimate attached to CXP packet as payload field
- Actual vs estimated tracked for future calibration
US-003: Progress Monitoring (High)
As a system operator I want real-time progress tracking during iterations So that I know if an iteration is stuck or on track
Acceptance Criteria:
- PM observes CXP packets flowing through Postman
- Tracks: design cycles completed, code files generated, review cycles completed, test files generated, pass/fail count
- Emits
progress_updateevent at each stage transition - Emits
iteration_stalledif no progress in 5 minutes
US-004: Budget Enforcement (High)
As a system operator I want warnings when iterations exceed resource budgets So that runaway iterations are caught early
Acceptance Criteria:
- Configurable budgets: max LLM calls (default 20), max duration (default 30 min), max fix cycles (default 3)
- PM emits
budget_warningwhen 80% consumed - PM emits
budget_exceededwhen 100% consumed - Budget exceeded does NOT kill iteration — warns only
US-005: Iteration Summary (High)
As a system operator I want a structured summary after each iteration So that I can track improvements across iterations
Acceptance Criteria:
- PM produces summary with: files generated, tests passed/failed, pass rate, LLM calls made, duration, design cycles, fix cycles
- Summary formatted as structured dict (not prose)
- Summary emitted as
iteration_summaryevent - Summary persisted to iteration conversation.md
Requirements
Functional Requirements
| ID | Requirement |
|---|---|
| REQ-012-001 | PM receives requirements packet from U:Cx via CXP |
| REQ-012-002 | PM validates scope against complexity heuristics |
| REQ-012-003 | PM estimates effort (files, tests, calls, duration) |
| REQ-012-004 | PM monitors CXP packet flow for progress tracking |
| REQ-012-005 | PM emits progress_update at each stage transition |
| REQ-012-006 | PM emits budget_warning at 80% consumption |
| REQ-012-007 | PM emits budget_exceeded at 100% consumption |
| REQ-012-008 | PM produces structured iteration_summary |
| REQ-012-009 | PM emits scope_validated or scope_warning |
| REQ-012-010 | PM tracks actual vs estimated for calibration |
| REQ-012-051 | PM monitors CXP packet flow for progress tracking; emits iteration_stalled after 5 minutes without progress |
| REQ-012-052 | PM emits progress_update at each stage transition |
| REQ-012-053 | PM emits budget_warning at 80% consumption (LLM calls, duration, fix cycles) |
| REQ-012-054 | PM emits budget_exceeded at 100% consumption; advisory only — never kills the iteration |
| REQ-012-055 | PM produces structured iteration_summary (files, tests, pass rate, calls, duration, cycles), emitted as an event and persisted to conversation.md |
| REQ-012-056 | PM budgets and scope thresholds are governed by PMConfig (§ Configuration) |
Non-Functional Requirements
| ID | Requirement |
|---|---|
| REQ-012-NFR-001 | PM processing adds < 1s latency to pipeline |
| REQ-012-NFR-002 | PM is advisory only — never blocks pipeline |
| REQ-012-NFR-003 | PM state survives process restart (Redis-backed) |
Architecture
Pipeline Position
HUMAN → U:Cx (Concierge) → U:PM (scope + estimate) → U:Ar (Architect) → ...
↓
monitors all CXP packets
↓
emits progress/budget/summary events
CXP Subjects
| Subject | From | To | Payload |
|---|---|---|---|
scope_review |
U:Cx | U:PM | requirements, task_summary |
scope_validated |
U:PM | U:Ar | requirements, estimate, warnings |
progress_update |
U:PM | HUMAN | stage, metrics |
budget_warning |
U:PM | HUMAN | metric, threshold, current |
iteration_summary |
U:PM | HUMAN | full metrics dict |
Configuration
@dataclass
class PMConfig:
max_llm_calls: int = 20
max_duration_minutes: int = 30
max_fix_cycles: int = 3
scope_file_threshold: int = 10 # warn if > this
scope_feature_threshold: int = 8 # warn if > this