packages feed

okf-cli-0.10.0.0: help/where.md

THE --where CONDITION LANGUAGE

"okf concepts --where" asks a question of each concept's frontmatter and keeps
the concepts that answer yes. The simplest question is KEY=VALUE. The same flag
also excludes values, names a set, and combines questions with and, or, and
not. This topic is the full reference; "okf help concepts" covers the command
around it.

THREE FORMS, CHOSEN BY HOW THE ARGUMENT STARTS

  okf decides which grammar applies by looking at the beginning of the
  argument. It never tries one grammar and falls back to another.

    Starts with          Read as                    Example
    (                    one expression             (status="draft" or has(owner))
    KEY!=                standalone exclusion       status!=completed
    KEY in               standalone set             status in ["accepted","proposed"]
    KEY not in           standalone excluded set    status not in ["completed"]
    anything else        equality                   status=draft

  An equality's value is everything after the first '=', taken verbatim:
  title=research and development compares with "research and development",
  and a value may contain '=' or keep its whitespace. That is why the new forms
  are recognized only from their first characters. A KEY=VALUE argument means
  exactly what it always has.

  Once a new form is recognized, a mistake is an error that points at the
  character where reading stopped. It is never quietly reread as an equality:

    okf concepts BUNDLE --where 'status in [accepted]'
    option --where: expected a JSON double-quoted string as a set member at offset 11
      status in [accepted]
                 ^

  Quote every new-form argument for the shell with single quotes, since '!',
  '(', '[', and '"' all mean something to it.

KEYS

  A key is a top-level frontmatter key (status) or one level of nesting
  (reviews.outcome, generated.by). Each part starts with a letter or underscore
  and continues with letters, digits, underscores, or hyphens. One level is the
  limit, because one level is what a profile can describe.

STANDALONE CONDITIONS

  KEY!=VALUE           The key holds a value and it is not VALUE. VALUE is
                       everything after "!=", verbatim, like KEY=VALUE.
  KEY in [...]         The key holds one of the listed values.
  KEY not in [...]     The key holds a value and none of them is listed.

  A set is a non-empty JSON array of double-quoted strings, and it must be the
  last thing in the argument:

    okf concepts BUNDLE --where 'status in ["accepted","proposed"]'

EXPRESSIONS

  An argument whose first non-space character is "(" is one parenthesized
  expression, and nothing may follow its closing parenthesis. Inside it:

    KEY="VALUE"        the key holds VALUE
    KEY!="VALUE"       the key holds a value and it is not VALUE
    KEY in [...]       the key holds one of the listed values
    KEY not in [...]   the key holds a value and none of them is listed
    has(KEY)           the concept carries KEY at all
    missing(KEY)       the concept does not carry KEY
    not C              C does not hold
    C and C            both hold
    C or C             either holds
    (C)                grouping

  not binds tighter than and, and and binds tighter than or, so

    (status="draft" or status="proposed" and not has(owner))

  reads as status="draft" or (status="proposed" and (not has(owner))). Use
  parentheses when you mean something else. Operators are lowercase.

  Every value inside an expression is a JSON double-quoted string, with JSON
  escapes. Outside parentheses quotes are part of the value:
  --where 'status="accepted"' compares with a value that has the quote marks in
  it, which is almost never what you want.

  Write one pair of parentheses around the whole condition.
  '(status="a") and (tags="b")' is rejected at offset 13, because the
  expression ended at the first closing parenthesis. Write
  '((status="a") and (tags="b"))' or '(status="a" and tags="b")'.

HOW A VALUE MATCHES

  Values are compared as text. A stored string, number, or boolean is a
  comparable value. Nothing is converted, so (usage_count="12") matches a
  stored 12 exactly as --where usage_count=12 does, and there is no "greater
  than".

  A LIST MATCHES IF ANY ELEMENT MATCHES. tags=cli and tags in ["cli","tui"]
  select a concept tagged [profiles, cli]. The same holds one level down for a
  list of records: reviews.outcome="approved" selects a concept with any
  approved review.

  AN EXCLUSION REJECTS THE LIST IF ANY ELEMENT IS EXCLUDED. tags!=cli and
  tags not in ["cli"] drop a concept tagged [profiles, cli]. Hiding cli means
  hiding every concept that mentions it.

  AN EXCLUSION NEEDS A VALUE TO JUDGE. status!=completed and status not in
  [...] keep only concepts that store at least one comparable value for status.
  A concept without the key, or with only null, an empty list, or records there,
  fails them exactly as it fails status=accepted. Absence never gets in through
  a value filter. Ask for it when you want it:

    okf concepts BUNDLE --where '(missing(status) or status!="completed")'

  not IS PLAIN NEGATION. It negates its whole operand, absence included, so

    okf concepts BUNDLE --where '(not (status="completed"))'

  also keeps concepts with no status at all. Choose between != and not by
  whether a concept that says nothing should pass.

  A CONCEPT THAT OMITS A KEY NEVER MATCHES A VALUE, even where OKF supplies a
  default. status="stable" selects concepts whose frontmatter says stable, not
  the ones that say nothing.

COMBINING SEVERAL --where FLAGS

  Repeated flags follow two rules, kept apart on purpose:

    Repeated KEY=VALUE equalities on the same key mean "or". --where
    status=accepted --where status=proposed selects both, as it always has.
    Equalities on different keys mean "and". --type obeys the same rule,
    because it is sugar for --where type=....

    Every other condition must hold on its own. Two status!= flags exclude both
    values. Two "in" flags keep only what both sets share. An expression and
    an equality must both hold.

  So to ask for a union of sets, write one larger set or use or. Inside an
  expression, and always means and, even on one key:
  (status="accepted" and status="proposed") selects nothing, because no
  concept's status is both. A condition that contradicts itself is not an
  error; it selects nothing.

CHECKING A CONDITION AGAINST A PROFILE

  With --profile, okf checks every key and value in the condition before it
  walks the bundle: equalities, excluded values, set members, operands under
  not, and both sides of or. A misspelled exclusion would otherwise exclude
  nothing and leave a listing that looks right:

    okf concepts BUNDLE --profile PROFILE --where 'status!=acepted'
    okf concepts: filter value acepted is outside the vocabulary for status
    status accepts: proposed, accepted, completed, rejected

  An undeclared key, a type outside a closed vocabulary, or a value that cannot
  occur is a hard error on stderr with exit 1. Only --type narrows which types'
  rules apply. A type="..." inside an expression does not narrow them.

WHAT IT IS NOT

  This is a filter, not a query language. There are no ordering comparisons,
  regular expressions, wildcards, arithmetic, or type conversion. For anything
  more, take the complete frontmatter as JSON and use jq:

    okf concepts BUNDLE --json | jq '.[] | select(.usage_count > 10)'

  The forms cost a sliver of legacy syntax. A key ending in "!", such as a!=x,
  or an argument with " in " or " not in " right after its key is now read as
  a new form.

EXAMPLES

  Open work, leaving out anything archived:

    okf concepts BUNDLE \
      --where '(status in ["accepted","proposed"] and not (tags="archived"))'

  Everything not completed, including concepts that never set a status:

    okf concepts BUNDLE --where '(missing(status) or status!="completed")'

  Policies that are drafts or have no owner yet:

    okf concepts BUNDLE --type Policy --where '(status="draft" or missing(owner))'

  Improvement requests not yet completed, with their IDs as a column, in ID
  order:

    okf concepts BUNDLE --where 'status!=completed' --show requestId --show status \
      --sort requestId

  Concepts whose provenance was not written by a given agent:

    okf concepts BUNDLE --where 'generated.by!=claude/sonnet-5'

SEE ALSO

  okf help concepts   Listing concepts, columns, and JSON output.
  okf help profiles   Profiles, vocabularies, and allowUnknownTypes.
  okf help format     Frontmatter and the keys OKF owns.