{
  "schemaVersion": 1,
  "studyId": "project-brief-structure-rubric",
  "version": "1.0.0",
  "license": {
    "name": "CC0 1.0 Universal",
    "url": "https://creativecommons.org/publicdomain/zero/1.0/",
    "scope": "The original fictional fixtures, machine-readable rubric specification, and generated result records are dedicated to the public domain. This dedication does not apply to linked or quoted third-party content or to third-party names, logos, and trademarks."
  },
  "scoring": {
    "aggregation": "sum-passed-rules",
    "pointsPerPassedRule": 1,
    "possiblePoints": 8,
    "weights": "equal"
  },
  "terms": {
    "genericActors": [
      "user",
      "someone",
      "person",
      "people"
    ],
    "observableGoalActionPatterns": [
      "\\b(download|export|open|read|save|retain|remove|restore|share|sort|submit|view)\\b"
    ],
    "explicitBoundaryPatterns": [
      "\\b\\d+\\b",
      "\\b(no limit|none known|unknown|not yet known)\\b"
    ],
    "vagueOutcomePatterns": [
      "\\b(quickly|easy|easily|intuitive|seamless|correctly|properly|user.?friendly|works?|successful(?:ly)?)\\b"
    ]
  },
  "rules": [
    {
      "id": "specific-role",
      "label": "Names a role beyond a generic “user”",
      "semantics": {
        "operator": "normalized-not-in-set",
        "field": "actor",
        "normalization": [
          "trim",
          "lowercase"
        ],
        "set": "genericActors",
        "requireNonEmpty": true
      }
    },
    {
      "id": "observable-goal-action",
      "label": "Goal contains a disclosed observable-action token",
      "semantics": {
        "operator": "matches-any-pattern",
        "field": "goal",
        "patterns": "observableGoalActionPatterns",
        "flags": "i"
      }
    },
    {
      "id": "boundary-recorded",
      "label": "Constraints record a number or explicit uncertainty",
      "semantics": {
        "operator": "matches-any-pattern",
        "field": "constraints",
        "patterns": "explicitBoundaryPatterns",
        "flags": "i"
      }
    },
    {
      "id": "positive-case",
      "label": "Includes a positive case",
      "semantics": {
        "operator": "case-kind-present",
        "kind": "positive"
      }
    },
    {
      "id": "negative-case",
      "label": "Includes a negative case",
      "semantics": {
        "operator": "case-kind-present",
        "kind": "negative"
      }
    },
    {
      "id": "edge-case",
      "label": "Includes an edge case",
      "semantics": {
        "operator": "case-kind-present",
        "kind": "edge"
      }
    },
    {
      "id": "complete-steps",
      "label": "Every case has Given, When and Then text",
      "semantics": {
        "operator": "all-cases-fields-nonempty",
        "fields": [
          "given",
          "when",
          "then"
        ],
        "normalization": [
          "trim"
        ],
        "requireAtLeastOneCase": true
      }
    },
    {
      "id": "specific-outcomes",
      "label": "Non-empty outcomes avoid the disclosed vague-word list",
      "semantics": {
        "operator": "nonempty-case-field-matches-no-pattern",
        "field": "then",
        "normalization": [
          "trim"
        ],
        "patterns": "vagueOutcomePatterns",
        "flags": "i"
      }
    }
  ]
}
