{
  "title": "Public Nostr note watchlist",
  "type": "object",
  "schemaVersion": 1,
  "description": "Read a bounded window of public kind1 notes from supported relays. Notes are cryptographically verified before saving. Omitted input reads ten notes per relay from the last seven days; with no author, hashtag or keyword given, the #nostr tag is sampled so the result is topical rather than arbitrary recent posts. No whole-network coverage, private messages or profile enrichment.",
  "properties": {
    "relays": {
      "title": "Public relays",
      "type": "array",
      "editor": "stringList",
      "description": "Select one or both supported anonymous public relays. Only wss://relay.damus.io and wss://nos.lol are accepted; no credentials, alternate hosts or custom paths. Omitted input uses both.",
      "prefill": [
        "wss://relay.damus.io",
        "wss://nos.lol"
      ],
      "items": {
        "type": "string"
      },
      "sectionCaption": "1 · Public relay sources",
      "sectionDescription": "Use the supported anonymous relays and optional exact author public keys."
    },
    "authors": {
      "title": "Author public keys",
      "type": "array",
      "editor": "stringList",
      "description": "Optional exact 64-character hexadecimal public keys, at most 20. Multiple keys use OR. Does not resolve usernames or npub values, enrich profiles, or identify a real person.",
      "prefill": [],
      "items": {
        "type": "string"
      }
    },
    "hashtags": {
      "title": "Hashtags",
      "type": "array",
      "editor": "stringList",
      "description": "Optional at most 10 exact Nostr t-tag values; leading # is removed. Tag matching is case sensitive, as in the relay protocol. Multiple values use OR. Author, tag, time and keyword groups combine with AND. When this field is omitted and no authors or keywords are given, the run samples the nostr tag (logged in the run) instead of an unfiltered window; pass an empty list explicitly to read the unfiltered window.",
      "prefill": [
        "nostr"
      ],
      "items": {
        "type": "string"
      },
      "sectionCaption": "2 · Text and tag filters",
      "sectionDescription": "Hashtags and content keywords follow the matching rules below."
    },
    "keywords": {
      "title": "Content keywords",
      "type": "array",
      "editor": "stringList",
      "description": "Optional at most 10 case-insensitive substrings, matched with OR locally after retrieving the bounded relay window. This is not a relay-wide full-text search; increase perRelayLimit if the window is too narrow.",
      "prefill": [],
      "items": {
        "type": "string"
      }
    },
    "since": {
      "title": "Window start",
      "type": "string",
      "editor": "textfield",
      "description": "Optional inclusive ISO8601 timestamp with timezone, for example 2026-10-01T00:00:00Z. Omitted start is lookbackHours before until. Windows may span at most 366 days.",
      "sectionCaption": "3 · Observation window",
      "sectionDescription": "Use explicit timestamps or the rolling lookback; EOSE does not establish whole-network coverage."
    },
    "until": {
      "title": "Window end",
      "type": "string",
      "editor": "textfield",
      "description": "Optional inclusive ISO8601 timestamp with timezone. Omitted end freezes at the current run start. Use fixed since/until timestamps for repeatable historical windows. Future endpoints over five minutes ahead are rejected."
    },
    "lookbackHours": {
      "title": "Lookback hours",
      "type": "integer",
      "editor": "number",
      "description": "Used only when since is omitted: look back this many hours from until. Default 168 means seven days.",
      "default": 168,
      "minimum": 1,
      "maximum": 8760
    },
    "perRelayLimit": {
      "title": "Events requested per relay",
      "type": "integer",
      "editor": "number",
      "description": "Request this many stored events per relay, from 1 to 100. Duplicate, invalid and locally filtered events can reduce saved results. The relay may return fewer, and this does not promise a full historical export.",
      "default": 10,
      "minimum": 1,
      "maximum": 100,
      "sectionCaption": "4 · Relay and result limits",
      "sectionDescription": "Bound events requested per relay separately from unique saved notes."
    },
    "maxResults": {
      "title": "Maximum saved notes",
      "type": "integer",
      "editor": "number",
      "description": "Maximum distinct verified notes saved across relays. Default 20 fits both ten-event windows. Unchanged notes skipped by onlyChanges do not consume this cap. At most 200 candidates can be retrieved with two relays.",
      "default": 20,
      "minimum": 1,
      "maximum": 1000
    },
    "comparePrevious": {
      "title": "Compare saved observations",
      "type": "boolean",
      "editor": "checkbox",
      "description": "Use a named key-value store to compare signed note snapshots for this exact watchlist. The first run warns and returns matching notes as new, establishing history only after confirmed dataset writes.",
      "default": false,
      "sectionCaption": "5 · Saved comparisons",
      "sectionDescription": "The first comparison establishes history. Reuse the same scope for later observations and avoid concurrent writers."
    },
    "onlyChanges": {
      "title": "Only notes not previously saved or changed",
      "type": "boolean",
      "editor": "checkbox",
      "description": "Enables comparison and skips unchanged signed snapshots. A valid empty repeat warns and succeeds. Signed kind1 content is immutable, so repeated IDs normally remain unchanged. No deletions are inferred.",
      "default": false
    },
    "snapshotName": {
      "title": "History name",
      "type": "string",
      "editor": "textfield",
      "description": "1-80 letters, numbers, underscores or hyphens. Separate logical workflows with different names. History also includes relay/filter/window settings. Run only one writer at a time per exact scope; concurrent changes are detected before commit but storage is not transactional.",
      "default": "default"
    },
    "relayTimeoutSeconds": {
      "title": "Time per relay",
      "type": "integer",
      "editor": "number",
      "description": "Total DNS, connection and bounded-response allowance per relay, from 3 to 30 seconds, further limited by the run deadline. Missing EOSE is reported as partial even when some notes were received.",
      "default": 12,
      "minimum": 3,
      "maximum": 30,
      "sectionCaption": "6 · Advanced time budgets",
      "sectionDescription": "Relay timeouts and total run time are bounded independently."
    },
    "maxRunSeconds": {
      "title": "Run time budget",
      "type": "integer",
      "editor": "number",
      "description": "Own wall-clock budget, default 240 seconds, further limited by the platform timeout minus a 25-second reserve. Source calls, verification loops and output respect the remaining budget.",
      "default": 240,
      "minimum": 30,
      "maximum": 3600
    }
  }
}
