{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://cleo-dev.com/schemas/v1/project-info.schema.json",
  "schemaVersion": "1.0.0",
  "title": "CLEO Project Info Schema",
  "description": "Device-local project metadata (.cleo/project-info.json, untracked per ADR-013 §9). The committed identity lives in .cleo/project.json {schemaVersion, id, name} (T12716; legacy mirror .cleo/project-id); here projectId is only a cache of that id, and name is a frozen legacy value. Also carries origin provenance, the per-checkout nonce and schema version tracking.",
  "type": "object",
  "required": ["schemaVersion", "projectHash", "projectId", "schemas"],
  "additionalProperties": false,

  "properties": {
    "$schema": {
      "type": "string",
      "description": "JSON Schema reference for validation."
    },
    "schemaVersion": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "description": "Schema version for this file (semver)."
    },
    "projectId": {
      "type": "string",
      "minLength": 1,
      "description": "Cache of the tracked portable id in .cleo/project.json (T12716; legacy .cleo/project-id). The tracked id always wins; a cache that disagrees is re-keyed only by `cleo doctor project-identity --resolve`. Used alone only by a project with no tracked id yet."
    },
    "checkoutNonce": {
      "type": "string",
      "pattern": "^[0-9a-f]{32}$",
      "description": "Random per-checkout secret (T12470). Lives only in this untracked file; the global registry records it on each confirmed location, so a moved or restored checkout is recognised while a clone (which cannot have it) stays an unconfirmed candidate. Never copy it between checkouts."
    },
    "projectHash": {
      "type": "string",
      "pattern": "^[a-f0-9]{12}$",
      "description": "Write-once 12-character hex identity key. Keys release ids, audit rows and idempotency. A new key is SHA-256('project-id:' + id) prefix, identical on every clone (T12716); keys written before T12716 are the SHA-256 prefix of the real main-checkout path. Never re-computed: not on project move, relocation, restore or `cleo upgrade` (T12557)."
    },
    "previousProjectIds": {
      "type": "array",
      "maxItems": 50,
      "items": { "type": "string", "minLength": 1 },
      "description": "Local ids this project was re-keyed away from by `cleo doctor project-identity --resolve` (T12353). Receipt only; they stay resolvable through the registry alias table."
    },
    "strippedFields": {
      "type": "array",
      "maxItems": 50,
      "description": "Receipt of persisted path facts removed by `cleo doctor project-identity --resolve` (T12557), newest last.",
      "items": {
        "type": "object",
        "required": ["file", "field", "value", "strippedAt"],
        "additionalProperties": false,
        "properties": {
          "file": { "type": "string", "enum": ["project-info.json", "project-context.json"] },
          "field": { "type": "string", "enum": ["projectRoot"] },
          "value": { "description": "The removed value, verbatim." },
          "strippedAt": { "type": "string", "format": "date-time" }
        }
      }
    },
    "displayName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120,
      "description": "Display name of a legacy project (no .cleo/project.json yet), written by `cleo project rename` / `cleo upgrade --name` (T12716). Kept apart from `name` so a rename never moves the path-fingerprint alias key. `cleo doctor project-identity --resolve` carries it into project.json."
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "Legacy name, written once (the directory basename at init). Kept only as the input to the path-fingerprint alias key older builds recorded. The display name lives in .cleo/project.json (T12716); it is read from here (after `displayName`) only for a legacy project not yet migrated by `cleo doctor project-identity --resolve`. Nothing rewrites it after init."
    },
    "description": {
      "type": "string",
      "maxLength": 500,
      "description": "Optional human-readable project description. Surfaces in nexus workspace listings and shared .cleo/ manifests."
    },
    "remoteUrl": {
      "type": "string",
      "format": "uri",
      "description": "Git remote origin URL (e.g. https://github.com/owner/repo.git). Detected at init time from git remote get-url origin. Null when no git remote exists. Provides source-code provenance for shared .cleo/ containers."
    },
    "cleoVersion": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z.-]+)?(\\+[0-9A-Za-z.-]+)?$",
      "description": "CLEO version that last modified this file (semver, including a prerelease such as -canary.1)."
    },
    "createdAt": {
      "type": "string",
      "format": "date-time",
      "description": "ISO 8601 timestamp of initial project creation (cleo init). Set once and preserved across moves and updates."
    },
    "lastUpdated": {
      "type": "string",
      "format": "date-time",
      "description": "ISO 8601 timestamp of last modification to this file."
    },
    "schemas": {
      "type": "object",
      "description": "Schema versions for core CLEO data files in this project. Used for schema-migration-aware init.",
      "required": ["config"],
      "additionalProperties": false,
      "properties": {
        "config": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "Schema version for config.json (semver)."
        },
        "sqlite": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "Schema version for tasks.db SQLite store (semver)."
        },
        "projectContext": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "Schema version for project-context.json (semver)."
        },
        "todo": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "Deprecated: JSON todo.json schema version. Kept for backward compatibility."
        },
        "archive": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "Deprecated: JSON archive schema version. Kept for backward compatibility."
        },
        "log": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "Deprecated: JSON log schema version. Kept for backward compatibility."
        }
      }
    }
  }
}
