Skip to content

feat: project-level config loading + default safety LIMIT - #1

Merged
AllenMuu merged 29 commits into
mainfrom
feat/project-config
Jul 24, 2026
Merged

feat: project-level config loading + default safety LIMIT#1
AllenMuu merged 29 commits into
mainfrom
feat/project-config

Conversation

@AllenMuu

@AllenMuu AllenMuu commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

Two features — feat/project-config builds on feat/default-limit (default-limit has not yet merged to main, so this PR carries both).

1. Project-level config loading (this branch's main feature)

  • Project-level config: walk up from cwd for .config/mysql-cli/config.toml (same relative path as global ~/.config/mysql-cli/config.toml; only the root differs).
  • Override-style merge: same-name datasource replaced wholesale (incl. SSH subtable); distinct names unioned; default/default_limit project overrides global (0/empty = unset).
  • Trust store (~/.config/mysql-cli/trusted, plaintext, EvalSymlinks-normalized, 0600): untrusted project config is silently skipped (exit 0); ${ENV} password placeholders expand only in trusted configs — prevents malicious repos from hijacking connections or siphoning env-var passwords.
  • MYSQL_CLI_CONFIG env var to specify a config path.
  • config subcommand group: path / show / trust / init (passwords masked in show: plaintext→***, ${ENV} as-is).
  • Priority chain: --config > MYSQL_CLI_CONFIG > project (trusted) > global > MYSQL_* field overrides > default.
  • Backward compatible: no project + no env + no explicit --config behaves exactly as before; --config single-file semantics unchanged.

2. Default safety LIMIT (default-limit, base of this branch)

  • SELECT without LIMIT auto-capped (default 1000); --no-limit disables; --limit N explicit.
  • default_limit config / MYSQL_CLI_DEFAULT_LIMIT env tune the cap.
  • meta.truncated marker (cap+1 probe, zero extra queries); --format jsonl slim envelope.

Design & Plan

  • Spec: docs/superpowers/specs/2026-07-24-project-level-config-design.md (+ default-limit spec)
  • Plan: docs/superpowers/plans/2026-07-24-project-level-config.md (+ default-limit plan)

Test plan

  • go test ./... — all packages green
  • go vet ./... clean, go build ./... clean, gofmt clean
  • Coverage: config 88.1%, format 89.1%, query 82.8%, schema 90.5%, safety 92.3%, cli 79.2% (cli 79.2% is pre-existing query/txn/repl; new config subcommands covered incl. -d single + unknown datasource)
  • Per-task TDD reviews + final whole-branch review: READY (no Critical/Important blockers)
  • Reviewer: verify trust-store security model + backward compat

Notes

  • Deferred minors (non-blocking polish): test-hygiene (unchecked errors in tests), AddTrust swallows ReadTrusted err (plan-mandated, benign), inline mode literals.
  • Skill docs updated: skills/mysql-shared/SKILL.md (version 1.1.0 → 1.2.0).

AllenMuu added 29 commits July 24, 2026 12:22
Brainstormed design for mysql-cli default safe LIMIT (cap=1000, cap+1 probe, meta.truncated) + JSON envelope slimming (drop rows_affected on SELECT, add --format jsonl). Driven by scripts/token-shootout.py findings: bare SELECT returns 6.8M (MCP) / 9.1M (CLI) tokens, both overflow any agent session.
Add ReadJSON for read queries (SELECT): omits rows_affected and reports
meta.truncated + meta.limit, consuming result.Result.Truncated from Task 1.

Add jsonl format branch to Format: one JSON object per line via
formatJSONL, with NULL rendered as native JSON null.

SuccessJSON unchanged; existing TestJSONEnvelope still passes.
- 项目级 config:从 cwd 向上找 .config/mysql-cli/config.toml(与全局同构)
- 覆盖式合并 + 信任清单机制(防恶意仓库/ENV 套取)
- MYSQL_CLI_CONFIG env + config 子命令族(path/show/trust/init)
- 优先级链:--config > env > 项目级(已信任) > 全局
- 分阶段实现建议(Phase 1-3)
12 TDD tasks across 3 phases:
- Phase 1: loader.go core (DiscoverProject/MergeConfigs/Load) + Globals.resolve wiring (compat)
- Phase 2: trust store + MYSQL_CLI_CONFIG env + 'config trust'
- Phase 3: config path/show/init + Masked + skill docs
- Task 12: full coverage gate (>=80%)
… drop stray roadmap.md

Finding 1 (loader.go): swap the loop order in DiscoverProject so the
home/root boundary check runs BEFORE the candidate stat. Because project
and global configs share the same relConfigPath (.config/mysql-cli/config.toml),
the prior order would walk up to home, find the global config there, and
wrongly return home as the project root. Now home is never searched as a
project root.

Finding 2 (loader_test.go): add TestDiscoverProject_HomeGlobalConfigIsNotProject
which installs the global config at home/.config/mysql-cli/config.toml and
asserts DiscoverProject from a home subdir returns found=false. The prior
TestDiscoverProject_StopsAtHome never installed a config at home, so it
passed regardless of boundary order.

Finding 3 (docs/roadmap.md): the file was newly added in 93d207c and
unrelated to Task 1; removed from the branch.
@AllenMuu
AllenMuu merged commit 28f3ac3 into main Jul 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant