// // CommandHelp.swift // Metrika // // Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // Copyright © 2026 Simon-Pierre Boucher. All rights reserved. // /// The in-app command reference (CLAUDE.md §13 v1.0: `help regress` /// in-app). One registry serves both the console `help` command and the /// app's Manual pane, so they can never drift apart. public struct ZQCommandDoc: Identifiable, Equatable, Sendable { public var id: String { verb } public var verb: String /// Shortest accepted abbreviation ("reg" for regress); nil if none. public var abbreviation: String? public var category: String public var summary: String public var syntax: String public var options: [(name: String, meaning: String)] public var examples: [String] public var notes: String? public init( verb: String, abbreviation: String? = nil, category: String, summary: String, syntax: String, options: [(name: String, meaning: String)] = [], examples: [String] = [], notes: String? = nil ) { self.verb = verb self.abbreviation = abbreviation self.category = category self.summary = summary self.syntax = syntax self.options = options self.examples = examples self.notes = notes } public static func == (lhs: ZQCommandDoc, rhs: ZQCommandDoc) -> Bool { lhs.verb == rhs.verb } } public enum ZQCommandReference { public static let categories = [ "Data management", "Descriptive statistics", "Estimation", "Machine learning", "Resampling & simulation", "Post-estimation", "Graphics", "Panel data", "Session & scripting", "User commands", ] public static func doc(for verb: String) -> ZQCommandDoc? { all.first { $0.verb == verb || $0.abbreviation == verb } } public static let all: [ZQCommandDoc] = [ // ------------------------------------------------ Data management ZQCommandDoc( verb: "use", category: "Data management", summary: "Load a dataset into memory. Format is inferred from the extension: .parquet, .csv, .tsv, .json, .arrow, and Stata .dta (formats 117–119).", syntax: "use filename", examples: ["use sales.parquet", "use ~/data/panel.dta"], notes: "Loading goes through DuckDB for columnar formats and a native reader for .dta. The sandboxed app reads user-selected files and its own container." ), ZQCommandDoc( verb: "sysuse", category: "Data management", summary: "Load a sample dataset shipped with Metrika. Bare `sysuse` lists what is available.", syntax: "sysuse [name]", examples: ["sysuse sales", "sysuse mtcars"], notes: "sales: 200-firm × 5-year panel (revenue, price, region, employees). mtcars: the R classic, with a string model column." ), ZQCommandDoc( verb: "save", category: "Data management", summary: "Write the working dataset to disk (.parquet, .csv, or Stata .dta format 118).", syntax: "save filename [, replace]", options: [("replace", "overwrite an existing file")], examples: ["save results.dta, replace"] ), ZQCommandDoc( verb: "clear", category: "Data management", summary: "Drop the working dataset from memory.", syntax: "clear" ), ZQCommandDoc( verb: "describe", abbreviation: "d", category: "Data management", summary: "List variables with their storage types and missing counts.", syntax: "describe" ), ZQCommandDoc( verb: "list", abbreviation: "l", category: "Data management", summary: "Print observations (first 50 shown).", syntax: "list [varlist] [if] [in]", examples: ["list revenue price in 1/10"] ), ZQCommandDoc( verb: "count", abbreviation: "cou", category: "Data management", summary: "Count observations satisfying a condition.", syntax: "count [if]", examples: ["count if revenue > 100 & !missing(price)"] ), ZQCommandDoc( verb: "generate", abbreviation: "gen", category: "Data management", summary: "Create a new variable from an expression. Observations excluded by `if` become missing.", syntax: "generate newvar = expression [if] [in]", examples: [ "gen log_rev = ln(revenue)", "gen high = revenue > 120 if !missing(revenue)", ], notes: "Functions: ln, log, log10, exp, sqrt, abs, floor, ceil, round, int, min, max, missing. Missing values propagate through arithmetic; division by zero and ln of a nonpositive number yield missing." ), ZQCommandDoc( verb: "replace", category: "Data management", summary: "Overwrite values of an existing variable; reports the number of real changes.", syntax: "replace varname = expression [if] [in]", examples: ["replace flag = 0 if missing(flag)"] ), ZQCommandDoc( verb: "drop", category: "Data management", summary: "Remove variables, or observations with `if`/`in`.", syntax: "drop varlist | drop if expression | drop in range", examples: ["drop temp1 temp2", "drop if price < 0"] ), ZQCommandDoc( verb: "keep", category: "Data management", summary: "Keep only the listed variables, or only observations satisfying a condition.", syntax: "keep varlist | keep if expression | keep in range", examples: ["keep in 1/1000"] ), // ------------------------------------------ Descriptive statistics ZQCommandDoc( verb: "summarize", abbreviation: "su", category: "Descriptive statistics", summary: "Means, standard deviations, and ranges; `detail` adds percentiles, skewness, and kurtosis (Stata definitions).", syntax: "summarize [varlist] [if] [in] [, detail]", options: [("detail", "percentiles p1–p99, skewness, kurtosis")], examples: ["summarize revenue price, detail"] ), ZQCommandDoc( verb: "tabulate", abbreviation: "tab", category: "Descriptive statistics", summary: "One-way frequency table or two-way cross-tabulation with totals.", syntax: "tabulate varname [varname2] [if] [, missing]", options: [("missing", "include missing values as a category")], examples: ["tab region", "tabulate region purchase"] ), ZQCommandDoc( verb: "correlate", abbreviation: "cor", category: "Descriptive statistics", summary: "Pearson correlation matrix with listwise deletion.", syntax: "correlate [varlist] [if]", examples: ["correlate revenue price orders"] ), // ------------------------------------------------------ Estimation ZQCommandDoc( verb: "regress", abbreviation: "reg", category: "Estimation", summary: "Ordinary least squares via LAPACK QR. Factor variables (i.var) expand to indicators; c.a#c.b forms continuous interactions.", syntax: "regress depvar [indepvars] [if] [in] [, robust hc2 hc3 cluster(varname) noconstant level(#)]", options: [ ("robust", "HC1 heteroskedasticity-consistent SE (Stata's robust)"), ("hc2 / hc3", "leverage-adjusted sandwich estimators"), ("cluster(var)", "cluster-robust SE, t on G−1 df"), ("noconstant", "suppress the intercept"), ("level(#)", "confidence level, default 95"), ], examples: [ "reg log_rev price, robust", "reg log_rev price i.region, cluster(firm_id)", "reg wage c.age#c.age education", ], notes: "Results match R to 1e-10. Listwise deletion is reported explicitly." ), ZQCommandDoc( verb: "logit", category: "Estimation", summary: "Logistic regression by Fisher scoring; reports LR χ², McFadden pseudo-R², z statistics.", syntax: "logit depvar indepvars [if] [, robust cluster(varname) level(#)]", examples: ["logit purchase price, robust"] ), ZQCommandDoc( verb: "probit", category: "Estimation", summary: "Probit regression (normal link), same options as logit.", syntax: "probit depvar indepvars [if] [, robust cluster(varname)]", examples: ["probit purchase price"] ), ZQCommandDoc( verb: "poisson", category: "Estimation", summary: "Poisson regression for counts (log link).", syntax: "poisson depvar indepvars [if] [, robust cluster(varname)]", examples: ["poisson orders price, robust"] ), ZQCommandDoc( verb: "ivregress", category: "Estimation", summary: "Two-stage least squares. Endogenous regressors and their instruments go in the parenthesized group.", syntax: "ivregress 2sls depvar [exogvars] (endogvars = instruments) [, robust cluster(varname)]", examples: ["ivregress 2sls log_rev (price = z1 z2), robust"], notes: "Residuals come from the original regressors; inference follows Stata's `small` convention (t statistics on N−K df)." ), ZQCommandDoc( verb: "xtreg", category: "Estimation", summary: "Panel fixed-effects (within) estimator. Declare the panel with xtset first.", syntax: "xtreg depvar indepvars, fe [cluster(panelvar)]", options: [ ("fe", "fixed effects (required — the only estimator so far)"), ("cluster(panelvar)", "panel-clustered SE, t on G−1 df"), ], examples: ["xtset firm_id", "xtreg log_rev price, fe cluster(firm_id)"] ), // ------------------------------------------------ Machine learning ZQCommandDoc( verb: "lasso", category: "Machine learning", summary: "L1-penalized linear regression (coordinate descent, glmnet conventions). Selects variables by zeroing coefficients.", syntax: "lasso depvar indepvars, lambda(#)", options: [("lambda(#)", "penalty strength; omit it to see lambda_max for your data")], examples: ["lasso log_rev price z1 z2 orders, lambda(0.05)"] ), ZQCommandDoc( verb: "elasticnet", category: "Machine learning", summary: "Elastic-net linear regression mixing L1 and L2 penalties.", syntax: "elasticnet depvar indepvars, lambda(#) [alpha(#)]", options: [ ("alpha(#)", "1 = lasso, 0 = ridge; default 1"), ("lambda(#)", "penalty strength"), ], examples: ["elasticnet log_rev price z1 z2, alpha(0.4) lambda(0.02)"], notes: "Matches R glmnet, including its gaussian y-standardization convention (ridge penalties scale with sd of the response)." ), ZQCommandDoc( verb: "boost", category: "Machine learning", summary: "Gradient-boosted regression trees (xgboost-style exact greedy, squared loss). Deterministic — no subsampling.", syntax: "boost depvar features, rounds(#) [eta(#) maxdepth(#) lambda(#)]", options: [ ("rounds(#)", "number of trees"), ("eta(#)", "learning rate, default 0.3"), ("maxdepth(#)", "tree depth, default 6"), ("lambda(#)", "L2 regularization on leaf weights, default 1"), ], examples: ["boost log_rev z1 z2 orders, rounds(100) eta(0.1) maxdepth(3)", "predict yhat"], notes: "Matches R xgboost predictions on identical settings. Training R² is in-sample — expect it to be optimistic." ), // ------------------------------------------ Resampling & simulation ZQCommandDoc( verb: "bootstrap", category: "Resampling & simulation", summary: "Pairs bootstrap of a regression. Large replication counts run batched on the Apple GPU; results are identical either way for a given seed.", syntax: "bootstrap, reps(#) [seed(#)]: regress depvar indepvars", options: [ ("reps(#)", "number of replications"), ("seed(#)", "Philox seed — full reproducibility across CPU and GPU"), ], examples: ["bootstrap, reps(10000) seed(42): reg log_rev price"], notes: "Replicates are counter-addressable: any subset recomputes identically regardless of chunking or backend. The planner dispatches ≥500 reps to the GPU when available." ), ZQCommandDoc( verb: "bayes", category: "Resampling & simulation", summary: "Bayesian linear regression by Gibbs sampling: posterior means, standard deviations, and 95% credible intervals.", syntax: "bayes [, mcmcsize(#) burnin(#) seed(#) normalprior(#)]: regress depvar indepvars", options: [ ("mcmcsize(#)", "posterior draws after burn-in (default 10000)"), ("burnin(#)", "discarded warm-up iterations (default 2500)"), ("seed(#)", "Philox seed — chains are exactly reproducible"), ("normalprior(#)", "prior variance of the N(0, #) coefficient priors (default 10000)"), ], examples: ["bayes, mcmcsize(20000) seed(42): reg log_rev price"], notes: "Priors: coefficients N(0, normalprior), variance InvGamma(0.01, 0.01) — Stata's bayes defaults. With diffuse priors the posterior reproduces OLS." ), ZQCommandDoc( verb: "permute", category: "Resampling & simulation", summary: "Permutation test: the response is permuted, the model refit, and empirical two-sided p-values reported per coefficient.", syntax: "permute, reps(#) [seed(#)]: regress depvar indepvars", examples: ["permute, reps(1000) seed(42): reg log_rev orders"] ), ZQCommandDoc( verb: "set", category: "Resampling & simulation", summary: "Set session parameters. `set seed` fixes the Philox key used by bootstrap and permute.", syntax: "set seed #", examples: ["set seed 42"] ), // ------------------------------------------------- Post-estimation ZQCommandDoc( verb: "predict", category: "Post-estimation", summary: "Generate predictions from the last estimation over all current observations.", syntax: "predict newvar [, xb residuals pr n]", options: [ ("xb", "linear prediction (default after regress/ivregress)"), ("residuals", "response residuals"), ("pr", "predicted probability (default after logit/probit)"), ("n", "predicted mean count (default after poisson)"), ], examples: ["reg log_rev price", "predict yhat", "predict e, residuals"] ), ZQCommandDoc( verb: "margins", abbreviation: "marg", category: "Post-estimation", summary: "Average marginal effects with delta-method standard errors. After OLS/IV the effect is the coefficient; after logit/probit/poisson it averages dμ/dx over the estimation sample.", syntax: "margins, dydx(varlist) [level(#)]", examples: ["logit purchase price", "margins, dydx(price)"], notes: "Continuous regressors only for now; factor and interaction terms are rejected with a message." ), // ------------------------------------------------------- Graphics ZQCommandDoc( verb: "scatter", category: "Graphics", summary: "Scatter plot (also available as `graph scatter`). `by()` splits into colored series.", syntax: "scatter yvar xvar [if] [, by(varname)]", examples: ["scatter log_rev price, by(region)"] ), ZQCommandDoc( verb: "histogram", abbreviation: "hist", category: "Graphics", summary: "Frequency histogram of one variable (Sturges bins by default).", syntax: "histogram varname [if] [, bins(#)]", options: [("bins(#)", "override the bin count")], examples: ["histogram revenue, bins(12)"] ), ZQCommandDoc( verb: "kdensity", abbreviation: "kden", category: "Graphics", summary: "Kernel density estimate (Epanechnikov kernel, Silverman bandwidth).", syntax: "kdensity varname [if]", examples: ["kdensity revenue"] ), ZQCommandDoc( verb: "graph", abbreviation: "gr", category: "Graphics", summary: "General plotting front end: graph scatter, graph line, graph histogram.", syntax: "graph scatter|line yvar xvar [if] [, by(varname)]", examples: ["graph line gdp year"] ), // ------------------------------------------------------ Panel data ZQCommandDoc( verb: "xtset", category: "Panel data", summary: "Declare the panel structure (unit and, optionally, time variable) for xtreg.", syntax: "xtset panelvar [timevar]", examples: ["xtset firm_id year"] ), // ---------------------------------------------- Session & scripting ZQCommandDoc( verb: "display", abbreviation: "di", category: "Session & scripting", summary: "Evaluate and print an expression.", syntax: "display expression", examples: ["display 2 + 2 * 3", "display ln(100)"] ), ZQCommandDoc( verb: "log", category: "Session & scripting", summary: "Record commands and output to a text file.", syntax: "log using filename | log close", examples: ["log using session.log"] ), ZQCommandDoc( verb: "help", category: "Session & scripting", summary: "Show this reference, or the entry for one command.", syntax: "help [command]", examples: ["help regress"] ), // ---------------------------------------------------- User commands ZQCommandDoc( verb: "zscore", category: "User commands", summary: "Sample native plugin: generates z_varname, the standardized version of a variable.", syntax: "zscore varname", examples: ["zscore revenue"], notes: "Native plugins are Swift types conforming to ZQCommandPlugin, compiled into the app. Script commands are .zyq files in ~/Library/Application Support/Metrika/Commands/ — an optional leading `args name…` line names positional arguments, referenced as `name' or `1' in the body." ), ] }