{
  "skill_name": "cse-forecast",
  "evals": [
    {
      "id": 1,
      "prompt": "Run the CSE forecast for today. I need the board review before the forecasting meeting.",
      "expected_output": "Report-only forecast written to forecasts/YYYY-MM-DD.md and cse-forecast log. All four named queries fully paginated before any totals. Zero dry-runs and zero writes. Capacity from a fresh bandwidth evidence file or marked unavailable. No builder/GitHub showcase section.",
      "assertions": [
        {
          "name": "file_saved_to_forecasts_dir",
          "description": "Forecast saved to forecasts/YYYY-MM-DD.md"
        },
        {
          "name": "canonical_forecast_log_written",
          "description": "Completion receipt written to ~/.config/cse-tools/logs/cse-forecast-YYYYMMDD-HHMM.log with ACTIONS EXECUTED and HELD blocks"
        },
        {
          "name": "all_named_queries_fully_paginated",
          "description": "all_open, completed_this_week, stalled, and closed_complete_no_resolution are each paginated to completion before any count, total, or action mode"
        },
        {
          "name": "default_report_mode_no_writes_or_dry_runs",
          "description": "REPORT/default intent never calls cse_apply, never dry-runs guarded capabilities, and never mutates Jira/Slack/cse-dq"
        },
        {
          "name": "capacity_from_fresh_bandwidth_or_unavailable",
          "description": "Capacity uses the newest schema-valid cse-bandwidth-reports/YYYY-MM-DD.evidence.json no older than 7 days, or is marked unavailable"
        },
        {
          "name": "no_builder_github_scan",
          "description": "Forecast does not scan GitHub, rank commits, or produce a builder showcase section"
        }
      ]
    },
    {
      "id": 2,
      "prompt": "CSE forecasting meeting prep -- which accounts are stalled, and how long has each open engagement been in its current stage?",
      "expected_output": "Stalled engagements listed with blocker categories. Time-in-stage derived from status changelog history for every open issue, with UNKNOWN when changelog is unavailable. updated is never used as stage-entry time.",
      "assertions": [
        {
          "name": "time_in_stage_from_changelog",
          "description": "Time-in-stage uses jira_get_issue changelog status history, not the updated field"
        },
        {
          "name": "unknown_when_changelog_missing",
          "description": "Missing changelog evidence yields UNKNOWN time-in-stage rather than substituting updated"
        },
        {
          "name": "stalled_blockers_categorized",
          "description": "Stalled/at-risk tickets include blocker category customer-dependent, internal-resource, technical, or unclear"
        },
        {
          "name": "top_risk_context_assemble_bounded",
          "description": "context_assemble enrichment is limited to the top 15 stalled/at-risk tickets with fan-out capped at 8"
        }
      ]
    },
    {
      "id": 3,
      "prompt": "Daily checklist / CSE health -- board review with portfolio totals.",
      "expected_output": "If any named-query pagination loop is incomplete, the run writes a blocked/partial receipt, omits portfolio totals, and disables PREVIEW and EXECUTE for that run.",
      "assertions": [
        {
          "name": "incomplete_pagination_blocks_totals",
          "description": "Incomplete pagination omits portfolio totals and does not invent counts"
        },
        {
          "name": "incomplete_pagination_disables_action_modes",
          "description": "Incomplete pagination disables PREVIEW and EXECUTE for the run"
        },
        {
          "name": "repeated_page_token_is_incomplete",
          "description": "A repeated nextPageToken for one named query is INCOMPLETE rather than looping or completing"
        },
        {
          "name": "is_last_false_without_token_is_incomplete",
          "description": "A response with isLast:false and no usable nextPageToken is INCOMPLETE rather than complete"
        },
        {
          "name": "page_failure_is_incomplete",
          "description": "Any named-query page error produces an INCOMPLETE pagination result"
        },
        {
          "name": "page_ceiling_is_incomplete",
          "description": "Reaching the 100-page per-query safety ceiling produces an INCOMPLETE pagination result"
        },
        {
          "name": "live_roster_ownership_validation",
          "description": "Assignees are validated against the live CSE roster from cse_orgchart_identity_snapshot; Jira remains authoritative for ownership and status"
        }
      ]
    },
    {
      "id": 4,
      "prompt": "Preview the board updates from today's CSE forecast. Show me the dry-runs but do not apply anything.",
      "expected_output": "PREVIEW mode after full REPORT: dry-runs each approved guarded capability, returns PROPOSED ACTIONS with preview digests, and applies nothing.",
      "assertions": [
        {
          "name": "preview_requires_explicit_preview_language",
          "description": "PREVIEW runs only after explicit preview intent language"
        },
        {
          "name": "preview_dry_runs_only",
          "description": "PREVIEW may dry-run guarded capabilities but never applies mutations"
        },
        {
          "name": "preview_zero_external_mutations",
          "description": "PREVIEW may read policy state and dry-run guarded cse-dq mutations, but no Jira/Slack/cse-dq write lands"
        },
        {
          "name": "preview_disabled_when_pagination_incomplete",
          "description": "PREVIEW is refused when named-query pagination was incomplete"
        }
      ]
    },
    {
      "id": 5,
      "prompt": "Apply the forecast actions / update the board from the CSE forecast execute path.",
      "expected_output": "EXECUTE mode: REPORT then dry-run each mutation, apply with preview_digest via two-phase cse_apply, Jira GET-back verify, and receipt. H1/H2/H3 holds retained. Transient retry once.",
      "assertions": [
        {
          "name": "execute_requires_explicit_apply_language",
          "description": "EXECUTE runs only after explicit apply/update/execute language"
        },
        {
          "name": "execute_preview_digest_required",
          "description": "Every mutation previews first; no preview_digest means no write"
        },
        {
          "name": "execute_two_phase_cse_apply",
          "description": "Every mutation uses two-phase cse_apply (preview omit underlying execute, then apply with digest)"
        },
        {
          "name": "execute_jira_get_back_verification",
          "description": "After each apply, jira_get_issue GET-back verifies the mutation before it is listed under ACTIONS EXECUTED"
        },
        {
          "name": "hold_conditions_h1_h2_h3",
          "description": "Stage transitions retain H1/H2/H3 hold checks and list held items with evidence"
        },
        {
          "name": "transient_retry_once",
          "description": "Transient mutation failures retry once; a second failure becomes HELD"
        }
      ]
    },
    {
      "id": 6,
      "prompt": "Forecast and fix the data-quality gaps on open tickets -- missing executive sponsor and technical counterpart.",
      "expected_output": "Data-quality resolution and escalation go only through resolve-or-escalate.md. Forecast never direct-writes jira_property cse-dq. No stale-ticket tracking property writes. Stale-ticket nudges and untracked-work Slack pings remain recommendation-only.",
      "assertions": [
        {
          "name": "dq_via_shared_policy_only",
          "description": "Data-quality writes route exclusively through resolve-or-escalate.md"
        },
        {
          "name": "no_direct_cse_dq_property_writes",
          "description": "Skill guidance does not instruct direct jira_property cse-dq writes outside the shared policy"
        },
        {
          "name": "no_stale_ticket_property_write",
          "description": "Direct stale-ticket cse-dq property writes are removed"
        },
        {
          "name": "stale_and_untracked_recommendation_only",
          "description": "Stale-ticket nudges and untracked-work Slack pings are recommendation-only, not executed"
        }
      ]
    },
    {
      "id": 7,
      "prompt": "Pipeline review / portfolio review -- show stage distribution, velocity, expected next movement, and recommended board updates.",
      "expected_output": "Portfolio by stage and changelog time-in-stage, completion velocity, expected next movement from explicit owner next step or scheduled milestone (no unsupported probability score), recommended board updates, ticket quick-jump index, and DL section.",
      "assertions": [
        {
          "name": "stage_velocity_next_movement_present",
          "description": "Report includes stage distribution, velocity, and expected next movement backed by explicit evidence"
        },
        {
          "name": "no_unsupported_probability_score",
          "description": "Expected movement does not invent unsupported probability scores"
        },
        {
          "name": "recommended_board_updates_section",
          "description": "Recommended board updates are listed even in REPORT mode without being applied"
        },
        {
          "name": "dl_section_present",
          "description": "DL -- [operator] only section exists for sensitive exec/customer context"
        }
      ]
    },
    {
      "id": 8,
      "prompt": "What did we build this week? Show the CSE codebase updates and what shipped for the builder war room.",
      "expected_output": "Forecast rejects builder-showcase routing. Do not scan GitHub or produce a builder agenda. Point the operator to war-room-prep for builder meeting intent.",
      "assertions": [
        {
          "name": "rejects_builder_showcase_routing",
          "description": "Builder-showcase / what-did-we-build prompts do not route into forecast board work"
        },
        {
          "name": "no_github_builder_scan",
          "description": "No gh/GitHub repository enumeration or commit ranking occurs"
        },
        {
          "name": "points_to_war_room_prep",
          "description": "Builder meeting intent is deferred to war-room-prep rather than blended into the forecast"
        }
      ]
    }
  ]
}
