Run artifact

workspace/targets/jq/LINEAGE.json

{
  "version": 1,
  "import": {
    "root": "/mnt/c/Users/barlo/projects/drydock/uat/jq/runs/20260822.044627/sources",
    "format": "markdown"
  },
  "sources": {
    "INSTRUCTIONS.md": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "51b43aaf9eec2855347c8e6f57ca4eb52e36b8cc9202d0177cffe429aaa8aeea",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "python-interpreter-architecture",
              "text": "The implementation language is Python, fixed by this Target's `TECHNOLOGY_STACK.md` and governed by `stack/python.md`.",
              "stories": [
                "architecture-foundation"
              ]
            },
            {
              "name": "jq-executable-interface",
              "text": "The interface contract",
              "stories": [
                "EXEC-001"
              ]
            },
            {
              "name": "process-exit-diagnostics",
              "text": "Exit codes follow jq's own, and the distinction is load-bearing because the harness grades on it:",
              "stories": [
                "EXEC-002"
              ]
            },
            {
              "name": "json-stream-io",
              "text": "It writes each value the program produces to **stdout** as one compact JSON value per line, and exits `0`.",
              "stories": [
                "EXEC-003"
              ]
            },
            {
              "name": "lexical-scanning",
              "text": "Follow `sources/lexer.l` and `sources/parser.y` directly. Produce an AST.",
              "stories": [
                "PARSE-001"
              ]
            },
            {
              "name": "literals-strings-interpolation",
              "text": "Precedence, `?` suffixes, string interpolation, and the `def` forms are all settled there.",
              "stories": [
                "PARSE-002"
              ]
            },
            {
              "name": "filter-grammar",
              "text": "jq is a small language with a large semantic core.",
              "stories": [
                "PARSE-003"
              ]
            },
            {
              "name": "advanced-grammar-rejection",
              "text": "The module *grammar* cases are **not** excluded and must pass.",
              "stories": [
                "PARSE-004"
              ]
            },
            {
              "name": "generator-evaluation",
              "text": "Almost every filter is a **generator**:\nit takes one input and produces a stream of zero, one, or many outputs, and downstream\nfilters run once per upstream output.",
              "stories": [
                "CORE-001",
                "CORE-002"
              ]
            },
            {
              "name": "runtime-errors-and-optional",
              "text": "A case may legitimately emit several values and then raise; the harness compares the values\nproduced before the raise, so exit `5` is not by itself a failure.",
              "stories": [
                "CORE-003"
              ]
            },
            {
              "name": "truthiness-comparison",
              "text": "`reduce`, `foreach`, `limit`, `first`,\n`label`/`break`, and the `?//` destructuring alternative are all defined in terms of it.",
              "stories": [
                "CORE-004"
              ]
            },
            {
              "name": "value-model-numbers",
              "text": "Numbers and edge cases. `nan`, `infinite`, integer/float equality, large literals,\nand the `have_decnum` builtin \u2014 return `false` from it and the corpus takes its\nnon-decNumber branch, which native floats satisfy.",
              "stories": [
                "VALUE-001"
              ]
            },
            {
              "name": "value-accessors",
              "text": "field access, iteration, arithmetic, comparison, and\n`empty`.",
              "stories": [
                "VALUE-002"
              ]
            },
            {
              "name": "slices-and-iteration",
              "text": "Get the core correctly before reaching for coverage.",
              "stories": [
                "VALUE-003"
              ]
            },
            {
              "name": "type-and-numeric-primitives",
              "text": "Builtins. Work outward from `sources/builtin.jq` and the manual: strings, arrays, objects,",
              "stories": [
                "VALUE-004"
              ]
            },
            {
              "name": "conformance-assets",
              "text": "These four files are the exam. They are hash-verified against the import and restored\nbefore grading, so a modification is reported as tampering rather than honoured:",
              "stories": [
                "CONF-001"
              ]
            },
            {
              "name": "arithmetic-structural-operators",
              "text": "Every later feature is expressed in terms of this.",
              "stories": [
                "FLOW-001"
              ]
            },
            {
              "name": "boolean-alternative-operators",
              "text": "`//`,\n`reduce`, `foreach`, `label`/`break`, `limit`, `first`, `last`, `until`, `while`,\n`recurse`.",
              "stories": [
                "FLOW-002"
              ]
            },
            {
              "name": "conditionals-exception-flow",
              "text": "Control flow. `if`/`then`/`elif`/`else`/`end`, `try`/`catch` and `?`, `//`,",
              "stories": [
                "FLOW-003"
              ]
            },
            {
              "name": "labels-breaks",
              "text": "`label`/`break`",
              "stories": [
                "FLOW-004"
              ]
            },
            {
              "name": "reductions-iteration-control",
              "text": "`reduce`, `foreach`, `limit`, `first`, `last`, `until`, `while`,",
              "stories": [
                "FLOW-005"
              ]
            },
            {
              "name": "recursive-generators",
              "text": "`recurse`.",
              "stories": [
                "FLOW-006"
              ]
            },
            {
              "name": "variable-bindings",
              "text": "Functions, variables, and destructuring.",
              "stories": [
                "FUNC-001"
              ]
            },
            {
              "name": "function-parameters",
              "text": "`def` with arity and closures,",
              "stories": [
                "FUNC-002"
              ]
            },
            {
              "name": "function-definitions",
              "text": "`def` with arity and closures, `as`\nbindings,",
              "stories": [
                "FUNC-003"
              ]
            },
            {
              "name": "destructuring-alternatives",
              "text": "object and array patterns, and the `?//` alternative operator.",
              "stories": [
                "FUNC-004"
              ]
            },
            {
              "name": "path-discovery",
              "text": "Paths and assignment. `path(f)`, getpath, setpath, delpaths, del,",
              "stories": [
                "PATH-001"
              ]
            },
            {
              "name": "path-primitives",
              "text": "`path(f)`, `getpath`, `setpath`, `delpaths`, `del`,",
              "stories": [
                "PATH-002"
              ]
            },
            {
              "name": "assignment-operators",
              "text": "and then `=`, `|=`, `+=`, and friends.",
              "stories": [
                "PATH-003"
              ]
            },
            {
              "name": "complex-assignments",
              "text": "Assignment is defined over path expressions, so this\ncannot precede step 2.",
              "stories": [
                "PATH-004"
              ]
            },
            {
              "name": "collection-transformations",
              "text": "Builtins. Work outward from `sources/builtin.jq` and the manual: strings, arrays, objects,",
              "stories": [
                "DATA-001"
              ]
            },
            {
              "name": "sorting-grouping-extrema",
              "text": "`sort_by`/`group_by`/`unique_by`,",
              "stories": [
                "DATA-002"
              ]
            },
            {
              "name": "object-entries-containment",
              "text": "objects,",
              "stories": [
                "DATA-003"
              ]
            },
            {
              "name": "index-membership-search",
              "text": "`in`,",
              "stories": [
                "DATA-004"
              ]
            },
            {
              "name": "string-manipulation",
              "text": "strings,",
              "stories": [
                "TEXT-001"
              ]
            },
            {
              "name": "formats-serialization",
              "text": "`@base64`/`@uri`/`@csv`/`@tsv`/`@sh`\nformats,",
              "stories": [
                "TEXT-002"
              ]
            },
            {
              "name": "regular-expressions",
              "text": "the date functions, `tostream`, `input`/`inputs`, `$__loc__`, `debug`.",
              "stories": [
                "TEXT-003"
              ]
            },
            {
              "name": "date-time-filters",
              "text": "the date functions,",
              "stories": [
                "TEXT-004"
              ]
            },
            {
              "name": "input-controls",
              "text": "`input`/`inputs`,",
              "stories": [
                "IO-001"
              ]
            },
            {
              "name": "diagnostics-stderr",
              "text": "`$__loc__`, `debug`.",
              "stories": [
                "IO-002"
              ]
            },
            {
              "name": "streaming-transformations",
              "text": "`tostream`,",
              "stories": [
                "IO-003"
              ]
            },
            {
              "name": "scoped-conformance",
              "text": "Every other story runs its own slice, and the slice executes cases.",
              "stories": [
                "CONF-002"
              ]
            },
            {
              "name": "full-conformance",
              "text": "Definition of Done",
              "stories": [
                "CONF-003"
              ]
            }
          ]
        }
      ]
    },
    "builtin.jq": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "b8a5fd9579be9b51c9a04e6620f8c1655539aa57eea33a84e202a8dea401f2a4",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "error-and-selection",
              "text": "def halt_error: halt_error(5);\ndef error(msg): msg|error;\ndef select(f): if f then . else empty end;",
              "stories": [
                "CORE-003",
                "FLOW-003"
              ]
            },
            {
              "name": "collection-mapping",
              "text": "def map(f): [.[] | f];\ndef map_values(f): .[] |= f;",
              "stories": [
                "DATA-001"
              ]
            },
            {
              "name": "sorting-and-grouping",
              "text": "def sort_by(f): _sort_by_impl(map([f]));\ndef group_by(f): _group_by_impl(map([f]));\ndef unique_by(f): _unique_by_impl(map([f]));\ndef max_by(f): _max_by_impl(map([f]));\ndef min_by(f): _min_by_impl(map([f]));",
              "stories": [
                "DATA-002"
              ]
            },
            {
              "name": "object-entries-and-containment",
              "text": "def to_entries: [keys_unsorted[] as $k | {key: $k, value: .[$k]}];\ndef from_entries: map({ (.key // .Key // .name // .Name):\n  if has(\"value\") then .value else .Value end }) | add // {};\ndef with_entries(f): to_entries | map(f) | from_entries;",
              "stories": [
                "DATA-003"
              ]
            },
            {
              "name": "index-and-membership",
              "text": "def indices($i): if type == \"array\" and ($i|type) == \"array\" then .[$i]\n  elif type == \"array\" then .[[$i]]\n  elif type == \"string\" and ($i|type) == \"string\" then _strindices($i)\n  else .[$i] end;\ndef index($i):   indices($i) | .[0];       # TODO: optimize\ndef rindex($i):  indices($i) | .[-1:][0];  # TODO: optimize\ndef in(xs): . as $x | xs | has($x);\ndef inside(xs): . as $x | xs | contains($x);",
              "stories": [
                "DATA-004"
              ]
            },
            {
              "name": "string-manipulation",
              "text": "def join($x): reduce .[] as $i (null;\n            (if .==null then \"\" else .+$x end) +\n            ($i | if type==\"boolean\" or type==\"number\" then tostring else .//\"\" end)\n        ) // \"\";\ndef ltrimstr($left): if startswith($left) then .[$left | length:] end;\ndef rtrimstr($right): if endswith($right) then .[:length - ($right | length)] end;\ndef trimstr($val): ltrimstr($val) | rtrimstr($val);",
              "stories": [
                "TEXT-001"
              ]
            },
            {
              "name": "regular-expression-filters",
              "text": "def match(re; mode): _match_impl(re; mode; false)|.[];\ndef test(re; mode): _match_impl(re; mode; true);\ndef capture(re; mods): match(re; mods) | reduce ( .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair ({}; . + $pair);\ndef scan($re; $flags):\n  match($re; \"g\" + $flags)\n    | if (.captures|length > 0)\n      then [ .captures | .[] | .string ]\n      else .string\n      end;",
              "stories": [
                "TEXT-003"
              ]
            },
            {
              "name": "date-and-time-filters",
              "text": "def fromdateiso8601: strptime(\"%Y-%m-%dT%H:%M:%SZ\")|mktime;\ndef todateiso8601: strftime(\"%Y-%m-%dT%H:%M:%SZ\");\ndef fromdate: fromdateiso8601;\ndef todate: todateiso8601;",
              "stories": [
                "TEXT-004"
              ]
            },
            {
              "name": "input-stream-controls",
              "text": "def inputs: try repeat(input) catch if .==\"break\" then empty else error end;",
              "stories": [
                "IO-001"
              ]
            },
            {
              "name": "diagnostics",
              "text": "def debug(msgs): (msgs | debug | empty), .;",
              "stories": [
                "IO-002"
              ]
            },
            {
              "name": "stream-valued-evaluation",
              "text": "def while(cond; update):\n     def _while:\n         if cond then ., (update | _while) else empty end;\n     _while;\ndef until(cond; next):\n     def _until:\n         if cond then . else (next|_until) end;\n     _until;\ndef limit($n; expr):\n  if $n > 0 then label $out | foreach expr as $item ($n; . - 1; $item, if . <= 0 then break $out else empty end)\n  elif $n == 0 then empty\n  else error(\"limit doesn't support negative count\") end;\ndef skip($n; expr):\n  if $n > 0 then foreach expr as $item ($n; . - 1; if . < 0 then $item else empty end)\n  elif $n == 0 then expr\n  else error(\"skip doesn't support negative count\") end;",
              "stories": [
                "CORE-001",
                "FLOW-005"
              ]
            },
            {
              "name": "composition-and-combinations",
              "text": "def combinations:\n    if length == 0 then [] else\n        .[0][] as $x\n          | (.[1:] | combinations) as $y\n          | [$x] + $y\n    end;\ndef combinations(n):\n    . as $dot\n      | [range(n) | $dot]\n      | combinations;",
              "stories": [
                "CORE-002"
              ]
            },
            {
              "name": "truthiness-and-membership",
              "text": "def IN(s): any(s == .; .);\ndef IN(src; s): any(src == s; .);",
              "stories": [
                "CORE-004",
                "FLOW-002"
              ]
            },
            {
              "name": "value-types-and-numeric-primitives",
              "text": "def abs: if . < 0 then - . else . end;\ndef isfinite: type == \"number\" and (isinfinite | not);\ndef arrays: select(type == \"array\");\ndef objects: select(type == \"object\");\ndef iterables: select(type|. == \"array\" or . == \"object\");\ndef booleans: select(type == \"boolean\");\ndef numbers: select(type == \"number\");\ndef normals: select(isnormal);\ndef finites: select(isfinite);\ndef strings: select(type == \"string\");\ndef nulls: select(. == null);\ndef values: select(. != null);\ndef scalars: select(type|. != \"array\" and . != \"object\");",
              "stories": [
                "VALUE-001",
                "VALUE-004",
                "FLOW-001"
              ]
            },
            {
              "name": "accessors-and-slices",
              "text": "def first: .[0];\ndef last: .[-1];\ndef nth($n): .[$n];\ndef reverse: [.[length - 1 - range(0;length)]];\ndef flatten($x): if $x < 0 then error(\"flatten depth must not be negative\") else _flatten($x) end;\ndef flatten: _flatten(-1);",
              "stories": [
                "VALUE-002",
                "VALUE-003"
              ]
            },
            {
              "name": "recursive-generators",
              "text": "def recurse(f): def r: ., (f | r); r;\ndef recurse(f; cond): def r: ., (f | select(cond) | r); r;\ndef recurse: recurse(.[]?);\ndef repeat(exp):\n     def _repeat:\n         exp, _repeat;\n     _repeat;",
              "stories": [
                "FLOW-006"
              ]
            },
            {
              "name": "labels-and-breaks",
              "text": "def _modify(paths; update):\n    reduce path(paths) as $p ([., []];\n        . as $dot\n      | null\n      | label $out\n      | ($dot[0] | getpath($p)) as $v\n      | (\n          (   $$$$v\n            | update\n            | (., break $out) as $v",
              "stories": [
                "FLOW-004"
              ]
            },
            {
              "name": "variable-bindings-and-parameters",
              "text": "def add(f): reduce f as $x (null; . + $x);\ndef add: add(.[]);\ndef all(generator; condition): isempty(generator|condition and empty);\ndef any(generator; condition): isempty(generator|condition or empty)|not;",
              "stories": [
                "FUNC-001",
                "FUNC-002"
              ]
            },
            {
              "name": "function-definitions-and-recursion",
              "text": "def _flatten($x): reduce .[] as $i ([]; if $i | type == \"array\" and $x != 0 then . + ($i | _flatten($x-1)) else . + [$i] end);",
              "stories": [
                "FUNC-003"
              ]
            },
            {
              "name": "path-discovery-and-projection",
              "text": "def paths: path(recurse)|select(length > 0);\ndef paths(node_filter): path(recurse|select(node_filter))|select(length > 0);\ndef pick(pathexps):\n  . as $in\n  | reduce path(pathexps) as $a (null;\n      setpath($a; $in|getpath($a)) );",
              "stories": [
                "PATH-001"
              ]
            },
            {
              "name": "path-access-and-mutation",
              "text": "def _assign(paths; $value): reduce path(paths) as $p (.; setpath($p; $value));\ndef _modify(paths; update):\n    reduce path(paths) as $p ([., []];\n        . as $dot\n      | ($dot[0] | getpath($p)) as $v\n      | $$$$dot\n      | setpath([0] + $p; $v)",
              "stories": [
                "PATH-002",
                "PATH-004"
              ]
            },
            {
              "name": "deletion-and-assignment",
              "text": "def del(f): delpaths([path(f)]);",
              "stories": [
                "PATH-003"
              ]
            },
            {
              "name": "conformance-verification",
              "text": "# ensure the output of debug(m1,m2) is kept together:\ndef debug(msgs): (msgs | debug | empty), .;",
              "stories": [
                "CONF-002",
                "CONF-003"
              ]
            }
          ]
        }
      ]
    },
    "exclusions.txt": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "0755022f0c2f339883aaa2668a10d6a11bc8f7c4a37b0743f213830d848a05d9",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "document-excluded-cases",
              "text": "The corpus in sources/jq.test is byte-for-byte upstream and is never edited. Where a case cannot run under this kit's harness, it is named here instead, so every skip is visible, reasoned, and auditable against the upstream file. This file is a scoring asset: it is hash-verified against the import and restored before grading.",
              "stories": [
                "CONF-001"
              ]
            },
            {
              "name": "validate-exclusion-entries",
              "text": "One verbatim program line per entry. An entry that matches no case in the corpus is a hard error (exit 2), not a shrug \u2014 a silent no-op would quietly re-admit a case the kit cannot run if the corpus pin ever moved.",
              "stories": [
                "CONF-001",
                "EXEC-002"
              ]
            },
            {
              "name": "exclude-module-loader-cases",
              "text": "Only the loader cases are excluded. The module *grammar* cases \u2014 `module (.+1); 0`, `module []; 0`, `include \"a\" (.+1); 0`, `include \"a\" []; 0`, `include \"\\ \"; 0`, `include \"\\(a)\"; 0`, and `%::wat` \u2014 remain in the scored set: they are parse errors that a correct front end rejects without ever touching the filesystem.",
              "stories": [
                "CONF-001"
              ]
            }
          ]
        }
      ]
    },
    "full_test.sh": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "4df25cda12c2741ee02cb7e22d5e3b62161bd90fde948c88a675cb2a94e70fc5",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "executable-json-interface",
              "text": "The deliverable is an executable named jq that reads JSON on stdin.",
              "stories": [
                "EXEC-001",
                "EXEC-003"
              ]
            },
            {
              "name": "distinguish-interface-and-conformance-failures",
              "text": "The interface check is separate from the conformance run so that a missing or non-executable program and a genuine conformance failure are distinguishable in the evidence.",
              "stories": [
                "EXEC-002"
              ]
            },
            {
              "name": "score-full-conformance-run",
              "text": "`drydock uat` runs `sh sources/full_test.sh` from the completed application root and takes its exit code and output as the score.",
              "stories": [
                "CONF-003"
              ]
            }
          ]
        }
      ]
    },
    "jq-manual.txt": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "92fc1c179ee6e33d75ffc1f24dd1f0b8ddf5ea666a51224be5088d9431cd8ab3",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "filter-model",
              "text": "A jq program is a \"filter\": it takes an input, and produces an output.",
              "stories": [
                "CORE-001"
              ]
            },
            {
              "name": "filter-composition",
              "text": "Filters can be combined in various ways - you can pipe the output of\none filter into another filter, or collect the output of a filter\ninto an array.",
              "stories": [
                "CORE-002"
              ]
            },
            {
              "name": "stream-values",
              "text": "Some filters produce multiple results, for instance there's one that\nproduces all the elements of its input array.",
              "stories": [
                "CORE-001"
              ]
            },
            {
              "name": "numeric-semantics",
              "text": "Numbers in jq are internally represented by their IEEE754 double\nprecision approximation.",
              "stories": [
                "VALUE-001"
              ]
            },
            {
              "name": "object-access",
              "text": "The simplest *useful* filter has the form `.foo`. When given a\nJSON object (aka dictionary or hash) as input, `.foo` produces\nthe value at the key \"foo\" if the key is present, or null otherwise.",
              "stories": [
                "VALUE-002"
              ]
            },
            {
              "name": "array-access-and-iteration",
              "text": "When the index value is an integer, `.[<number>]` can index\narrays. Arrays are zero-based, so `.[2]` returns the third\nelement.",
              "stories": [
                "VALUE-003"
              ]
            },
            {
              "name": "slices",
              "text": "The `.[<number>:<number>]` syntax can be used to return a\nsubarray of an array or substring of a string.",
              "stories": [
                "VALUE-003"
              ]
            },
            {
              "name": "lexical-scanning",
              "text": "A `#` character (not part of a string) starts a comment.",
              "stories": [
                "PARSE-001"
              ]
            },
            {
              "name": "literals-and-interpolation",
              "text": "Inside a string, you can put an expression inside parens\nafter a backslash. Whatever the expression returns will be\ninterpolated into the string.",
              "stories": [
                "PARSE-002"
              ]
            },
            {
              "name": "core-filter-grammar",
              "text": "The | operator combines two filters by feeding the output(s) of\nthe one on the left into the input of the one on the right.",
              "stories": [
                "PARSE-003"
              ]
            },
            {
              "name": "advanced-filter-grammar",
              "text": "You can give a filter a name using \"def\" syntax:",
              "stories": [
                "PARSE-004"
              ]
            },
            {
              "name": "runtime-errors-and-optional-evaluation",
              "text": "Errors can be caught by using `try EXP catch EXP`.",
              "stories": [
                "CORE-003"
              ]
            },
            {
              "name": "truthiness-and-comparison",
              "text": "The expression 'a == b' will produce 'true' if the results of evaluating\na and b are equal (that is, if they represent equivalent JSON values) and\n'false' otherwise.",
              "stories": [
                "CORE-004"
              ]
            },
            {
              "name": "arithmetic-and-structural-operators",
              "text": "The operator `+` takes two filters, applies them both\nto the same input, and adds the results together.",
              "stories": [
                "FLOW-001"
              ]
            },
            {
              "name": "boolean-and-default-operators",
              "text": "jq supports the normal Boolean operators `and`, `or`, `not`.",
              "stories": [
                "FLOW-002"
              ]
            },
            {
              "name": "conditionals-and-exception-flow",
              "text": "`if A then B else C end` will act the same as `B` if `A`\nproduces a value other than false or null, but act the same as\n`C` otherwise.",
              "stories": [
                "FLOW-003"
              ]
            },
            {
              "name": "labels-and-breaks",
              "text": "jq has a syntax for named lexical labels to\nbreak or go (back) to:",
              "stories": [
                "FLOW-004"
              ]
            },
            {
              "name": "reductions-and-iteration-control",
              "text": "The `reduce` syntax allows you to combine all of the results of\nan expression by accumulating them into a single answer.",
              "stories": [
                "FLOW-005"
              ]
            },
            {
              "name": "recursive-generators",
              "text": "The `recurse(f)` function allows you to search through a\nrecursive structure, and extract interesting data from all\nlevels.",
              "stories": [
                "FLOW-006"
              ]
            },
            {
              "name": "variable-bindings",
              "text": "jq lets you define variables using\n`expression as $variable`.",
              "stories": [
                "FUNC-001"
              ]
            },
            {
              "name": "function-parameters",
              "text": "Arguments are passed as _filters_ (functions with no\narguments), _not_ as values.",
              "stories": [
                "FUNC-002"
              ]
            },
            {
              "name": "function-definitions-and-scope",
              "text": "It is also possible to define functions in jq, although this\nis a feature whose biggest use is defining jq's standard library",
              "stories": [
                "FUNC-003"
              ]
            },
            {
              "name": "destructuring-alternatives",
              "text": "The destructuring alternative operator provides a concise mechanism\nfor destructuring an input that can take one of several forms.",
              "stories": [
                "FUNC-004"
              ]
            },
            {
              "name": "path-discovery-and-projection",
              "text": "`paths` outputs the paths to all the elements in its input",
              "stories": [
                "PATH-001"
              ]
            },
            {
              "name": "path-access-and-mutation",
              "text": "The builtin function `getpath` outputs the values in `.` found\nat each path in `PATHS`.",
              "stories": [
                "PATH-002"
              ]
            },
            {
              "name": "assignment-operators",
              "text": "Most users will want to use modification assignment operators,\nsuch as `|=` or `+=`, rather than `=`.",
              "stories": [
                "PATH-003"
              ]
            },
            {
              "name": "complex-assignments",
              "text": "Any filter may be used on the\nleft-hand side of an equals - whichever paths it selects from the\ninput will be where the assignment is performed.",
              "stories": [
                "PATH-004"
              ]
            },
            {
              "name": "collection-transformations",
              "text": "For any filter `f`, `map(f)` and `map_values(f)` apply `f`\nto each of the values in the input array or object, that is,\nto the values of `.[]`.",
              "stories": [
                "DATA-001"
              ]
            },
            {
              "name": "sorting-grouping-and-extrema",
              "text": "The `sort` functions sorts its input, which must be an\narray.",
              "stories": [
                "DATA-002"
              ]
            },
            {
              "name": "object-entries-and-containment",
              "text": "These functions convert between an object and an array of\nkey-value pairs.",
              "stories": [
                "DATA-003"
              ]
            },
            {
              "name": "index-membership-and-sql-utilities",
              "text": "The builtin function `has` returns whether the input object\nhas the given key, or the input array has an element\nat the given index.",
              "stories": [
                "DATA-004"
              ]
            },
            {
              "name": "string-manipulation",
              "text": "The `split` function splits an input string on the separator argument.",
              "stories": [
                "TEXT-001"
              ]
            },
            {
              "name": "json-conversion-and-output-formats",
              "text": "The `tojson` and `fromjson` builtins dump values as JSON texts\nor parse JSON texts into values, respectively.",
              "stories": [
                "TEXT-002"
              ]
            },
            {
              "name": "regular-expression-filters",
              "text": "jq uses the\n[Oniguruma regular expression library](https://github.com/kkos/oniguruma/blob/master/doc/RE),",
              "stories": [
                "TEXT-003"
              ]
            },
            {
              "name": "date-and-time-filters",
              "text": "jq provides some basic date handling functionality, with some\nhigh-level and low-level builtins.",
              "stories": [
                "TEXT-004"
              ]
            },
            {
              "name": "input-stream-controls",
              "text": "Two builtins functions\nare provided for this, `input` and `inputs`, that read from\nthe same sources",
              "stories": [
                "IO-001"
              ]
            },
            {
              "name": "diagnostics-and-stderr",
              "text": "The `debug` builtin can have as a side-effect the production of one or more messages on stderr.",
              "stories": [
                "IO-002"
              ]
            },
            {
              "name": "streaming-transformations",
              "text": "With the `--stream` option jq can parse input texts in a streaming\nfashion, allowing jq programs to start processing large JSON texts\nimmediately rather than after the parse completes.",
              "stories": [
                "IO-003"
              ]
            },
            {
              "name": "process-exit-and-errors",
              "text": "The given `exit_code` (defaulting to `5`) will be jq's\nexit status.",
              "stories": [
                "EXEC-002"
              ]
            },
            {
              "name": "json-input-and-output",
              "text": "jq's output values are always\noutput as JSON texts on `stdout`.",
              "stories": [
                "EXEC-003"
              ]
            },
            {
              "name": "value-types-and-primitives",
              "text": "jq supports the same set of datatypes as JSON - numbers,\nstrings, booleans, arrays, objects (which in JSON-speak are\nhashes with only string keys), and \"null\".",
              "stories": [
                "VALUE-004"
              ]
            }
          ]
        }
      ]
    },
    "jq.test": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "329689763b651096989bd8260b643731083fc5fd17f6bd7834d158713f738cbd",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "test-input-output-contract",
              "text": "# Tests are groups of three lines: program, input, expected output\n# Blank lines and lines starting with # are ignored",
              "stories": [
                "EXEC-003"
              ]
            },
            {
              "name": "lexical-scanning",
              "text": "# The input line starts with a 0xFEFF (byte order mark) codepoint",
              "stories": [
                "PARSE-001"
              ]
            },
            {
              "name": "literals-strings-interpolation",
              "text": "# We test escapes by matching them against Unicode codepoints",
              "stories": [
                "PARSE-002"
              ]
            },
            {
              "name": "core-filter-grammar",
              "text": "# Field access, piping",
              "stories": [
                "PARSE-003"
              ]
            },
            {
              "name": "advanced-filter-grammar",
              "text": "# module system",
              "stories": [
                "PARSE-004"
              ]
            },
            {
              "name": "stream-evaluation",
              "text": "# Multiple outputs, iteration",
              "stories": [
                "CORE-001"
              ]
            },
            {
              "name": "composition-cartesian-evaluation",
              "text": "# Check that various builtins evaluate all arguments where appropriate,\n# doing cartesian products where appropriate.",
              "stories": [
                "CORE-002"
              ]
            },
            {
              "name": "errors-and-optional-evaluation",
              "text": "# Try/catch and general `?` operator",
              "stories": [
                "CORE-003"
              ]
            },
            {
              "name": "truthiness-comparison",
              "text": "# And some in/equality tests",
              "stories": [
                "CORE-004"
              ]
            },
            {
              "name": "value-model-numeric-edge-cases",
              "text": "# Basic numbers tests: integers, powers of two",
              "stories": [
                "VALUE-001"
              ]
            },
            {
              "name": "field-index-access",
              "text": "# Negative array indices",
              "stories": [
                "VALUE-002"
              ]
            },
            {
              "name": "slices-and-iteration",
              "text": "# Slices",
              "stories": [
                "VALUE-003"
              ]
            },
            {
              "name": "type-length-math-primitives",
              "text": "# abs, fabs, length",
              "stories": [
                "VALUE-004"
              ]
            },
            {
              "name": "arithmetic-structural-operators",
              "text": "# Builtin functions",
              "stories": [
                "FLOW-001"
              ]
            },
            {
              "name": "boolean-alternative-operators",
              "text": "# containment operator",
              "stories": [
                "FLOW-002"
              ]
            },
            {
              "name": "conditionals-exception-flow",
              "text": "# Conditionals",
              "stories": [
                "FLOW-003"
              ]
            },
            {
              "name": "labels-and-breaks",
              "text": "[label $out | foreach .[] as $item ([3, null]; if .[0] < 1 then break $out else [.[0] -1, $item] end; .[1])]",
              "stories": [
                "FLOW-004"
              ]
            },
            {
              "name": "reductions-iteration-control",
              "text": "[foreach .[] as $x (0; . + $x) as $x | $x]",
              "stories": [
                "FLOW-005"
              ]
            },
            {
              "name": "recursive-generators",
              "text": "# test recursion",
              "stories": [
                "FLOW-006"
              ]
            },
            {
              "name": "variable-bindings",
              "text": "# Variables",
              "stories": [
                "FUNC-001"
              ]
            },
            {
              "name": "function-parameters",
              "text": "def f(a;b;c;d;e;f): [a+1,b,c,d,e,f]; f(.[0];.[1];.[0];.[0];.[0];.[0])",
              "stories": [
                "FUNC-002"
              ]
            },
            {
              "name": "function-definitions-scope",
              "text": "# test multiple function arities and redefinition",
              "stories": [
                "FUNC-003"
              ]
            },
            {
              "name": "destructuring-alternatives",
              "text": "# Destructuring with alternation",
              "stories": [
                "FUNC-004"
              ]
            },
            {
              "name": "path-discovery-projection",
              "text": "# Paths",
              "stories": [
                "PATH-001"
              ]
            },
            {
              "name": "path-access-mutation",
              "text": "[\"foo\",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])",
              "stories": [
                "PATH-002"
              ]
            },
            {
              "name": "deletion-assignment",
              "text": "#\n# Assignment\n#\n.message = \"goodbye\"",
              "stories": [
                "PATH-003"
              ]
            },
            {
              "name": "complex-assignment-edge-cases",
              "text": "# #1358, getpath/1 should work in path expressions",
              "stories": [
                "PATH-004"
              ]
            },
            {
              "name": "collection-transformations",
              "text": "# Collection transformations",
              "stories": [
                "DATA-001"
              ]
            },
            {
              "name": "sorting-grouping-extrema",
              "text": "sort\n[42,[2,5,3,11],10,{\"a\":42,\"b\":2},{\"a\":42},true,2,[2,6],\"hello\",null,[2,5,6],{\"a\":[],\"b\":1},\"abc\",\"ab\",[3,10],{},false,\"abcd\",null]",
              "stories": [
                "DATA-002"
              ]
            },
            {
              "name": "object-entries-containment",
              "text": "to_entries\n{\"a\": 1, \"b\": 2}\n[{\"key\":\"a\", \"value\":1}, {\"key\":\"b\", \"value\":2}]",
              "stories": [
                "DATA-003"
              ]
            },
            {
              "name": "index-membership-search",
              "text": "# check that dead code removal occurs after builtin it generation",
              "stories": [
                "DATA-004"
              ]
            },
            {
              "name": "string-manipulation",
              "text": "# string operations",
              "stories": [
                "TEXT-001"
              ]
            },
            {
              "name": "formats-serialization",
              "text": "[.[]|tojson|fromjson]\n[\"foo\", 1, [\"a\", 1, \"b\", 2, {\"foo\":\"bar\"}]]\n[\"foo\",1,[\"a\",1,\"b\",2,{\"foo\":\"bar\"}]]",
              "stories": [
                "TEXT-002"
              ]
            },
            {
              "name": "regular-expression-filters",
              "text": "# string operations",
              "stories": [
                "TEXT-003"
              ]
            },
            {
              "name": "date-time-filters",
              "text": "# module system",
              "stories": [
                "TEXT-004"
              ]
            },
            {
              "name": "input-stream-controls",
              "text": "# calling input/0, or debug/0 in a test doesn't crash jq",
              "stories": [
                "IO-001"
              ]
            },
            {
              "name": "diagnostics-stderr-filters",
              "text": "debug\n1\n1",
              "stories": [
                "IO-002"
              ]
            },
            {
              "name": "streaming-transformations",
              "text": "# Multiple outputs, iteration",
              "stories": [
                "IO-003"
              ]
            },
            {
              "name": "full-conformance-verification",
              "text": "# Tests are groups of three lines: program, input, expected output",
              "stories": [
                "CONF-001",
                "CONF-002",
                "CONF-003"
              ]
            }
          ]
        }
      ]
    },
    "lexer.l": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "cfb3af17a786df30d7e30dae5861b84747d4904f8ce7ae9ab9b48bde342ee7f3",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "handle-comments",
              "text": "\"#\" { yy_push_state(IN_COMMENT, yyscanner); }\n<IN_COMMENT>{\n  \\\\(\\\\|\\r?\\n)|. { }\n  \\r?\\n { yy_pop_state(yyscanner); }\n}\n<IN_COMMENT><<EOF>> { yy_pop_state(yyscanner); }",
              "stories": [
                "PARSE-001"
              ]
            },
            {
              "name": "recognize-keywords",
              "text": "\"as\" { return AS; }\n\"import\" { return IMPORT; }\n\"include\" { return INCLUDE; }\n\"module\" { return MODULE; }\n\"def\" { return DEF; }\n\"if\" { return IF; }\n\"then\" { return THEN; }\n\"else\" { return ELSE; }\n\"elif\" { return ELSE_IF; }\n\"and\" { return AND; }\n\"or\" { return OR; }\n\"end\" { return END; }\n\"reduce\" { return REDUCE; }\n\"foreach\" { return FOREACH; }\n\"try\" { return TRY; }\n\"catch\" { return CATCH; }\n\"label\" { return LABEL; }\n\"break\" { return BREAK; }\n\"$__loc__\" { return LOC; }",
              "stories": [
                "PARSE-001",
                "PARSE-003",
                "PARSE-004",
                "FUNC-003",
                "FLOW-003",
                "FLOW-004",
                "FLOW-005"
              ]
            },
            {
              "name": "recognize-operators",
              "text": "\"!=\" { return NEQ; }\n\"==\" { return EQ; }\n\"//\" { return DEFINEDOR; }\n\"|=\" { return SETPIPE; }\n\"+=\" { return SETPLUS; }\n\"-=\" { return SETMINUS; }\n\"*=\" { return SETMULT; }\n\"/=\" { return SETDIV; }\n\"%=\" { return SETMOD; }\n\"//=\" { return SETDEFINEDOR; }\n\"<=\" { return LESSEQ; }\n\">=\" { return GREATEREQ; }\n\"..\" { return REC; }\n\"?//\" { return ALTERNATION; }\n\".\"|\"?\"|\"=\"|\";\"|\",\"|\":\"|\"|\"|\"+\"|\"-\"|\"*\"|\"/\"|\"%\"|\"\\$\"|\"<\"|\">\" { return yytext[0];}",
              "stories": [
                "PARSE-001",
                "FLOW-001",
                "FLOW-002",
                "FLOW-003",
                "FLOW-004",
                "FLOW-006",
                "PATH-003"
              ]
            },
            {
              "name": "track-delimited-states",
              "text": "\"[\"|\"{\"|\"(\" {\n  return enter(yytext[0], YY_START, yyscanner);\n}\n\n\"]\"|\"}\"|\")\" {\n  return try_exit(yytext[0], YY_START, yyscanner);\n}",
              "stories": [
                "PARSE-001",
                "PARSE-003",
                "PARSE-004"
              ]
            },
            {
              "name": "scan-formats-and-numbers",
              "text": "\"@\"[a-zA-Z0-9_]+ {\n  yylval->literal = jv_string_sized(yytext + 1, yyleng - 1); return FORMAT;\n}\n\n([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][+-]?[0-9]+)? {\n   yylval->literal = jv_parse_sized(yytext, yyleng); return LITERAL;\n}",
              "stories": [
                "PARSE-001",
                "PARSE-002",
                "VALUE-001",
                "TEXT-002"
              ]
            },
            {
              "name": "scan-strings-and-interpolation",
              "text": "\"\\\"\" {\n  yy_push_state(IN_QQSTRING, yyscanner);\n  return QQSTRING_START;\n}\n\n<IN_QQSTRING>{\n  \"\\\\(\" {\n    return enter(QQSTRING_INTERP_START, YY_START, yyscanner);\n  }\n  \"\\\"\" {\n    yy_pop_state(yyscanner);\n    return QQSTRING_END;\n  }\n  (\\\\[^u(]|\\\\u[a-zA-Z0-9]{0,4})+ {\n    /* pass escapes to the json parser */\n    jv escapes = jv_string_fmt(\"\\\"%.*s\\\"\", (int)yyleng, yytext);\n    yylval->literal = jv_parse_sized(jv_string_value(escapes), jv_string_length_bytes(jv_copy(escapes)));\n    jv_free(escapes);\n    return QQSTRING_TEXT;\n  }\n  [^\\\\\\\"]+ {\n    yylval->literal = jv_string_sized(yytext, yyleng);\n    return QQSTRING_TEXT;\n  }\n  . {\n    return INVALID_CHARACTER;\n  }\n}",
              "stories": [
                "PARSE-001",
                "PARSE-002"
              ]
            },
            {
              "name": "scan-identifiers-and-accessors",
              "text": "([a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*  { yylval->literal = jv_string(yytext); return IDENT;}\n\\.[a-zA-Z_][a-zA-Z_0-9]*  { yylval->literal = jv_string(yytext+1); return FIELD;}\n\\$([a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*  { yylval->literal = jv_string(yytext+1); return BINDING;}",
              "stories": [
                "PARSE-001",
                "FUNC-001",
                "FUNC-002",
                "VALUE-002"
              ]
            },
            {
              "name": "ignore-whitespace-and-reject-invalid-characters",
              "text": "[ \\r\\n\\t]+  {}\n\n. { return INVALID_CHARACTER; }",
              "stories": [
                "PARSE-001",
                "PARSE-004"
              ]
            }
          ]
        }
      ]
    },
    "parser.y": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "803aa7c0b1acba2228e52d1de392fb51e60a7bbe23e42870aea1d62c43360c60",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "lexical-scanning",
              "text": "%token INVALID_CHARACTER\n%token <literal> IDENT\n%token <literal> FIELD\n%token <literal> BINDING\n%token <literal> LITERAL\n%token <literal> FORMAT",
              "stories": [
                "PARSE-001"
              ]
            },
            {
              "name": "literals-strings-interpolation",
              "text": "String:\nStringStart QQString QQSTRING_END {\n  $$ = $2;\n  jv_free($1);\n};",
              "stories": [
                "PARSE-002"
              ]
            },
            {
              "name": "core-filter-grammar",
              "text": "Expr:\nExpr \"//\" Expr {\n  $$ = gen_definedor($1, $3);\n} |\nExpr '=' Expr {\n  $$ = gen_call(\"_assign\", BLOCK(gen_lambda($1), gen_lambda($3)));\n} |\nTerm %prec NONOPT {\n  $$ = $1;\n}",
              "stories": [
                "PARSE-003"
              ]
            },
            {
              "name": "declarations-control-rejection",
              "text": "TopLevel:\nModule Imports Query {\n  *answer = BLOCK($1, $2, gen_op_simple(TOP), $3);\n} |\nModule Imports FuncDefs {\n  *answer = BLOCK($1, $2, $3);\n}",
              "stories": [
                "PARSE-004"
              ]
            },
            {
              "name": "stream-valued-filters",
              "text": "Query:\nFuncDef Query %prec FUNCDEF {\n  $$ = block_bind_referenced($1, $2, OP_IS_CALL_PSEUDO);\n} |\nExpr {\n  $$ = $1;\n}",
              "stories": [
                "CORE-001"
              ]
            },
            {
              "name": "filter-composition",
              "text": "Query '|' Query {\n  $$ = block_join($1, $3);\n} |\nQuery ',' Query {\n  $$ = gen_both($1, $3);\n}",
              "stories": [
                "CORE-002"
              ]
            },
            {
              "name": "errors-and-optional-evaluation",
              "text": "Term FIELD '?' {\n  $$ = gen_index_opt($1, gen_const($2));\n} |\nTerm '?' {\n  $$ = gen_try($1, gen_op_simple(BACKTRACK));\n}",
              "stories": [
                "CORE-003"
              ]
            },
            {
              "name": "truthiness-comparison",
              "text": "Expr \"or\" Expr {\n  $$ = gen_or($1, $3);\n} |\nExpr \"and\" Expr {\n  $$ = gen_and($1, $3);\n} |\nExpr \"==\" Expr {\n  $$ = gen_binop($1, $3, EQ);\n}",
              "stories": [
                "CORE-004"
              ]
            },
            {
              "name": "value-constants",
              "text": "LITERAL {\n  $$ = gen_const($1);\n} |\nIDENT {\n  const char *s = jv_string_value($1);\n  if (strcmp(s, \"false\") == 0)\n    $$ = gen_const(jv_false());\n  else if (strcmp(s, \"true\") == 0)\n    $$ = gen_const(jv_true());\n  else if (strcmp(s, \"null\") == 0)\n    $$ = gen_const(jv_null());",
              "stories": [
                "VALUE-001"
              ]
            },
            {
              "name": "field-index-access",
              "text": "Term FIELD %prec NONOPT {\n  $$ = gen_index($1, gen_const($2));\n} |\nTerm '[' Query ']' %prec NONOPT {\n  $$ = gen_index($1, $3);\n}",
              "stories": [
                "VALUE-002"
              ]
            },
            {
              "name": "slices-and-iteration",
              "text": "Term '[' ']' %prec NONOPT {\n  $$ = block_join($1, gen_op_simple(EACH));\n} |\nTerm '[' Query ':' Query ']' %prec NONOPT {\n  $$ = gen_slice_index($1, $3, $5, INDEX);\n}",
              "stories": [
                "VALUE-003"
              ]
            },
            {
              "name": "arithmetic-structural-operators",
              "text": "Expr '+' Expr {\n  $$ = gen_binop($1, $3, '+');\n} |\nExpr \"+=\" Expr {\n  $$ = gen_update($1, $3, '+');\n}",
              "stories": [
                "FLOW-001"
              ]
            },
            {
              "name": "boolean-alternative-operators",
              "text": "Expr \"//\" Expr {\n  $$ = gen_definedor($1, $3);\n} |\nExpr \"//=\" Expr {\n  $$ = gen_definedor_assign($1, $3);\n}",
              "stories": [
                "FLOW-002"
              ]
            },
            {
              "name": "conditionals-exception-flow",
              "text": "\"if\" Query \"then\" Query ElseBody {\n  $$ = gen_cond($2, $4, $5);\n} |\n\"try\" Expr \"catch\" Expr {\n  $$ = gen_try($2, $4);\n}",
              "stories": [
                "FLOW-003"
              ]
            },
            {
              "name": "labels-and-breaks",
              "text": "\"label\" BINDING '|' Query {\n  jv v = jv_string_fmt(\"*label-%s\", jv_string_value($2));\n  $$ = gen_location(@$, locations, gen_label(jv_string_value(v), $4));\n} |\nBREAK BINDING {\n  jv v = jv_string_fmt(\"*label-%s\", jv_string_value($2));",
              "stories": [
                "FLOW-004"
              ]
            },
            {
              "name": "reductions-and-iteration-control",
              "text": "\"reduce\" Expr \"as\" Patterns '(' Query ';' Query ')' {\n  $$ = gen_reduce($2, $4, $6, $8);\n} |\n\"foreach\" Expr \"as\" Patterns '(' Query ';' Query ';' Query ')' {\n  $$ = gen_foreach($2, $4, $6, $8, $10);\n}",
              "stories": [
                "FLOW-005"
              ]
            },
            {
              "name": "recursive-generators",
              "text": "REC {\n  $$ = gen_call(\"recurse\", gen_noop());\n}",
              "stories": [
                "FLOW-006"
              ]
            },
            {
              "name": "variable-bindings",
              "text": "Expr \"as\" Patterns '|' Query {\n  $$ = gen_destructure($1, $3, $5);\n} |\nBINDING {\n  $$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($1)));\n  jv_free($1);\n}",
              "stories": [
                "FUNC-001"
              ]
            },
            {
              "name": "function-parameters",
              "text": "Params:\nParam {\n  $$ = $1;\n} |\nParams ';' Param {\n  $$ = BLOCK($1, $3);\n}",
              "stories": [
                "FUNC-002"
              ]
            },
            {
              "name": "function-definitions",
              "text": "FuncDef:\n\"def\" IDENT ':' Query ';' {\n  $$ = gen_function(jv_string_value($2), gen_noop(), $4);\n  jv_free($2);\n}",
              "stories": [
                "FUNC-003"
              ]
            },
            {
              "name": "destructuring-alternatives",
              "text": "RepPatterns:\nRepPatterns \"?//\" Pattern {\n  $$ = BLOCK($1, gen_destructure_alt($3));\n} |\nPattern {\n  $$ = gen_destructure_alt($1);\n}",
              "stories": [
                "FUNC-004"
              ]
            },
            {
              "name": "path-access-mutation",
              "text": "static block gen_update(block object, block val, int optype) {\n  block tmp = gen_op_var_fresh(STOREV, \"tmp\");\n  return BLOCK(gen_op_simple(DUP),\n               val,\n               tmp,\n               gen_call(\"_modify\", BLOCK(gen_lambda(object),\n                                         gen_lambda(gen_binop(gen_noop(),\n                                                              gen_op_bound(LOADV, tmp),\n                                                              optype)))));\n}",
              "stories": [
                "PATH-002"
              ]
            },
            {
              "name": "assignment-operators",
              "text": "Expr \"|=\" Expr {\n  $$ = gen_call(\"_modify\", BLOCK(gen_lambda($1), gen_lambda($3)));\n} |\nExpr \"+=\" Expr {\n  $$ = gen_update($1, $3, '+');\n}",
              "stories": [
                "PATH-003"
              ]
            },
            {
              "name": "complex-assignments",
              "text": "Expr '=' Expr {\n  $$ = gen_call(\"_assign\", BLOCK(gen_lambda($1), gen_lambda($3)));\n} |\nExpr SETMOD Expr {\n  $$ = gen_update($1, $3, '%');\n}",
              "stories": [
                "PATH-004"
              ]
            },
            {
              "name": "formats-and-serialization",
              "text": "static block gen_format(block a, jv fmt) {\n  return BLOCK(a, gen_call(\"format\", gen_lambda(gen_const(fmt))));\n}",
              "stories": [
                "TEXT-002"
              ]
            },
            {
              "name": "parser-diagnostics",
              "text": "void yyerror(YYLTYPE* loc, block* answer, int* errors,\n             struct locfile* locations, struct lexer_param* lexer_param_ptr, const char *s){\n  (*errors)++;\n  locfile_locate(locations, *loc, \"jq: error: %s\", s);\n}",
              "stories": [
                "IO-002"
              ]
            }
          ]
        }
      ]
    },
    "run_conformance.py": {
      "state": "current",
      "versions": [
        {
          "commit": "4ce30eb",
          "date": "2026-08-22",
          "hash": "c1b5be717d542f2d2dc4f4a694dd02ae8c8f84b25f15c6224fbb6a784abe7492",
          "release": "",
          "state": "consumed",
          "via": "plan",
          "ticket": null,
          "requirements": [
            {
              "name": "stage-conformance-assets",
              "text": "It is supplied, not authored: it is staged verbatim into the build directory, hash-verified against the import, and restored before grading.",
              "stories": [
                "CONF-001"
              ]
            },
            {
              "name": "run-conformance-corpus",
              "text": "Run the upstream jq conformance corpus against a candidate implementation.",
              "stories": [
                "CONF-003"
              ]
            },
            {
              "name": "execute-candidate-cases",
              "text": "This runner re-implements the corpus protocol and drives the candidate as a subprocess, one process per case.",
              "stories": [
                "EXEC-001",
                "EXEC-003"
              ]
            },
            {
              "name": "enforce-process-contract",
              "text": "Its exit status is the acceptance verdict.",
              "stories": [
                "EXEC-002"
              ]
            },
            {
              "name": "parse-corpus",
              "text": "Parse the jq test corpus.",
              "stories": [
                "CONF-003"
              ]
            },
            {
              "name": "apply-exclusions",
              "text": "An exclusion that matches nothing is a hard error rather than a shrug.",
              "stories": [
                "CONF-001"
              ]
            },
            {
              "name": "compare-outputs",
              "text": "Structural, not textual: ``1`` and ``1.0`` are the same jq value and the corpus relies on that.",
              "stories": [
                "EXEC-003"
              ]
            },
            {
              "name": "handle-timeouts",
              "text": "A case that has not produced output in this long is not going to.",
              "stories": [
                "EXEC-002"
              ]
            },
            {
              "name": "support-scoped-runs",
              "text": "run only cases whose program matches REGEX",
              "stories": [
                "CONF-002"
              ]
            },
            {
              "name": "report-results",
              "text": "jq conformance: {tally[PASS]} passed, {tally[FAIL]} failed, {tally[ERROR]} errored, {tally[SKIP]} skipped",
              "stories": [
                "EXEC-002"
              ]
            },
            {
              "name": "provide-cli-options",
              "text": "--json",
              "stories": [
                "EXEC-001"
              ]
            }
          ]
        }
      ]
    }
  }
}