From 2b4d548aadd766e02fe5ecbf1a75ee50efd4110f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Pe=CC=81rez?= Date: Fri, 23 Jan 2026 16:12:15 +0000 Subject: [PATCH] chore: add ci defs files --- .cargo/audit.toml | 37 + .cargo/config.toml | 72 ++ .clippy.toml | 17 + .github/workflows/nickel-typecheck.yml | 116 +++ .github/workflows/rust-ci.yml | 47 ++ .gitignore | 67 ++ .kb-config/README.md | 83 +++ .kb-config/core/kb.ncl | 56 ++ .kb-config/platform/dev.ncl | 53 ++ .kb-config/platform/prod.ncl | 73 ++ .kb-config/platform/test.ncl | 67 ++ .kogral/config.dev.json | 36 + .kogral/config.json | 36 + .kogral/config.prod.json | 45 ++ .kogral/config.test.json | 40 + .markdownlint-cli2.jsonc | 110 +++ .pre-commit-config.yaml | 128 ++++ .rustfmt.toml | 53 ++ .shellcheckrc | 40 + .taplo.toml | 49 ++ .typedialog/README.md | 162 ++++ .typedialog/ci/README.md | 317 ++++++++ .typedialog/ci/config.ncl | 120 +++ .typedialog/ci/config.ncl.20260117_193849.bak | 203 +++++ .typedialog/ci/configure.sh | 116 +++ .typedialog/ci/envrc | 27 + .typedialog/ci/form.toml | 189 +++++ .typedialog/kogral/ARCHITECTURE.md | 290 ++++++++ .../kogral/FORM-TO-TEMPLATE-MAPPING.md | 156 ++++ .typedialog/kogral/README.md | 211 ++++++ .typedialog/kogral/SYNC.md | 56 ++ .typedialog/kogral/core/contracts.ncl | 268 +++++++ .typedialog/kogral/core/defaults.ncl | 97 +++ .typedialog/kogral/core/helpers.ncl | 111 +++ .typedialog/kogral/forms/README.md | 111 +++ .../kogral/forms/fragments/embeddings.toml | 57 ++ .typedialog/kogral/forms/fragments/graph.toml | 34 + .typedialog/kogral/forms/fragments/mcp.toml | 113 +++ .typedialog/kogral/forms/fragments/query.toml | 49 ++ .../kogral/forms/fragments/storage.toml | 64 ++ .typedialog/kogral/forms/fragments/sync.toml | 42 ++ .typedialog/kogral/forms/kogral-config.toml | 76 ++ .typedialog/kogral/modes/dev.ncl | 48 ++ .typedialog/kogral/modes/prod.ncl | 57 ++ .typedialog/kogral/modes/test.ncl | 52 ++ .../kogral/scripts/generate-configs.nu | 55 ++ .typedialog/kogral/scripts/validate-config.nu | 72 ++ .typedialog/kogral/templates/config.json.tera | 84 +++ .vale.ini | 41 + .vale/Vocab/TypeDialog/accept.txt | 25 + .vale/Vocab/TypeDialog/reject.txt | 2 + .vale/styles/Google/AMPM.yml | 9 + .vale/styles/Google/Acronyms.yml | 64 ++ .vale/styles/Google/Colons.yml | 8 + .vale/styles/Google/Contractions.yml | 30 + .vale/styles/Google/DateFormat.yml | 9 + .vale/styles/Google/Ellipses.yml | 9 + .vale/styles/Google/EmDash.yml | 12 + .vale/styles/Google/Exclamation.yml | 12 + .vale/styles/Google/FirstPerson.yml | 13 + .vale/styles/Google/Gender.yml | 9 + .vale/styles/Google/GenderBias.yml | 43 ++ .vale/styles/Google/HeadingPunctuation.yml | 13 + .vale/styles/Google/Headings.yml | 29 + .vale/styles/Google/Latin.yml | 11 + .vale/styles/Google/LyHyphens.yml | 14 + .vale/styles/Google/OptionalPlurals.yml | 12 + .vale/styles/Google/Ordinal.yml | 7 + .vale/styles/Google/OxfordComma.yml | 7 + .vale/styles/Google/Parens.yml | 7 + .vale/styles/Google/Passive.yml | 184 +++++ .vale/styles/Google/Periods.yml | 7 + .vale/styles/Google/Quotes.yml | 7 + .vale/styles/Google/Ranges.yml | 7 + .vale/styles/Google/Semicolons.yml | 8 + .vale/styles/Google/Slang.yml | 11 + .vale/styles/Google/Spacing.yml | 10 + .vale/styles/Google/Spelling.yml | 10 + .vale/styles/Google/Units.yml | 8 + .vale/styles/Google/We.yml | 11 + .vale/styles/Google/Will.yml | 7 + .vale/styles/Google/WordList.yml | 80 ++ .vale/styles/Google/meta.json | 4 + .vale/styles/Google/vocab.txt | 0 .vale/styles/write-good/Cliches.yml | 702 ++++++++++++++++++ .vale/styles/write-good/E-Prime.yml | 32 + .vale/styles/write-good/Illusions.yml | 11 + .vale/styles/write-good/Passive.yml | 183 +++++ .vale/styles/write-good/README.md | 27 + .vale/styles/write-good/So.yml | 5 + .vale/styles/write-good/ThereIs.yml | 6 + .vale/styles/write-good/TooWordy.yml | 221 ++++++ .vale/styles/write-good/Weasel.yml | 29 + .vale/styles/write-good/meta.json | 4 + .woodpecker/Dockerfile | 45 ++ .woodpecker/Dockerfile.cross | 42 ++ .woodpecker/README.md | 78 ++ .woodpecker/ci-advanced.yml | 168 +++++ .woodpecker/ci.yml | 84 +++ .yamllint-ci.yml | 18 + config/defaults.ncl | 157 ++++ config/minimal.ncl | 17 + config/production.ncl | 136 ++++ deny.toml | 74 ++ 104 files changed, 7241 insertions(+) create mode 100644 .cargo/audit.toml create mode 100644 .cargo/config.toml create mode 100644 .clippy.toml create mode 100644 .github/workflows/nickel-typecheck.yml create mode 100644 .github/workflows/rust-ci.yml create mode 100644 .gitignore create mode 100644 .kb-config/README.md create mode 100644 .kb-config/core/kb.ncl create mode 100644 .kb-config/platform/dev.ncl create mode 100644 .kb-config/platform/prod.ncl create mode 100644 .kb-config/platform/test.ncl create mode 100644 .kogral/config.dev.json create mode 100644 .kogral/config.json create mode 100644 .kogral/config.prod.json create mode 100644 .kogral/config.test.json create mode 100644 .markdownlint-cli2.jsonc create mode 100644 .pre-commit-config.yaml create mode 100644 .rustfmt.toml create mode 100644 .shellcheckrc create mode 100644 .taplo.toml create mode 100644 .typedialog/README.md create mode 100644 .typedialog/ci/README.md create mode 100644 .typedialog/ci/config.ncl create mode 100644 .typedialog/ci/config.ncl.20260117_193849.bak create mode 100755 .typedialog/ci/configure.sh create mode 100644 .typedialog/ci/envrc create mode 100644 .typedialog/ci/form.toml create mode 100644 .typedialog/kogral/ARCHITECTURE.md create mode 100644 .typedialog/kogral/FORM-TO-TEMPLATE-MAPPING.md create mode 100644 .typedialog/kogral/README.md create mode 100644 .typedialog/kogral/SYNC.md create mode 100644 .typedialog/kogral/core/contracts.ncl create mode 100644 .typedialog/kogral/core/defaults.ncl create mode 100644 .typedialog/kogral/core/helpers.ncl create mode 100644 .typedialog/kogral/forms/README.md create mode 100644 .typedialog/kogral/forms/fragments/embeddings.toml create mode 100644 .typedialog/kogral/forms/fragments/graph.toml create mode 100644 .typedialog/kogral/forms/fragments/mcp.toml create mode 100644 .typedialog/kogral/forms/fragments/query.toml create mode 100644 .typedialog/kogral/forms/fragments/storage.toml create mode 100644 .typedialog/kogral/forms/fragments/sync.toml create mode 100644 .typedialog/kogral/forms/kogral-config.toml create mode 100644 .typedialog/kogral/modes/dev.ncl create mode 100644 .typedialog/kogral/modes/prod.ncl create mode 100644 .typedialog/kogral/modes/test.ncl create mode 100644 .typedialog/kogral/scripts/generate-configs.nu create mode 100644 .typedialog/kogral/scripts/validate-config.nu create mode 100644 .typedialog/kogral/templates/config.json.tera create mode 100644 .vale.ini create mode 100644 .vale/Vocab/TypeDialog/accept.txt create mode 100644 .vale/Vocab/TypeDialog/reject.txt create mode 100644 .vale/styles/Google/AMPM.yml create mode 100644 .vale/styles/Google/Acronyms.yml create mode 100644 .vale/styles/Google/Colons.yml create mode 100644 .vale/styles/Google/Contractions.yml create mode 100644 .vale/styles/Google/DateFormat.yml create mode 100644 .vale/styles/Google/Ellipses.yml create mode 100644 .vale/styles/Google/EmDash.yml create mode 100644 .vale/styles/Google/Exclamation.yml create mode 100644 .vale/styles/Google/FirstPerson.yml create mode 100644 .vale/styles/Google/Gender.yml create mode 100644 .vale/styles/Google/GenderBias.yml create mode 100644 .vale/styles/Google/HeadingPunctuation.yml create mode 100644 .vale/styles/Google/Headings.yml create mode 100644 .vale/styles/Google/Latin.yml create mode 100644 .vale/styles/Google/LyHyphens.yml create mode 100644 .vale/styles/Google/OptionalPlurals.yml create mode 100644 .vale/styles/Google/Ordinal.yml create mode 100644 .vale/styles/Google/OxfordComma.yml create mode 100644 .vale/styles/Google/Parens.yml create mode 100644 .vale/styles/Google/Passive.yml create mode 100644 .vale/styles/Google/Periods.yml create mode 100644 .vale/styles/Google/Quotes.yml create mode 100644 .vale/styles/Google/Ranges.yml create mode 100644 .vale/styles/Google/Semicolons.yml create mode 100644 .vale/styles/Google/Slang.yml create mode 100644 .vale/styles/Google/Spacing.yml create mode 100644 .vale/styles/Google/Spelling.yml create mode 100644 .vale/styles/Google/Units.yml create mode 100644 .vale/styles/Google/We.yml create mode 100644 .vale/styles/Google/Will.yml create mode 100644 .vale/styles/Google/WordList.yml create mode 100644 .vale/styles/Google/meta.json create mode 100644 .vale/styles/Google/vocab.txt create mode 100644 .vale/styles/write-good/Cliches.yml create mode 100644 .vale/styles/write-good/E-Prime.yml create mode 100644 .vale/styles/write-good/Illusions.yml create mode 100644 .vale/styles/write-good/Passive.yml create mode 100644 .vale/styles/write-good/README.md create mode 100644 .vale/styles/write-good/So.yml create mode 100644 .vale/styles/write-good/ThereIs.yml create mode 100644 .vale/styles/write-good/TooWordy.yml create mode 100644 .vale/styles/write-good/Weasel.yml create mode 100644 .vale/styles/write-good/meta.json create mode 100644 .woodpecker/Dockerfile create mode 100644 .woodpecker/Dockerfile.cross create mode 100644 .woodpecker/README.md create mode 100644 .woodpecker/ci-advanced.yml create mode 100644 .woodpecker/ci.yml create mode 100644 .yamllint-ci.yml create mode 100644 config/defaults.ncl create mode 100644 config/minimal.ncl create mode 100644 config/production.ncl create mode 100644 deny.toml diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 0000000..b965267 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,37 @@ +# Generated by dev-system/ci +# cargo-audit configuration for security vulnerability scanning + +# Database configuration +[advisories] +# The database path +db-path = "~/.cargo/advisory-db" + +# Advisory database URLs +db-urls = ["https://github.com/rustsec/advisory-db"] + +# How to handle different kinds of advisories +# "allow" - Pass the check despite the warning +# "warn" - Pass the check but warn about the issue +# "deny" - Fail the check +deny = ["unmaintained", "unsound", "yanked"] + +# Specific vulnerability IDs to ignore (in case of false positives) +# You can use: https://rustsec.org/ +ignore = [ + # Example: { id = "RUSTSEC-2023-XXXX", reason = "Not applicable to our use case" } +] + +# How to handle vulnerabilities based on severity +[output] +# Deny on high severity vulnerabilities +deny = ["high", "critical"] +# Warn on medium severity vulnerabilities +warn = ["medium", "low"] +# Advisory format: "terminal", "json" +format = "terminal" + +# Target configuration +[target] +# Check only specific targets +# Uncomment to restrict to specific target triples +# triple = "x86_64-unknown-linux-gnu" diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..cb95ce4 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,72 @@ +# Generated by dev-system/ci +# Cargo configuration for build and compilation settings + +[build] +# Number of parallel jobs for compilation +jobs = 4 + +# Code generation backend +# codegen-backend = "llvm" + +[profile.dev] +# Development profile - fast compilation, debug info +opt-level = 0 +debug = true +debug-assertions = true +overflow-checks = true +lto = false +panic = "unwind" +incremental = true + +[profile.release] +# Release profile - slow compilation, optimized binary +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = "thin" +codegen-units = 1 +panic = "abort" +incremental = false +strip = false + +[profile.test] +# Test profile - inherits from dev but can be optimized +opt-level = 1 +debug = true +debug-assertions = true +overflow-checks = true +lto = false +incremental = true + +[profile.bench] +# Benchmark profile - same as release +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = "thin" +codegen-units = 1 +incremental = false + +[term] +# Terminal colors +color = "auto" +verbose = false +progress.when = "auto" +progress.width = 80 + +[net] +# Network settings +git-fetch-with-cli = true +offline = false + +# Strict version requirements for dependencies +# force-non-semver-pre = true + +[alias] +# Custom cargo commands +build-all = "build --all-targets" +check-all = "check --all-targets --all-features" +test-all = "test --all-features --workspace" +doc-all = "doc --all-features --no-deps --open" diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 0000000..5da36da --- /dev/null +++ b/.clippy.toml @@ -0,0 +1,17 @@ +# Generated by dev-system/ci +# Clippy configuration for Rust linting + +# Lint level thresholds +cognitive-complexity-threshold = 25 +type-complexity-threshold = 500 +excessive-nesting-threshold = 5 + +# Allowed patterns (prevent lints on specific code) +# allow-expect-in-tests = true +# allow-unwrap-in-tests = true + +# Single-character variable name threshold +single-char-binding-names-threshold = 4 + +# Note: Lint configurations belong in Cargo.toml under [lints.clippy] or [workspace.lints.clippy] +# This file only contains clippy configuration parameters, not lint levels diff --git a/.github/workflows/nickel-typecheck.yml b/.github/workflows/nickel-typecheck.yml new file mode 100644 index 0000000..325a550 --- /dev/null +++ b/.github/workflows/nickel-typecheck.yml @@ -0,0 +1,116 @@ +# GitHub Actions Nickel Type Checking Workflow +# Generated by dev-system/ci +# Validates all Nickel schemas with nickel typecheck + +name: Nickel Type Check + +on: + push: + branches: [main, develop] + paths: ['**.ncl'] + pull_request: + branches: [main] + paths: ['**.ncl'] + +jobs: + typecheck: + name: Nickel Type Checking + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nickel + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ“¦ Installing Nickel..." + + if command -v nickel &> /dev/null; then + echo "βœ“ Nickel already installed" + nickel --version + else + echo "Installing via homebrew..." + brew install nickel || { + echo "Homebrew installation failed, trying from source..." + curl --proto '=https' --tlsv1.2 -sSf https://install.nickel-lang.org | bash || exit 1 + } + fi + + nickel --version + + - name: Setup environment + run: | + #!/usr/bin/env bash + # Set NICKEL_IMPORT_PATH for schema imports + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults" + echo "NICKEL_IMPORT_PATH=$NICKEL_IMPORT_PATH" >> $GITHUB_ENV + + - name: Type check schemas + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ” Type checking Nickel schemas..." + + # Find all .ncl files + SCHEMAS=$(find . -name "*.ncl" -type f \ + ! -path "./target/*" \ + ! -path "./.git/*" \ + ! -path "./node_modules/*" \ + | sort) + + if [ -z "$SCHEMAS" ]; then + echo "⚠️ No Nickel schemas found" + exit 0 + fi + + FAILED=0 + PASSED=0 + + # Set import path + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:." + + for schema in $SCHEMAS; do + echo "Checking: $schema" + if nickel typecheck "$schema" > /dev/null 2>&1; then + echo " βœ“ Valid" + ((PASSED++)) + else + echo " ❌ Type error" + nickel typecheck "$schema" || true + ((FAILED++)) + fi + done + + echo "" + echo "Summary: $PASSED passed, $FAILED failed" + + if [ $FAILED -gt 0 ]; then + exit 1 + fi + + - name: Export and validate + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ“Š Exporting Nickel configurations..." + + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:." + + # Export main configs if they exist + if [ -f ".typedialog/ci/schemas/ci-local.ncl" ]; then + echo "Exporting CI config..." + nickel export .typedialog/ci/schemas/ci-local.ncl > /tmp/ci-export.json + if [ $? -eq 0 ]; then + echo " βœ“ Successfully exported" + else + echo " ❌ Export failed" + exit 1 + fi + fi + + echo "βœ“ All exports successful" diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml new file mode 100644 index 0000000..73c2af1 --- /dev/null +++ b/.github/workflows/rust-ci.yml @@ -0,0 +1,47 @@ +jobs: + audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + - name: Audit + run: cargo audit --deny warnings + - name: Deny Check + run: cargo deny check licenses advisories + check: + name: Check + Test + Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust-version }} + - name: Cache + uses: Swatinem/rust-cache@v2 + - name: Check + run: cargo check --all-targets + - name: Format Check + run: cargo fmt --all -- --check + - name: Clippy + run: cargo clippy --all-targets -- -D warnings + - name: Tests + run: cargo test --workspace + strategy: + matrix: + rust-version: + - stable + - nightly +name: Rust CI +on: + pull_request: + branches: + - main + push: + branches: + - main + - develop diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f93f883 --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +CLAUDE.md +.claude +utils/save*sh +COMMIT_MESSAGE.md +.wrks +nushell +nushell-* +*.tar.gz +#*-nushell-plugins.tar.gz +github-com +.coder +target +distribution +.qodo +# enviroment to load on bin/build +.env +# OSX trash +.DS_Store + +# Vscode files +.vscode + +# Emacs save files +*~ +\#*\# +.\#* + +# Vim-related files +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist + +# cscope-related files +cscope.* + +# User cluster configs +.kubeconfig + +.tags* + +# direnv .envrc files +.envrc + +# make-related metadata +/.make/ + +# Just in time generated data in the source, should never be committed +/test/e2e/generated/bindata.go + +# This file used by some vendor repos (e.g. github.com/go-openapi/...) to store secret variables and should not be ignored +!\.drone\.sec + +# Godeps workspace +/Godeps/_workspace + +/bazel-* +*.pyc + +# generated by verify-vendor.sh +vendordiff.patch +.claude/settings.local.json + +# Generated SBOM files +SBOM.*.json +*.sbom.json diff --git a/.kb-config/README.md b/.kb-config/README.md new file mode 100644 index 0000000..acb4658 --- /dev/null +++ b/.kb-config/README.md @@ -0,0 +1,83 @@ +# KB Configuration + +Configuration directory for Knowledge Base project using Nickel schemas. + +## Structure + +``` +.kb-config/ +β”œβ”€β”€ README.md # This file +β”œβ”€β”€ core/ # Core KB configuration +β”‚ └── kb.ncl # Main KB config +β”œβ”€β”€ platform/ # Platform-specific configs +β”‚ β”œβ”€β”€ dev.ncl # Development mode +β”‚ β”œβ”€β”€ prod.ncl # Production mode +β”‚ └── test.ncl # Testing mode +└── targets/ # Target-specific configs (generated) + β”œβ”€β”€ kb-cli.json + β”œβ”€β”€ kb-mcp.json + └── kb-core.json +``` + +## Pattern + +Follows the typedialog + provisioning pattern: + +1. **Schemas** define types and contracts (`schemas/kb/`) +2. **Defaults** provide base values +3. **Mode overlays** adjust for environment (dev/prod/test) +4. **User customization** overrides for specific needs +5. **Composition** merges layers using Nickel helpers + +## Usage + +```bash +# Validate configuration +just nickel::validate .kb-config/core/kb.ncl + +# Export to JSON for targets +nickel export --format json .kb-config/core/kb.ncl > .kb-config/targets/kb-core.json + +# Use in Rust +let config = KbConfig::from_file(".kb-config/targets/kb-core.json")?; +``` + +## Modes + +### Development (`dev.ncl`) +- Filesystem storage only +- Local embeddings (fastembed) +- Debug logging +- Fast iteration + +### Production (`prod.ncl`) +- Hybrid storage (filesystem + SurrealDB) +- Cloud embeddings (OpenAI/Claude) +- Production logging +- Performance optimized + +### Testing (`test.ncl`) +- In-memory storage +- No embeddings +- Verbose logging +- Test fixtures + +## Configuration Layers + +``` +Base Schema (contracts.ncl) + ↓ +Default Values (defaults.ncl) + ↓ +Mode Overlay (dev/prod/test) + ↓ +User Customization (kb.ncl) + ↓ +Exported JSON (targets/*.json) +``` + +## See Also + +- [Nickel Schemas](../schemas/kb/) - Type definitions +- [Configuration Guide](../docs/config/overview.md) - User documentation +- [ADR-001: Nickel vs TOML](../docs/architecture/adrs/001-nickel-vs-toml.md) - Decision rationale diff --git a/.kb-config/core/kb.ncl b/.kb-config/core/kb.ncl new file mode 100644 index 0000000..bc6bd8e --- /dev/null +++ b/.kb-config/core/kb.ncl @@ -0,0 +1,56 @@ +# Knowledge Base Core Configuration +# +# User customization layer - compose with mode overlays +# Pattern: defaults + mode + user_custom β†’ final config + +let contracts = import "../../schemas/kb/contracts.ncl" in +let defaults = import "../../schemas/kb/defaults.ncl" in +let helpers = import "../../schemas/kb/helpers.ncl" in + +# Select mode overlay (dev, prod, or test) +let mode = import "../../schemas/kb/modes/dev.ncl" in + +# User customizations (override defaults and mode) +let user_custom = { + graph = { + name = "knowledge-base", + version = "1.0.0", + description = "Personal knowledge base for the KB project", + }, + + # Example: Override inheritance base + # inheritance = { + # base = "/Users/Akasha/Tools/.kb-shared", + # guidelines = [ + # "/Users/Akasha/Tools/.claude/guidelines/rust", + # ], + # priority = 100, + # }, + + # Example: Use different embedding provider + # embeddings = { + # provider = 'openai, + # model = "text-embedding-3-small", + # dimensions = 1536, + # }, + + # Example: Customize query behavior + # query = { + # similarity_threshold = 0.5, + # max_results = 15, + # }, + + # Example: Enable SurrealDB for larger projects + # storage = { + # secondary = { + # enabled = true, + # url = "ws://localhost:8000", + # namespace = "kb", + # database = "knowledge_base", + # }, + # }, +} in + +# Compose configuration: defaults + mode + user customizations +helpers.compose_config defaults.base mode user_custom + | contracts.KbConfig diff --git a/.kb-config/platform/dev.ncl b/.kb-config/platform/dev.ncl new file mode 100644 index 0000000..725f389 --- /dev/null +++ b/.kb-config/platform/dev.ncl @@ -0,0 +1,53 @@ +# Development Platform Configuration +# +# Runtime configuration for development environment +# Loaded by kb-cli/kb-mcp in development mode + +let contracts = import "../../schemas/kb/contracts.ncl" in +let defaults = import "../../schemas/kb/defaults.ncl" in +let helpers = import "../../schemas/kb/helpers.ncl" in +let dev_mode = import "../../schemas/kb/modes/dev.ncl" in + +# Development-specific overrides +let dev_platform = { + graph = { + name = "knowledge-base-dev", + description = "Development instance of KB", + }, + + storage = { + primary = 'filesystem, + secondary = { + enabled = false, # No SurrealDB in dev + }, + }, + + embeddings = { + enabled = true, + provider = 'fastembed, # Local provider, no API costs + model = "BAAI/bge-small-en-v1.5", + dimensions = 384, + }, + + query = { + similarity_threshold = 0.4, # Permissive for exploration + max_results = 20, + cross_graph = true, + }, + + sync = { + auto_index = false, # Manual sync in development + debounce_ms = 1000, + }, + + mcp = { + server = { + name = "kb-mcp-dev", + version = "1.0.0", + transport = 'stdio, + }, + }, +} in + +helpers.compose_config defaults.base dev_mode dev_platform + | contracts.KbConfig diff --git a/.kb-config/platform/prod.ncl b/.kb-config/platform/prod.ncl new file mode 100644 index 0000000..220f16d --- /dev/null +++ b/.kb-config/platform/prod.ncl @@ -0,0 +1,73 @@ +# Production Platform Configuration +# +# Runtime configuration for production environment +# Optimized for performance, reliability, and scalability + +let contracts = import "../../schemas/kb/contracts.ncl" in +let defaults = import "../../schemas/kb/defaults.ncl" in +let helpers = import "../../schemas/kb/helpers.ncl" in +let prod_mode = import "../../schemas/kb/modes/prod.ncl" in + +# Production-specific overrides +let prod_platform = { + graph = { + name = "knowledge-base-prod", + description = "Production instance of KB", + }, + + storage = { + primary = 'filesystem, # Git-tracked knowledge + secondary = { + enabled = true, # SurrealDB for scalable queries + type = 'surrealdb, + url = "ws://surrealdb.production:8000", + namespace = "kb", + database = "production", + # username and password should be set via environment variables + }, + }, + + embeddings = { + enabled = true, + provider = 'openai, # High-quality cloud embeddings + model = "text-embedding-3-small", + dimensions = 1536, + api_key_env = "OPENAI_API_KEY", + }, + + query = { + similarity_threshold = 0.6, # Stricter threshold for quality + max_results = 10, + recency_weight = 3.0, + cross_graph = true, + }, + + sync = { + auto_index = true, # Auto-sync enabled + debounce_ms = 300, # Fast response to changes + watch_paths = ["notes", "decisions", "guidelines", "patterns", "journal"], + }, + + mcp = { + server = { + name = "kb-mcp-prod", + version = "1.0.0", + transport = 'stdio, + }, + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + resources = { + expose_project = true, + expose_shared = true, + }, + }, +} in + +helpers.compose_config defaults.base prod_mode prod_platform + | contracts.KbConfig diff --git a/.kb-config/platform/test.ncl b/.kb-config/platform/test.ncl new file mode 100644 index 0000000..d99ff78 --- /dev/null +++ b/.kb-config/platform/test.ncl @@ -0,0 +1,67 @@ +# Test Platform Configuration +# +# Runtime configuration for test environment +# Optimized for fast, isolated, deterministic tests + +let contracts = import "../../schemas/kb/contracts.ncl" in +let defaults = import "../../schemas/kb/defaults.ncl" in +let helpers = import "../../schemas/kb/helpers.ncl" in +let test_mode = import "../../schemas/kb/modes/test.ncl" in + +# Test-specific overrides +let test_platform = { + graph = { + name = "knowledge-base-test", + description = "Test instance of KB (ephemeral)", + }, + + storage = { + primary = 'memory, # Ephemeral, fast, isolated + secondary = { + enabled = false, # No external dependencies in tests + }, + }, + + embeddings = { + enabled = false, # Disable for test speed + provider = 'fastembed, # Fallback if needed by specific tests + model = "BAAI/bge-small-en-v1.5", + dimensions = 384, + }, + + query = { + similarity_threshold = 0.3, # Permissive for test coverage + max_results = 50, # More results for verification + recency_weight = 1.0, # No recency bias in tests + cross_graph = false, # Isolated tests + }, + + sync = { + auto_index = false, # Manual control in tests + debounce_ms = 0, # No debounce for deterministic behavior + watch_paths = [], # No file watching in tests + }, + + mcp = { + server = { + name = "kb-mcp-test", + version = "1.0.0-test", + transport = 'stdio, + }, + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + resources = { + expose_project = false, # Isolated tests + expose_shared = false, + }, + }, +} in + +helpers.compose_config defaults.base test_mode test_platform + | contracts.KbConfig diff --git a/.kogral/config.dev.json b/.kogral/config.dev.json new file mode 100644 index 0000000..c1b9c20 --- /dev/null +++ b/.kogral/config.dev.json @@ -0,0 +1,36 @@ +{ + "embeddings": { + "dimensions": 384, + "enabled": true, + "model": "BAAI/bge-small-en-v1.5", + "provider": "fastembed" + }, + "mcp": { + "server": { + "transport": "stdio" + }, + "tools": { + "add_decision": true, + "add_note": true, + "export": true, + "get_guidelines": true, + "link": true, + "search": true + } + }, + "query": { + "cross_graph": true, + "max_results": 20, + "similarity_threshold": 0.4 + }, + "storage": { + "primary": "filesystem", + "secondary": { + "enabled": false + } + }, + "sync": { + "auto_index": false, + "debounce_ms": 1000 + } +} diff --git a/.kogral/config.json b/.kogral/config.json new file mode 100644 index 0000000..c1b9c20 --- /dev/null +++ b/.kogral/config.json @@ -0,0 +1,36 @@ +{ + "embeddings": { + "dimensions": 384, + "enabled": true, + "model": "BAAI/bge-small-en-v1.5", + "provider": "fastembed" + }, + "mcp": { + "server": { + "transport": "stdio" + }, + "tools": { + "add_decision": true, + "add_note": true, + "export": true, + "get_guidelines": true, + "link": true, + "search": true + } + }, + "query": { + "cross_graph": true, + "max_results": 20, + "similarity_threshold": 0.4 + }, + "storage": { + "primary": "filesystem", + "secondary": { + "enabled": false + } + }, + "sync": { + "auto_index": false, + "debounce_ms": 1000 + } +} diff --git a/.kogral/config.prod.json b/.kogral/config.prod.json new file mode 100644 index 0000000..7da8fb7 --- /dev/null +++ b/.kogral/config.prod.json @@ -0,0 +1,45 @@ +{ + "embeddings": { + "api_key_env": "OPENAI_API_KEY", + "dimensions": 1536, + "enabled": true, + "model": "text-embedding-3-small", + "provider": "openai" + }, + "mcp": { + "resources": { + "expose_project": true, + "expose_shared": true + }, + "server": { + "transport": "stdio" + }, + "tools": { + "add_decision": true, + "add_note": true, + "export": true, + "get_guidelines": true, + "link": true, + "search": true + } + }, + "query": { + "cross_graph": true, + "max_results": 10, + "similarity_threshold": 0.6 + }, + "storage": { + "primary": "filesystem", + "secondary": { + "database": "production", + "enabled": true, + "namespace": "kogral", + "type": "surrealdb", + "url": "ws://localhost:8000" + } + }, + "sync": { + "auto_index": true, + "debounce_ms": 300 + } +} diff --git a/.kogral/config.test.json b/.kogral/config.test.json new file mode 100644 index 0000000..4d58dd9 --- /dev/null +++ b/.kogral/config.test.json @@ -0,0 +1,40 @@ +{ + "embeddings": { + "dimensions": 384, + "enabled": false, + "model": "BAAI/bge-small-en-v1.5", + "provider": "fastembed" + }, + "mcp": { + "resources": { + "expose_project": false, + "expose_shared": false + }, + "server": { + "transport": "stdio" + }, + "tools": { + "add_decision": true, + "add_note": true, + "export": true, + "get_guidelines": true, + "link": true, + "search": true + } + }, + "query": { + "cross_graph": false, + "max_results": 50, + "similarity_threshold": 0.3 + }, + "storage": { + "primary": "memory", + "secondary": { + "enabled": false + } + }, + "sync": { + "auto_index": false, + "debounce_ms": 0 + } +} diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 0000000..fad431d --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,110 @@ +// Markdownlint-cli2 Configuration +// Documentation quality enforcement for technical projects +// See: https://github.com/DavidAnson/markdownlint-cli2 +// Generated by dev-system/ci + +{ + "config": { + "default": true, + + // Headings - enforce proper hierarchy + "MD001": false, // heading-increment (relaxed - allow flexibility) + "MD026": { "punctuation": ".,;:!?" }, // heading-punctuation + + // Lists - enforce consistency + "MD004": { "style": "consistent" }, // ul-style (consistent list markers) + "MD005": false, // inconsistent-indentation (relaxed) + "MD007": { "indent": 2 }, // ul-indent + "MD029": false, // ol-prefix (allow flexible list numbering) + "MD030": { "ul_single": 1, "ol_single": 1, "ul_multi": 1, "ol_multi": 1 }, + + // Code blocks - fenced only + "MD046": { "style": "fenced" }, // code-block-style + + // CRITICAL: MD040 only checks opening fences, NOT closing fences + // It does NOT catch malformed closing fences with language specifiers (e.g., ```plaintext) + // CommonMark spec requires closing fences to be ``` only (no language) + // Use separate validation script to check closing fences + "MD040": true, // fenced-code-language (code blocks need language on OPENING fence) + + // Formatting - strict whitespace + "MD009": true, // no-hard-tabs + "MD010": true, // hard-tabs + "MD011": true, // reversed-link-syntax + "MD018": true, // no-missing-space-atx + "MD019": true, // no-multiple-space-atx + "MD020": true, // no-missing-space-closed-atx + "MD021": true, // no-multiple-space-closed-atx + "MD023": true, // heading-starts-line + "MD027": true, // no-multiple-spaces-blockquote + "MD037": true, // no-space-in-emphasis + "MD039": true, // no-space-in-links + + // Trailing content + "MD012": false, // no-multiple-blanks (relaxed - allow formatting space) + "MD024": false, // no-duplicate-heading (too strict for docs) + "MD028": false, // no-blanks-blockquote (relaxed) + "MD047": true, // single-trailing-newline + + // Links and references + "MD034": true, // no-bare-urls (links must be formatted) + "MD042": true, // no-empty-links + + // HTML - allow for documentation formatting and images + "MD033": { "allowed_elements": ["br", "hr", "details", "summary", "p", "img"] }, + + // Line length - relaxed for technical documentation + "MD013": { + "line_length": 150, + "heading_line_length": 150, + "code_block_line_length": 150, + "code_blocks": true, + "tables": true, + "headers": true, + "headers_line_length": 150, + "strict": false, + "stern": false + }, + + // Images + "MD045": true, // image-alt-text + + // Tables - enforce proper formatting + "MD060": true, // table-column-style (proper spacing: | ---- | not |------|) + + // Disable rules that conflict with relaxed style + "MD003": false, // consistent-indentation + "MD041": false, // first-line-heading + "MD025": false, // single-h1 / multiple-top-level-headings + "MD022": false, // blanks-around-headings (flexible spacing) + "MD032": false, // blanks-around-lists (flexible spacing) + "MD035": false, // hr-style (consistent) + "MD036": false, // no-emphasis-as-heading + "MD044": false // proper-names + }, + + // Documentation patterns + "globs": [ + "**/*.md", + "!node_modules/**", + "!target/**", + "!.git/**", + "!build/**", + "!dist/**" + ], + + // Ignore build artifacts, external content, and operational directories + "ignores": [ + "node_modules/**", + "target/**", + ".git/**", + "build/**", + "dist/**", + "COPY/**", + ".coder/**", + ".claude/**", + ".wrks/**", + ".vale/**", + "vendor/**" + ] +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..72f9a42 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,128 @@ +# Pre-commit Framework Configuration +# Generated by dev-system/ci +# Configures git pre-commit hooks for Rust projects + +repos: + # ============================================================================ + # Rust Hooks + # ============================================================================ + - repo: local + hooks: + - id: rust-fmt + name: Rust formatting (cargo +nightly fmt) + entry: bash -c 'cargo +nightly fmt --all -- --check' + language: system + types: [rust] + pass_filenames: false + stages: [pre-commit] + + - id: rust-clippy + name: Rust linting (cargo clippy) + entry: bash -c 'cargo clippy --all-targets -- -D warnings' + language: system + types: [rust] + pass_filenames: false + stages: [pre-commit] + + - id: rust-test + name: Rust tests + entry: bash -c 'cargo test --workspace' + language: system + types: [rust] + pass_filenames: false + stages: [pre-push] + + - id: cargo-deny + name: Cargo deny (licenses & advisories) + entry: bash -c 'cargo deny check licenses advisories' + language: system + pass_filenames: false + stages: [pre-push] + + # ============================================================================ + # Nushell Hooks (optional - enable if using Nushell) + # ============================================================================ + # - repo: local + # hooks: + # - id: nushell-check + # name: Nushell validation (nu --ide-check) + # entry: >- + # bash -c 'for f in $(git diff --cached --name-only --diff-filter=ACM | grep "\.nu$"); do + # echo "Checking: $f"; nu --ide-check 100 "$f" || exit 1; done' + # language: system + # types: [file] + # files: \.nu$ + # pass_filenames: false + # stages: [pre-commit] + + # ============================================================================ + # Nickel Hooks (optional - enable if using Nickel) + # ============================================================================ + # - repo: local + # hooks: + # - id: nickel-typecheck + # name: Nickel type checking + # entry: >- + # bash -c 'export NICKEL_IMPORT_PATH="../:."; for f in $(git diff --cached --name-only --diff-filter=ACM | grep "\.ncl$"); do + # echo "Checking: $f"; nickel typecheck "$f" || exit 1; done' + # language: system + # types: [file] + # files: \.ncl$ + # pass_filenames: false + # stages: [pre-commit] + + # ============================================================================ + # Bash Hooks (optional - enable if using Bash) + # ============================================================================ + # - repo: local + # hooks: + # - id: shellcheck + # name: Shellcheck (bash linting) + # entry: shellcheck + # language: system + # types: [shell] + # stages: [pre-commit] + # + # - id: shfmt + # name: Shell script formatting + # entry: bash -c 'shfmt -i 2 -d' + # language: system + # types: [shell] + # stages: [pre-commit] + + # ============================================================================ + # Markdown Hooks (RECOMMENDED - enable for documentation quality) + # ============================================================================ + - repo: local + hooks: + - id: markdownlint + name: Markdown linting (markdownlint-cli2) + entry: markdownlint-cli2 + language: system + types: [markdown] + stages: [pre-commit] + + # ============================================================================ + # General Pre-commit Hooks + # ============================================================================ + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + args: ['--maxkb=1000'] + + - id: check-case-conflict + + - id: check-merge-conflict + + - id: check-toml + + - id: check-yaml + exclude: ^\.woodpecker/ + + - id: end-of-file-fixer + + - id: trailing-whitespace + exclude: \.md$ + + - id: mixed-line-ending diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..8bd3887 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,53 @@ +# Generated by dev-system/ci +# Rustfmt configuration for consistent Rust code formatting +# Configured for cargo +nightly fmt with advanced features enabled + +# Basic formatting options +edition = "2021" +max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Unix" + +# Code structure +use_small_heuristics = "Default" + +# Imports +reorder_imports = true +reorder_modules = true +remove_nested_parens = true +group_imports = "StdExternalCrate" + +# Match expressions +match_block_trailing_comma = false + +# Chains +chain_width = 60 + +# Comment formatting (nightly) +comment_width = 80 +wrap_comments = true +normalize_comments = true +normalize_doc_attributes = true + +# Spaces and indentation (nightly) +fn_single_line = false +fn_params_layout = "Tall" +where_single_line = false + +# Formatting (nightly) +format_strings = true +format_code_in_doc_comments = false + +# Spaces (nightly) +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false + +# Line breaks (nightly) +match_arm_blocks = true +blank_lines_lower_bound = 0 +blank_lines_upper_bound = 1 + +# Enable nightly features +unstable_features = true diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..5eaa967 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,40 @@ +# ShellCheck Configuration Template +# Bash/shell script linting configuration +# Generated by dev-system/ci +# Location: .shellcheckrc + + +# Generated by dev-system/ci +# ShellCheck configuration for Bash script validation + +# Enable all optional checks +enable=all + +# Disable specific checks that are too strict +# SC1091 - Not following sourced files (noisy in monorepos) +# disable=SC1091 + +# Source path for sourced files +source-path=SCRIPTDIR + +# Severity levels: error, warning, info, style +severity=warning + +# Format: gcc, json, json1, quiet +format=gcc + +# Exit status thresholds +# 0: All checks passed +# 1: Warning found +# 2: Error found + +# Shell dialect (bash, sh, ksh, etc) +# shell=bash + +# Check style guide compliance +# These are considered good practices but optional + +# Common problematic patterns +# SC2086 - Double quote to prevent globbing +# SC2181 - Check exit code explicitly +# SC2207 - Array from command substitution diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 0000000..5d20bf8 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,49 @@ +# Taplo configuration for TOML formatting and linting +# https://taplo.tamasfe.dev/configuration/ + +[formatting] +# Indent tables with 2 spaces +indent_string = " " +indent_tables = true + +# Reorder keys alphabetically within tables +reorder_keys = true + +# Reorder arrays to be more readable +reorder_arrays = false + +# Align entries vertically in inline tables +align_entries = false + +# Allow compact inline tables +allowed_blank_lines = 1 + +# Trailing newline +trailing_newline = true + +# Column width for wrapping +column_width = 100 + +# Compact arrays +compact_arrays = true + +# Compact inline tables +compact_inline_tables = false + +# === INCLUDE/EXCLUDE PATTERNS === + +include = ["Cargo.toml", "*/Cargo.toml", "config/**/*.toml", "**/*.toml"] + +exclude = ["target/**", "node_modules/**", ".git/**"] + +# === SCHEMA VALIDATION === + +# Cargo.toml schema validation +[[rule]] +include = ["**/Cargo.toml"] +# Taplo includes built-in Cargo.toml schema + +# TypeDialog form definition TOML files +[[rule]] +include = ["**/.typedialog/**/*.toml", "config/**/forms/*.toml", "tests/fixtures/**/*.toml"] +keys = ["name", "description", "fields", "items", "elements"] diff --git a/.typedialog/README.md b/.typedialog/README.md new file mode 100644 index 0000000..b8b0e20 --- /dev/null +++ b/.typedialog/README.md @@ -0,0 +1,162 @@ +# TypeDialog Configuration Hub + +Central repository for all KOGRAL system configurations, schemas, and automation scripts. + +## Structure + +``` +.typedialog/ +β”œβ”€β”€ ci/ # CI/CD configuration and pipeline setup +β”‚ β”œβ”€β”€ config.ncl # CI configuration (GitHub Actions, deployment) +β”‚ β”œβ”€β”€ README.md # CI documentation +β”‚ └── ... +β”‚ +└── kogral/ # KOGRAL knowledge base configuration + β”œβ”€β”€ core/ # Core Nickel schemas + β”‚ β”œβ”€β”€ contracts.ncl # Type contracts and validation + β”‚ β”œβ”€β”€ defaults.ncl # Base default configuration + β”‚ └── helpers.ncl # Utility functions + β”‚ + β”œβ”€β”€ modes/ # Environment-specific overrides + β”‚ β”œβ”€β”€ dev.ncl # Development mode + β”‚ β”œβ”€β”€ prod.ncl # Production mode + β”‚ └── test.ncl # Test mode + β”‚ + β”œβ”€β”€ scripts/ # NuShell automation scripts + β”‚ β”œβ”€β”€ kogral-sync.nu # Bidirectional sync + β”‚ β”œβ”€β”€ kogral-reindex.nu # Embeddings indexing + β”‚ β”œβ”€β”€ kogral-import-logseq.nu # Logseq import + β”‚ β”œβ”€β”€ kogral-export-logseq.nu # Logseq export + β”‚ └── kogral-migrate.nu # Schema migration + β”‚ + └── README.md # KOGRAL configuration guide +``` + +## Quick Navigation + +### For Configuration Management + +- **[KOGRAL Configuration](kogral/README.md)** - How KOGRAL schemas and modes work +- **Understanding the stack**: Nickel β†’ JSON β†’ Rust β†’ Runtime + +### For CI/CD + +- **[CI Configuration](ci/README.md)** - Pipeline setup and deployment + +### For Automation + +- **[NuShell Scripts](kogral/scripts/)** - All automation scripts (5 total) +- **[Scripts Documentation](../docs/cli/nushell-scripts.md)** - Detailed usage guide + +## Configuration Pattern + +KOGRAL uses a **3-layer configuration system**: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 1: Nickel Schemas (kogral/core/) β”‚ ← Type safety + validation +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Layer 2: Mode Overrides (kogral/modes/) β”‚ ← Environment-specific +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Layer 3: User Customization (.kogral/) β”‚ ← Project-level +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ Exported to JSON ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Rust Deserialization + Runtime Use β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Files by Purpose + +### Core Configuration Files + +| File | Purpose | +|------|---------| +| `kogral/core/contracts.ncl` | Type contracts + field documentation | +| `kogral/core/defaults.ncl` | Base configuration values | +| `kogral/core/helpers.ncl` | Composition functions (merge, override) | +| `kogral/modes/dev.ncl` | Development environment overrides | +| `kogral/modes/prod.ncl` | Production environment overrides | +| `kogral/modes/test.ncl` | Test environment overrides | + +### Automation Scripts + +| Script | Purpose | +|--------|---------| +| `kogral/scripts/kogral-sync.nu` | Sync filesystem ↔ SurrealDB | +| `kogral/scripts/kogral-reindex.nu` | Regenerate embeddings index | +| `kogral/scripts/kogral-import-logseq.nu` | Import from Logseq graphs | +| `kogral/scripts/kogral-export-logseq.nu` | Export to Logseq format | +| `kogral/scripts/kogral-migrate.nu` | Schema version migrations | + +## Usage + +### Validate Configuration + +```bash +# Validate Nickel schemas +nickel export --format json .typedialog/kogral/core/contracts.ncl +``` + +### Generate Mode-Specific Config + +```bash +# Development +nickel export --format json .typedialog/kogral/modes/dev.ncl > .kogral/config.dev.json + +# Production +nickel export --format json .typedialog/kogral/modes/prod.ncl > .kogral/config.prod.json +``` + +### Run Automation Scripts + +```bash +# From repository root: +nu .typedialog/kogral/scripts/kogral-sync.nu +nu .typedialog/kogral/scripts/kogral-reindex.nu +nu .typedialog/kogral/scripts/kogral-migrate.nu +``` + +Or via justfile: + +```bash +just scripts::sync +just scripts::reindex +just scripts::migrate +``` + +## Integration with Codebase + +### Documentation + +- **User Guide**: [docs/cli/nushell-scripts.md](../docs/cli/nushell-scripts.md) +- **Configuration Guide**: [docs/config/](../docs/config/) +- **Architecture**: [docs/architecture/config-driven.md](../docs/architecture/config-driven.md) + +### Build Process + +- Core library loads JSON config via serde +- CLI respects `.kogral/config.toml` or Nickel-exported JSON +- Scripts are standalone executables + +### Environment Variables + +- `TOOLS_PATH` - For shared configuration resolution +- `OPENAI_API_KEY` - For embedding providers +- `ANTHROPIC_API_KEY` - For Claude provider + +## Synchronization with /schemas/ + +The `/schemas/kogral/` directory and `.typedialog/kogral/` are synchronized: + +- **Source of Truth**: `.typedialog/kogral/` (this directory) +- **/schemas/kogral/** - Symlink or copy for build compatibility +- **Update Flow**: Edit in `.typedialog/kogral/` β†’ sync to `/schemas/kogral/` + +## Related Directories + +- `schemas/` - Global schema definitions (generated from .typedialog) +- `config/` - Config examples (generated from modes) +- `scripts/` - Main scripts location (symlink to .typedialog/kogral/scripts) +- `docs/cli/` - User-facing documentation +- `crates/kogral-core/` - Rust library using config diff --git a/.typedialog/ci/README.md b/.typedialog/ci/README.md new file mode 100644 index 0000000..1e854b7 --- /dev/null +++ b/.typedialog/ci/README.md @@ -0,0 +1,317 @@ +# CI System - Configuration Guide + +**Installed**: 2026-01-17 +**Detected Languages**: rust, markdown + +--- + +## Quick Start + +### Option 1: Using configure.sh (Recommended) + +A convenience script is installed in `.typedialog/ci/`: + +```bash +# Use web backend (default) - Opens in browser +.typedialog/ci/configure.sh + +# Use TUI backend - Terminal interface +.typedialog/ci/configure.sh tui + +# Use CLI backend - Command-line prompts +.typedialog/ci/configure.sh cli +``` + +**This script automatically:** +- Sources `.typedialog/ci/envrc` for environment setup +- Loads defaults from `config.ncl` (Nickel format) +- Uses cascading search for fragments (local β†’ Tools) +- Creates backup before overwriting existing config +- Saves output in Nickel format using nickel-roundtrip with documented template +- Generates `config.ncl` compatible with `nickel doc` command + +### Option 2: Direct TypeDialog Commands + +Use TypeDialog nickel-roundtrip directly with manual paths: + +#### Web Backend (Recommended - Easy Viewing) + +```bash +cd .typedialog/ci # Change to CI directory +source envrc # Load environment +typedialog-web nickel-roundtrip config.ncl form.toml \ + --output config.ncl \ + --ncl-template $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 +``` + +#### TUI Backend + +```bash +cd .typedialog/ci +source envrc +typedialog-tui nickel-roundtrip config.ncl form.toml \ + --output config.ncl \ + --ncl-template $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 +``` + +#### CLI Backend + +```bash +cd .typedialog/ci +source envrc +typedialog nickel-roundtrip config.ncl form.toml \ + --output config.ncl \ + --ncl-template $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 +``` + +**Note:** The `--ncl-template` flag uses a Tera template that adds: +- Descriptive comments for each section +- Documentation compatible with `nickel doc config.ncl` +- Consistent formatting and structure + +**All backends will:** +- Show only options relevant to your detected languages +- Guide you through all configuration choices +- Validate your inputs +- Generate config.ncl in Nickel format + +### Option 3: Manual Configuration + +Edit `config.ncl` directly: + +```bash +vim .typedialog/ci/config.ncl +``` + +--- + +## Configuration Format: Nickel + +**This project uses Nickel format by default** for all configuration files. + +### Why Nickel? + +- βœ… **Typed configuration** - Static type checking with `nickel typecheck` +- βœ… **Documentation** - Generate docs with `nickel doc config.ncl` +- βœ… **Validation** - Built-in schema validation +- βœ… **Comments** - Rich inline documentation support +- βœ… **Modular** - Import/export system for reusable configs + +### Nickel Template + +The output structure is controlled by a **Tera template** at: +- **Tools default**: `$TOOLS_PATH/dev-system/ci/templates/config.ncl.j2` +- **Local override**: `.typedialog/ci/config.ncl.j2` (optional) + +**To customize the template:** + +```bash +# Copy the default template +cp $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 \ + .typedialog/ci/config.ncl.j2 + +# Edit to add custom comments, documentation, or structure +vim .typedialog/ci/config.ncl.j2 + +# Your template will now be used automatically +``` + +**Template features:** +- Customizable comments per section +- Control field ordering +- Add project-specific documentation +- Configure output for `nickel doc` command + +### TypeDialog Environment Variables + +You can customize TypeDialog behavior with environment variables: + +```bash +# Web server configuration +export TYPEDIALOG_PORT=9000 # Port for web backend (default: 9000) +export TYPEDIALOG_HOST=localhost # Host binding (default: localhost) + +# Localization +export TYPEDIALOG_LANG=en_US.UTF-8 # Form language (default: system locale) + +# Run with custom settings +TYPEDIALOG_PORT=8080 .typedialog/ci/configure.sh web +``` + +**Common use cases:** + +```bash +# Access from other machines in network +TYPEDIALOG_HOST=0.0.0.0 TYPEDIALOG_PORT=8080 .typedialog/ci/configure.sh web + +# Use different port if 9000 is busy +TYPEDIALOG_PORT=3000 .typedialog/ci/configure.sh web + +# Spanish interface +TYPEDIALOG_LANG=es_ES.UTF-8 .typedialog/ci/configure.sh web +``` + +## Configuration Structure + +Your config.ncl is organized in the `ci` namespace (Nickel format): + +```nickel +{ + ci = { + project = { + name = "rust", + detected_languages = ["rust, markdown"], + primary_language = "rust", + }, + tools = { + # Tools are added based on detected languages + }, + features = { + # CI features (pre-commit, GitHub Actions, etc.) + }, + ci_providers = { + # CI provider configurations + }, + }, +} +``` + +## Available Fragments + +Tool configurations are modular. Check `.typedialog/ci/fragments/` for: + +- rust-tools.toml - Tools for rust +- markdown-tools.toml - Tools for markdown +- general-tools.toml - Cross-language tools +- ci-providers.toml - GitHub Actions, Woodpecker, etc. + +## Cascading Override System + +This project uses a **local β†’ Tools cascading search** for all resources: + +### How It Works + +Resources are searched in priority order: + +1. **Local files** (`.typedialog/ci/`) - **FIRST** (highest priority) +2. **Tools files** (`$TOOLS_PATH/dev-system/ci/`) - **FALLBACK** (default) + +### Affected Resources + +| Resource | Local Path | Tools Path | +|----------|------------|------------| +| Fragments | `.typedialog/ci/fragments/` | `$TOOLS_PATH/dev-system/ci/forms/fragments/` | +| Schemas | `.typedialog/ci/schemas/` | `$TOOLS_PATH/dev-system/ci/schemas/` | +| Validators | `.typedialog/ci/validators/` | `$TOOLS_PATH/dev-system/ci/validators/` | +| Defaults | `.typedialog/ci/defaults/` | `$TOOLS_PATH/dev-system/ci/defaults/` | +| Nickel Template | `.typedialog/ci/config.ncl.j2` | `$TOOLS_PATH/dev-system/ci/templates/config.ncl.j2` | + +### Environment Setup (.envrc) + +The `.typedialog/ci/.envrc` file configures search paths: + +```bash +# Source this file to load environment +source .typedialog/ci/.envrc + +# Or use direnv for automatic loading +echo 'source .typedialog/ci/.envrc' >> .envrc +``` + +**What's in .envrc:** + +```bash +export NICKEL_IMPORT_PATH="schemas:$TOOLS_PATH/dev-system/ci/schemas:validators:..." +export TYPEDIALOG_FRAGMENT_PATH=".:$TOOLS_PATH/dev-system/ci/forms" +export NCL_TEMPLATE="" +export TYPEDIALOG_PORT=9000 # Web server port +export TYPEDIALOG_HOST=localhost # Web server host +export TYPEDIALOG_LANG="${LANG}" # Form localization +``` + +### Creating Overrides + +**By default:** All resources come from Tools (no duplication). + +**To customize:** Create file in local directory with same name: + +```bash +# Override a fragment +cp $TOOLS_PATH/dev-system/ci/fragments/rust-tools.toml \ + .typedialog/ci/fragments/rust-tools.toml + +# Edit your local version +vim .typedialog/ci/fragments/rust-tools.toml + +# Override Nickel template (customize comments, structure, nickel doc output) +cp $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 \ + .typedialog/ci/config.ncl.j2 + +# Edit to customize documentation and structure +vim .typedialog/ci/config.ncl.j2 + +# Now your version will be used instead of Tools version +``` + +**Benefits:** + +- βœ… Override only what you need +- βœ… Everything else stays synchronized with Tools +- βœ… No duplication by default +- βœ… Automatic updates when Tools is updated + +**See:** `$TOOLS_PATH/dev-system/ci/docs/cascade-override.md` for complete documentation. + +## Testing Your Configuration + +### Validate Configuration + +```bash +nu $env.TOOLS_PATH/dev-system/ci/scripts/validator.nu \ + --config .typedialog/ci/config.ncl \ + --project . \ + --namespace ci +``` + +### Regenerate CI Files + +```bash +nu $env.TOOLS_PATH/dev-system/ci/scripts/generate-configs.nu \ + --config .typedialog/ci/config.ncl \ + --templates $env.TOOLS_PATH/dev-system/ci/templates \ + --output . \ + --namespace ci +``` + +## Common Tasks + +### Add a New Tool + +Edit `config.ncl` and add under `ci.tools`: + +```nickel +{ + ci = { + tools = { + newtool = { + enabled = true, + install_method = "cargo", + version = "latest", + }, + }, + }, +} +``` + +### Disable a Feature + +```toml +[ci.features] +enable_pre_commit = false +``` + +## Need Help? + +For detailed documentation, see: +- $env.TOOLS_PATH/dev-system/ci/docs/configuration-guide.md +- $env.TOOLS_PATH/dev-system/ci/docs/installation-guide.md diff --git a/.typedialog/ci/config.ncl b/.typedialog/ci/config.ncl new file mode 100644 index 0000000..7f5d04e --- /dev/null +++ b/.typedialog/ci/config.ncl @@ -0,0 +1,120 @@ +# CI Configuration - Nickel Format +# Auto-generated by dev-system CI installer +# +# This file is managed by TypeDialog using nickel-roundtrip. +# Edit via: .typedialog/ci/configure.sh +# Or manually edit and validate with: nickel typecheck config.ncl +# +# Documentation: nickel doc config.ncl + +{ + # CI namespace - all configuration lives under 'ci' + ci = { + # Project Information + # Detected languages and primary language for this project + project = { + # Project name + name = "knowledge-base", + # Project description + description = "knowledge-base", + # Project website or documentation site URL + site_url = "https://repo.jesusperez.pro/jesus/kogral", + # Project repository URL (GitHub, GitLab, etc.) + repo_url = "https://repo.jesusperez.pro/jesus/kogral", + # Languages detected in codebase (auto-detected by installer) + detected_languages = [ + "rust", + "markdown" + ], + # Primary language (determines default tooling) + primary_language = "rust", + }, + + # CI Tools Configuration + # Each tool can be enabled/disabled and configured here + tools = { + # Taplo - TOML formatter and linter + taplo = { + enabled = true, + install_method = "cargo", + }, + # YAMLlint - YAML formatter and linter + yamllint = { + enabled = true, + install_method = "pip", + }, + # Clippy - Rust linting tool + clippy = { + enabled = true, + install_method = "cargo", + deny_warnings = true, + }, + # Cargo Audit - Security vulnerability scanner + audit = { + enabled = true, + install_method = "cargo", + }, + # Cargo Deny - Dependency checker + deny = { + enabled = true, + install_method = "cargo", + }, + # Cargo SBOM - Software Bill of Materials + sbom = { + enabled = true, + install_method = "cargo", + }, + # LLVM Coverage - Code coverage tool + llvm-cov = { + enabled = true, + install_method = "cargo", + }, + # Markdownlint - Markdown linter + markdownlint = { + enabled = true, + install_method = "npm", + }, + # Vale - Prose linter + vale = { + enabled = true, + install_method = "brew", + }, + }, + + # CI Features + # High-level feature flags for CI behavior + features = { + enable_ci_cd = true, + enable_pre_commit = true, + generate_taplo_config = true, + generate_contributing = true, + generate_security = true, + generate_code_of_conduct = true, + generate_dockerfiles = true, + enable_cross_compilation = true, + }, + + # CI Provider Configurations + # Settings for GitHub Actions, Woodpecker, GitLab CI, etc. + ci_providers = { + # GitHub Actions + github_actions = { + enabled = true, + branches_push = "main,develop", + branches_pr = "main", + }, + # Woodpecker CI + woodpecker = { + enabled = true, + }, + }, + + # CI Settings + settings = { + parallel_jobs = 1, + job_timeout_minutes = 1, + require_status_checks = true, + run_on_draft_prs = true, + }, + }, +} diff --git a/.typedialog/ci/config.ncl.20260117_193849.bak b/.typedialog/ci/config.ncl.20260117_193849.bak new file mode 100644 index 0000000..72b2ecf --- /dev/null +++ b/.typedialog/ci/config.ncl.20260117_193849.bak @@ -0,0 +1,203 @@ +# CI Configuration - Nickel Format +# Auto-generated by dev-system CI installer +# +# This file is managed by TypeDialog using nickel-roundtrip. +# Edit via: .typedialog/ci/configure.sh +# Or manually edit and validate with: nickel typecheck config.ncl +# +# Documentation: nickel doc config.ncl + +{ + # CI namespace - all configuration lives under 'ci' + ci = { + # Project Information + # Detected languages and primary language for this project + project = { + # Project name + name = "", + # Project description + description = "", + # Project website or documentation site URL + site_url = "", + # Project repository URL (GitHub, GitLab, etc.) + repo_url = "", + # Languages detected in codebase (auto-detected by installer) + detected_languages = [ + "rust", + "markdown", + "nickel" + ], + # Primary language (determines default tooling) + primary_language = "rust", + }, + + # CI Tools Configuration + # Each tool can be enabled/disabled and configured here + tools = { + # Taplo - TOML formatter and linter + taplo = { + enabled = true, + install_method = "cargo", + }, + # YAMLlint - YAML formatter and linter + yamllint = { + enabled = true, + install_method = "pip", + }, + # Clippy - Rust linting tool + clippy = { + enabled = true, + install_method = "cargo", + deny_warnings = true, + }, + # Cargo Audit - Security vulnerability scanner + audit = { + enabled = true, + install_method = "cargo", + }, + # Cargo Deny - Dependency checker + deny = { + enabled = true, + install_method = "cargo", + }, + # Cargo SBOM - Software Bill of Materials + sbom = { + enabled = true, + install_method = "cargo", + }, + # LLVM Coverage - Code coverage tool + llvm-cov = { + enabled = true, + install_method = "cargo", + }, + # Shellcheck - Bash/shell script linter + shellcheck = { + enabled = true, + install_method = "brew", + }, + # Shfmt - Shell script formatter + shfmt = { + enabled = true, + install_method = "brew", + }, + # Markdownlint - Markdown linter + markdownlint = { + enabled = true, + install_method = "npm", + }, + # Vale - Prose linter + vale = { + enabled = true, + install_method = "brew", + }, + # Nickel - Configuration language type checker + nickel = { + enabled = true, + install_method = "brew", + check_all = true, + }, + # NuShell - Shell script validator + nushell = { + enabled = true, + install_method = "builtin", + check_all = true, + }, + # Ruff - Fast Python linter + ruff = { + enabled = true, + install_method = "pip", + }, + # Black - Python code formatter + black = { + enabled = true, + install_method = "pip", + }, + # Mypy - Python static type checker + mypy = { + enabled = false, + install_method = "pip", + }, + # Pytest - Python testing framework + pytest = { + enabled = true, + install_method = "pip", + }, + # Golangci-lint - Go linter aggregator + "golangci-lint" = { + enabled = true, + install_method = "brew", + }, + # Gofmt - Go code formatter + gofmt = { + enabled = true, + install_method = "builtin", + }, + # Staticcheck - Go static analysis + staticcheck = { + enabled = true, + install_method = "brew", + }, + # Gosec - Go security checker + gosec = { + enabled = false, + install_method = "brew", + }, + # ESLint - JavaScript linter + eslint = { + enabled = true, + install_method = "npm", + }, + # Prettier - Code formatter + prettier = { + enabled = true, + install_method = "npm", + }, + # TypeScript - Type checking + typescript = { + enabled = false, + install_method = "npm", + }, + # Jest - JavaScript testing framework + jest = { + enabled = true, + install_method = "npm", + }, + }, + + # CI Features + # High-level feature flags for CI behavior + features = { + enable_ci_cd = true, + enable_pre_commit = true, + generate_taplo_config = true, + generate_contributing = true, + generate_security = true, + generate_code_of_conduct = true, + generate_dockerfiles = true, + enable_cross_compilation = true, + }, + + # CI Provider Configurations + # Settings for GitHub Actions, Woodpecker, GitLab CI, etc. + ci_providers = { + # GitHub Actions + github_actions = { + enabled = true, + branches_push = "main,develop", + branches_pr = "main", + }, + # Woodpecker CI + woodpecker = { + enabled = true, + }, + }, + + # CI Settings + settings = { + parallel_jobs = 1, + job_timeout_minutes = 1, + require_status_checks = true, + run_on_draft_prs = true, + }, + }, +} diff --git a/.typedialog/ci/configure.sh b/.typedialog/ci/configure.sh new file mode 100755 index 0000000..28cf7c8 --- /dev/null +++ b/.typedialog/ci/configure.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# CI Configuration Script +# Auto-generated by dev-system/ci installer +# +# Interactive configuration for CI tools using TypeDialog. +# Uses Nickel format for configuration files. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TYPEDIALOG_CI="${SCRIPT_DIR}" + +# Source envrc to load fragment paths and other environment variables +if [[ -f "${TYPEDIALOG_CI}/envrc" ]]; then + # shellcheck source=/dev/null + source "${TYPEDIALOG_CI}/envrc" +fi + +# Configuration files +FORM_FILE="${TYPEDIALOG_CI}/form.toml" +CONFIG_FILE="${TYPEDIALOG_CI}/config.ncl" + +# NCL_TEMPLATE is set by envrc (cascading: local β†’ Tools) +# If not set, use default from Tools +NCL_TEMPLATE="${NCL_TEMPLATE:-${TOOLS_PATH}/dev-system/ci/templates/config.ncl.j2}" + +# TypeDialog environment variables (can be overridden) +# Port for web backend (default: 9000) +export TYPEDIALOG_PORT="${TYPEDIALOG_PORT:-9000}" + +# Host for web backend (default: localhost) +export TYPEDIALOG_HOST="${TYPEDIALOG_HOST:-localhost}" + +# Locale for form localization (default: system locale) +export TYPEDIALOG_LANG="${TYPEDIALOG_LANG:-${LANG:-en_US.UTF-8}}" + +# Detect which TypeDialog backend to use (default: web) +BACKEND="${1:-web}" + +# Validate backend +case "$BACKEND" in + cli|tui|web) + ;; + *) + echo "Usage: $0 [cli|tui|web]" + echo "" + echo "Launches TypeDialog for interactive CI configuration." + echo "Backend options:" + echo " cli - Command-line interface (simple prompts)" + echo " tui - Terminal UI (interactive panels)" + echo " web - Web server (browser-based) [default]" + exit 1 + ;; +esac + +# Check if form exists +if [[ ! -f "$FORM_FILE" ]]; then + echo "Error: Form file not found: $FORM_FILE" + exit 1 +fi + +# Create backup if config exists +if [[ -f "$CONFIG_FILE" ]]; then + BACKUP="${CONFIG_FILE}.$(date +%Y%m%d_%H%M%S).bak" + cp "$CONFIG_FILE" "$BACKUP" + echo "ℹ️ Backed up existing config to: $(basename "$BACKUP")" +fi + +# Launch TypeDialog with Nickel roundtrip (preserves Nickel format) +echo "πŸ”§ Launching TypeDialog ($BACKEND backend)..." +echo "" + +# Show web server info if using web backend +if [[ "$BACKEND" == "web" ]]; then + echo "🌐 Web server will start on: http://${TYPEDIALOG_HOST}:${TYPEDIALOG_PORT}" + echo " (Override with: TYPEDIALOG_PORT=8080 TYPEDIALOG_HOST=0.0.0.0 $0)" + echo "" +fi + +# Build nickel-roundtrip command with optional template +NCL_TEMPLATE_ARG="" +if [[ -f "$NCL_TEMPLATE" ]]; then + NCL_TEMPLATE_ARG="--ncl-template $NCL_TEMPLATE" + echo "ℹ️ Using Nickel template: $NCL_TEMPLATE" +fi + +case "$BACKEND" in + cli) + typedialog nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" $NCL_TEMPLATE_ARG + ;; + tui) + typedialog-tui nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" $NCL_TEMPLATE_ARG + ;; + web) + typedialog-web nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" $NCL_TEMPLATE_ARG + ;; +esac + +EXIT_CODE=$? + +if [[ $EXIT_CODE -eq 0 ]]; then + echo "" + echo "βœ… Configuration saved to: $CONFIG_FILE" + echo "" + echo "Next steps:" + echo " - Review the configuration: cat $CONFIG_FILE" + echo " - Apply CI tools: (run your CI setup command)" + echo " - Re-run this script anytime to update: $0" +else + echo "" + echo "❌ Configuration cancelled or failed (exit code: $EXIT_CODE)" + if [[ -f "${CONFIG_FILE}.bak" ]]; then + echo " Previous config restored from backup" + fi + exit $EXIT_CODE +fi diff --git a/.typedialog/ci/envrc b/.typedialog/ci/envrc new file mode 100644 index 0000000..4c00a1b --- /dev/null +++ b/.typedialog/ci/envrc @@ -0,0 +1,27 @@ +# Auto-generated by dev-system/ci +# +# Cascading Path Strategy: +# 1. Local files in .typedialog/ci/ take precedence (overrides) +# 2. Central files in $TOOLS_PATH/dev-system/ci/ as fallback (defaults) +# +# To customize: Create file in .typedialog/ci/{schemas,validators,defaults,fragments}/ +# Your local version will be used instead of the Tools version. + +# Nickel import paths (cascading: local β†’ Tools) +export NICKEL_IMPORT_PATH="schemas:$TOOLS_PATH/dev-system/ci/schemas:validators:$TOOLS_PATH/dev-system/ci/validators:defaults:$TOOLS_PATH/dev-system/ci/defaults" + +# TypeDialog fragment search paths (cascading: local β†’ Tools) +export TYPEDIALOG_FRAGMENT_PATH=".typedialog/ci:$TOOLS_PATH/dev-system/ci/forms" + +# Nickel template for config.ncl generation (with cascading) +# Local template takes precedence if exists +if [[ -f ".typedialog/ci/config.ncl.j2" ]]; then + export NCL_TEMPLATE=".typedialog/ci/config.ncl.j2" +else + export NCL_TEMPLATE="$TOOLS_PATH/dev-system/ci/templates/config.ncl.j2" +fi + +# TypeDialog web backend configuration (override if needed) +export TYPEDIALOG_PORT=${TYPEDIALOG_PORT:-9000} +export TYPEDIALOG_HOST=${TYPEDIALOG_HOST:-localhost} +export TYPEDIALOG_LANG=${TYPEDIALOG_LANG:-${LANG:-en_US.UTF-8}} diff --git a/.typedialog/ci/form.toml b/.typedialog/ci/form.toml new file mode 100644 index 0000000..91d80cb --- /dev/null +++ b/.typedialog/ci/form.toml @@ -0,0 +1,189 @@ +description = "Interactive configuration for continuous integration and code quality tools" +display_mode = "complete" +locales_path = "" +name = "CI Configuration Form" + +[[elements]] +border_bottom = true +border_top = true +name = "project_header" +title = "πŸ“¦ Project Information" +type = "section_header" + +[[elements]] +help = "Name of the project" +name = "project_name" +nickel_path = [ + "ci", + "project", + "name", +] +placeholder = "my-project" +prompt = "Project name" +required = true +type = "text" + +[[elements]] +help = "Optional description" +name = "project_description" +nickel_path = [ + "ci", + "project", + "description", +] +placeholder = "Brief description of what this project does" +prompt = "Project description" +required = false +type = "text" + +[[elements]] +default = "" +help = "Project website or documentation site URL" +name = "project_site_url" +nickel_path = [ + "ci", + "project", + "site_url", +] +placeholder = "https://example.com" +prompt = "Project Site URL" +required = false +type = "text" + +[[elements]] +default = "" +help = "Project repository URL (GitHub, GitLab, etc.)" +name = "project_repo_url" +nickel_path = [ + "ci", + "project", + "repo_url", +] +placeholder = "https://github.com/user/repo" +prompt = "Project Repo URL" +required = false +type = "text" + +[[elements]] +border_bottom = true +border_top = true +name = "languages_header" +title = "πŸ” Detected Languages" +type = "section_header" + +[[elements]] +default = "rust" +display_mode = "grid" +help = "Select all languages detected or used in the project" +min_selected = 1 +name = "detected_languages" +nickel_path = [ + "ci", + "project", + "detected_languages", +] +prompt = "Which languages are used in this project?" +required = true +searchable = true +type = "multiselect" + +[[elements.options]] +value = "rust" +label = "πŸ¦€ Rust" + +[[elements.options]] +value = "markdown" +label = "πŸ“ Markdown/Documentation" + +[[elements]] +help = "Main language used for defaults (e.g., in GitHub Actions workflows)" +name = "primary_language" +nickel_path = [ + "ci", + "project", + "primary_language", +] +options_from = "detected_languages" +prompt = "Primary language" +required = true +type = "select" +default = "rust" + +[[elements.options]] +value = "rust" +label = "πŸ¦€ Rust" + +[[elements.options]] +value = "markdown" +label = "πŸ“ Markdown" + +[[elements]] +includes = ["fragments/rust-tools.toml"] +name = "rust_tools_group" +type = "group" +when = "rust in detected_languages" + +[[elements]] +includes = ["fragments/markdown-tools.toml"] +name = "markdown_tools_group" +type = "group" +when = "markdown in detected_languages" + +[[elements]] +includes = ["fragments/general-tools.toml"] +name = "general_tools_group" +type = "group" + +[[elements]] +border_bottom = true +border_top = true +name = "ci_cd_header" +title = "πŸ”„ CI/CD Configuration" +type = "section_header" + +[[elements]] +default = "true" +help = "Set up continuous integration and deployment pipelines" +name = "enable_ci_cd" +nickel_path = [ + "ci", + "features", + "enable_ci_cd", +] +prompt = "Enable CI/CD integration?" +type = "confirm" + +[[elements]] +includes = ["fragments/ci-providers.toml"] +name = "ci_providers_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/ci-settings.toml"] +name = "ci_settings_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/build-deployment.toml"] +name = "build_deployment_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/documentation.toml"] +name = "documentation_group" +type = "group" + +[[elements]] +border_bottom = true +border_top = true +name = "confirmation_header" +title = "βœ… Ready to Install" +type = "section_header" + +[[elements]] +content = "Review your configuration above. After confirming, the CI system will be installed with your chosen settings." +name = "confirmation_footer" +type = "footer" diff --git a/.typedialog/kogral/ARCHITECTURE.md b/.typedialog/kogral/ARCHITECTURE.md new file mode 100644 index 0000000..478ffdf --- /dev/null +++ b/.typedialog/kogral/ARCHITECTURE.md @@ -0,0 +1,290 @@ +# KOGRAL Configuration Architecture + +Complete reference showing how form fragments, templates, and Nickel schemas work together. + +## Three-Tier Configuration Pipeline + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ USER INTERACTION LAYER β”‚ +β”‚ typedialog-web UI (interactive configuration) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FORM LAYER (forms/) β”‚ +β”‚ - kogral-config.toml (composes fragments) β”‚ +β”‚ - fragments/*.toml (field definitions with nickel_path) β”‚ +β”‚ β”œβ”€ graph.toml [nickel_path: ["graph", ...]] β”‚ +β”‚ β”œβ”€ storage.toml [nickel_path: ["storage", ...]] β”‚ +β”‚ β”œβ”€ embeddings.toml [nickel_path: ["embeddings", ...]] +β”‚ β”œβ”€ query.toml [nickel_path: ["query", ...]] β”‚ +β”‚ β”œβ”€ mcp.toml [nickel_path: ["mcp", ...]] β”‚ +β”‚ └─ sync.toml [nickel_path: ["sync", ...]] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + typedialog-web writes changes to .ncl files + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ NICKEL LAYER (core/ + modes/) β”‚ +β”‚ β”‚ +β”‚ core/contracts.ncl (type definitions) β”‚ +β”‚ β”œβ”€ GraphConfig { name, version, description } β”‚ +β”‚ β”œβ”€ StorageConfig { primary, secondary } β”‚ +β”‚ β”œβ”€ EmbeddingConfig { enabled, provider, model, ... } β”‚ +β”‚ β”œβ”€ QueryConfig { similarity_threshold, max_results, ... } β”‚ +β”‚ β”œβ”€ McpConfig { server, tools, resources } β”‚ +β”‚ └─ SyncConfig { auto_index, watch_paths, debounce_ms } β”‚ +β”‚ β”‚ +β”‚ core/defaults.ncl (base values for all environments) β”‚ +β”‚ └─ base = { graph, storage, embeddings, query, mcp, sync } β”‚ +β”‚ β”‚ +β”‚ modes/dev.ncl (override specific values for dev) β”‚ +β”‚ modes/prod.ncl (override specific values for production) β”‚ +β”‚ modes/test.ncl (override specific values for testing) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + nickel export --format json + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ TEMPLATE LAYER (templates/) β”‚ +β”‚ β”‚ +β”‚ config.json.tera (Tera template) β”‚ +β”‚ - {{ graph.name }} ← renders from Nickel export β”‚ +β”‚ - {{ storage.primary }} β”‚ +β”‚ - {{ embeddings.enabled }} β”‚ +β”‚ - {{ query.similarity_threshold }} β”‚ +β”‚ - {{ mcp.tools.search }} β”‚ +β”‚ - {{ sync.auto_index }} β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + just nickel::generate-config dev + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ JSON OUTPUT (.kogral/config.json) β”‚ +β”‚ β”‚ +β”‚ { β”‚ +β”‚ "graph": { "name": "...", "version": "...", ... }, β”‚ +β”‚ "storage": { "primary": "filesystem", ... }, β”‚ +β”‚ "embeddings": { "enabled": true, "provider": "fastembed" }, β”‚ +β”‚ "query": { "similarity_threshold": 0.4, ... }, β”‚ +β”‚ "mcp": { "server": {...}, "tools": {...}, ... }, β”‚ +β”‚ "sync": { "auto_index": true, ... } β”‚ +β”‚ } β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + Rust Deserialization + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ RUST LAYER (crates/kogral-core/) β”‚ +β”‚ β”‚ +β”‚ KbConfig struct (serde deserialization) β”‚ +β”‚ β”œβ”€ graph: GraphConfig β”‚ +β”‚ β”œβ”€ storage: StorageConfig β”‚ +β”‚ β”œβ”€ embeddings: EmbeddingConfig β”‚ +β”‚ β”œβ”€ query: QueryConfig β”‚ +β”‚ β”œβ”€ mcp: McpConfig β”‚ +β”‚ └─ sync: SyncConfig β”‚ +β”‚ β”‚ +β”‚ Runtime Usage: β”‚ +β”‚ if config.embeddings.enabled { ... } β”‚ +β”‚ create_storage(&config.storage)? β”‚ +β”‚ initialize_mcp(&config.mcp) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Field Synchronization Example + +### Storage Configuration + +User edits "Primary Storage" field in form: + +``` +FORM FRAGMENT (forms/fragments/storage.toml) +────────────────────────────────────────── +[[elements]] +name = "storage_primary" +nickel_path = ["storage", "primary"] +type = "select" +options = ["filesystem", "memory", "surrealdb"] +default = "filesystem" + ↓ typedialog-web writes to ↓ + +NICKEL CONTRACT (core/contracts.ncl) +──────────────────────────────────── +StorageConfig = { + primary | StorageType + | doc "Primary storage backend" + | default = 'filesystem, +} + ↓ user modifies, nickel export ↓ + +NICKEL MODE (modes/dev.ncl) +─────────────────────────── +{ + storage = { + primary = 'filesystem, # ← User changed to 'surrealdb + } +} + ↓ export renders ↓ + +TERA TEMPLATE (templates/config.json.tera) +────────────────────────────────────────── +{ + "storage": { + "primary": "{{ storage.primary }}" # renders: "surrealdb" + } +} + ↓ generates ↓ + +JSON OUTPUT (.kogral/config.json) +───────────────────────────────── +{ + "storage": { + "primary": "surrealdb" + } +} + ↓ Rust deserializes ↓ + +RUST CODE (crates/kogral-core/src/config.rs) +───────────────────────────────────────────── +pub struct StorageConfig { + pub primary: StorageType, // enum: Filesystem | Memory | SurrealDB + ... +} + +// Usage +match config.storage.primary { + StorageType::SurrealDB => create_surrealdb_storage()?, + StorageType::Filesystem => create_filesystem_storage()?, + ... +} +``` + +## Component Relationships + +``` +Form Fragments ←→ Nickel Contracts + ↓ ↓ + └─→ Tera Template β†β”˜ + ↓ + JSON Output + ↓ + Rust Struct +``` + +### Consistency Rules + +1. **Fragment β†’ Nickel**: Every `nickel_path` must have corresponding type in contracts +2. **Nickel β†’ Template**: Every Nickel field must have corresponding Tera variable +3. **Template β†’ JSON**: Every Tera variable must render valid JSON +4. **JSON β†’ Rust**: Every JSON field must deserialize to KbConfig + +## Validation Pipeline + +``` +User edits form + ↓ +typedialog-web validates against fragment constraints + ↓ +Writes to .ncl files + ↓ +just nickel::validate-config + β”œβ”€β†’ Nickel typechecks contracts + └─→ Exports to JSON + ↓ +just nickel::generate-config + β”œβ”€β†’ Tera renders template + └─→ Produces .kogral/config.json + ↓ +Rust deserializes KbConfig + β”œβ”€β†’ Serde validates JSON structure + └─→ Type mismatch = compile error +``` + +## Adding a New Configuration Field + +To add a new field (e.g., logging level): + +### 1. Add to Nickel Contract + +```nickel +# core/contracts.ncl +LoggingConfig = { + level | [| 'debug, 'info, 'warn, 'error |] + | doc "Logging verbosity level" + | default = 'info, +} + +KbConfig = { + ... + logging | LoggingConfig, + ... +} +``` + +### 2. Add Default Value + +```nickel +# core/defaults.ncl +logging = { + level = 'info, +} +``` + +### 3. Create Form Fragment + +```toml +# forms/fragments/logging.toml +[[elements]] +name = "logging_section_header" +title = "πŸ“ Logging" +type = "section_header" + +[[elements]] +name = "logging_level" +nickel_path = ["logging", "level"] +type = "select" +options = ["debug", "info", "warn", "error"] +default = "info" +prompt = "Log Level" +help = "Logging verbosity level" +``` + +### 4. Add to Main Form + +```toml +# forms/kogral-config.toml +[[items]] +includes = ["fragments/logging.toml"] +name = "logging_group" +title = "Logging" +type = "group" +``` + +### 5. Update Template + +```tera +# templates/config.json.tera +"logging": { + "level": "{{ logging.level }}" +} +``` + +### 6. Verify + +```bash +just nickel::validate-config # Contracts valid? +just nickel::export-modes # JSON valid? +just nickel::generate-config dev # Config generates? +``` + +## Integration Checklist + +- [ ] Fragment defines field with `nickel_path` +- [ ] Contract defines type for that path +- [ ] Default provides value +- [ ] Template has corresponding Tera variable +- [ ] Mode overlays include any environment-specific values +- [ ] Validation passes +- [ ] JSON output contains field +- [ ] Rust struct deserializes successfully diff --git a/.typedialog/kogral/FORM-TO-TEMPLATE-MAPPING.md b/.typedialog/kogral/FORM-TO-TEMPLATE-MAPPING.md new file mode 100644 index 0000000..54f81a5 --- /dev/null +++ b/.typedialog/kogral/FORM-TO-TEMPLATE-MAPPING.md @@ -0,0 +1,156 @@ +# Form β†’ Template β†’ Nickel Mapping + +This document shows how form fields (`nickel_path`), Tera template variables, and Nickel contracts are synchronized across the three-layer configuration system. + +## Pattern Overview + +``` +Form Fragment (forms/fragments/*.toml) + nickel_path = ["section", "field"] + ↓ +Tera Template (templates/config.json.tera) + {{ section.field }} + ↓ +Nickel Contracts (core/contracts.ncl) + SectionConfig = { field | Type } +``` + +## Complete Mapping + +### Graph Configuration + +| Fragment | nickel_path | Tera Variable | Contract | Type | +|----------|------------|---------------|----------|------| +| graph.toml | `["graph", "name"]` | `{{ graph.name }}` | GraphConfig.name | String | +| graph.toml | `["graph", "version"]` | `{{ graph.version }}` | GraphConfig.version | String | +| graph.toml | `["graph", "description"]` | `{{ graph.description }}` | GraphConfig.description | String | + +### Storage Configuration + +| Fragment | nickel_path | Tera Variable | Contract | Type | +|----------|------------|---------------|----------|------| +| storage.toml | `["storage", "primary"]` | `{{ storage.primary }}` | StorageConfig.primary | StorageType | +| storage.toml | `["storage", "secondary", "enabled"]` | `{{ storage.secondary.enabled }}` | SecondaryStorageConfig.enabled | Bool | +| storage.toml | `["storage", "secondary", "type"]` | `{{ storage.secondary.type }}` | SecondaryStorageConfig.type | [surrealdb, sqlite] | +| storage.toml | `["storage", "secondary", "url"]` | `{{ storage.secondary.url }}` | SecondaryStorageConfig.url | String | +| storage.toml | `["storage", "secondary", "namespace"]` | `{{ storage.secondary.namespace }}` | SecondaryStorageConfig.namespace | String | +| storage.toml | `["storage", "secondary", "database"]` | `{{ storage.secondary.database }}` | SecondaryStorageConfig.database | String | + +### Embeddings Configuration + +| Fragment | nickel_path | Tera Variable | Contract | Type | +|----------|------------|---------------|----------|------| +| embeddings.toml | `["embeddings", "enabled"]` | `{{ embeddings.enabled }}` | EmbeddingConfig.enabled | Bool | +| embeddings.toml | `["embeddings", "provider"]` | `{{ embeddings.provider }}` | EmbeddingConfig.provider | EmbeddingProviderType | +| embeddings.toml | `["embeddings", "model"]` | `{{ embeddings.model }}` | EmbeddingConfig.model | String | +| embeddings.toml | `["embeddings", "dimensions"]` | `{{ embeddings.dimensions }}` | EmbeddingConfig.dimensions | Number | +| embeddings.toml | `["embeddings", "api_key_env"]` | `{{ embeddings.api_key_env }}` | EmbeddingConfig.api_key_env | String | + +### Query Configuration + +| Fragment | nickel_path | Tera Variable | Contract | Type | +|----------|------------|---------------|----------|------| +| query.toml | `["query", "similarity_threshold"]` | `{{ query.similarity_threshold }}` | QueryConfig.similarity_threshold | Number | +| query.toml | `["query", "max_results"]` | `{{ query.max_results }}` | QueryConfig.max_results | Number | +| query.toml | `["query", "recency_weight"]` | `{{ query.recency_weight }}` | QueryConfig.recency_weight | Number | +| query.toml | `["query", "cross_graph"]` | `{{ query.cross_graph }}` | QueryConfig.cross_graph | Bool | + +### MCP Configuration + +| Fragment | nickel_path | Tera Variable | Contract | Type | +|----------|------------|---------------|----------|------| +| mcp.toml | `["mcp", "server", "name"]` | `{{ mcp.server.name }}` | McpServerConfig.name | String | +| mcp.toml | `["mcp", "server", "version"]` | `{{ mcp.server.version }}` | McpServerConfig.version | String | +| mcp.toml | `["mcp", "server", "transport"]` | `{{ mcp.server.transport }}` | McpServerConfig.transport | [stdio, sse] | +| mcp.toml | `["mcp", "tools", "search"]` | `{{ mcp.tools.search }}` | McpToolsConfig.search | Bool | +| mcp.toml | `["mcp", "tools", "add_note"]` | `{{ mcp.tools.add_note }}` | McpToolsConfig.add_note | Bool | +| mcp.toml | `["mcp", "tools", "add_decision"]` | `{{ mcp.tools.add_decision }}` | McpToolsConfig.add_decision | Bool | +| mcp.toml | `["mcp", "tools", "link"]` | `{{ mcp.tools.link }}` | McpToolsConfig.link | Bool | +| mcp.toml | `["mcp", "tools", "get_guidelines"]` | `{{ mcp.tools.get_guidelines }}` | McpToolsConfig.get_guidelines | Bool | +| mcp.toml | `["mcp", "tools", "export"]` | `{{ mcp.tools.export }}` | McpToolsConfig.export | Bool | +| mcp.toml | `["mcp", "resources", "expose_project"]` | `{{ mcp.resources.expose_project }}` | McpResourcesConfig.expose_project | Bool | +| mcp.toml | `["mcp", "resources", "expose_shared"]` | `{{ mcp.resources.expose_shared }}` | McpResourcesConfig.expose_shared | Bool | + +### Sync Configuration + +| Fragment | nickel_path | Tera Variable | Contract | Type | +|----------|------------|---------------|----------|------| +| sync.toml | `["sync", "auto_index"]` | `{{ sync.auto_index }}` | SyncConfig.auto_index | Bool | +| sync.toml | `["sync", "watch_paths"]` | `{{ sync.watch_paths }}` | SyncConfig.watch_paths | Array String | +| sync.toml | `["sync", "debounce_ms"]` | `{{ sync.debounce_ms }}` | SyncConfig.debounce_ms | Number | + +## Data Flow Example + +### User edits form in typedialog-web: + +```toml +Field: "Primary Storage" +nickel_path = ["storage", "primary"] +User selects: "surrealdb" +``` + +### typedialog-web writes to Nickel: + +```nickel +storage = { + primary = 'surrealdb, + ... +} +``` + +### Script exports to JSON via template: + +```tera +{{ storage.primary }} # renders as: "surrealdb" +``` + +### Result in config.json: + +```json +{ + "storage": { + "primary": "surrealdb", + ... + } +} +``` + +### Rust loads from JSON: + +```rust +let config: KbConfig = serde_json::from_str(json)?; +// config.storage.primary == "surrealdb" +``` + +## Verification Steps + +When adding or modifying configuration: + +1. **Fragment** - Add field with `nickel_path` +2. **Template** - Add corresponding Tera variable +3. **Contract** - Add type definition in `core/contracts.ncl` +4. **Default** - Add default value in `core/defaults.ncl` +5. **Validate** - Run: `just nickel::validate-config` +6. **Export** - Run: `just nickel::export-modes` +7. **Verify** - Check `.kogral/config.*.json` contains new field + +## Conditional Visibility Example + +Form field with conditional rendering: + +```toml +[[elements]] +name = "storage_secondary_url" +nickel_path = ["storage", "secondary", "url"] +visible_if = "storage_secondary_enabled == true" +``` + +Template with conditional rendering: + +```tera +{% if storage.secondary.enabled %} +"url": "{{ storage.secondary.url }}" +{% endif %} +``` + +Both use the same condition pattern for consistency. diff --git a/.typedialog/kogral/README.md b/.typedialog/kogral/README.md new file mode 100644 index 0000000..1e08291 --- /dev/null +++ b/.typedialog/kogral/README.md @@ -0,0 +1,211 @@ +# KOGRAL Configuration Structure + +Central configuration hub for KOGRAL knowledge base system. + +## Directory Structure + +``` +.typedialog/kogral/ +β”œβ”€β”€ core/ # Core Nickel schemas (source of truth) +β”‚ β”œβ”€β”€ contracts.ncl # Type contracts and validation rules +β”‚ β”œβ”€β”€ defaults.ncl # Base default values +β”‚ └── helpers.ncl # Composition utilities (merge_with_override) +β”‚ +β”œβ”€β”€ modes/ # Environment-specific overrides +β”‚ β”œβ”€β”€ dev.ncl # Development mode (filesystem, fastembed, manual sync) +β”‚ β”œβ”€β”€ prod.ncl # Production mode (SurrealDB, OpenAI, auto-sync) +β”‚ └── test.ncl # Test mode (in-memory, no embeddings, isolated) +β”‚ +β”œβ”€β”€ forms/ # typedialog-web UI configuration (fragment composition) +β”‚ β”œβ”€β”€ kogral-config.toml # Main form definition (composes fragments) +β”‚ β”œβ”€β”€ README.md # Forms architecture documentation +β”‚ └── fragments/ # Reusable form fragments +β”‚ β”œβ”€β”€ graph.toml # Knowledge graph metadata +β”‚ β”œβ”€β”€ storage.toml # Storage backend options +β”‚ β”œβ”€β”€ embeddings.toml # Vector search provider +β”‚ β”œβ”€β”€ query.toml # Query engine tuning +β”‚ β”œβ”€β”€ mcp.toml # MCP server configuration +β”‚ └── sync.toml # Synchronization settings +β”‚ +β”œβ”€β”€ templates/ # Tera templates for rendering JSON +β”‚ └── config.json.tera # JSON template (maps to Nickel structure) +β”‚ +└── scripts/ # Configuration generation and validation scripts + β”œβ”€β”€ generate-configs.nu # Generate JSON config from Nickel modes + └── validate-config.nu # Validate all schemas +``` + +## Three-Layer Configuration System + +**Pattern**: Nickel Schemas β†’ Mode Overrides β†’ User Customization β†’ JSON β†’ Rust + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 1: Nickel Core (kogral/core/) β”‚ ← Type safety + validation +β”‚ - contracts.ncl (validation rules) β”‚ +β”‚ - defaults.ncl (base values) β”‚ +β”‚ - helpers.ncl (utilities) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Layer 2: Mode Overrides (kogral/modes/) β”‚ ← Environment-specific +β”‚ - dev.ncl (development) β”‚ +β”‚ - prod.ncl (production) β”‚ +β”‚ - test.ncl (testing) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Layer 3: User Customization β”‚ ← Project-level +β”‚ - .kogral-config/core/kogral.ncl β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ Generated by scripts/ ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Rendered Output (forms/ + templates/) β”‚ ← typedialog-web UI +β”‚ - JSON config β”‚ +β”‚ - TOML settings β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ Loaded by Rust ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Runtime Configuration β”‚ ← Deserialized + validated +β”‚ - KbConfig struct β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Components + +### 1. Core Schemas (Source of Truth) + +`core/contracts.ncl` - Type contracts and validation rules: +- Defines all fields with types and documentation +- Enforced by Nickel at export time +- Example: `version | doc "Schema version" = "1.0.0"` + +`core/defaults.ncl` - Base configuration values across all environments + +`core/helpers.ncl` - Utility functions (merge, compose, etc.) + +### 2. Mode Overrides (Environment-Specific) + +Each environment has specific requirements: + +- **dev.ncl** - Filesystem storage, local fastembed, manual sync +- **prod.ncl** - SurrealDB storage, OpenAI/Claude, auto-sync +- **test.ncl** - In-memory storage, no embeddings, isolated + +### 3. UI Forms (typedialog-web Integration) + +`forms/config.toml` - Interactive form definition: +- Defines UI fields for each configuration option +- Supports conditional visibility (visible_if) +- Enables roundtrip editing via typedialog-web + +### 4. Templates (Configuration Rendering) + +`templates/config.json.tera` - Tera template: +- Renders configuration to JSON format +- Supports conditional blocks for environment-specific values +- Can be extended for TOML, YAML, or other formats + +### 5. Configuration Scripts + +`scripts/generate-configs.nu` - Generate JSON from Nickel mode: +```bash +nu scripts/generate-configs.nu --mode dev --output .kogral +``` + +`scripts/validate-config.nu` - Validate all schemas: +```bash +nu scripts/validate-config.nu +``` + +## Form Fragment Architecture + +Forms use **fragment composition pattern** for modularity: + +``` +kogral-config.toml (main form) + └─ includes: fragments/graph.toml + └─ includes: fragments/storage.toml + └─ includes: fragments/embeddings.toml + └─ includes: fragments/query.toml + └─ includes: fragments/mcp.toml + └─ includes: fragments/sync.toml +``` + +Each fragment defines fields with: +- **nickel_path** - Path in Nickel config (e.g., `["storage", "primary"]`) +- **type** - Input control type (text, select, boolean, number, text_array) +- **visible_if** - Conditional visibility rules +- **default** - Default value + +See [FORM-TO-TEMPLATE-MAPPING.md](FORM-TO-TEMPLATE-MAPPING.md) for complete field mapping across: +- Form fragments (user input) +- Tera template (JSON rendering) +- Nickel contracts (type validation) + +## Double Validation + +1. **Nickel validation** - Type contracts enforced at export time +2. **Serde validation** - Rust deserialization in KbConfig struct + +## Usage + +### Validate Configuration + +```bash +nickel export --format json schemas/kogral/defaults.ncl +``` + +### Generate Modes + +```bash +# Development +nickel export --format json schemas/kogral/modes/dev.ncl > .kogral/config.dev.json + +# Production +nickel export --format json schemas/kogral/modes/prod.ncl > .kogral/config.prod.json +``` + +### Run Scripts + +All scripts in `scripts/` are production-ready automation: + +```bash +# Sync knowledge base +nu scripts/kogral-sync.nu + +# Reindex embeddings +nu scripts/kogral-reindex.nu --provider fastembed + +# Import from Logseq +nu scripts/kogral-import-logseq.nu ~/Logseq/mydb + +# Export to Logseq +nu scripts/kogral-export-logseq.nu ~/logseq-export + +# Migrate schema +nu scripts/kogral-migrate.nu --target latest +``` + +## Environment Variables + +Configuration system supports environment variables for resolution: + +- **TOOLS_PATH** - Base directory for shared tools (used by Nickel helper functions) +- **OPENAI_API_KEY** - OpenAI API credentials (embedding provider) +- **ANTHROPIC_API_KEY** - Claude API credentials (embedding provider) + +Export with custom TOOLS_PATH: + +```bash +TOOLS_PATH=/opt/mytools nickel export --format json schemas/kogral/defaults.ncl +``` + +## Integration with Codebase + +- **Core Library** (`crates/kogral-core/`) - Uses exported JSON config +- **CLI Binary** (`crates/kogral-cli/`) - Loads config from `.kogral/config.json` +- **MCP Server** (`crates/kogral-mcp/`) - Inherits config from core +- **Scripts** (`scripts/`) - May read config for behavior customization + +## See Also + +- [Schemas Documentation](../../schemas/) +- [Configuration Guide](../../docs/config/) +- [NuShell Scripts Reference](../../docs/cli/nushell-scripts.md) diff --git a/.typedialog/kogral/SYNC.md b/.typedialog/kogral/SYNC.md new file mode 100644 index 0000000..4087033 --- /dev/null +++ b/.typedialog/kogral/SYNC.md @@ -0,0 +1,56 @@ +# Synchronization with /schemas/kogral/ + +This directory (`.typedialog/kogral/`) is the **source of truth** for all KOGRAL configuration schemas. + +## File Mapping + +| .typedialog/kogral | /schemas/kogral | Purpose | +|--------------------|-----------------|---------| +| core/contracts.ncl | contracts.ncl | Type contracts + validation | +| core/defaults.ncl | defaults.ncl | Base configuration | +| core/helpers.ncl | helpers.ncl | Utility functions | +| modes/dev.ncl | modes/dev.ncl | Development overrides | +| modes/prod.ncl | modes/prod.ncl | Production overrides | +| modes/test.ncl | modes/test.ncl | Test overrides | + +## Build Integration + +1. **Edit here** (`.typedialog/kogral/`) +2. **Build copies to** `/schemas/kogral/` +3. **Rust crate uses** from `/schemas/kogral/` + +### Justfile Target + +```bash +just dev::sync-config # Sync .typedialog β†’ /schemas/ +``` + +### Manual Sync + +```bash +cp -r .typedialog/kogral/core/* schemas/kogral/ +cp -r .typedialog/kogral/modes/* schemas/kogral/modes/ +``` + +## When to Update + +- **Configuration changes** β†’ Update in `.typedialog/kogral/core/` or `.typedialog/kogral/modes/` +- **Add new mode** β†’ Add `.typedialog/kogral/modes/new-mode.ncl` +- **New scripts** β†’ Add to `.typedialog/kogral/scripts/` +- **Helper functions** β†’ Update `.typedialog/kogral/core/helpers.ncl` + +## Validation + +```bash +# Validate all schemas +nickel export --format json .typedialog/kogral/core/contracts.ncl +nickel export --format json .typedialog/kogral/modes/dev.ncl +nickel export --format json .typedialog/kogral/modes/prod.ncl +``` + +## Never Edit + +❌ Do NOT directly edit `/schemas/kogral/` files +βœ… Always edit in `.typedialog/kogral/` instead + +This ensures a single source of truth and prevents divergence. diff --git a/.typedialog/kogral/core/contracts.ncl b/.typedialog/kogral/core/contracts.ncl new file mode 100644 index 0000000..07b7f28 --- /dev/null +++ b/.typedialog/kogral/core/contracts.ncl @@ -0,0 +1,268 @@ +# Knowledge Base Configuration Contracts (Schema Definitions) +# +# Pattern: Pure schema definitions using Nickel contracts +# Follows: provisioning/schemas pattern + +{ + # === CORE TYPES === + + GraphConfig = { + name | String + | doc "Graph name identifier", + + version | String + | doc "Semantic version string" + | default = "1.0.0", + + description | String + | doc "Human-readable description" + | default = "", + }, + + InheritanceConfig = { + base | String + | doc "Path to shared KOGRAL directory" + | default = "/Users/Akasha/Tools/.kogral-shared", + + guidelines | Array String + | doc "Additional guideline paths to inherit" + | default = [], + + priority | Number + | doc "Override priority (higher wins)" + | default = 100, + }, + + # === STORAGE === + + StorageType = [| 'filesystem, 'memory, 'surrealdb |], + + SecondaryStorageConfig = { + enabled | Bool + | doc "Enable secondary storage backend" + | default = false, + + type | [| 'surrealdb, 'sqlite |] + | doc "Secondary storage type" + | default = 'surrealdb, + + url | String + | doc "Connection URL" + | default = "ws://localhost:8000", + + namespace | String + | doc "SurrealDB namespace" + | default = "kb", + + database | String + | doc "SurrealDB database name" + | default = "default", + + username | String + | doc "Database username" + | optional, + + password | String + | doc "Database password" + | optional, + }, + + StorageConfig = { + primary | StorageType + | doc "Primary storage backend" + | default = 'filesystem, + + secondary | SecondaryStorageConfig + | doc "Optional secondary storage" + | default = { enabled = false }, + }, + + # === EMBEDDINGS === + + EmbeddingProviderType = [| 'openai, 'claude, 'ollama, 'fastembed |], + + EmbeddingConfig = { + enabled | Bool + | doc "Enable embedding generation" + | default = true, + + provider | EmbeddingProviderType + | doc "Embedding provider" + | default = 'fastembed, + + model | String + | doc "Model name/identifier" + | default = "BAAI/bge-small-en-v1.5", + + dimensions | Number + | doc "Embedding vector dimensions" + | default = 384, + + api_key_env | String + | doc "Environment variable for API key" + | default = "OPENAI_API_KEY", + }, + + # === TEMPLATES === + + DocumentTemplates = { + note | String + | default = "note.md.tera", + + decision | String + | default = "decision.md.tera", + + guideline | String + | default = "guideline.md.tera", + + pattern | String + | default = "pattern.md.tera", + + journal | String + | default = "journal.md.tera", + + execution | String + | default = "execution.md.tera", + }, + + ExportTemplates = { + logseq_page | String + | default = "export/logseq-page.md.tera", + + logseq_journal | String + | default = "export/logseq-journal.md.tera", + + summary | String + | default = "export/summary.md.tera", + + json | String + | default = "export/graph.json.tera", + }, + + TemplateConfig = { + templates_dir | String + | doc "Directory containing templates" + | default = "templates", + + templates | DocumentTemplates + | doc "Template files for each node type" + | default = {}, + + export | ExportTemplates + | doc "Export format templates" + | default = {}, + + custom | { _ : String } + | doc "Custom template registry (name β†’ path)" + | default = {}, + }, + + # === QUERY === + + QueryConfig = { + similarity_threshold | Number + | doc "Minimum similarity for semantic matches (0-1)" + | default = 0.4, + + max_results | Number + | doc "Maximum results to return" + | default = 10, + + recency_weight | Number + | doc "Weight factor for recent documents" + | default = 3.0, + + cross_graph | Bool + | doc "Enable cross-graph queries" + | default = true, + }, + + # === MCP === + + McpServerConfig = { + name | String + | default = "kogral-mcp", + + version | String + | default = "1.0.0", + + transport | [| 'stdio, 'sse |] + | default = 'stdio, + }, + + McpToolsConfig = { + search | Bool | default = true, + add_note | Bool | default = true, + add_decision | Bool | default = true, + link | Bool | default = true, + get_guidelines | Bool | default = true, + export | Bool | default = true, + }, + + McpResourcesConfig = { + expose_project | Bool | default = true, + expose_shared | Bool | default = true, + }, + + McpConfig = { + server | McpServerConfig + | default = {}, + + tools | McpToolsConfig + | default = {}, + + resources | McpResourcesConfig + | default = {}, + }, + + # === SYNC === + + SyncConfig = { + auto_index | Bool + | doc "Automatically sync filesystem to storage" + | default = true, + + watch_paths | Array String + | doc "Directories to watch for changes" + | default = ["notes", "decisions", "guidelines", "patterns", "journal"], + + debounce_ms | Number + | doc "Debounce delay for file system events" + | default = 500, + }, + + # === MAIN CONFIG === + + KbConfig = { + graph | GraphConfig + | doc "Graph metadata configuration", + + inheritance | InheritanceConfig + | doc "Inheritance configuration" + | default = {}, + + storage | StorageConfig + | doc "Storage backend configuration" + | default = {}, + + embeddings | EmbeddingConfig + | doc "Embedding provider configuration" + | default = {}, + + templates | TemplateConfig + | doc "Template system configuration" + | default = {}, + + query | QueryConfig + | doc "Query engine configuration" + | default = {}, + + mcp | McpConfig + | doc "MCP server configuration" + | default = {}, + + sync | SyncConfig + | doc "Sync configuration" + | default = {}, + }, +} diff --git a/.typedialog/kogral/core/defaults.ncl b/.typedialog/kogral/core/defaults.ncl new file mode 100644 index 0000000..2ae3033 --- /dev/null +++ b/.typedialog/kogral/core/defaults.ncl @@ -0,0 +1,97 @@ +# Knowledge Base Default Configuration Values +# +# Pattern: Default values for all configuration options +# These are base values that modes can override + +let contracts = import "contracts.ncl" in + +{ + # Base configuration with all defaults + base = { + graph = { + name = "knowledge-base", + version = "1.0.0", + description = "Knowledge Base graph", + }, + + # Inheritance paths: set via TOOLS_PATH env var at export time + # Default paths resolve: $TOOLS_PATH/.kogral-shared (or $HOME/Tools/.kogral-shared) + inheritance = { + # Paths with $TOOLS_PATH are resolved at runtime by Rust code + base = "$TOOLS_PATH/.kogral-shared", + guidelines = [], + priority = 100, + }, + + storage = { + primary = 'filesystem, + secondary = { + enabled = false, + type = 'surrealdb, + url = "ws://localhost:8000", + namespace = "kogral", + database = "default", + }, + }, + + embeddings = { + enabled = true, + provider = 'fastembed, + model = "BAAI/bge-small-en-v1.5", + dimensions = 384, + api_key_env = "OPENAI_API_KEY", + }, + + templates = { + templates_dir = "templates", + templates = { + note = "note.md.tera", + decision = "decision.md.tera", + guideline = "guideline.md.tera", + pattern = "pattern.md.tera", + journal = "journal.md.tera", + execution = "execution.md.tera", + }, + export = { + logseq_page = "export/logseq-page.md.tera", + logseq_journal = "export/logseq-journal.md.tera", + summary = "export/summary.md.tera", + json = "export/graph.json.tera", + }, + custom = {}, + }, + + query = { + similarity_threshold = 0.4, + max_results = 10, + recency_weight = 3.0, + cross_graph = true, + }, + + mcp = { + server = { + name = "kogral-mcp", + version = "1.0.0", + transport = 'stdio, + }, + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + resources = { + expose_project = true, + expose_shared = true, + }, + }, + + sync = { + auto_index = true, + watch_paths = ["notes", "decisions", "guidelines", "patterns", "journal"], + debounce_ms = 500, + }, + } | contracts.KbConfig, +} diff --git a/.typedialog/kogral/core/helpers.ncl b/.typedialog/kogral/core/helpers.ncl new file mode 100644 index 0000000..8f6fe39 --- /dev/null +++ b/.typedialog/kogral/core/helpers.ncl @@ -0,0 +1,111 @@ +# Knowledge Base Configuration Composition Helpers +# +# Provides utilities for merging configurations from multiple layers: +# 1. Schema (type contracts) +# 2. Defaults (base values) +# 3. Mode Overlay (mode-specific tuning: dev/prod/test) +# 4. User Customization (overrides) +# +# Pattern: Follows provisioning/schemas/platform/common/helpers.ncl + +{ + # Recursively merge two record configurations + # Override values take precedence over base (shallow merge at each level) + # + # Example: + # let base = { storage = { primary = 'filesystem }, embeddings = { enabled = true } } + # let override = { storage = { primary = 'surrealdb } } + # merge_with_override base override + # # Result: { storage = { primary = 'surrealdb }, embeddings = { enabled = true } } + merge_with_override | not_exported = fun base override => + if std.is_record base && std.is_record override then + let base_fields = std.record.fields base in + let override_fields = std.record.fields override in + + base_fields + |> std.array.fold_right + (fun key acc => + let base_value = base."%{key}" in + + if std.record.has_field key override then + let override_value = override."%{key}" in + + if std.is_record base_value && std.is_record override_value then + acc + & { "%{key}" = merge_with_override base_value override_value } + else + # Override value takes precedence + acc & { "%{key}" = override_value } + else + # Keep base value + acc & { "%{key}" = base_value } + ) + (override_fields + |> std.array.fold_right + (fun key acc => + if !std.record.has_field key base then + acc & { "%{key}" = override."%{key}" } + else + acc + ) + {} + ) + else + # If either is not a record, override takes precedence + if std.is_null override then base else override, + + # Compose configuration from multiple layers with proper merging + # + # Layer 1: defaults (base values) + # Layer 2: mode_config (mode-specific overrides: dev/prod/test) + # Layer 3: user_custom (user customizations) + # + # Example: + # let defaults = { embeddings = { provider = 'fastembed } } + # let mode = { embeddings = { provider = 'openai } } # Production override + # let user = { graph = { name = "my-project" } } + # compose_config defaults mode user + compose_config | not_exported = fun defaults mode_config user_custom => + let with_mode = merge_with_override defaults mode_config in + merge_with_override with_mode user_custom, + + # Compose minimal config (defaults + user only, no mode) + # Useful for simple cases where mode-specific tuning isn't needed + compose_minimal | not_exported = fun defaults user_custom => + merge_with_override defaults user_custom, + + # Validate that required fields are present + # Returns config if valid, throws error if invalid + validate_required | not_exported = fun config required_fields => + required_fields + |> std.array.fold_right + (fun field acc => + if std.record.has_field field config then + acc + else + std.fail "Required field missing: %{field}" + ) + config, + + # Extract specific subsection from config + # Example: extract_section config "storage" + extract_section | not_exported = fun config section => + if std.record.has_field section config then + config."%{section}" + else + std.fail "Section not found: %{section}", + + # Merge arrays (for things like watch_paths, tags, etc.) + # Deduplicates and preserves order + merge_arrays | not_exported = fun base override => + let combined = base @ override in + std.array.fold_right + (fun item acc => + if std.array.elem item acc then + acc + else + [item] @ acc + ) + [] + combined, +} diff --git a/.typedialog/kogral/forms/README.md b/.typedialog/kogral/forms/README.md new file mode 100644 index 0000000..ba7bd01 --- /dev/null +++ b/.typedialog/kogral/forms/README.md @@ -0,0 +1,111 @@ +# KOGRAL Forms & Configuration UI + +This directory contains form definitions for the typedialog-web UI, enabling interactive configuration of KOGRAL knowledge bases. + +## Architecture + +Forms use a **fragment composition pattern** for modularity and maintainability: + +``` +kogral-config.toml (main form) + β”œβ”€β”€ includes: fragments/graph.toml + β”œβ”€β”€ includes: fragments/storage.toml + β”œβ”€β”€ includes: fragments/embeddings.toml + β”œβ”€β”€ includes: fragments/query.toml + β”œβ”€β”€ includes: fragments/mcp.toml + └── includes: fragments/sync.toml +``` + +## File Structure + +``` +forms/ +β”œβ”€β”€ kogral-config.toml # Main form definition (composition) +β”œβ”€β”€ README.md # This file +└── fragments/ # Reusable configuration fragments + β”œβ”€β”€ graph.toml # Knowledge graph metadata + β”œβ”€β”€ storage.toml # Storage backend options + β”œβ”€β”€ embeddings.toml # Vector search & embedding provider + β”œβ”€β”€ query.toml # Query engine tuning + β”œβ”€β”€ mcp.toml # MCP server settings + └── sync.toml # Synchronization configuration +``` + +## Fragment Design + +Each fragment contains: + +1. **Section Headers** - Visual grouping in UI +2. **Field Elements** - Input controls with: + - `nickel_path` - Path in Nickel config (e.g., `["storage", "primary"]`) + - `type` - Field type (text, select, boolean, number, text_array) + - `default` - Default value + - `visible_if` - Conditional visibility rules + - `help` - User help text + +### Example Fragment + +```toml +[[elements]] +border_top = true +name = "storage_section_header" +title = "πŸ’Ύ Storage Backend" +type = "section_header" + +[[elements]] +default = "filesystem" +help = "Primary storage backend for knowledge base" +name = "storage_primary" +nickel_path = ["storage", "primary"] +options = ["filesystem", "memory", "surrealdb"] +prompt = "Primary Storage" +type = "select" +``` + +## nickel_path Mapping + +The `nickel_path` field maps form fields to Nickel configuration structure: + +``` +nickel_path = ["storage", "primary"] + ↓ +Nickel: storage.primary = "filesystem" + ↓ +JSON export: { storage: { primary: "filesystem" } } + ↓ +Rust struct: config.storage.primary +``` + +## Conditional Visibility + +Fields can appear/disappear based on other field values: + +```toml +visible_if = "storage_secondary_enabled == true" +visible_if = "embeddings_provider != 'fastembed'" +visible_if = "sync_auto_index == true && query_cross_graph == true" +``` + +## Integration with typedialog-web + +1. **Edit** - User modifies form in typedialog-web +2. **Validate** - Fields validated against nickel_path contracts +3. **Export** - Changes written back to `.ncl` files +4. **Generate** - `generate-configs.nu` exports to JSON +5. **Load** - Rust code loads from `.kogral/config.json` + +## Adding New Configuration Sections + +To add a new configuration section: + +1. Add new type to `core/contracts.ncl` +2. Add defaults to `core/defaults.ncl` +3. Create fragment file: `fragments/new-section.toml` +4. Add `includes` reference in `kogral-config.toml` +5. Run validation: `nu scripts/validate-config.nu` + +## Fragment Naming Convention + +- Use descriptive names: `storage.toml`, `embeddings.toml`, not `section1.toml` +- For sub-sections: `fragments/mcp/tools.toml`, `fragments/storage/secondary.toml` +- Use lowercase with hyphens: `mcp-server.toml`, not `MCPServer.toml` diff --git a/.typedialog/kogral/forms/fragments/embeddings.toml b/.typedialog/kogral/forms/fragments/embeddings.toml new file mode 100644 index 0000000..6896b4d --- /dev/null +++ b/.typedialog/kogral/forms/fragments/embeddings.toml @@ -0,0 +1,57 @@ +# Embeddings & Vector Search Configuration Fragment +# Used by: kogral-config form + +[[elements]] +border_top = true +border_bottom = false +name = "embeddings_section_header" +title = "πŸ” Embeddings & Vector Search" +type = "section_header" + +[[elements]] +default = true +help = "Enable embedding generation for semantic search" +name = "embeddings_enabled" +nickel_path = ["embeddings", "enabled"] +prompt = "Enable Embeddings" +type = "boolean" + +[[elements]] +default = "fastembed" +help = "Embedding provider (local or cloud APIs)" +name = "embeddings_provider" +nickel_path = ["embeddings", "provider"] +options = ["fastembed", "openai", "claude", "ollama"] +prompt = "Embedding Provider" +type = "select" +visible_if = "embeddings_enabled == true" + +[[elements]] +default = "BAAI/bge-small-en-v1.5" +help = "Model identifier or name for embeddings" +name = "embeddings_model" +nickel_path = ["embeddings", "model"] +placeholder = "BAAI/bge-small-en-v1.5" +prompt = "Model" +type = "text" +visible_if = "embeddings_enabled == true" + +[[elements]] +default = 384 +help = "Vector dimension (typical values: 384, 768, 1024, 1536)" +name = "embeddings_dimensions" +nickel_path = ["embeddings", "dimensions"] +options = [384, 768, 1024, 1536] +prompt = "Vector Dimensions" +type = "number" +visible_if = "embeddings_enabled == true" + +[[elements]] +default = "OPENAI_API_KEY" +help = "Environment variable containing API credentials" +name = "embeddings_api_key_env" +nickel_path = ["embeddings", "api_key_env"] +placeholder = "OPENAI_API_KEY" +prompt = "API Key Variable" +type = "text" +visible_if = "embeddings_enabled == true && embeddings_provider != 'fastembed' && embeddings_provider != 'ollama'" diff --git a/.typedialog/kogral/forms/fragments/graph.toml b/.typedialog/kogral/forms/fragments/graph.toml new file mode 100644 index 0000000..e406aeb --- /dev/null +++ b/.typedialog/kogral/forms/fragments/graph.toml @@ -0,0 +1,34 @@ +# Graph Configuration Fragment +# Basic knowledge graph metadata + +[[elements]] +border_top = true +border_bottom = false +name = "graph_section_header" +title = "πŸ“š Knowledge Graph" +type = "section_header" + +[[elements]] +help = "Unique identifier for this knowledge base" +name = "graph_name" +nickel_path = ["graph", "name"] +placeholder = "knowledge-base" +prompt = "Graph Name" +type = "text" + +[[elements]] +default = "1.0.0" +help = "Schema version (read-only)" +name = "graph_version" +nickel_path = ["graph", "version"] +prompt = "Schema Version" +readonly = true +type = "text" + +[[elements]] +help = "Human-readable description of this knowledge base" +name = "graph_description" +nickel_path = ["graph", "description"] +placeholder = "Knowledge Base graph" +prompt = "Description" +type = "text" diff --git a/.typedialog/kogral/forms/fragments/mcp.toml b/.typedialog/kogral/forms/fragments/mcp.toml new file mode 100644 index 0000000..ac6ca81 --- /dev/null +++ b/.typedialog/kogral/forms/fragments/mcp.toml @@ -0,0 +1,113 @@ +# Model Context Protocol (MCP) Server Configuration Fragment +# Used by: kogral-config form + +[[elements]] +border_top = true +border_bottom = false +name = "mcp_section_header" +title = "πŸ”Œ MCP Server" +type = "section_header" + +[[elements]] +default = "kogral-mcp" +help = "MCP server name identifier" +name = "mcp_server_name" +nickel_path = ["mcp", "server", "name"] +prompt = "Server Name" +type = "text" + +[[elements]] +default = "1.0.0" +help = "MCP server version" +name = "mcp_server_version" +nickel_path = ["mcp", "server", "version"] +placeholder = "1.0.0" +prompt = "Server Version" +type = "text" + +[[elements]] +default = "stdio" +help = "Transport protocol for MCP communication" +name = "mcp_server_transport" +nickel_path = ["mcp", "server", "transport"] +options = ["stdio", "sse"] +prompt = "Transport" +type = "select" + +[[elements]] +border_top = false +border_bottom = false +name = "mcp_tools_header" +title = "Available Tools" +type = "section_header" + +[[elements]] +default = true +help = "Enable kb/search tool" +name = "mcp_tools_search" +nickel_path = ["mcp", "tools", "search"] +prompt = "Search Tool" +type = "boolean" + +[[elements]] +default = true +help = "Enable kb/add_note tool" +name = "mcp_tools_add_note" +nickel_path = ["mcp", "tools", "add_note"] +prompt = "Add Note Tool" +type = "boolean" + +[[elements]] +default = true +help = "Enable kb/add_decision tool" +name = "mcp_tools_add_decision" +nickel_path = ["mcp", "tools", "add_decision"] +prompt = "Add Decision Tool" +type = "boolean" + +[[elements]] +default = true +help = "Enable kb/link tool" +name = "mcp_tools_link" +nickel_path = ["mcp", "tools", "link"] +prompt = "Link Tool" +type = "boolean" + +[[elements]] +default = true +help = "Enable kb/get_guidelines tool" +name = "mcp_tools_get_guidelines" +nickel_path = ["mcp", "tools", "get_guidelines"] +prompt = "Get Guidelines Tool" +type = "boolean" + +[[elements]] +default = true +help = "Enable kb/export tool" +name = "mcp_tools_export" +nickel_path = ["mcp", "tools", "export"] +prompt = "Export Tool" +type = "boolean" + +[[elements]] +border_top = true +border_bottom = false +name = "mcp_resources_header" +title = "Resource Exposure" +type = "section_header" + +[[elements]] +default = true +help = "Expose project-specific knowledge graphs" +name = "mcp_resources_expose_project" +nickel_path = ["mcp", "resources", "expose_project"] +prompt = "Expose Project Resources" +type = "boolean" + +[[elements]] +default = true +help = "Expose shared organizational knowledge graphs" +name = "mcp_resources_expose_shared" +nickel_path = ["mcp", "resources", "expose_shared"] +prompt = "Expose Shared Resources" +type = "boolean" diff --git a/.typedialog/kogral/forms/fragments/query.toml b/.typedialog/kogral/forms/fragments/query.toml new file mode 100644 index 0000000..012f9d6 --- /dev/null +++ b/.typedialog/kogral/forms/fragments/query.toml @@ -0,0 +1,49 @@ +# Query Engine Configuration Fragment +# Used by: kogral-config form + +[[elements]] +border_top = true +border_bottom = false +name = "query_section_header" +title = "πŸ“Š Query Engine" +type = "section_header" + +[[elements]] +default = 0.4 +help = "Minimum similarity score for semantic matches (0-1)" +max = 1.0 +min = 0.0 +name = "query_similarity_threshold" +nickel_path = ["query", "similarity_threshold"] +prompt = "Similarity Threshold" +step = 0.05 +type = "number" + +[[elements]] +default = 10 +help = "Maximum results returned per query" +max = 100 +min = 1 +name = "query_max_results" +nickel_path = ["query", "max_results"] +prompt = "Max Results" +type = "number" + +[[elements]] +default = 3.0 +help = "Weight factor for recency scoring (higher = favor recent results)" +max = 10.0 +min = 0.0 +name = "query_recency_weight" +nickel_path = ["query", "recency_weight"] +prompt = "Recency Weight" +step = 0.5 +type = "number" + +[[elements]] +default = true +help = "Enable queries across multiple graphs (shared + project)" +name = "query_cross_graph" +nickel_path = ["query", "cross_graph"] +prompt = "Enable Cross-Graph Queries" +type = "boolean" diff --git a/.typedialog/kogral/forms/fragments/storage.toml b/.typedialog/kogral/forms/fragments/storage.toml new file mode 100644 index 0000000..9f017c7 --- /dev/null +++ b/.typedialog/kogral/forms/fragments/storage.toml @@ -0,0 +1,64 @@ +# Storage Backend Configuration Fragment +# Used by: kogral-config form + +[[elements]] +border_top = true +border_bottom = false +name = "storage_section_header" +title = "πŸ’Ύ Storage Backend" +type = "section_header" + +[[elements]] +default = "filesystem" +help = "Primary storage backend for knowledge base" +name = "storage_primary" +nickel_path = ["storage", "primary"] +options = ["filesystem", "memory", "surrealdb"] +prompt = "Primary Storage" +type = "select" + +[[elements]] +default = false +help = "Enable secondary storage backend" +name = "storage_secondary_enabled" +nickel_path = ["storage", "secondary", "enabled"] +prompt = "Enable Secondary Storage" +type = "boolean" + +[[elements]] +default = "surrealdb" +help = "Secondary storage type (when enabled)" +name = "storage_secondary_type" +nickel_path = ["storage", "secondary", "type"] +options = ["surrealdb", "sqlite"] +prompt = "Secondary Type" +type = "select" +visible_if = "storage_secondary_enabled == true" + +[[elements]] +default = "ws://localhost:8000" +help = "Connection URL for secondary storage" +name = "storage_secondary_url" +nickel_path = ["storage", "secondary", "url"] +placeholder = "ws://localhost:8000" +prompt = "Secondary URL" +type = "text" +visible_if = "storage_secondary_enabled == true" + +[[elements]] +default = "kb" +help = "SurrealDB namespace" +name = "storage_secondary_namespace" +nickel_path = ["storage", "secondary", "namespace"] +prompt = "Namespace" +type = "text" +visible_if = "storage_secondary_type == 'surrealdb'" + +[[elements]] +default = "default" +help = "SurrealDB database name" +name = "storage_secondary_database" +nickel_path = ["storage", "secondary", "database"] +prompt = "Database" +type = "text" +visible_if = "storage_secondary_type == 'surrealdb'" diff --git a/.typedialog/kogral/forms/fragments/sync.toml b/.typedialog/kogral/forms/fragments/sync.toml new file mode 100644 index 0000000..55f0044 --- /dev/null +++ b/.typedialog/kogral/forms/fragments/sync.toml @@ -0,0 +1,42 @@ +# Synchronization Configuration Fragment +# Used by: kogral-config form + +[[elements]] +border_top = true +border_bottom = false +name = "sync_section_header" +title = "πŸ”„ Synchronization" +type = "section_header" + +[[elements]] +default = true +help = "Automatically sync filesystem changes to storage" +name = "sync_auto_index" +nickel_path = ["sync", "auto_index"] +prompt = "Auto-Sync" +type = "boolean" + +[[elements]] +default = 500 +help = "Debounce delay in milliseconds for filesystem events" +max = 5000 +min = 100 +name = "sync_debounce_ms" +nickel_path = ["sync", "debounce_ms"] +prompt = "Debounce Delay (ms)" +type = "number" + +[[elements]] +border_top = false +border_bottom = false +name = "sync_paths_header" +title = "Watched Paths" +type = "section_header" + +[[elements]] +default = ["notes", "decisions", "guidelines", "patterns", "journal"] +help = "Directories to watch for changes (comma-separated)" +name = "sync_watch_paths" +nickel_path = ["sync", "watch_paths"] +prompt = "Watch Paths" +type = "text_array" diff --git a/.typedialog/kogral/forms/kogral-config.toml b/.typedialog/kogral/forms/kogral-config.toml new file mode 100644 index 0000000..93b7ca7 --- /dev/null +++ b/.typedialog/kogral/forms/kogral-config.toml @@ -0,0 +1,76 @@ +# KOGRAL Knowledge Base Configuration Form +# Interactive configuration via typedialog-web UI +# +# This form uses fragment composition pattern for modular configuration. +# All fragments are located in ./fragments/ subdirectory. +# +# Pattern: +# - Fragments define [[elements]] with nickel_path mappings +# - Form composes fragments via includes = [...] +# - typedialog-web renders all elements in order + +description = "Configure your Git-native knowledge base system" +display_mode = "complete" +fallback_locale = "en-US" +name = "kogral_configuration" +title = "KOGRAL Knowledge Base Configuration" + +# ============================================================================ +# GRAPH CONFIGURATION +# ============================================================================ +[[items]] +description = "Basic metadata and naming for this knowledge base" +includes = ["fragments/graph.toml"] +name = "graph_group" +title = "Knowledge Graph" +type = "group" + +# ============================================================================ +# STORAGE BACKEND CONFIGURATION +# ============================================================================ +[[items]] +description = "Choose storage backend and secondary sync options" +includes = ["fragments/storage.toml"] +name = "storage_group" +title = "Storage Backend" +type = "group" + +# ============================================================================ +# EMBEDDINGS & VECTOR SEARCH CONFIGURATION +# ============================================================================ +[[items]] +description = "Enable semantic search with embeddings and select provider" +includes = ["fragments/embeddings.toml"] +name = "embeddings_group" +title = "Vector Search" +type = "group" + +# ============================================================================ +# QUERY ENGINE CONFIGURATION +# ============================================================================ +[[items]] +description = "Tune query behavior, similarity thresholds, and cross-graph search" +includes = ["fragments/query.toml"] +name = "query_group" +title = "Query Engine" +type = "group" + +# ============================================================================ +# MCP SERVER CONFIGURATION +# ============================================================================ +[[items]] +description = "Configure Model Context Protocol server for Claude Code integration" +includes = ["fragments/mcp.toml"] +name = "mcp_group" +title = "MCP Server" +type = "group" + +# ============================================================================ +# SYNCHRONIZATION CONFIGURATION +# ============================================================================ +[[items]] +description = "Configure automatic filesystem-to-storage synchronization" +includes = ["fragments/sync.toml"] +name = "sync_group" +title = "Synchronization" +type = "group" diff --git a/.typedialog/kogral/modes/dev.ncl b/.typedialog/kogral/modes/dev.ncl new file mode 100644 index 0000000..727fa82 --- /dev/null +++ b/.typedialog/kogral/modes/dev.ncl @@ -0,0 +1,48 @@ +# Development Mode Configuration Overlay +# +# Optimized for: Fast iteration, local development, debugging +# Storage: Filesystem only (git-tracked) +# Embeddings: Local fastembed (no API costs) +# Logging: Debug level +# Sync: Disabled (manual only) + +{ + storage = { + primary = 'filesystem, + secondary = { + enabled = false, # No database in dev mode + }, + }, + + embeddings = { + enabled = true, + provider = 'fastembed, # Local, no API costs + model = "BAAI/bge-small-en-v1.5", + dimensions = 384, + }, + + query = { + similarity_threshold = 0.4, # Permissive for exploration + max_results = 20, # More results for discovery + cross_graph = true, + }, + + sync = { + auto_index = false, # Manual sync in dev + debounce_ms = 1000, # Longer debounce + }, + + mcp = { + server = { + transport = 'stdio, + }, + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + }, +} diff --git a/.typedialog/kogral/modes/prod.ncl b/.typedialog/kogral/modes/prod.ncl new file mode 100644 index 0000000..adaa4f9 --- /dev/null +++ b/.typedialog/kogral/modes/prod.ncl @@ -0,0 +1,57 @@ +# Production Mode Configuration Overlay +# +# Optimized for: Scalability, performance, reliability +# Storage: Hybrid (filesystem + SurrealDB) +# Embeddings: Cloud providers (OpenAI/Claude via rig-core) +# Logging: Info level +# Sync: Auto-enabled with optimized debounce + +{ + storage = { + primary = 'filesystem, + secondary = { + enabled = true, # SurrealDB for scalable queries + type = 'surrealdb, + url = "ws://localhost:8000", + namespace = "kogral", + database = "production", + }, + }, + + embeddings = { + enabled = true, + provider = 'openai, # Cloud API for production quality + model = "text-embedding-3-small", + dimensions = 1536, + api_key_env = "OPENAI_API_KEY", + }, + + query = { + similarity_threshold = 0.6, # Stricter for quality results + max_results = 10, # Conservative for performance + cross_graph = true, + }, + + sync = { + auto_index = true, # Auto-sync enabled + debounce_ms = 300, # Faster response to changes + }, + + mcp = { + server = { + transport = 'stdio, + }, + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + resources = { + expose_project = true, + expose_shared = true, + }, + }, +} diff --git a/.typedialog/kogral/modes/test.ncl b/.typedialog/kogral/modes/test.ncl new file mode 100644 index 0000000..7703ce3 --- /dev/null +++ b/.typedialog/kogral/modes/test.ncl @@ -0,0 +1,52 @@ +# Test Mode Configuration Overlay +# +# Optimized for: Fast tests, isolation, no side effects +# Storage: In-memory only (ephemeral) +# Embeddings: Disabled (tests don't need semantic search) +# Logging: Debug level +# Sync: Disabled (manual control in tests) + +{ + storage = { + primary = 'memory, # Ephemeral, fast, isolated + secondary = { + enabled = false, # No database in tests + }, + }, + + embeddings = { + enabled = false, # Disable for test speed + provider = 'fastembed, # Fallback if needed + model = "BAAI/bge-small-en-v1.5", + dimensions = 384, + }, + + query = { + similarity_threshold = 0.3, # Permissive for test coverage + max_results = 50, # More results for verification + cross_graph = false, # Isolated tests + }, + + sync = { + auto_index = false, # Manual control in tests + debounce_ms = 0, # No debounce for deterministic tests + }, + + mcp = { + server = { + transport = 'stdio, + }, + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + resources = { + expose_project = false, # Isolated tests + expose_shared = false, + }, + }, +} diff --git a/.typedialog/kogral/scripts/generate-configs.nu b/.typedialog/kogral/scripts/generate-configs.nu new file mode 100644 index 0000000..fc009db --- /dev/null +++ b/.typedialog/kogral/scripts/generate-configs.nu @@ -0,0 +1,55 @@ +#!/usr/bin/env nu +# Generate configuration files from Nickel schemas +# +# Usage: nu generate-configs.nu [--mode ] [--output ] + +def main [ + --mode: string = "dev" # Configuration mode + --output: string = ".kogral" # Output directory +] { + print $"(ansi green_bold)KOGRAL Config Generator(ansi reset)" + print $"Mode: ($mode)" + print $"Output: ($output)" + + # Phase 1: Validate mode + let valid_modes = ["dev" "prod" "test"] + if ($mode | str downcase) not-in $valid_modes { + print $"(ansi red)Error: Invalid mode. Must be: (ansi reset)($valid_modes | str join ', ')" + exit 1 + } + + # Phase 2: Export Nickel schema to JSON + print "" + print $"(ansi cyan_bold)Exporting Nickel configuration...(ansi reset)" + + let nickel_file = $".typedialog/kogral/modes/($mode).ncl" + if not ($nickel_file | path exists) { + print $"(ansi red)Error: Mode file not found: $nickel_file(ansi reset)" + exit 1 + } + + # Phase 3: Run Nickel export + let output_file = $"($output)/config.json" + nickel export --format json $nickel_file | save --force $output_file + print $"(ansi green)βœ“ Config exported to $output_file(ansi reset)" + + # Phase 4: Validate generated config + print "" + print $"(ansi cyan_bold)Validating configuration...(ansi reset)" + + let config_json = open $output_file + print $"(ansi green)βœ“ Configuration is valid(ansi reset)" + if ($config_json | type) == "record" { + let section_count = ($config_json | length) + print $" - Sections: $section_count" + if ($config_json | has "embeddings") { + let embeddings_enabled = $config_json.embeddings.enabled + print $" - Embeddings: $embeddings_enabled" + } + } + + print "" + print $"(ansi green_bold)βœ“ Configuration generation complete(ansi reset)" +} + +main diff --git a/.typedialog/kogral/scripts/validate-config.nu b/.typedialog/kogral/scripts/validate-config.nu new file mode 100644 index 0000000..f0f0306 --- /dev/null +++ b/.typedialog/kogral/scripts/validate-config.nu @@ -0,0 +1,72 @@ +#!/usr/bin/env nu +# Validate KOGRAL configuration schemas +# +# Usage: nu validate-config.nu [--schema ] + +def main [ + --schema: string # Specific schema to validate + --schema-dir: string = ".typedialog/kogral" # Directory containing schemas +] { + print $"(ansi green_bold)KOGRAL Config Validator(ansi reset)" + + # Phase 1: Discover schemas to validate + let schemas = if ($schema | is-empty) { + print "Discovering schemas..." + let glob_pattern = $"($schema_dir)/**/*.ncl" + let all_files = (glob $glob_pattern | collect) + # Filter out library files (contracts, helpers) - they're imported, not standalone configs + $all_files | where { not ($in | str contains "contracts.ncl") and not ($in | str contains "helpers.ncl") } + } else { + if not ($schema | path exists) { + print $"(ansi red)Error: Schema not found: ($schema)(ansi reset)" + exit 1 + } + [$schema] + } + + let schema_count = ($schemas | length) + print $"Found ($schema_count) schemas to validate" + print "" + + # Phase 2: Validate each schema + mut valid_count = 0 + mut invalid_count = 0 + + for schema_file in $schemas { + let filename = $schema_file | path basename + print $"Validating ($filename)..." + + # Export schema and check exit status + let export_result = (nickel export --format json $schema_file | complete) + + if $export_result.exit_code == 0 { + print $" (ansi green)βœ“ Valid(ansi reset)" + $valid_count = $valid_count + 1 + } else { + print $" (ansi red)βœ— Invalid(ansi reset)" + if ($export_result.stderr | str length) > 0 { + let err_lines = ($export_result.stderr | str trim | split row '\n' | first 3) + print $" Error: ($err_lines | str join ' ')" + } + $invalid_count = $invalid_count + 1 + } + } + + # Phase 3: Summary + print "" + print $"(ansi cyan_bold)Validation Summary:(ansi reset)" + print $" Valid: ($valid_count)" + print $" Invalid: ($invalid_count)" + print $" Total: ($schema_count)" + + if $invalid_count > 0 { + print "" + print $"(ansi red)βœ— Validation FAILED(ansi reset)" + exit 1 + } else { + print "" + print $"(ansi green_bold)βœ“ All schemas valid(ansi reset)" + } +} + +main diff --git a/.typedialog/kogral/templates/config.json.tera b/.typedialog/kogral/templates/config.json.tera new file mode 100644 index 0000000..a7159b9 --- /dev/null +++ b/.typedialog/kogral/templates/config.json.tera @@ -0,0 +1,84 @@ +{ + "graph": { + "name": "{{ graph.name }}", + "version": "{{ graph.version }}", + "description": "{{ graph.description }}" + }, + "inheritance": { + "base": "{{ inheritance.base }}", + "guidelines": [{% for g in inheritance.guidelines %}"{{ g }}"{% if not loop.last %},{% endif %}{% endfor %}], + "priority": {{ inheritance.priority }} + }, + "storage": { + "primary": "{{ storage.primary }}", + "secondary": { + "enabled": {{ storage.secondary.enabled }}, + "type": "{{ storage.secondary.type }}", + "url": "{{ storage.secondary.url }}", + "namespace": "{{ storage.secondary.namespace }}", + "database": "{{ storage.secondary.database }}" + {% if storage.secondary.username %}, + "username": "{{ storage.secondary.username }}" + {% endif %} + {% if storage.secondary.password %}, + "password": "{{ storage.secondary.password }}" + {% endif %} + } + }, + "embeddings": { + "enabled": {{ embeddings.enabled }}, + {% if embeddings.enabled %} + "provider": "{{ embeddings.provider }}", + "model": "{{ embeddings.model }}", + "dimensions": {{ embeddings.dimensions }}, + "api_key_env": "{{ embeddings.api_key_env }}" + {% endif %} + }, + "templates": { + "templates_dir": "{{ templates.templates_dir }}", + "templates": { + "note": "{{ templates.templates.note }}", + "decision": "{{ templates.templates.decision }}", + "guideline": "{{ templates.templates.guideline }}", + "pattern": "{{ templates.templates.pattern }}", + "journal": "{{ templates.templates.journal }}", + "execution": "{{ templates.templates.execution }}" + }, + "export": { + "logseq_page": "{{ templates.export.logseq_page }}", + "logseq_journal": "{{ templates.export.logseq_journal }}", + "summary": "{{ templates.export.summary }}", + "json": "{{ templates.export.json }}" + } + }, + "query": { + "similarity_threshold": {{ query.similarity_threshold }}, + "max_results": {{ query.max_results }}, + "recency_weight": {{ query.recency_weight }}, + "cross_graph": {{ query.cross_graph }} + }, + "mcp": { + "server": { + "name": "{{ mcp.server.name }}", + "version": "{{ mcp.server.version }}", + "transport": "{{ mcp.server.transport }}" + }, + "tools": { + "search": {{ mcp.tools.search }}, + "add_note": {{ mcp.tools.add_note }}, + "add_decision": {{ mcp.tools.add_decision }}, + "link": {{ mcp.tools.link }}, + "get_guidelines": {{ mcp.tools.get_guidelines }}, + "export": {{ mcp.tools.export }} + }, + "resources": { + "expose_project": {{ mcp.resources.expose_project }}, + "expose_shared": {{ mcp.resources.expose_shared }} + } + }, + "sync": { + "auto_index": {{ sync.auto_index }}, + "watch_paths": [{% for p in sync.watch_paths %}"{{ p }}"{% if not loop.last %},{% endif %}{% endfor %}], + "debounce_ms": {{ sync.debounce_ms }} + } +} diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000..6289603 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,41 @@ +# Vale configuration for TypeDialog documentation +# https://vale.sh/docs/topics/config/ + +StylesPath = .vale/styles +MinAlertLevel = warning + +# Global settings +[*] +Packages = Google, write-good +Vocab = TypeDialog + +# Markdown files: docs/**/*.md and root *.md (excluding .claude, .coder, CLAUDE.md) +[*.md] +BasedOnStyles = write-good, Google + +# Ignore code blocks and specific patterns +TokenIgnores = (\$\{[^\}]+\}), (`[^`]+`), (\*\*[^\*]+\*\*) + +# Disable noisy rules for technical documentation +Google.Headings = NO +Google.Parens = NO +Google.Acronyms = NO +Google.Passive = NO +Google.We = NO +Google.Will = NO +Google.WordList = NO +Google.Colons = NO + +write-good.E-Prime = NO +write-good.TooWordy = NO +write-good.Passive = NO + +Vale.Spelling = NO + +# Keep enabled (useful for technical docs): +# - write-good.Weasel (vague words like "various") +# - Google.Contractions (maintain formal tone) +# - Google.FirstPerson (avoid "we/our") +# - Google.Exclamation +# - Google.Slang +# - Google.Units diff --git a/.vale/Vocab/TypeDialog/accept.txt b/.vale/Vocab/TypeDialog/accept.txt new file mode 100644 index 0000000..ffc7ad8 --- /dev/null +++ b/.vale/Vocab/TypeDialog/accept.txt @@ -0,0 +1,25 @@ +# TypeDialog accepted terms (case-insensitive) +# Technical acronyms and abbreviations +API +CLI +TUI +JSON +YAML +TOML +REST +HTTP +HTTPS +TLS +SSL +CORS +URL +URI +NPM +SDK +HTML +CSS +JWT +WASM +WebAssembly +README +CHANGELOG diff --git a/.vale/Vocab/TypeDialog/reject.txt b/.vale/Vocab/TypeDialog/reject.txt new file mode 100644 index 0000000..a7f5a8f --- /dev/null +++ b/.vale/Vocab/TypeDialog/reject.txt @@ -0,0 +1,2 @@ +# TypeDialog rejected terms +# Add terms that should never be used diff --git a/.vale/styles/Google/AMPM.yml b/.vale/styles/Google/AMPM.yml new file mode 100644 index 0000000..37b49ed --- /dev/null +++ b/.vale/styles/Google/AMPM.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'AM' or 'PM' (preceded by a space)." +link: "https://developers.google.com/style/word-list" +level: error +nonword: true +tokens: + - '\d{1,2}[AP]M\b' + - '\d{1,2} ?[ap]m\b' + - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/.vale/styles/Google/Acronyms.yml b/.vale/styles/Google/Acronyms.yml new file mode 100644 index 0000000..f41af01 --- /dev/null +++ b/.vale/styles/Google/Acronyms.yml @@ -0,0 +1,64 @@ +extends: conditional +message: "Spell out '%s', if it's unfamiliar to the audience." +link: 'https://developers.google.com/style/abbreviations' +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP diff --git a/.vale/styles/Google/Colons.yml b/.vale/styles/Google/Colons.yml new file mode 100644 index 0000000..4a027c3 --- /dev/null +++ b/.vale/styles/Google/Colons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' should be in lowercase." +link: 'https://developers.google.com/style/colons' +nonword: true +level: warning +scope: sentence +tokens: + - '(?=1.0.0" +} diff --git a/.vale/styles/Google/vocab.txt b/.vale/styles/Google/vocab.txt new file mode 100644 index 0000000..e69de29 diff --git a/.vale/styles/write-good/Cliches.yml b/.vale/styles/write-good/Cliches.yml new file mode 100644 index 0000000..c953143 --- /dev/null +++ b/.vale/styles/write-good/Cliches.yml @@ -0,0 +1,702 @@ +extends: existence +message: "Try to avoid using clichΓ©s like '%s'." +ignorecase: true +level: warning +tokens: + - a chip off the old block + - a clean slate + - a dark and stormy night + - a far cry + - a fine kettle of fish + - a loose cannon + - a penny saved is a penny earned + - a tough row to hoe + - a word to the wise + - ace in the hole + - acid test + - add insult to injury + - against all odds + - air your dirty laundry + - all fun and games + - all in a day's work + - all talk, no action + - all thumbs + - all your eggs in one basket + - all's fair in love and war + - all's well that ends well + - almighty dollar + - American as apple pie + - an axe to grind + - another day, another dollar + - armed to the teeth + - as luck would have it + - as old as time + - as the crow flies + - at loose ends + - at my wits end + - avoid like the plague + - babe in the woods + - back against the wall + - back in the saddle + - back to square one + - back to the drawing board + - bad to the bone + - badge of honor + - bald faced liar + - ballpark figure + - banging your head against a brick wall + - baptism by fire + - barking up the wrong tree + - bat out of hell + - be all and end all + - beat a dead horse + - beat around the bush + - been there, done that + - beggars can't be choosers + - behind the eight ball + - bend over backwards + - benefit of the doubt + - bent out of shape + - best thing since sliced bread + - bet your bottom dollar + - better half + - better late than never + - better mousetrap + - better safe than sorry + - between a rock and a hard place + - beyond the pale + - bide your time + - big as life + - big cheese + - big fish in a small pond + - big man on campus + - bigger they are the harder they fall + - bird in the hand + - bird's eye view + - birds and the bees + - birds of a feather flock together + - bit the hand that feeds you + - bite the bullet + - bite the dust + - bitten off more than he can chew + - black as coal + - black as pitch + - black as the ace of spades + - blast from the past + - bleeding heart + - blessing in disguise + - blind ambition + - blind as a bat + - blind leading the blind + - blood is thicker than water + - blood sweat and tears + - blow off steam + - blow your own horn + - blushing bride + - boils down to + - bolt from the blue + - bone to pick + - bored stiff + - bored to tears + - bottomless pit + - boys will be boys + - bright and early + - brings home the bacon + - broad across the beam + - broken record + - brought back to reality + - bull by the horns + - bull in a china shop + - burn the midnight oil + - burning question + - burning the candle at both ends + - burst your bubble + - bury the hatchet + - busy as a bee + - by hook or by crook + - call a spade a spade + - called onto the carpet + - calm before the storm + - can of worms + - can't cut the mustard + - can't hold a candle to + - case of mistaken identity + - cat got your tongue + - cat's meow + - caught in the crossfire + - caught red-handed + - checkered past + - chomping at the bit + - cleanliness is next to godliness + - clear as a bell + - clear as mud + - close to the vest + - cock and bull story + - cold shoulder + - come hell or high water + - cool as a cucumber + - cool, calm, and collected + - cost a king's ransom + - count your blessings + - crack of dawn + - crash course + - creature comforts + - cross that bridge when you come to it + - crushing blow + - cry like a baby + - cry me a river + - cry over spilt milk + - crystal clear + - curiosity killed the cat + - cut and dried + - cut through the red tape + - cut to the chase + - cute as a bugs ear + - cute as a button + - cute as a puppy + - cuts to the quick + - dark before the dawn + - day in, day out + - dead as a doornail + - devil is in the details + - dime a dozen + - divide and conquer + - dog and pony show + - dog days + - dog eat dog + - dog tired + - don't burn your bridges + - don't count your chickens + - don't look a gift horse in the mouth + - don't rock the boat + - don't step on anyone's toes + - don't take any wooden nickels + - down and out + - down at the heels + - down in the dumps + - down the hatch + - down to earth + - draw the line + - dressed to kill + - dressed to the nines + - drives me up the wall + - dull as dishwater + - dyed in the wool + - eagle eye + - ear to the ground + - early bird catches the worm + - easier said than done + - easy as pie + - eat your heart out + - eat your words + - eleventh hour + - even the playing field + - every dog has its day + - every fiber of my being + - everything but the kitchen sink + - eye for an eye + - face the music + - facts of life + - fair weather friend + - fall by the wayside + - fan the flames + - feast or famine + - feather your nest + - feathered friends + - few and far between + - fifteen minutes of fame + - filthy vermin + - fine kettle of fish + - fish out of water + - fishing for a compliment + - fit as a fiddle + - fit the bill + - fit to be tied + - flash in the pan + - flat as a pancake + - flip your lid + - flog a dead horse + - fly by night + - fly the coop + - follow your heart + - for all intents and purposes + - for the birds + - for what it's worth + - force of nature + - force to be reckoned with + - forgive and forget + - fox in the henhouse + - free and easy + - free as a bird + - fresh as a daisy + - full steam ahead + - fun in the sun + - garbage in, garbage out + - gentle as a lamb + - get a kick out of + - get a leg up + - get down and dirty + - get the lead out + - get to the bottom of + - get your feet wet + - gets my goat + - gilding the lily + - give and take + - go against the grain + - go at it tooth and nail + - go for broke + - go him one better + - go the extra mile + - go with the flow + - goes without saying + - good as gold + - good deed for the day + - good things come to those who wait + - good time was had by all + - good times were had by all + - greased lightning + - greek to me + - green thumb + - green-eyed monster + - grist for the mill + - growing like a weed + - hair of the dog + - hand to mouth + - happy as a clam + - happy as a lark + - hasn't a clue + - have a nice day + - have high hopes + - have the last laugh + - haven't got a row to hoe + - head honcho + - head over heels + - hear a pin drop + - heard it through the grapevine + - heart's content + - heavy as lead + - hem and haw + - high and dry + - high and mighty + - high as a kite + - hit paydirt + - hold your head up high + - hold your horses + - hold your own + - hold your tongue + - honest as the day is long + - horns of a dilemma + - horse of a different color + - hot under the collar + - hour of need + - I beg to differ + - icing on the cake + - if the shoe fits + - if the shoe were on the other foot + - in a jam + - in a jiffy + - in a nutshell + - in a pig's eye + - in a pinch + - in a word + - in hot water + - in the gutter + - in the nick of time + - in the thick of it + - in your dreams + - it ain't over till the fat lady sings + - it goes without saying + - it takes all kinds + - it takes one to know one + - it's a small world + - it's only a matter of time + - ivory tower + - Jack of all trades + - jockey for position + - jog your memory + - joined at the hip + - judge a book by its cover + - jump down your throat + - jump in with both feet + - jump on the bandwagon + - jump the gun + - jump to conclusions + - just a hop, skip, and a jump + - just the ticket + - justice is blind + - keep a stiff upper lip + - keep an eye on + - keep it simple, stupid + - keep the home fires burning + - keep up with the Joneses + - keep your chin up + - keep your fingers crossed + - kick the bucket + - kick up your heels + - kick your feet up + - kid in a candy store + - kill two birds with one stone + - kiss of death + - knock it out of the park + - knock on wood + - knock your socks off + - know him from Adam + - know the ropes + - know the score + - knuckle down + - knuckle sandwich + - knuckle under + - labor of love + - ladder of success + - land on your feet + - lap of luxury + - last but not least + - last hurrah + - last-ditch effort + - law of the jungle + - law of the land + - lay down the law + - leaps and bounds + - let sleeping dogs lie + - let the cat out of the bag + - let the good times roll + - let your hair down + - let's talk turkey + - letter perfect + - lick your wounds + - lies like a rug + - life's a bitch + - life's a grind + - light at the end of the tunnel + - lighter than a feather + - lighter than air + - like clockwork + - like father like son + - like taking candy from a baby + - like there's no tomorrow + - lion's share + - live and learn + - live and let live + - long and short of it + - long lost love + - look before you leap + - look down your nose + - look what the cat dragged in + - looking a gift horse in the mouth + - looks like death warmed over + - loose cannon + - lose your head + - lose your temper + - loud as a horn + - lounge lizard + - loved and lost + - low man on the totem pole + - luck of the draw + - luck of the Irish + - make hay while the sun shines + - make money hand over fist + - make my day + - make the best of a bad situation + - make the best of it + - make your blood boil + - man of few words + - man's best friend + - mark my words + - meaningful dialogue + - missed the boat on that one + - moment in the sun + - moment of glory + - moment of truth + - money to burn + - more power to you + - more than one way to skin a cat + - movers and shakers + - moving experience + - naked as a jaybird + - naked truth + - neat as a pin + - needle in a haystack + - needless to say + - neither here nor there + - never look back + - never say never + - nip and tuck + - nip it in the bud + - no guts, no glory + - no love lost + - no pain, no gain + - no skin off my back + - no stone unturned + - no time like the present + - no use crying over spilled milk + - nose to the grindstone + - not a hope in hell + - not a minute's peace + - not in my backyard + - not playing with a full deck + - not the end of the world + - not written in stone + - nothing to sneeze at + - nothing ventured nothing gained + - now we're cooking + - off the top of my head + - off the wagon + - off the wall + - old hat + - older and wiser + - older than dirt + - older than Methuselah + - on a roll + - on cloud nine + - on pins and needles + - on the bandwagon + - on the money + - on the nose + - on the rocks + - on the spot + - on the tip of my tongue + - on the wagon + - on thin ice + - once bitten, twice shy + - one bad apple doesn't spoil the bushel + - one born every minute + - one brick short + - one foot in the grave + - one in a million + - one red cent + - only game in town + - open a can of worms + - open and shut case + - open the flood gates + - opportunity doesn't knock twice + - out of pocket + - out of sight, out of mind + - out of the frying pan into the fire + - out of the woods + - out on a limb + - over a barrel + - over the hump + - pain and suffering + - pain in the + - panic button + - par for the course + - part and parcel + - party pooper + - pass the buck + - patience is a virtue + - pay through the nose + - penny pincher + - perfect storm + - pig in a poke + - pile it on + - pillar of the community + - pin your hopes on + - pitter patter of little feet + - plain as day + - plain as the nose on your face + - play by the rules + - play your cards right + - playing the field + - playing with fire + - pleased as punch + - plenty of fish in the sea + - point with pride + - poor as a church mouse + - pot calling the kettle black + - pretty as a picture + - pull a fast one + - pull your punches + - pulling your leg + - pure as the driven snow + - put it in a nutshell + - put one over on you + - put the cart before the horse + - put the pedal to the metal + - put your best foot forward + - put your foot down + - quick as a bunny + - quick as a lick + - quick as a wink + - quick as lightning + - quiet as a dormouse + - rags to riches + - raining buckets + - raining cats and dogs + - rank and file + - rat race + - reap what you sow + - red as a beet + - red herring + - reinvent the wheel + - rich and famous + - rings a bell + - ripe old age + - ripped me off + - rise and shine + - road to hell is paved with good intentions + - rob Peter to pay Paul + - roll over in the grave + - rub the wrong way + - ruled the roost + - running in circles + - sad but true + - sadder but wiser + - salt of the earth + - scared stiff + - scared to death + - sealed with a kiss + - second to none + - see eye to eye + - seen the light + - seize the day + - set the record straight + - set the world on fire + - set your teeth on edge + - sharp as a tack + - shoot for the moon + - shoot the breeze + - shot in the dark + - shoulder to the wheel + - sick as a dog + - sigh of relief + - signed, sealed, and delivered + - sink or swim + - six of one, half a dozen of another + - skating on thin ice + - slept like a log + - slinging mud + - slippery as an eel + - slow as molasses + - smart as a whip + - smooth as a baby's bottom + - sneaking suspicion + - snug as a bug in a rug + - sow wild oats + - spare the rod, spoil the child + - speak of the devil + - spilled the beans + - spinning your wheels + - spitting image of + - spoke with relish + - spread like wildfire + - spring to life + - squeaky wheel gets the grease + - stands out like a sore thumb + - start from scratch + - stick in the mud + - still waters run deep + - stitch in time + - stop and smell the roses + - straight as an arrow + - straw that broke the camel's back + - strong as an ox + - stubborn as a mule + - stuff that dreams are made of + - stuffed shirt + - sweating blood + - sweating bullets + - take a load off + - take one for the team + - take the bait + - take the bull by the horns + - take the plunge + - takes one to know one + - takes two to tango + - the more the merrier + - the real deal + - the real McCoy + - the red carpet treatment + - the same old story + - there is no accounting for taste + - thick as a brick + - thick as thieves + - thin as a rail + - think outside of the box + - third time's the charm + - this day and age + - this hurts me worse than it hurts you + - this point in time + - three sheets to the wind + - through thick and thin + - throw in the towel + - tie one on + - tighter than a drum + - time and time again + - time is of the essence + - tip of the iceberg + - tired but happy + - to coin a phrase + - to each his own + - to make a long story short + - to the best of my knowledge + - toe the line + - tongue in cheek + - too good to be true + - too hot to handle + - too numerous to mention + - touch with a ten foot pole + - tough as nails + - trial and error + - trials and tribulations + - tried and true + - trip down memory lane + - twist of fate + - two cents worth + - two peas in a pod + - ugly as sin + - under the counter + - under the gun + - under the same roof + - under the weather + - until the cows come home + - unvarnished truth + - up the creek + - uphill battle + - upper crust + - upset the applecart + - vain attempt + - vain effort + - vanquish the enemy + - vested interest + - waiting for the other shoe to drop + - wakeup call + - warm welcome + - watch your p's and q's + - watch your tongue + - watching the clock + - water under the bridge + - weather the storm + - weed them out + - week of Sundays + - went belly up + - wet behind the ears + - what goes around comes around + - what you see is what you get + - when it rains, it pours + - when push comes to shove + - when the cat's away + - when the going gets tough, the tough get going + - white as a sheet + - whole ball of wax + - whole hog + - whole nine yards + - wild goose chase + - will wonders never cease? + - wisdom of the ages + - wise as an owl + - wolf at the door + - words fail me + - work like a dog + - world weary + - worst nightmare + - worth its weight in gold + - wrong side of the bed + - yanking your chain + - yappy as a dog + - years young + - you are what you eat + - you can run but you can't hide + - you only live once + - you're the boss + - young and foolish + - young and vibrant diff --git a/.vale/styles/write-good/E-Prime.yml b/.vale/styles/write-good/E-Prime.yml new file mode 100644 index 0000000..074a102 --- /dev/null +++ b/.vale/styles/write-good/E-Prime.yml @@ -0,0 +1,32 @@ +extends: existence +message: "Try to avoid using '%s'." +ignorecase: true +level: suggestion +tokens: + - am + - are + - aren't + - be + - been + - being + - he's + - here's + - here's + - how's + - i'm + - is + - isn't + - it's + - she's + - that's + - there's + - they're + - was + - wasn't + - we're + - were + - weren't + - what's + - where's + - who's + - you're diff --git a/.vale/styles/write-good/Illusions.yml b/.vale/styles/write-good/Illusions.yml new file mode 100644 index 0000000..b4f1321 --- /dev/null +++ b/.vale/styles/write-good/Illusions.yml @@ -0,0 +1,11 @@ +extends: repetition +message: "'%s' is repeated!" +level: warning +alpha: true +action: + name: edit + params: + - truncate + - " " +tokens: + - '[^\s]+' diff --git a/.vale/styles/write-good/Passive.yml b/.vale/styles/write-good/Passive.yml new file mode 100644 index 0000000..f472cb9 --- /dev/null +++ b/.vale/styles/write-good/Passive.yml @@ -0,0 +1,183 @@ +extends: existence +message: "'%s' may be passive voice. Use active voice if you can." +ignorecase: true +level: warning +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/.vale/styles/write-good/README.md b/.vale/styles/write-good/README.md new file mode 100644 index 0000000..3edcc9b --- /dev/null +++ b/.vale/styles/write-good/README.md @@ -0,0 +1,27 @@ +Based on [write-good](https://github.com/btford/write-good). + +> Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too. + +``` +The MIT License (MIT) + +Copyright (c) 2014 Brian Ford + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` diff --git a/.vale/styles/write-good/So.yml b/.vale/styles/write-good/So.yml new file mode 100644 index 0000000..e57f099 --- /dev/null +++ b/.vale/styles/write-good/So.yml @@ -0,0 +1,5 @@ +extends: existence +message: "Don't start a sentence with '%s'." +level: error +raw: + - '(?:[;-]\s)so[\s,]|\bSo[\s,]' diff --git a/.vale/styles/write-good/ThereIs.yml b/.vale/styles/write-good/ThereIs.yml new file mode 100644 index 0000000..8b82e8f --- /dev/null +++ b/.vale/styles/write-good/ThereIs.yml @@ -0,0 +1,6 @@ +extends: existence +message: "Don't start a sentence with '%s'." +ignorecase: false +level: error +raw: + - '(?:[;-]\s)There\s(is|are)|\bThere\s(is|are)\b' diff --git a/.vale/styles/write-good/TooWordy.yml b/.vale/styles/write-good/TooWordy.yml new file mode 100644 index 0000000..275701b --- /dev/null +++ b/.vale/styles/write-good/TooWordy.yml @@ -0,0 +1,221 @@ +extends: existence +message: "'%s' is too wordy." +ignorecase: true +level: warning +tokens: + - a number of + - abundance + - accede to + - accelerate + - accentuate + - accompany + - accomplish + - accorded + - accrue + - acquiesce + - acquire + - additional + - adjacent to + - adjustment + - admissible + - advantageous + - adversely impact + - advise + - aforementioned + - aggregate + - aircraft + - all of + - all things considered + - alleviate + - allocate + - along the lines of + - already existing + - alternatively + - amazing + - ameliorate + - anticipate + - apparent + - appreciable + - as a matter of fact + - as a means of + - as far as I'm concerned + - as of yet + - as to + - as yet + - ascertain + - assistance + - at the present time + - at this time + - attain + - attributable to + - authorize + - because of the fact that + - belated + - benefit from + - bestow + - by means of + - by virtue of + - by virtue of the fact that + - cease + - close proximity + - commence + - comply with + - concerning + - consequently + - consolidate + - constitutes + - demonstrate + - depart + - designate + - discontinue + - due to the fact that + - each and every + - economical + - eliminate + - elucidate + - employ + - endeavor + - enumerate + - equitable + - equivalent + - evaluate + - evidenced + - exclusively + - expedite + - expend + - expiration + - facilitate + - factual evidence + - feasible + - finalize + - first and foremost + - for all intents and purposes + - for the most part + - for the purpose of + - forfeit + - formulate + - have a tendency to + - honest truth + - however + - if and when + - impacted + - implement + - in a manner of speaking + - in a timely manner + - in a very real sense + - in accordance with + - in addition + - in all likelihood + - in an effort to + - in between + - in excess of + - in lieu of + - in light of the fact that + - in many cases + - in my opinion + - in order to + - in regard to + - in some instances + - in terms of + - in the case of + - in the event that + - in the final analysis + - in the nature of + - in the near future + - in the process of + - inception + - incumbent upon + - indicate + - indication + - initiate + - irregardless + - is applicable to + - is authorized to + - is responsible for + - it is + - it is essential + - it seems that + - it was + - magnitude + - maximum + - methodology + - minimize + - minimum + - modify + - monitor + - multiple + - necessitate + - nevertheless + - not certain + - not many + - not often + - not unless + - not unlike + - notwithstanding + - null and void + - numerous + - objective + - obligate + - obtain + - on the contrary + - on the other hand + - one particular + - optimum + - overall + - owing to the fact that + - participate + - particulars + - pass away + - pertaining to + - point in time + - portion + - possess + - preclude + - previously + - prior to + - prioritize + - procure + - proficiency + - provided that + - purchase + - put simply + - readily apparent + - refer back + - regarding + - relocate + - remainder + - remuneration + - requirement + - reside + - residence + - retain + - satisfy + - shall + - should you wish + - similar to + - solicit + - span across + - strategize + - subsequent + - substantial + - successfully complete + - sufficient + - terminate + - the month of + - the point I am trying to make + - therefore + - time period + - took advantage of + - transmit + - transpire + - type of + - until such time as + - utilization + - utilize + - validate + - various different + - what I mean to say is + - whether or not + - with respect to + - with the exception of + - witnessed diff --git a/.vale/styles/write-good/Weasel.yml b/.vale/styles/write-good/Weasel.yml new file mode 100644 index 0000000..d1d90a7 --- /dev/null +++ b/.vale/styles/write-good/Weasel.yml @@ -0,0 +1,29 @@ +extends: existence +message: "'%s' is a weasel word!" +ignorecase: true +level: warning +tokens: + - clearly + - completely + - exceedingly + - excellent + - extremely + - fairly + - huge + - interestingly + - is a number + - largely + - mostly + - obviously + - quite + - relatively + - remarkably + - several + - significantly + - substantially + - surprisingly + - tiny + - usually + - various + - vast + - very diff --git a/.vale/styles/write-good/meta.json b/.vale/styles/write-good/meta.json new file mode 100644 index 0000000..a115d28 --- /dev/null +++ b/.vale/styles/write-good/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/errata-ai/write-good/releases.atom", + "vale_version": ">=1.0.0" +} diff --git a/.woodpecker/Dockerfile b/.woodpecker/Dockerfile new file mode 100644 index 0000000..892a63a --- /dev/null +++ b/.woodpecker/Dockerfile @@ -0,0 +1,45 @@ +# Custom Docker image for Woodpecker CI +# Pre-installs common tools to speed up CI runs +# +# Build: docker build -t your-registry/ci:latest -f .woodpecker/Dockerfile . +# Push: docker push your-registry/ci:latest +# +# Then update .woodpecker/ci.yml to use: image: your-registry/ci:latest + +FROM rust:latest + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + shellcheck \ + curl \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Install just +RUN curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + +# Install Rust components +RUN rustup component add clippy rustfmt + +# Install Rust tools (pre-compiled to speed up CI) +RUN cargo install \ + cargo-audit \ + cargo-deny \ + cargo-sbom \ + nickel-lang-cli \ + nu \ + --locked + +# Set working directory +WORKDIR /workspace + +# Verify installations +RUN just --version && \ + cargo --version && \ + cargo audit --version && \ + cargo deny --version && \ + cargo sbom --version && \ + nickel --version && \ + nu --version + +CMD ["/bin/bash"] \ No newline at end of file diff --git a/.woodpecker/Dockerfile.cross b/.woodpecker/Dockerfile.cross new file mode 100644 index 0000000..ea1edca --- /dev/null +++ b/.woodpecker/Dockerfile.cross @@ -0,0 +1,42 @@ +# Dockerfile for cross-platform compilation +# Supports building for multiple targets using docker + +FROM ubuntu:22.04 + +# Install build essentials +RUN apt-get update && apt-get install -y \ + build-essential \ + curl \ + git \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Install Rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install cross tool for cross-compilation +RUN cargo install cross --locked + +# Create workspace directory +WORKDIR /workspace + +# Copy entire project +COPY . . + +# Default build target +ARG TARGET=x86_64-unknown-linux-gnu +ENV BUILD_TARGET="${TARGET}" + +# Build command +RUN cross build --target "${BUILD_TARGET}" --release + +# Extract binaries to output directory +RUN mkdir -p /output/bin && \ + find target/"${BUILD_TARGET}"/release -maxdepth 1 -type f -executable -exec cp {} /output/bin/ \; + +# Create manifest +RUN echo "{ \"target\": \"${BUILD_TARGET}\", \"built\": \"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\" }" > /output/BUILD_INFO.json + +# Default command +CMD ["/bin/bash"] \ No newline at end of file diff --git a/.woodpecker/README.md b/.woodpecker/README.md new file mode 100644 index 0000000..58b4853 --- /dev/null +++ b/.woodpecker/README.md @@ -0,0 +1,78 @@ +# Woodpecker CI Configuration + +Pipelines for Gitea/Forgejo + Woodpecker CI. + +## Files + +- **`ci.yml`** - Main CI pipeline (push, pull requests) +- **`Dockerfile`** - Custom CI image with pre-installed tools +- **`Dockerfile.cross`** - Cross-compilation image for multi-platform builds + +## Setup + +### 1. Activate Woodpecker CI + +Enable Woodpecker CI in your Gitea/Forgejo repository settings. + +### 2. (Optional) Build Custom Image + +Speeds up CI by pre-installing tools (~5 min faster per run). + +```bash +# Build CI image +docker build -t your-registry/ci:latest -f .woodpecker/Dockerfile . + +# Push to your registry +docker push your-registry/ci:latest + +# Update .woodpecker/ci.yml +# Change: image: rust:latest +# To: image: your-registry/ci:latest +``` + +### 3. Cross-Compilation Setup + +For multi-platform builds: + +```bash +# Build cross-compilation image +docker build -t your-registry/ci-cross:latest -f .woodpecker/Dockerfile.cross . + +# Push to registry +docker push your-registry/ci-cross:latest +``` + +## CI Pipeline (`ci.yml`) + +**Triggers**: Push to `main`/`develop`, Pull Requests + +**Jobs**: +1. Lint (Rust, Bash, Nickel, Nushell, Markdown) - Parallel +2. Test (all features) +3. Build (release) +4. Security audit +5. License compliance check + +**Duration**: ~15-20 minutes (without custom image), ~10-15 minutes (with custom image) + +## Triggering Pipelines + +```bash +# CI pipeline (automatic on push/PR) +git push origin main +``` + +## Viewing Results + +- **Gitea/Forgejo**: Repository β†’ Actions β†’ Pipeline runs +- **Woodpecker UI**: https://your-woodpecker.instance/repos/{user}/{repo} + +## Differences from GitHub Actions + +| Feature | GitHub Actions | Woodpecker CI | +|---------|---------------|---------------| +| Matrix builds | βœ… 3 OS | ❌ Linux only* | +| Caching | βœ… Built-in | ⚠️ Server-side** | + +\* Multi-OS builds require multiple Woodpecker agents +\*\* Configure in Woodpecker server settings diff --git a/.woodpecker/ci-advanced.yml b/.woodpecker/ci-advanced.yml new file mode 100644 index 0000000..3bda3c4 --- /dev/null +++ b/.woodpecker/ci-advanced.yml @@ -0,0 +1,168 @@ +# Woodpecker CI - Advanced Pipeline +# Multi-platform builds, coverage, benchmarks, and security scanning + +when: + event: [push, pull_request, manual] + branch: + - main + - develop + +matrix: + PLATFORM: + - linux/amd64 + - linux/arm64 + +steps: + # === LINTING (Parallel) === + + lint-rust: + image: rust:latest + commands: + - curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + - rustup component add clippy rustfmt + - cargo fmt --all -- --check + - cargo clippy --all-targets --all-features -- -D warnings + environment: + CARGO_TERM_COLOR: always + + lint-bash: + image: koalaman/shellcheck-alpine:stable + commands: + - apk add --no-cache curl bash + - find . -name '*.sh' -type f ! -path './target/*' -exec shellcheck {} + + + lint-nickel: + image: rust:latest + commands: + - cargo install nickel-lang-cli --locked + - find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \; + + lint-nushell: + image: rust:latest + commands: + - cargo install nu --locked + - find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \; + + lint-markdown: + image: node:alpine + commands: + - npm install -g markdownlint-cli2 + - markdownlint-cli2 '**/*.md' '#node_modules' '#target' + + # === TESTING === + + test: + image: rust:latest + commands: + - cargo test --workspace --all-features --no-fail-fast + depends_on: + - lint-rust + - lint-bash + - lint-nickel + - lint-nushell + - lint-markdown + environment: + RUST_BACKTRACE: 1 + + # === CODE COVERAGE === + + coverage: + image: rust:latest + commands: + - cargo install cargo-tarpaulin --locked + - cargo tarpaulin --workspace --all-features --out Xml --output-dir coverage + - | + if [ -f coverage/cobertura.xml ]; then + echo "Coverage report generated successfully" + fi + depends_on: + - test + when: + event: [push, pull_request] + branch: [main, develop] + + # === BUILD (Multi-platform) === + + build-native: + image: rust:latest + commands: + - cargo build --release --workspace + - ls -lh target/release/ + depends_on: + - test + + build-cross: + image: rust:latest + commands: + - cargo install cross --locked + - cross build --target x86_64-unknown-linux-musl --release + - cross build --target aarch64-unknown-linux-musl --release + depends_on: + - test + when: + matrix: + PLATFORM: linux/amd64 + + # === BENCHMARKS === + + benchmark: + image: rust:latest + commands: + - rustup toolchain install nightly + - cargo +nightly bench --workspace --no-fail-fast + - | + if [ -d target/criterion ]; then + echo "Benchmark results available in target/criterion" + fi + depends_on: + - build-native + when: + event: pull_request + + # === SECURITY AUDITS === + + security-audit: + image: rust:latest + commands: + - cargo install cargo-audit --locked + - cargo audit --deny warnings --deny unmaintained --deny unsound + depends_on: + - lint-rust + + license-check: + image: rust:latest + commands: + - cargo install cargo-deny --locked + - cargo deny check licenses advisories sources bans + depends_on: + - lint-rust + + dependency-check: + image: rust:latest + commands: + - cargo install cargo-outdated --locked + - cargo outdated --exit-code 1 --root-deps-only + depends_on: + - lint-rust + when: + event: manual + + # === SONARQUBE ANALYSIS === + + sonarqube: + image: sonarsource/sonar-scanner-cli:latest + commands: + - | + sonar-scanner \ + -Dsonar.projectKey=${CI_REPO_NAME} \ + -Dsonar.sources=. \ + -Dsonar.host.url=${SONAR_HOST_URL} \ + -Dsonar.token=${SONAR_TOKEN} \ + -Dsonar.rust.clippy.reportPaths=clippy-report.json \ + -Dsonar.coverageReportPaths=coverage/cobertura.xml + depends_on: + - coverage + secrets: [sonar_host_url, sonar_token] + when: + event: [push, pull_request] + branch: [main, develop] diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml new file mode 100644 index 0000000..be8aba9 --- /dev/null +++ b/.woodpecker/ci.yml @@ -0,0 +1,84 @@ +# Woodpecker CI Pipeline +# Equivalent to GitHub Actions CI workflow +# Generated by dev-system/ci + +when: + event: [push, pull_request, manual] + branch: + - main + - develop + +steps: + # === LINTING === + + lint-rust: + image: rust:latest + commands: + - curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + - rustup component add clippy + - cargo fmt --all -- --check + - cargo clippy --all-targets -- -D warnings + + lint-bash: + image: koalaman/shellcheck-alpine:stable + commands: + - apk add --no-cache curl bash + - find . -name '*.sh' -type f ! -path './target/*' -exec shellcheck {} + + + lint-nickel: + image: rust:latest + commands: + - cargo install nickel-lang-cli --locked + - find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \; + + lint-nushell: + image: rust:latest + commands: + - cargo install nu --locked + - find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \; + + lint-markdown: + image: node:alpine + commands: + - npm install -g markdownlint-cli2 + - markdownlint-cli2 '**/*.md' '#node_modules' '#target' + + # === TESTING === + + test: + image: rust:latest + commands: + - cargo test --workspace --all-features + depends_on: + - lint-rust + - lint-bash + - lint-nickel + - lint-nushell + - lint-markdown + + # === BUILD === + + build: + image: rust:latest + commands: + - cargo build --release + depends_on: + - test + + # === SECURITY === + + security-audit: + image: rust:latest + commands: + - cargo install cargo-audit --locked + - cargo audit --deny warnings + depends_on: + - lint-rust + + license-check: + image: rust:latest + commands: + - cargo install cargo-deny --locked + - cargo deny check licenses advisories + depends_on: + - lint-rust diff --git a/.yamllint-ci.yml b/.yamllint-ci.yml new file mode 100644 index 0000000..3575afe --- /dev/null +++ b/.yamllint-ci.yml @@ -0,0 +1,18 @@ +extends: default + +rules: + line-length: + max: 200 # More reasonable for infrastructure code + comments: + min-spaces-from-content: 1 # Allow single space before comments + document-start: disable # Cloud-init files don't need --- start + truthy: + allowed-values: ["true", "false", "yes", "no", "on", "off"] # Allow cloud-init and GitHub Actions common values + +# Ignore cloud-init files for comment spacing since #cloud-config is a special directive +# Ignore directories with generated/runtime files +ignore: | + **/cloud-init.yml + build/** + data/** + envs/** diff --git a/config/defaults.ncl b/config/defaults.ncl new file mode 100644 index 0000000..2ddc47c --- /dev/null +++ b/config/defaults.ncl @@ -0,0 +1,157 @@ +# Default Knowledge Base Configuration +# +# This file provides sensible defaults for a project-local knowledge base. +# Copy to `.kogral/config.ncl` and customize as needed. +# +# Usage: +# nickel export --format json defaults.ncl > .kogral/config.json +# With custom TOOLS_PATH: +# TOOLS_PATH=/opt/mytools nickel export --format json defaults.ncl > .kogral/config.json +# +# Paths use $TOOLS_PATH variable which resolves to: +# - Value of TOOLS_PATH environment variable if set +# - $HOME/Tools if TOOLS_PATH not set +# - /tmp/tools as final fallback + +let Schema = import "../schemas/kogral-config.ncl" in + +{ + graph = { + name = "my-project", + version = "1.0.0", + description = "Project knowledge base", + }, + + inheritance = { + # Inherit from shared KOGRAL (resolves via TOOLS_PATH env var) + base = "$TOOLS_PATH/.kogral-shared", + + # Additional guideline paths (also resolve via TOOLS_PATH env var) + guidelines = [ + "$TOOLS_PATH/.claude/guidelines/rust", + "$TOOLS_PATH/.claude/guidelines/nushell", + ], + + priority = 100, + }, + + storage = { + # Primary storage: filesystem (git-friendly) + primary = 'filesystem, + + # Secondary storage: disabled by default + secondary = { + enabled = false, + type = 'surrealdb, + url = "ws://localhost:8000", + namespace = "kogral", + database = "default", + }, + }, + + embeddings = { + enabled = true, + + # Use local fastembed by default (no API key needed) + provider = 'fastembed, + model = "BAAI/bge-small-en-v1.5", + dimensions = 384, + + # For API providers (openai, claude, ollama), specify API key env var + api_key_env = "OPENAI_API_KEY", + }, + + blocks = { + # Enable Logseq content blocks support (opt-in feature) + enabled = false, + + # Auto-parse blocks when importing from Logseq + parse_on_import = true, + + # Serialize blocks to outliner format on export + serialize_on_export = true, + + # Enable block-related MCP tools (kogral/find_blocks, kogral/find_todos, kogral/find_cards) + enable_mcp_tools = true, + }, + + templates = { + templates_dir = "templates", + + # Node type templates + templates = { + note = "note.md.tera", + decision = "decision.md.tera", + guideline = "guideline.md.tera", + pattern = "pattern.md.tera", + journal = "journal.md.tera", + execution = "execution.md.tera", + }, + + # Export templates + export = { + logseq_page = "export/logseq-page.md.tera", + logseq_journal = "export/logseq-journal.md.tera", + summary = "export/summary.md.tera", + json = "export/graph.json.tera", + }, + + # Custom templates (add your own) + custom = {}, + }, + + query = { + # Semantic search threshold (0.0 = any match, 1.0 = exact match) + similarity_threshold = 0.4, + + # Maximum results to return + max_results = 10, + + # Recency bias (higher = prefer newer content) + recency_weight = 3.0, + + # Enable cross-graph queries (local + shared) + cross_graph = true, + }, + + mcp = { + server = { + name = "kogral-mcp", + version = "1.0.0", + transport = 'stdio, + }, + + # Enable/disable MCP tools + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + + # Expose resources via MCP + resources = { + expose_project = true, + expose_shared = true, + }, + }, + + sync = { + # Auto-sync filesystem changes to secondary storage + auto_index = true, + + # Paths to watch for changes + watch_paths = [ + "notes", + "decisions", + "guidelines", + "patterns", + "journal", + ], + + # Debounce time (ms) before syncing + debounce_ms = 500, + }, +} | Schema.KbConfig diff --git a/config/minimal.ncl b/config/minimal.ncl new file mode 100644 index 0000000..f880401 --- /dev/null +++ b/config/minimal.ncl @@ -0,0 +1,17 @@ +# Minimal Knowledge Base Configuration +# +# Minimal configuration with only essential settings. +# Useful for quick setup or embedded use cases. +# +# Usage: +# nickel export --format json minimal.ncl > .kogral/config.json + +let Schema = import "../schemas/kogral-config.ncl" in + +{ + graph = { + name = "minimal", + }, + + # Everything else uses defaults +} | Schema.KbConfig diff --git a/config/production.ncl b/config/production.ncl new file mode 100644 index 0000000..0261a0b --- /dev/null +++ b/config/production.ncl @@ -0,0 +1,136 @@ +# Production Knowledge Base Configuration +# +# Configuration for a shared/production KB with SurrealDB backend. +# Suitable for team-wide knowledge bases or central documentation. +# +# Usage: +# nickel export --format json production.ncl > config.json +# With custom TOOLS_PATH: +# TOOLS_PATH=/opt/mytools nickel export --format json production.ncl > config.json +# +# Paths use $TOOLS_PATH variable which resolves to: +# - Value of TOOLS_PATH environment variable if set +# - $HOME/Tools if TOOLS_PATH not set +# - /tmp/tools as final fallback + +let Schema = import "../schemas/kogral-config.ncl" in + +{ + graph = { + name = "tools-ecosystem", + version = "1.0.0", + description = "Shared knowledge base for Tools ecosystem", + }, + + inheritance = { + # This is the central KOGRAL, no inheritance (this path is itself the shared store) + base = "$TOOLS_PATH/.kogral-shared", + guidelines = [], + priority = 200, # Higher priority (wins over project-local) + }, + + storage = { + # Primary: still filesystem for git-friendly versioning + primary = 'filesystem, + + # Secondary: SurrealDB for scalable queries + secondary = { + enabled = true, + type = 'surrealdb, + url = "ws://localhost:8000", + namespace = "tools_kogral", + database = "production", + }, + }, + + embeddings = { + enabled = true, + + # Use API provider for better quality + provider = 'openai, + model = "text-embedding-3-small", + dimensions = 1536, + api_key_env = "OPENAI_API_KEY", + + # Alternative: use Claude + # provider = 'claude, + # model = "claude-3-haiku", + # api_key_env = "ANTHROPIC_API_KEY", + }, + + blocks = { + # Enable blocks for Logseq compatibility in production + enabled = true, + parse_on_import = true, + serialize_on_export = true, + enable_mcp_tools = true, + }, + + templates = { + templates_dir = "templates", + + templates = { + note = "note.md.tera", + decision = "decision.md.tera", + guideline = "guideline.md.tera", + pattern = "pattern.md.tera", + journal = "journal.md.tera", + execution = "execution.md.tera", + }, + + export = { + logseq_page = "export/logseq-page.md.tera", + logseq_journal = "export/logseq-journal.md.tera", + summary = "export/summary.md.tera", + json = "export/graph.json.tera", + }, + + custom = {}, + }, + + query = { + # Stricter threshold for production + similarity_threshold = 0.5, + max_results = 20, + recency_weight = 2.0, + cross_graph = false, # Only search this graph + }, + + mcp = { + server = { + name = "kogral-mcp-production", + version = "1.0.0", + transport = 'stdio, + }, + + tools = { + search = true, + add_note = true, + add_decision = true, + link = true, + get_guidelines = true, + export = true, + }, + + resources = { + expose_project = true, + expose_shared = true, + }, + }, + + sync = { + # Active sync to SurrealDB + auto_index = true, + + watch_paths = [ + "notes", + "decisions", + "guidelines", + "patterns", + "journal", + ], + + # Faster sync for production + debounce_ms = 300, + }, +} | Schema.KbConfig diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..a6a8652 --- /dev/null +++ b/deny.toml @@ -0,0 +1,74 @@ +# Generated by dev-system/ci +# Configuration for cargo-deny +# See: https://embarkstudios.github.io/cargo-deny/ + +[advisories] +# The path where the advisory database is cloned/fetched into +db-path = "~/.cargo/advisory-db" +# The url(s) of the advisory databases to use +db-urls = ["https://github.com/rustsec/advisory-db"] +# How to handle crates with security vulnerabilities +vulnerability = "deny" +# How to handle unmaintained crates +unmaintained = "warn" +# How to handle crates that have been yanked from crates.io +yanked = "warn" + +[licenses] +# The lint level for crates which do not have a detectable license +unlicensed = "deny" +# List of explicitly allowed licenses +allow = [ + "MIT", + "MIT-0", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Unicode-DFS-2016", +] +# List of explicitly disallowed licenses +deny = [ + "GPL-2.0", + "GPL-3.0", + "AGPL-3.0", +] +# Lint level for licenses considered copyleft +copyleft = "warn" +# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses +allow-osi-fsf-free = "both" +# Lint level used when no other predicates are matched +default = "deny" + +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when an allow-listed crate is detected without an exact version +allow = [ + # Each entry can be just the name and an optional wildcard version. + # This would ideally be pulled from Cargo.lock deps to keep up to date + # but that is more complex. It depends on the use case. +] +# Each entry must be a single version number +deny = [ + # Each entry is a crate name. Optionally with a version +] +# Certain crates/versions that will be skipped when doing duplicate detection +skip = [ + # { name = "ansi_term", version = "<= 0.11.0" } +] +# Similarly named crates that are allowed to coexist +skip-tree = [ + # { name = "windows", version = "<=0.46.0" } +] + +[sources] +# Lint level for what to happen when a crate from a crate registry that is not in the allow list is detected +unknown-registry = "deny" +# Lint level for what to happen when a crate from a Git repository that is not in the allow list is detected +unknown-git = "deny" +# The allow list of crate registries +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# The allow list of Git repositories +allow-git = []