Use when the user asks to run an MCDA sales comparison analysis, rank comparable sales using multi-criteria decision analysis, value a commercial property using ordinal ranking, produce an MCDA valuation report, or apply MCDA to a comparable sales dataset. Trigger phrases include: "MCDA analysis", "ordinal ranking valuation", "run MCDA", "value this property using comparables", "sales comparison using MCDA".
How this skill is triggered — by the user, by Claude, or both
Slash command
/mcda-sales-comparison:mcda-sales-comparisonThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The MCDA Sales Comparison method produces a defensible, auditable value indication. Unlike
The MCDA Sales Comparison method produces a defensible, auditable value indication. Unlike traditional DCA with sequential dollar adjustments, ordinal ranking is more stable across heterogeneous comparable sets. The output markdown report must be immediately presentation-ready — complete ranking tables, score-to-price mapping, and a clear value conclusion.
Triggered by messages such as:
Parse the user's message for:
--profile <weight-profile> flag (industrial_default, industrial_logistics,
industrial_manufacturing, office_default, retail_default)--output <report-path> flaginputs/ directory and askBefore dispatching the subagent, resolve these values in the primary context.
Plugin root — run in Bash:
echo "${CLAUDE_PLUGIN_ROOT}"
If empty, find it:
find ~ -path "*/mcda-sales-comparison/skills/mcda-sales-comparison/SKILL.md" -maxdepth 8 2>/dev/null | head -1 | sed 's|/skills/mcda-sales-comparison/SKILL.md||'
If still empty, use: /home/reggiechan/021-CRE-150/plugins/mcda-sales-comparison
Workspace path — current working directory. Create Reports/ if absent:
mkdir -p "$(pwd)/Reports"
Timestamp — run TZ=America/Toronto date +%Y-%m-%d_%H%M%S.
From the resolved plugin root, construct:
SCRIPTS_DIR = <plugin_root>/skills/mcda-sales-comparison/scriptsCALCULATOR = <SCRIPTS_DIR>/mcda_sales_calculator.pyVerify the calculator exists:
ls "<CALCULATOR>"
If missing, report the error and stop.
Input JSON path — resolve to absolute path. If the user provided a relative path, resolve relative to workspace. Verify the file exists before dispatching.
Weight profile — use the --profile value if provided; otherwise use "auto" (the
calculator will auto-detect from property_type in the JSON).
Use the Agent tool to dispatch a subagent. This offloads the calculator run and report generation to a fresh 200k-token context window, keeping the primary context clean.
If the Agent tool is unavailable, execute Steps A through E directly in the current context.
Substitute the resolved values for {{ }} placeholders, then call the Agent tool with
description: "MCDA sales comparison analysis" and the prompt below:
--- BEGIN SUBAGENT PROMPT ---
You are an MCDA sales comparison analysis agent. Your sole job is to complete the analysis pipeline below and return a structured summary. Do not ask questions — execute all steps and report results.
Read the input JSON file using the Read tool:
Confirm it contains:
subject_property with address and building_sfcomparable_sales array with at least 3 entriesvaluation_date at root or in market_parametersIf validation fails, stop and report the specific missing fields.
Run the following in Bash. Note: cd to the scripts directory first — the calculator uses
sibling imports (validation, score_to_price, weight_profiles) that resolve relative to CWD.
If weight profile is "auto":
cd "{{ SCRIPTS_DIR }}" && python3 mcda_sales_calculator.py \
"{{ INPUT_JSON_PATH }}" \
--output /tmp/mcda_results.json \
--verbose
If weight profile is specified:
cd "{{ SCRIPTS_DIR }}" && python3 mcda_sales_calculator.py \
"{{ INPUT_JSON_PATH }}" \
--output /tmp/mcda_results.json \
--profile {{ PROFILE }} \
--verbose
Capture stdout/stderr. If the command exits non-zero, report the error and stop.
Read the results file: Read(file_path="/tmp/mcda_results.json")
Verify ALL of the following before proceeding to report generation:
value_indication.indicated_value_psf is present, non-null, and positive (> 0)value_indication.indicated_value_total is present, non-null, and positivecomparable_analysis array has at least 3 entriessubject_property.composite_score is present and numericanalysis_summary.comparables_used equals len(comparable_analysis)value_indication.regression.r_squared is present and between 0 and 1If ANY check fails:
Using the results from /tmp/mcda_results.json, write a complete markdown report to:
{{ WORKSPACE_PATH }}/Reports/{{ TIMESTAMP }}_mcda_sales_comparison.md
Use this template, filling every placeholder with real values from the results JSON:
# MCDA Sales Comparison Analysis
**Subject Property:** {subject_property.address}
**Property Type:** {analysis_summary.property_type}
**Valuation Date:** {analysis_summary.valuation_date}
**Analysis Date:** {analysis_summary.analysis_date}
**Weight Profile:** {analysis_summary.weights_profile}
---
## Executive Summary
**Indicated Value:** ${value_indication.indicated_value_psf:.2f}/SF (${value_indication.indicated_value_total:,.0f} total)
**Value Range:** ${value_indication.value_range_psf[0]:.2f} – ${value_indication.value_range_psf[1]:.2f}/SF
**Methodology:**
- MCDA Ordinal Ranking with Score-to-Price Mapping
- {analysis_summary.comparables_used} comparable sales analyzed
({analysis_summary.comparables_excluded} excluded — non-arm's length or data issues)
- Interpolation weight: {value_indication.reconciliation.method_weights.interpolation:.0%},
Regression weight: {value_indication.reconciliation.method_weights.regression:.0%}
- **Reconciliation rationale:** {value_indication.reconciliation.rationale}
---
## Subject Property
**Address:** {subject_property.address}
**Building SF:** {subject_property.building_sf:,}
**Composite Score:** {subject_property.composite_score:.3f} (lower = better)
---
## Comparable Sales Analysis
| # | ID | Address | Sale Date | Price | PSF | Score | Rank |
|---|----|---------|-----------|-------|-----|-------|------|
[For each entry in comparable_analysis, sorted by composite_score ascending:]
| {rank} | {id} | {address} | {sale_date} | ${sale_price:,.0f} | ${price_psf:.2f} | {composite_score:.3f} | {rank} |
| **Subject** | — | {subject_property.address} | — | TBD | TBD | {subject_property.composite_score:.3f} | {subject_rank} |
---
## Score-to-Price Mapping
### Interpolation Method
**Lower Bracket:** {value_indication.interpolation.lower_bracket} (Score: X.XX, $XX.XX/SF)
**Upper Bracket:** {value_indication.interpolation.upper_bracket} (Score: X.XX, $XX.XX/SF)
**Confidence:** {value_indication.interpolation.confidence}
**Indicated Value (Interpolation):** ${value_indication.interpolation.indicated_psf:.2f}/SF
### Regression Method
**Method:** {value_indication.regression.method}
**R²:** {value_indication.regression.r_squared:.3f}
**Slope (β):** ${value_indication.regression.beta:.4f}/score point
**Indicated Value (Regression):** ${value_indication.regression.indicated_psf:.2f}/SF
### Reconciliation
| Method | Weight | Indicated Value |
|--------|--------|-----------------|
| Interpolation | {value_indication.reconciliation.method_weights.interpolation:.0%} | ${value_indication.interpolation.indicated_psf:.2f}/SF |
| Regression | {value_indication.reconciliation.method_weights.regression:.0%} | ${value_indication.regression.indicated_psf:.2f}/SF |
| **Reconciled** | **100%** | **${value_indication.indicated_value_psf:.2f}/SF** |
**Rationale:** {value_indication.reconciliation.rationale}
---
## Value Indication
**Indicated Value Per SF:** ${value_indication.indicated_value_psf:.2f}
**Indicated Total Value:** ${value_indication.indicated_value_total:,.0f}
**Value Range:** ${value_indication.value_range_total[0]:,.0f} – ${value_indication.value_range_total[1]:,.0f} (±5%)
**Confidence:** {value_indication.interpolation.confidence} / R² = {value_indication.regression.r_squared:.3f}
---
## Methodology Notes
### MCDA vs Traditional DCA
**Traditional DCA** requires paired sales data and applies sequential dollar adjustments — errors
compound and adjustment order matters. **MCDA Ordinal Ranking** ranks all properties on each
characteristic; relative rankings are more stable than dollar estimates. Score-to-price mapping
via interpolation and regression provides a model-based value check on the interpolation result.
### Weight Profile: {analysis_summary.weights_profile}
[Enumerate the top variables from the results and their directional meaning.]
### Limitations
1. Ordinal ranking captures relative position, not magnitude of differences
2. Requires minimum 3 comparables for meaningful analysis
3. Score-to-price assumes monotonicity (better score → higher price)
4. Extrapolation beyond comparable range carries lower confidence
---
[If analysis_summary.warnings is non-empty:]
## Warnings
{For each warning in analysis_summary.warnings, format as a bullet point}
---
**Report Generated By:** Claude Code — MCDA Sales Comparison Plugin
**Analysis Date:** {analysis_summary.analysis_date}
**Framework:** MCDA Ordinal Ranking with Score-to-Price Mapping
Compute subject_rank by counting how many comparables have a lower composite_score than
the subject (lower = better), then adding 1.
Write the completed report to the Reports/ path using the Write tool.
Copy the results JSON for reproducibility:
cp /tmp/mcda_results.json \
"{{ WORKSPACE_PATH }}/Reports/{{ TIMESTAMP }}_mcda_sales_comparison.json"
Confirm:
ls -lh "{{ WORKSPACE_PATH }}/Reports/{{ TIMESTAMP }}_mcda_sales_comparison.md"ls -lh "{{ WORKSPACE_PATH }}/Reports/{{ TIMESTAMP }}_mcda_sales_comparison.json"Return ONLY this block — no other commentary:
ANALYSIS_RESULT subject: <subject_property.address> indicated_value_psf: $<XX.XX> indicated_value_total: $<X,XXX,XXX> value_range: $<X,XXX,XXX> – $<X,XXX,XXX> comparables_used: regression_r2: <X.XXX> regression_method: <ols|monotone|theil_sen> report: Reports/.md json: Reports/.json errors: <none, or description of any issues encountered>
--- END SUBAGENT PROMPT ---
When the subagent returns, parse the ANALYSIS_RESULT block and report:
✅ MCDA analysis complete — {comparables_used} comparables
💰 Indicated Value: {indicated_value_psf}/SF ({indicated_value_total})
📊 Value Range: {value_range}
📈 R² ({regression_method}): {regression_r2}
📄 Report: {report}
📋 JSON: {json}
If errors is not "none":
⚠️ Issues encountered: {errors}
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub reggiechan74/021-cre-150 --plugin mcda-sales-comparison