{
  "schema_version": "0.1",
  "artifact_type": "implementation_plan",
  "canonical": true,
  "artifact_id": "IMP-012",
  "agent_summary": {
    "title": "fabric.* model-profile binding policy layer",
    "status": "complete",
    "summary": "Implement REQ-120 (ai-collab-v3 REQ-134): a declarative, evidence-bound fabric.model_profiles binding map in the unified config contract with fail-safe raw default, a pure resolver exposed as a read-only UTCP tool, and evidence-gated writes through the existing structured-key path. Policy layer only: profiles and their consumption stay in AI-Collab.",
    "last_reviewed_at": "2026-07-16",
    "load_notes": "Grounded against ai-collab-v3 wiki (controlled-abc-benchmark, idle-retrieval-fabric, predictive-behaviour-routing-fabric) and canonical records EV-477/EV-478/DEC-073/DEC-075 read 2026-07-16."
  },
  "source_ids": [
    "REQ-120"
  ],
  "phases": [
    {
      "id": "IMP-PHASE-038",
      "title": "Config contract: the fabric namespace",
      "tasks": [
        {
          "id": "IMP-TASK-097",
          "summary": "Red tests for the fabric.* contract: fabric.default_when_unmapped enum (raw|abstain, default raw), fabric.binding_requires_evidence bool (default true), and the structured key fabric.model_profiles validating {model: {task_type|'*': {profile, evidence}}}; rejection cases for non-map shapes, missing/empty profile, missing evidence when required, and malformed evidence refs; prd_config audit surfaces each defect.",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-089"
          ]
        },
        {
          "id": "IMP-TASK-098",
          "summary": "Implement the contract: TOGGLES entries for the two scalar keys, structured-key registration and validation for fabric.model_profiles modeled exactly on configuration.custom_profiles, defaults seeded in all four config templates (empty map; raw; true).",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-089"
          ]
        }
      ]
    },
    {
      "id": "IMP-PHASE-039",
      "title": "Resolver, read surface, evidence-gated writes",
      "tasks": [
        {
          "id": "IMP-TASK-099",
          "summary": "Red tests for resolve_fabric_profile(root, model, task_type=None): specific task_type overrides '*'; unmapped model honors fabric.default_when_unmapped ({action: raw} means run with no prediction, never a guessed profile \u2014 the EV-477 lesson); bound lookups return {profile, evidence, source: binding}.",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-090"
          ]
        },
        {
          "id": "IMP-TASK-100",
          "summary": "Implement the pure resolver in prd_config.py plus a set-fabric-binding CLI verb (deterministic single-binding merge, fail-closed on validation, evidence ref mandatory while binding_requires_evidence is true). Writes ride the EXISTING prd_config_set structured-key path \u2014 no new hand-written MCP handler, per the REQ-107 UTCP-first direction.",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-090"
          ]
        },
        {
          "id": "IMP-TASK-101",
          "summary": "Expose the resolver read-only on the UTCP surface: new 'fabric' tool in prd_tools.py (args: model, optional task_type), regenerate the manual, add tool-surface capability fabric.resolve (utcp-only, transport rationale recorded), and add coverage-map feature fabric_model_profile_binding with tool_capabilities [fabric.resolve] so tool parity holds by construction.",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-091"
          ]
        }
      ]
    },
    {
      "id": "IMP-PHASE-040",
      "title": "Delivery, documentation, downstream handoff",
      "tasks": [
        {
          "id": "IMP-TASK-102",
          "summary": "Documentation: /prd-config command doc names the fabric.* namespace; wiki unified-configuration article gains the binding-policy section (why the default is raw, how bindings stay measured); skeleton config parity maintained.",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-092"
          ]
        },
        {
          "id": "IMP-TASK-103",
          "summary": "Ship: full suite + five release gates, cut the release, mark REQ-120 implemented with graduated_to links, and record the downstream handoff (AI-Collab's calibration harness mints bindings via prd_config_set/set-fabric-binding with EV refs; its runtime resolves via the UTCP fabric tool).",
          "status": "complete",
          "validation_ids": [
            "IMP-VAL-092"
          ]
        }
      ]
    }
  ],
  "validations": [
    {
      "id": "IMP-VAL-089",
      "summary": "Contract tests green: both scalar keys validated, structured-map shape enforced, every rejection case surfaced by prd_config audit; config-template parity tests pass across all four copies."
    },
    {
      "id": "IMP-VAL-090",
      "summary": "Resolver e2e in a temp downstream install: set-fabric-binding with an EV ref succeeds and resolves; binding without evidence rejected fail-closed; unmapped model resolves to raw; task-type override beats the model-wide '*' entry."
    },
    {
      "id": "IMP-VAL-091",
      "summary": "Tool-surface parity green: regenerated manual matches checked-in utcp.json, fabric.resolve capability accounted for in the catalog and claimed by the coverage-map feature, feature_skill_audit reports zero tool-parity findings."
    },
    {
      "id": "IMP-VAL-092",
      "summary": "Release gates green at the target version and REQ-120 carries graduated_to links to the tracking goal, changelog, and evidence records."
    }
  ]
}
