Establishes version control for the personal Logseq DB fork before starting the server-client architecture migration and domain features described in docs/agent-guide and the approved implementation plan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
121 lines
4.0 KiB
Clojure
121 lines
4.0 KiB
Clojure
(ns logseq.cli.e2e.coverage
|
|
(:require [clojure.set :as set]
|
|
[clojure.string :as string]))
|
|
|
|
(defn- normalize-commands
|
|
[commands]
|
|
(->> commands
|
|
(map str)
|
|
(remove string/blank?)
|
|
distinct
|
|
sort
|
|
vec))
|
|
|
|
(defn- normalize-options
|
|
[options]
|
|
(->> options
|
|
(map str)
|
|
(remove string/blank?)
|
|
distinct
|
|
sort
|
|
vec))
|
|
|
|
(defn- excluded-command?
|
|
[excluded-prefixes command]
|
|
(let [head (first (string/split (str command) #" "))]
|
|
(contains? (set excluded-prefixes) head)))
|
|
|
|
(defn validate-inventory!
|
|
[{:keys [excluded-command-prefixes scopes] :as inventory}]
|
|
(let [invalid-commands (->> scopes
|
|
vals
|
|
(mapcat :commands)
|
|
(filter #(excluded-command? excluded-command-prefixes %))
|
|
normalize-commands)
|
|
invalid-scopes (->> scopes
|
|
(keep (fn [[scope {:keys [commands]}]]
|
|
(when (some #(excluded-command? excluded-command-prefixes %) commands)
|
|
scope)))
|
|
sort
|
|
vec)]
|
|
(when (seq invalid-commands)
|
|
(throw (ex-info "Excluded commands cannot appear in cli-e2e inventory"
|
|
{:invalid-commands invalid-commands
|
|
:invalid-scopes invalid-scopes
|
|
:inventory inventory})))
|
|
inventory))
|
|
|
|
(defn validate-cases!
|
|
[{:keys [excluded-command-prefixes] :as inventory} cases]
|
|
(let [invalid-cases (->> cases
|
|
(filter (fn [{:keys [covers]}]
|
|
(some #(excluded-command? excluded-command-prefixes %)
|
|
(get covers :commands []))))
|
|
(mapv :id))]
|
|
(when (seq invalid-cases)
|
|
(throw (ex-info "Excluded commands cannot be covered by cli-e2e cases"
|
|
{:invalid-case-ids invalid-cases
|
|
:inventory inventory})))
|
|
cases))
|
|
|
|
(defn command->scope
|
|
[{:keys [scopes]}]
|
|
(into {}
|
|
(mapcat (fn [[scope {:keys [commands]}]]
|
|
(map (fn [command]
|
|
[command scope])
|
|
commands)))
|
|
scopes))
|
|
|
|
(defn required-commands
|
|
[{:keys [scopes]}]
|
|
(->> scopes
|
|
vals
|
|
(mapcat :commands)
|
|
normalize-commands))
|
|
|
|
(defn covered-commands
|
|
[cases]
|
|
(->> cases
|
|
(mapcat #(get-in % [:covers :commands]))
|
|
normalize-commands))
|
|
|
|
(defn required-options-by-scope
|
|
[{:keys [scopes]}]
|
|
(into {}
|
|
(map (fn [[scope {:keys [options]}]]
|
|
[scope (normalize-options options)]))
|
|
scopes))
|
|
|
|
(defn covered-options-by-scope
|
|
[cases]
|
|
(reduce (fn [acc {:keys [covers]}]
|
|
(reduce-kv (fn [acc' scope options]
|
|
(update acc' scope (fnil into #{}) options))
|
|
acc
|
|
(get covers :options {})))
|
|
{}
|
|
cases))
|
|
|
|
(defn coverage-report
|
|
[inventory cases]
|
|
(validate-inventory! inventory)
|
|
(validate-cases! inventory cases)
|
|
(let [required-commands* (set (required-commands inventory))
|
|
covered-commands* (set (covered-commands cases))
|
|
covered-options* (covered-options-by-scope cases)
|
|
required-options* (required-options-by-scope inventory)]
|
|
{:missing-commands (->> (set/difference required-commands* covered-commands*)
|
|
normalize-commands)
|
|
:missing-options (into {}
|
|
(map (fn [[scope options]]
|
|
[scope (->> (set/difference (set options)
|
|
(get covered-options* scope #{}))
|
|
normalize-options)]))
|
|
required-options*)}))
|
|
|
|
(defn complete?
|
|
[{:keys [missing-commands missing-options]}]
|
|
(and (empty? missing-commands)
|
|
(every? empty? (vals missing-options))))
|