score_initiative
Score product initiatives via RICE or Impact-Effort. Resolve from source record with initiative_id, or score ad-hoc using raw_text and optional overrides. Returns score, breakdown, priority tier, and rationale.
Instructions
Score one initiative with RICE or Impact-Effort. Pass initiative_id to score a source-resolved record (RICE inputs are read from raw_metadata) or raw_text + overrides for an ad-hoc score without a source record. method = 'rice' (default) or 'impact_effort'. overrides = {reach, impact, confidence, effort} — any subset; takes precedence over what was in the source. RICE tier thresholds: P0 > 25, P1 10..25, P2 3..10, P3 < 3. Every call with initiative_id appends a scored decision to the index at PLAN_PROJECT_ROOT/.mk-plan-master/index.json. Returns {initiative_id, method, score, breakdown, tier, rationale, stored}.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| initiative_id | No | ||
| raw_text | No | ||
| method | No | rice | |
| overrides | No |
Implementation Reference
- Main handler function for score_initiative tool. Orchestrates scoring by parsing arguments, fetching initiative metadata if initiative_id provided, delegating to _score_with_method, recording to index, and returning the result.
def score_initiative_tool(arguments: dict) -> dict[str, Any]: method = (arguments.get("method") or "rice").lower() if method not in _VALID_METHODS: return _error( f"unknown scoring method: {method!r}", retryable=False, hint=f"Use one of {sorted(_VALID_METHODS)}.", ) initiative_id = arguments.get("initiative_id") raw_text = arguments.get("raw_text") overrides = arguments.get("overrides") or {} if not initiative_id and not raw_text: return _error( "either initiative_id or raw_text is required", retryable=False, hint=( "Pass initiative_id (resolved via the active adapter) or " "raw_text + overrides for ad-hoc scoring without a source record." ), ) initiative: Initiative | None = None meta: dict = {} title = "" url = "" source_name = "" if initiative_id: try: initiative = _fetch_initiative(str(initiative_id)) except ValueError as exc: return _error( str(exc), retryable=False, hint="Confirm initiative_id via list_initiatives.", ) except Exception as exc: return _error( f"{type(exc).__name__}: {exc}", retryable=True, hint="Transient adapter error — retry, then check credentials / network.", ) meta = dict(initiative.raw_metadata) title = initiative.title url = initiative.url source_name = initiative.source result = _score_with_method(method, meta, overrides) used_id = str(initiative_id) if initiative_id else "" stored = False if used_id: try: decisions_index.record_score( used_id, method=method, score=result["score"], tier=result["tier"], breakdown=result["breakdown"], source=source_name, title=title, url=url, ) stored = True except OSError as exc: return _error( f"index write failed: {exc}", retryable=True, hint="Confirm PLAN_PROJECT_ROOT is writable.", ) return { "initiative_id": used_id, "method": method, "score": result["score"], "breakdown": result["breakdown"], "tier": result["tier"], "rationale": result["rationale"], "stored": stored, } - Internal scoring dispatcher that routes to RICE or Impact-Effort scoring based on method parameter, computing score, breakdown, tier, and rationale.
def _score_with_method(method: str, meta: dict, overrides: dict) -> dict: """Returns {score, breakdown, tier, rationale}. Pure arithmetic — no side effects, no index writes; that's the caller's job.""" if method == "rice": inputs = _rice_inputs(meta, overrides) score = rice_score(**inputs) return { "score": score, "breakdown": inputs, "tier": rice_tier(score), "rationale": rice_rationale(**inputs), } # impact_effort inputs = _impact_effort_inputs(meta, overrides) score = impact_effort_score(**inputs) return { "score": score, "breakdown": inputs, "tier": impact_effort_quadrant(**inputs), "rationale": impact_effort_rationale(**inputs), } - Builds RICE input dict from initiative metadata and applies overrides (reach, impact, confidence, effort).
def _rice_inputs(meta: dict, overrides: dict) -> dict: """Build the RICE input dict from initiative metadata, then apply any explicit overrides on top (AI / user wins over what's in the source).""" inputs = { "reach": _to_float(meta.get("reach"), RICE_DEFAULTS["reach"]), "impact": _coerce_impact(meta.get("impact")), "confidence": _to_float(meta.get("confidence"), RICE_DEFAULTS["confidence"]), "effort": _to_float(meta.get("effort"), RICE_DEFAULTS["effort"]), } if "reach" in overrides: inputs["reach"] = _to_float(overrides["reach"], inputs["reach"]) if "impact" in overrides: inputs["impact"] = _coerce_impact(overrides["impact"]) if "confidence" in overrides: inputs["confidence"] = _to_float(overrides["confidence"], inputs["confidence"]) if "effort" in overrides: inputs["effort"] = _to_float(overrides["effort"], inputs["effort"]) return inputs - Builds Impact-Effort input dict (1..5 scale) from metadata and overrides.
def _impact_effort_inputs(meta: dict, overrides: dict) -> dict: """1..5 scale for both axes. If raw RICE-style values are present (impact 0.25..3), pass them through unchanged — the quadrant cutoff is independent of scale magnitude.""" impact = _to_float(overrides.get("impact"), _coerce_impact(meta.get("impact"))) effort = _to_float(overrides.get("effort"), _to_float(meta.get("effort"), 1)) return {"impact": impact, "effort": effort} - src/mk_plan_master/server.py:36-50 (registration)Dispatch table registering 'score_initiative' -> scoring_tools.score_initiative_tool
_DISPATCH: dict[str, Callable[[dict], dict]] = { "get_plan_source_info": initiatives_tools.get_plan_source_info_tool, "list_initiatives": initiatives_tools.list_initiatives_tool, "fetch_initiative": initiatives_tools.fetch_initiative_tool, "add_initiative": initiatives_tools.add_initiative_tool, "analyze_initiative": analysis_tools.analyze_initiative_tool, "score_initiative": scoring_tools.score_initiative_tool, "rank_backlog": scoring_tools.rank_backlog_tool, "generate_spec_draft": bridge_tools.generate_spec_draft_tool, "generate_roadmap": roadmap_tools.generate_roadmap_tool, "analyze_roadmap_balance": roadmap_tools.analyze_roadmap_balance_tool, "init_plan_knowledge": plan_knowledge_tools.init_plan_knowledge_tool, "get_plan_context": plan_knowledge_tools.get_plan_context_tool, "get_planning_history": history_tools.get_planning_history_tool, "get_decision_signature": history_tools.get_decision_signature_tool, - src/mk_plan_master/server.py:172-196 (schema)Tool registration with name, description, and inputSchema for score_initiative
Tool( name="score_initiative", description=( "Score one initiative with RICE or Impact-Effort. Pass " "initiative_id to score a source-resolved record (RICE inputs are " "read from raw_metadata) or raw_text + overrides for an ad-hoc " "score without a source record. method = 'rice' (default) or " "'impact_effort'. overrides = {reach, impact, confidence, effort} " "— any subset; takes precedence over what was in the source. " "RICE tier thresholds: P0 > 25, P1 10..25, P2 3..10, P3 < 3. " "Every call with initiative_id appends a `scored` decision to the " "index at PLAN_PROJECT_ROOT/.mk-plan-master/index.json. " "Returns {initiative_id, method, score, breakdown, tier, " "rationale, stored}." ), inputSchema={ "type": "object", "properties": { "initiative_id": {"type": "string"}, "raw_text": {"type": "string"}, "method": {"type": "string", "default": "rice"}, "overrides": {"type": "object"}, }, }, ),