PowerFill Module — Phase 5 Architect Kickoff
This is the prompt Kevin pastes into a new Cursor session to bootstrap the Systems Architect on PowerFill Phase 5 (Carry-Cost Calculator).
Important context for this kickoff: Phase 4's first attempt was the catalyst for canonicalizing the v4.1 Deploy Verification Gate and the "Verification Avoidance" antipattern candidate. Phase 5 inherits those lessons — they are baked into the prompt below. Use Opus 4.7 High Thinking (or equivalent reasoning model). Do NOT use Cursor Auto for this phase — Phase 4's auto-mode attempt produced a known-broken commit that required substantial rework.
Usage
- Open a new Cursor session in the PSSaaS repo.
- Set the model to Opus 4.7 High Thinking (or your project's strongest reasoning model).
- Copy everything inside the fenced block below.
- Paste as the first message in the new session.
- The Architect will self-onboard and respond with an acknowledgement.
The Prompt
You are the PSSaaS Systems Architect agent. This is a new session.
Start with your session-start checklist:
1. Read `CLAUDE.md` (project identity, invariants, role-identification procedure)
2. Read `AGENTS.md` (agent memory: principles, lessons, preferences,
especially the "push is an ask" convention and the F-PSD findings summary)
3. Read `docs-site/docs/agents/architect-context.md` (your role definition,
including v4 Required Delegation Categories)
4. Read `docs-site/docs/agents/process-discipline.md` (canonical v4.1)
5. Read `docs-site/docs/agents/handoff-prompts.md` (templates for delegating)
6. Read `docs-site/docs/handoffs/pssaas-session-handoff.md` (current state)
7. Read `docs-site/docs/agents/powerfill-architect-phase5-kickoff.md`
(this kickoff doc — full task description below)
After you have read those, acknowledge your role and proceed with the
Phase 5 task as described below.
== YOUR TASK — PowerFill Phase 5 ==
**Scope: Carry-Cost Calculator service.**
Phase 4 delivered the configuration management surface for `pfill_carry_cost`
(CRUD APIs, monotonicity-warning validation). Phase 5 builds the
**runtime calculator** that consumes those configured curves to compute
carry cost for loan-trade pairs. The calculator is a Phase 6 prerequisite —
the allocation engine scores candidates by `prx_and_carry` (price plus
carry), so without a working calculator Phase 6 cannot allocate correctly.
Per the spec at `docs-site/docs/specs/powerfill-engine.md` line 419:
"Phase 5: Carry cost calculator + CRUD APIs — 3-5 days." The CRUD half
already shipped in Phase 4; Phase 5 is the calculator half plus any
calculator-specific APIs the Architect surfaces.
== KEY CONTEXT FROM TONIGHT'S POC SESSION (2026-04-16) ==
A real customer database (PS_DemoData) is now live as a tenant accessible
via X-Tenant-Id: ps-demodata. It contains:
* 295 rows of production carry-cost data in pfill_carry_cost
* Sample carry-cost row shape (verified):
investor_instrument_name='15 fhlmc cash 85k', on_day=0, to_day=15, annual_rate=0.270000
investor_instrument_name='15 fhlmc cash 85k', on_day=16, to_day=30, annual_rate=0.270000
investor_instrument_name='15 fhlmc cash 85k', on_day=31, to_day=45, annual_rate=0.270000
* The instrument-name vocabulary includes patterns like '15 fhlmc cash 85k',
'15 fhlmc cash 110k', '10/6mo fnma 4929', '10 umbs', etc.
Phase 5 work should be designed AND validated against PS_DemoData, not just
the local pssaas-db container. Use `X-Tenant-Id: ps-demodata` for all
real-data validation. PS_DemoData is at SQL compatibility level 150 and
kevin_pssaas_dev now has db_ddladmin (Phase 4 confirmed both empirically).
== LEGACY REFERENCE (carry-cost computation in Desktop App) ==
The legacy NVO at `X:\dev\other\PowerSeller-App\plugins\powerfill\n_cst_powerfill.sru`
computes carry cost in `psp_powerfill_conset` via this pattern (search
for `pfill_carry_cost` in the NVO; key lines around 1330-1360):
WITH @average_carry_rate AS (
SELECT loan_id, trade_id, instrument_name,
AVG(pcc03.annual_rate) AS avg_rate,
interest_earning_days
FROM (...working set...)
INNER JOIN dbo.pfill_carry_cost pcc03
ON ...investor_instrument_name AND day-bucket containment...
GROUP BY ...)
SET carry_cost = CAST(acr04.avg_rate * acr04.interest_earning_days
AS NUMERIC(9,6))
SET prx_plus_carry = CAST(price + carry_cost AS NUMERIC(11,8))
The shape: for each (loan, trade) pair, find the matching carry curve row
by (investor_instrument, day-bucket), apply rate to interest-earning-days,
add to base price. Assumption A11 frames this as "days x rate" but flags
the exact day-bucket and interpolation rules as needing Tom/Greg confirmation.
Phase 5 must verify A11 against the actual NVO formula.
== EXPLICIT OUT OF SCOPE ==
* Allocation engine (Phase 6) — psp_powerfill_conset, the allocation
passes that USE the carry-cost calculator
* psp_powerfillUE / synthetic trades subsystem (Phase 6, A28) — see
`docs-site/docs/legacy/powerfill-syn-trades-deep-dive.md`
* React UI (Phase 8)
* PowerBuilder Connector Plugin spec/code (separate workstream)
== PROCESS DISCIPLINE REQUIREMENTS (v4.1 + tonight's lessons) ==
1. **Verification-before-completion is non-negotiable.** Phase 4's first
attempt shipped a known-broken commit because dotnet build/test were
not run before commit. Required pattern in this project:
docker exec pssaas-api dotnet build --nologo
docker exec pssaas-api dotnet test --nologo --no-build
These are documented in AGENTS.md technical-lessons section. If your
shell can't access the container, surface that fact to the Collaborator
BEFORE committing — don't proceed past a failed verification step.
2. **Primary-Source Verification Gate** — both arms:
- Static: read the NVO carry-cost computation directly. Verify A11 against
real SQL. The NVO is the source of truth; the spec and the assumptions
log are derived.
- Live: probe pfill_carry_cost in PS_DemoData. Sample several
investor_instrument_name values. Confirm column types match what the
PowerFillCarryCost entity declares. Tonight's session caught 4
entity-drift findings against PS_DemoData — assume nothing.
3. **Deploy Verification Gate** — Phase 4's hardening pattern (e.g., the
GET /settings/preflight endpoint with a `source` field showing
tenant/defaults/builtin) is the model. If Phase 5 introduces new SQL
artifacts, follow the A32 PRINT-in-guard convention.
4. **Required Delegation Categories** — the calculator is computation-
heavy, not boilerplate-heavy. Delegation candidates are limited:
probably just unit tests if you write enough of them. Document
Deliberate Non-Delegation justification per v4 §8 if you self-implement
work that matches a default-delegate category.
5. **Gate Output Action mandatory disposition per finding** — corrected
in place / scope-changed / deferred-with-justification. Phase 4's F3
escalation is the exemplar for how to handle a finding that requires
PO input.
6. **Push is an ask, not a tell** — never `git push`. Commit only.
== WHAT I WANT FROM YOU ==
1. **Enter Plan mode** (use the SwitchMode tool).
2. **Read carry-cost specifics:**
- Spec §"Carry Cost Configuration" (lines 85-90) — what the spec says
- Assumption A2 (carry cost is a scoring modifier, not a filter)
- Assumption A11 (days x rate; needs Tom/Greg confirmation on exact rules)
- The NVO carry-cost computation (grep for `pfill_carry_cost` in
`n_cst_powerfill.sru`; key lines around 1330-1360)
- PowerFillCarryCost entity to understand current EF mapping
3. **Run the Primary-Source Verification Gate** against:
- Spec claims about carry-cost shape
- PowerFillCarryCost entity vs PS_DemoData column-by-column
- The actual NVO computation vs A11's framing
4. **Probe PS_DemoData**:
- Sample 5-10 carry curves and characterize the data shape
- Confirm whether day-buckets are contiguous, whether they ever overlap,
whether annual_rate ever varies within a single instrument's curve
5. **Produce a CreatePlan output** with these sections (mirror Phase 4
plan structure at `.cursor/plans/powerfill-phase-4.plan.md`):
- §1 Scope (in / out)
- §2 Primary-Source Verification Gate findings + dispositions
- §3 The carry-cost computation (formal algorithm; reference NVO line
ranges; flag any deviations from A11)
- §4 New service (PowerFillCarryCostCalculator or similar) — surface,
inputs, outputs, where it lives, who calls it (currently nobody
in Phase 5; Phase 6 will)
- §5 Edge cases — loan with close_date after settlement_date (negative
days), instrument missing from pfill_carry_cost, day-bucket gap
between rows, etc. Each gets an explicit handling decision.
- §6 Calculator-specific APIs (if any) — e.g., GET /carry-cost/preview
that takes a loan/trade pair and returns the computed carry cost
for diagnostic purposes. Optional; Architect's call.
- §7 Alternatives-First decisions
- §8 Delegation plan (likely small for this phase)
- §9 Test strategy (unit tests against the calculator with synthetic
curves; integration test against PS_DemoData with real curves)
- §10 Risks captured
- §11 Counterfactual Retro placeholder (filled post-implementation)
6. **Surface open questions for PO input** rather than silently resolving:
- Day-bucket lookup semantics: closed interval [on_day, to_day]?
Half-open [on_day, to_day)? What if a loan's days falls in a gap
between rows?
- Interpolation between buckets (none / linear / step)?
- Behavior when loan's days exceeds the highest to_day in the curve
(extrapolate / cap / error)?
- A2 says "scoring modifier, not filter" — confirm Phase 5 calculator
never returns "loan disqualified" verdicts; that's strictly Phase 6's
allocation pass
7. **Before executing the plan,** wait for me (Kevin, PO) to review and
approve. The Collaborator will read the plan first and offer notes,
same protocol as Phase 4.
== COLLABORATION PROTOCOL ==
* PO is Kevin. Collaborator is in a different Cursor session.
* Escalate decisions affecting: spec/ADR text, BestEx module, tenant
provisioning, cross-product integration. Use handoff-prompts.md
Template 3 for escalations.
* Commit when a logical milestone is complete. Never push.
== CONSTRAINTS ==
* `decimal` for all carry-cost arithmetic — never `float` or `double`
(CLAUDE.md invariant #5)
* Tenant isolation absolute (CLAUDE.md invariant #4)
* Schema preservation per ADR-006 — pfill_carry_cost columns are not
changeable
* Phase 4's PoC artifact (is_ready:true) was achieved against PS_DemoData
with 3 sample constraints. Phase 5 success criterion: a calculator
invocation against PS_DemoData with real configured constraints
returns a sensible carry-cost number.
== WHEN YOU'RE DONE PLANNING ==
Respond with your plan via the CreatePlan tool. Include a short summary
and the resolution of each open question above (resolved with rationale,
or escalated with proposed options).
What Happens After
- Kevin pastes the prompt into a new Cursor session running Opus 4.7 High Thinking.
- Architect acknowledges role, reads onboarding docs.
- Architect produces a
CreatePlanfor Phase 5 calculator. - Architect surfaces open questions (especially day-bucket semantics) to PO via Collaborator.
- PO and Collaborator review.
- PO approves; Architect dispatches any delegation per §8 and self-implements the calculator.
- Architect produces completion report following the Phase 4 v2 report style (gate findings with dispositions, delegation outcomes, counterfactual retro).
- Collaborator reviews and commits.
Notes
- The Phase 4 plan at
.cursor/plans/powerfill-phase-4.plan.md(gitignored — local copy on the Architect's machine) is the structural reference. Match its format. - Phase 4 had a known-broken first attempt (Cursor Auto agent shipped without verification). Tonight's PoC session demonstrated the verification pattern that prevents it. Follow the verification pattern.
- The PoC is "live" against PS_DemoData with 3 sample constraints + 1 lockdown configured. Phase 5's calculator can use those configurations as input data for integration testing.