{
  "description": "Shape of session-state.json, persisted per project so Ask/Agent turns and persona hand-offs never re-derive context that was already gathered.",
  "path": "~/.analyzthis_design/sessions/{project-id}/session-state.json",
  "shape": {
    "project_id": "string — derived from cwd or explicit --project flag",
    "created_at": "ISO 8601 timestamp",
    "updated_at": "ISO 8601 timestamp",
    "task_map": [
      {
        "task": "string — primary user task",
        "frequency": "daily | weekly | monthly | one_time",
        "priority": "string"
      }
    ],
    "figma_node": { "url": "string", "confirmed": "boolean" },
    "content_sources": ["string — e.g. ppt, docx, prd, figma"],
    "ds_checklist": {
      "no_invented_hex": "boolean | null",
      "no_important_overrides": "boolean | null",
      "kit_components_preferred": "boolean | null",
      "light_dark_from_tokens_only": "boolean | null",
      "contrast_checked_against_wcag": "boolean | null"
    },
    "information_hierarchy": {
      "declared_by": "noor | undeclared",
      "ranking": ["string — rank #1 first"]
    },
    "routing_decision": {
      "problem_type": "string — from agents/router.json",
      "experts": ["string — persona ids"],
      "reason": "string"
    },
    "persona_outputs": {
      "<persona_id>": "object — structured output block per agents/manifests/<persona_id>.json"
    },
    "full_prompts": {
      "<persona_id>": "object — { system: string, user: string } exact prompts sent to LLM for training"
    },
    "structured_outputs": {
      "<persona_id>": "object — { grades: object, score: number, top_fixes: string[] } parsed from persona output"
    },
    "covered_points": [
      "object — { persona: string, claim: string, category: string, key: string } deduplicated findings across personas"
    ],
    "task_type": "string — canonical task type (contrast_fix, ia_redesign, onboarding_flow, etc.)",
    "verify_results": {
      "primary_task": "pass | fail | not_run",
      "screenshots": ["string — file paths"],
      "reason": "string — why not_run, when applicable (e.g. 'assess_only, no URL')"
    },
    "mode": "assess_only | build_approved",
    "design_spec": {
      "version": "1.0",
      "screen_name": "string",
      "status": "draft | spec_review | ship | revise",
      "intent": "object — primary_user_task, primary_action, north_star_metric",
      "information_hierarchy": ["string — rank #1 first"],
      "layout": "object — grid, regions, nav_level",
      "tokens": "object — colors, typography, spacing, source",
      "components": "array — region, component, import_path, hierarchy_rank",
      "states": "object — empty, loading, error, success",
      "spec_verdict": "object — arjun_visual, ds_gate, hierarchy_gate, notes",
      "updated_at": "ISO 8601"
    },
    "feedback_log": [
      {
        "id": "string — unique feedback entry id",
        "at": "ISO 8601",
        "persona": "string — persona id",
        "satisfied": "boolean — true if user was happy",
        "rating": "number | null — 1 (very unhappy) to 5 (very happy)",
        "comment": "string — what was wrong or what they liked",
        "correction": "string — how the user corrected or what they wanted instead",
        "tags": ["string — e.g. wrong_hierarchy, invented_tokens, off_brief"],
        "original_output": "string — snapshot of persona output at feedback time",
        "submitted_at": "ISO 8601 | omitted — set when feedback submit succeeds",
        "context": "object — task_map_summary, problem_type, mode"
      }
    ],
    "outcome": {
      "inferred": { "<persona_id>": "object — { value: string, confidence: number, reason: string, at: string } auto-inferred from next session" },
      "confirmed": { "<persona_id>": "object — { value: string, at: string } user-confirmed outcome" }
    },
    "vault_path": "string — Obsidian vault written by Kavi collect (empty until first collect)",
    "last_collect_at": "ISO 8601 timestamp — last successful collect run",
    "deliberation": {
      "round": "number — current deliberation round",
      "max_rounds": "number",
      "satisfaction_threshold": "number 0.0–1.0",
      "open_objections": ["object — unresolved blocking objections"],
      "round_log": ["object — per-persona per-round parsed output"],
      "consensus_reached": "boolean",
      "raj_escalated": "boolean",
      "mode": "adversarial | legacy"
    },
    "host_run": {
      "run_id": "string — host LLM run directory id",
      "run_dir": "string — absolute path to pending/responses queue",
      "task": "string — task text for --continue",
      "status": "in_progress | pending_devi | complete",
      "last_pending": { "step_id": "string", "persona": "string" },
      "checkpoint": "object | null — deliberation resume state",
      "started_at": "ISO 8601",
      "completed_at": "ISO 8601 | omitted"
    },
    "chunk_run": {
      "plan": "object — chunk plan from the frontier planner",
      "planner_model": "object — { provider, model } used for planning",
      "planner_warning": "string | null — warning if planner fell back to host model",
      "results": "array — per-chunk execution results",
      "synthesis": "object — final merged verdict",
      "total_cost": "number — estimated USD cost",
      "total_tokens": "object — { input, output }",
      "models_used": "array — model names used across chunks",
      "failed_chunks": "array — chunks that could not complete",
      "budget": "free | cheap | auto",
      "mode": "sequential | parallel"
    },
    "synthesis": {
      "scores": "object — per-persona scores",
      "total": "number",
      "max_total": "number",
      "verdict": "SHIP | REVISE | BLOCK",
      "top3": ["object — ranked actionable changes"],
      "hierarchy_gate": "object — gate status"
    },
    "synthesis_markdown": "string — Phase 5 composite block for display/export",
    "digest": {
      "task_map_summary": "string — short summary passed to persona calls instead of the full task_map/persona_outputs history",
      "hierarchy_top3": ["string — top 3 ranked hierarchy items, if declared"],
      "ds_at_risk": ["string — ds_checklist keys currently at risk"],
      "experts": ["string — persona ids selected for this run"],
      "prior_scores": { "<persona_id>": "number | string — last known score for delta re-evaluation" },
      "design_spec_status": "draft | spec_review | ship | revise — shortcut from design_spec.status",
      "mode": "assess_only | build_approved"
    },
    "metrics": {
      "llm_calls": "number — persona calls made in the last run",
      "experts_run": ["string — persona ids actually executed"],
      "input_tokens_est": "number — estimated input tokens across the last run",
      "output_tokens_est": "number — estimated output tokens across the last run",
      "cache_hits": "number — retrieve/cache hits during the last run",
      "mode": "lite | full",
      "effort_log": [{ "persona": "string", "effort": "trivial|standard|hard", "model": "string|null", "scoped_mode": "string|null" }],
      "cost_usd": "number — estimated $ cost of the run from config.pricing (0 when pricing missing)",
      "deliberation_rounds": "number — adversarial rounds executed in last run",
      "objections_raised": "number",
      "objections_resolved": "number",
      "raj_escalations": "number"
    }
  }
}
