chore: add ci defs files
This commit is contained in:
parent
22e9473e69
commit
2b4d548aad
37
.cargo/audit.toml
Normal file
37
.cargo/audit.toml
Normal file
@ -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"
|
||||
72
.cargo/config.toml
Normal file
72
.cargo/config.toml
Normal file
@ -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"
|
||||
17
.clippy.toml
Normal file
17
.clippy.toml
Normal file
@ -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
|
||||
116
.github/workflows/nickel-typecheck.yml
vendored
Normal file
116
.github/workflows/nickel-typecheck.yml
vendored
Normal file
@ -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"
|
||||
47
.github/workflows/rust-ci.yml
vendored
Normal file
47
.github/workflows/rust-ci.yml
vendored
Normal file
@ -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
|
||||
67
.gitignore
vendored
Normal file
67
.gitignore
vendored
Normal file
@ -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
|
||||
83
.kb-config/README.md
Normal file
83
.kb-config/README.md
Normal file
@ -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
|
||||
56
.kb-config/core/kb.ncl
Normal file
56
.kb-config/core/kb.ncl
Normal file
@ -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
|
||||
53
.kb-config/platform/dev.ncl
Normal file
53
.kb-config/platform/dev.ncl
Normal file
@ -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
|
||||
73
.kb-config/platform/prod.ncl
Normal file
73
.kb-config/platform/prod.ncl
Normal file
@ -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
|
||||
67
.kb-config/platform/test.ncl
Normal file
67
.kb-config/platform/test.ncl
Normal file
@ -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
|
||||
36
.kogral/config.dev.json
Normal file
36
.kogral/config.dev.json
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
36
.kogral/config.json
Normal file
36
.kogral/config.json
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
45
.kogral/config.prod.json
Normal file
45
.kogral/config.prod.json
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
40
.kogral/config.test.json
Normal file
40
.kogral/config.test.json
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
110
.markdownlint-cli2.jsonc
Normal file
110
.markdownlint-cli2.jsonc
Normal file
@ -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/**"
|
||||
]
|
||||
}
|
||||
128
.pre-commit-config.yaml
Normal file
128
.pre-commit-config.yaml
Normal file
@ -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
|
||||
53
.rustfmt.toml
Normal file
53
.rustfmt.toml
Normal file
@ -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
|
||||
40
.shellcheckrc
Normal file
40
.shellcheckrc
Normal file
@ -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
|
||||
49
.taplo.toml
Normal file
49
.taplo.toml
Normal file
@ -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"]
|
||||
162
.typedialog/README.md
Normal file
162
.typedialog/README.md
Normal file
@ -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
|
||||
317
.typedialog/ci/README.md
Normal file
317
.typedialog/ci/README.md
Normal file
@ -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="<local or Tools path to config.ncl.j2>"
|
||||
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
|
||||
120
.typedialog/ci/config.ncl
Normal file
120
.typedialog/ci/config.ncl
Normal file
@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
203
.typedialog/ci/config.ncl.20260117_193849.bak
Normal file
203
.typedialog/ci/config.ncl.20260117_193849.bak
Normal file
@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
116
.typedialog/ci/configure.sh
Executable file
116
.typedialog/ci/configure.sh
Executable file
@ -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
|
||||
27
.typedialog/ci/envrc
Normal file
27
.typedialog/ci/envrc
Normal file
@ -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}}
|
||||
189
.typedialog/ci/form.toml
Normal file
189
.typedialog/ci/form.toml
Normal file
@ -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"
|
||||
290
.typedialog/kogral/ARCHITECTURE.md
Normal file
290
.typedialog/kogral/ARCHITECTURE.md
Normal file
@ -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
|
||||
156
.typedialog/kogral/FORM-TO-TEMPLATE-MAPPING.md
Normal file
156
.typedialog/kogral/FORM-TO-TEMPLATE-MAPPING.md
Normal file
@ -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.
|
||||
211
.typedialog/kogral/README.md
Normal file
211
.typedialog/kogral/README.md
Normal file
@ -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)
|
||||
56
.typedialog/kogral/SYNC.md
Normal file
56
.typedialog/kogral/SYNC.md
Normal file
@ -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.
|
||||
268
.typedialog/kogral/core/contracts.ncl
Normal file
268
.typedialog/kogral/core/contracts.ncl
Normal file
@ -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 = {},
|
||||
},
|
||||
}
|
||||
97
.typedialog/kogral/core/defaults.ncl
Normal file
97
.typedialog/kogral/core/defaults.ncl
Normal file
@ -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,
|
||||
}
|
||||
111
.typedialog/kogral/core/helpers.ncl
Normal file
111
.typedialog/kogral/core/helpers.ncl
Normal file
@ -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,
|
||||
}
|
||||
111
.typedialog/kogral/forms/README.md
Normal file
111
.typedialog/kogral/forms/README.md
Normal file
@ -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`
|
||||
57
.typedialog/kogral/forms/fragments/embeddings.toml
Normal file
57
.typedialog/kogral/forms/fragments/embeddings.toml
Normal file
@ -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'"
|
||||
34
.typedialog/kogral/forms/fragments/graph.toml
Normal file
34
.typedialog/kogral/forms/fragments/graph.toml
Normal file
@ -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"
|
||||
113
.typedialog/kogral/forms/fragments/mcp.toml
Normal file
113
.typedialog/kogral/forms/fragments/mcp.toml
Normal file
@ -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"
|
||||
49
.typedialog/kogral/forms/fragments/query.toml
Normal file
49
.typedialog/kogral/forms/fragments/query.toml
Normal file
@ -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"
|
||||
64
.typedialog/kogral/forms/fragments/storage.toml
Normal file
64
.typedialog/kogral/forms/fragments/storage.toml
Normal file
@ -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'"
|
||||
42
.typedialog/kogral/forms/fragments/sync.toml
Normal file
42
.typedialog/kogral/forms/fragments/sync.toml
Normal file
@ -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"
|
||||
76
.typedialog/kogral/forms/kogral-config.toml
Normal file
76
.typedialog/kogral/forms/kogral-config.toml
Normal file
@ -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"
|
||||
48
.typedialog/kogral/modes/dev.ncl
Normal file
48
.typedialog/kogral/modes/dev.ncl
Normal file
@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
57
.typedialog/kogral/modes/prod.ncl
Normal file
57
.typedialog/kogral/modes/prod.ncl
Normal file
@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
52
.typedialog/kogral/modes/test.ncl
Normal file
52
.typedialog/kogral/modes/test.ncl
Normal file
@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
55
.typedialog/kogral/scripts/generate-configs.nu
Normal file
55
.typedialog/kogral/scripts/generate-configs.nu
Normal file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env nu
|
||||
# Generate configuration files from Nickel schemas
|
||||
#
|
||||
# Usage: nu generate-configs.nu [--mode <dev|prod|test>] [--output <dir>]
|
||||
|
||||
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
|
||||
72
.typedialog/kogral/scripts/validate-config.nu
Normal file
72
.typedialog/kogral/scripts/validate-config.nu
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env nu
|
||||
# Validate KOGRAL configuration schemas
|
||||
#
|
||||
# Usage: nu validate-config.nu [--schema <file>]
|
||||
|
||||
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
|
||||
84
.typedialog/kogral/templates/config.json.tera
Normal file
84
.typedialog/kogral/templates/config.json.tera
Normal file
@ -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 }}
|
||||
}
|
||||
}
|
||||
41
.vale.ini
Normal file
41
.vale.ini
Normal file
@ -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
|
||||
25
.vale/Vocab/TypeDialog/accept.txt
Normal file
25
.vale/Vocab/TypeDialog/accept.txt
Normal file
@ -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
|
||||
2
.vale/Vocab/TypeDialog/reject.txt
Normal file
2
.vale/Vocab/TypeDialog/reject.txt
Normal file
@ -0,0 +1,2 @@
|
||||
# TypeDialog rejected terms
|
||||
# Add terms that should never be used
|
||||
9
.vale/styles/Google/AMPM.yml
Normal file
9
.vale/styles/Google/AMPM.yml
Normal file
@ -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]\.'
|
||||
64
.vale/styles/Google/Acronyms.yml
Normal file
64
.vale/styles/Google/Acronyms.yml
Normal file
@ -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
|
||||
8
.vale/styles/Google/Colons.yml
Normal file
8
.vale/styles/Google/Colons.yml
Normal file
@ -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:
|
||||
- '(?<!:[^ ]+?):\s[A-Z]'
|
||||
30
.vale/styles/Google/Contractions.yml
Normal file
30
.vale/styles/Google/Contractions.yml
Normal file
@ -0,0 +1,30 @@
|
||||
extends: substitution
|
||||
message: "Use '%s' instead of '%s'."
|
||||
link: 'https://developers.google.com/style/contractions'
|
||||
level: suggestion
|
||||
ignorecase: true
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
are not: aren't
|
||||
cannot: can't
|
||||
could not: couldn't
|
||||
did not: didn't
|
||||
do not: don't
|
||||
does not: doesn't
|
||||
has not: hasn't
|
||||
have not: haven't
|
||||
how is: how's
|
||||
is not: isn't
|
||||
it is: it's
|
||||
should not: shouldn't
|
||||
that is: that's
|
||||
they are: they're
|
||||
was not: wasn't
|
||||
we are: we're
|
||||
we have: we've
|
||||
were not: weren't
|
||||
what is: what's
|
||||
when is: when's
|
||||
where is: where's
|
||||
will not: won't
|
||||
9
.vale/styles/Google/DateFormat.yml
Normal file
9
.vale/styles/Google/DateFormat.yml
Normal file
@ -0,0 +1,9 @@
|
||||
extends: existence
|
||||
message: "Use 'July 31, 2016' format, not '%s'."
|
||||
link: 'https://developers.google.com/style/dates-times'
|
||||
ignorecase: true
|
||||
level: error
|
||||
nonword: true
|
||||
tokens:
|
||||
- '\d{1,2}(?:\.|/)\d{1,2}(?:\.|/)\d{4}'
|
||||
- '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?) \d{4}'
|
||||
9
.vale/styles/Google/Ellipses.yml
Normal file
9
.vale/styles/Google/Ellipses.yml
Normal file
@ -0,0 +1,9 @@
|
||||
extends: existence
|
||||
message: "In general, don't use an ellipsis."
|
||||
link: 'https://developers.google.com/style/ellipses'
|
||||
nonword: true
|
||||
level: warning
|
||||
action:
|
||||
name: remove
|
||||
tokens:
|
||||
- '\.\.\.'
|
||||
12
.vale/styles/Google/EmDash.yml
Normal file
12
.vale/styles/Google/EmDash.yml
Normal file
@ -0,0 +1,12 @@
|
||||
extends: existence
|
||||
message: "Don't put a space before or after a dash."
|
||||
link: "https://developers.google.com/style/dashes"
|
||||
nonword: true
|
||||
level: error
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- trim
|
||||
- " "
|
||||
tokens:
|
||||
- '\s[—–]\s'
|
||||
12
.vale/styles/Google/Exclamation.yml
Normal file
12
.vale/styles/Google/Exclamation.yml
Normal file
@ -0,0 +1,12 @@
|
||||
extends: existence
|
||||
message: "Don't use exclamation points in text."
|
||||
link: "https://developers.google.com/style/exclamation-points"
|
||||
nonword: true
|
||||
level: error
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- trim_right
|
||||
- "!"
|
||||
tokens:
|
||||
- '\w+!(?:\s|$)'
|
||||
13
.vale/styles/Google/FirstPerson.yml
Normal file
13
.vale/styles/Google/FirstPerson.yml
Normal file
@ -0,0 +1,13 @@
|
||||
extends: existence
|
||||
message: "Avoid first-person pronouns such as '%s'."
|
||||
link: 'https://developers.google.com/style/pronouns#personal-pronouns'
|
||||
ignorecase: true
|
||||
level: warning
|
||||
nonword: true
|
||||
tokens:
|
||||
- (?:^|\s)I\s
|
||||
- (?:^|\s)I,\s
|
||||
- \bI'm\b
|
||||
- \bme\b
|
||||
- \bmy\b
|
||||
- \bmine\b
|
||||
9
.vale/styles/Google/Gender.yml
Normal file
9
.vale/styles/Google/Gender.yml
Normal file
@ -0,0 +1,9 @@
|
||||
extends: existence
|
||||
message: "Don't use '%s' as a gender-neutral pronoun."
|
||||
link: 'https://developers.google.com/style/pronouns#gender-neutral-pronouns'
|
||||
level: error
|
||||
ignorecase: true
|
||||
tokens:
|
||||
- he/she
|
||||
- s/he
|
||||
- \(s\)he
|
||||
43
.vale/styles/Google/GenderBias.yml
Normal file
43
.vale/styles/Google/GenderBias.yml
Normal file
@ -0,0 +1,43 @@
|
||||
extends: substitution
|
||||
message: "Consider using '%s' instead of '%s'."
|
||||
ignorecase: true
|
||||
link: "https://developers.google.com/style/inclusive-documentation"
|
||||
level: error
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
(?:alumna|alumnus): graduate
|
||||
(?:alumnae|alumni): graduates
|
||||
air(?:m[ae]n|wom[ae]n): pilot(s)
|
||||
anchor(?:m[ae]n|wom[ae]n): anchor(s)
|
||||
authoress: author
|
||||
camera(?:m[ae]n|wom[ae]n): camera operator(s)
|
||||
door(?:m[ae]|wom[ae]n): concierge(s)
|
||||
draft(?:m[ae]n|wom[ae]n): drafter(s)
|
||||
fire(?:m[ae]n|wom[ae]n): firefighter(s)
|
||||
fisher(?:m[ae]n|wom[ae]n): fisher(s)
|
||||
fresh(?:m[ae]n|wom[ae]n): first-year student(s)
|
||||
garbage(?:m[ae]n|wom[ae]n): waste collector(s)
|
||||
lady lawyer: lawyer
|
||||
ladylike: courteous
|
||||
mail(?:m[ae]n|wom[ae]n): mail carriers
|
||||
man and wife: husband and wife
|
||||
man enough: strong enough
|
||||
mankind: human kind|humanity
|
||||
manmade: manufactured
|
||||
manpower: personnel
|
||||
middle(?:m[ae]n|wom[ae]n): intermediary
|
||||
news(?:m[ae]n|wom[ae]n): journalist(s)
|
||||
ombuds(?:man|woman): ombuds
|
||||
oneupmanship: upstaging
|
||||
poetess: poet
|
||||
police(?:m[ae]n|wom[ae]n): police officer(s)
|
||||
repair(?:m[ae]n|wom[ae]n): technician(s)
|
||||
sales(?:m[ae]n|wom[ae]n): salesperson or sales people
|
||||
service(?:m[ae]n|wom[ae]n): soldier(s)
|
||||
steward(?:ess)?: flight attendant
|
||||
tribes(?:m[ae]n|wom[ae]n): tribe member(s)
|
||||
waitress: waiter
|
||||
woman doctor: doctor
|
||||
woman scientist[s]?: scientist(s)
|
||||
work(?:m[ae]n|wom[ae]n): worker(s)
|
||||
13
.vale/styles/Google/HeadingPunctuation.yml
Normal file
13
.vale/styles/Google/HeadingPunctuation.yml
Normal file
@ -0,0 +1,13 @@
|
||||
extends: existence
|
||||
message: "Don't put a period at the end of a heading."
|
||||
link: "https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings"
|
||||
nonword: true
|
||||
level: warning
|
||||
scope: heading
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- trim_right
|
||||
- "."
|
||||
tokens:
|
||||
- '[a-z0-9][.]\s*$'
|
||||
29
.vale/styles/Google/Headings.yml
Normal file
29
.vale/styles/Google/Headings.yml
Normal file
@ -0,0 +1,29 @@
|
||||
extends: capitalization
|
||||
message: "'%s' should use sentence-style capitalization."
|
||||
link: "https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings"
|
||||
level: warning
|
||||
scope: heading
|
||||
match: $sentence
|
||||
indicators:
|
||||
- ":"
|
||||
exceptions:
|
||||
- Azure
|
||||
- CLI
|
||||
- Cosmos
|
||||
- Docker
|
||||
- Emmet
|
||||
- gRPC
|
||||
- I
|
||||
- Kubernetes
|
||||
- Linux
|
||||
- macOS
|
||||
- Marketplace
|
||||
- MongoDB
|
||||
- REPL
|
||||
- Studio
|
||||
- TypeScript
|
||||
- URLs
|
||||
- Visual
|
||||
- VS
|
||||
- Windows
|
||||
- JSON
|
||||
11
.vale/styles/Google/Latin.yml
Normal file
11
.vale/styles/Google/Latin.yml
Normal file
@ -0,0 +1,11 @@
|
||||
extends: substitution
|
||||
message: "Use '%s' instead of '%s'."
|
||||
link: 'https://developers.google.com/style/abbreviations'
|
||||
ignorecase: true
|
||||
level: error
|
||||
nonword: true
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
'\b(?:eg|e\.g\.)(?=[\s,;])': for example
|
||||
'\b(?:ie|i\.e\.)(?=[\s,;])': that is
|
||||
14
.vale/styles/Google/LyHyphens.yml
Normal file
14
.vale/styles/Google/LyHyphens.yml
Normal file
@ -0,0 +1,14 @@
|
||||
extends: existence
|
||||
message: "'%s' doesn't need a hyphen."
|
||||
link: "https://developers.google.com/style/hyphens"
|
||||
level: error
|
||||
ignorecase: false
|
||||
nonword: true
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- regex
|
||||
- "-"
|
||||
- " "
|
||||
tokens:
|
||||
- '\b[^\s-]+ly-\w+\b'
|
||||
12
.vale/styles/Google/OptionalPlurals.yml
Normal file
12
.vale/styles/Google/OptionalPlurals.yml
Normal file
@ -0,0 +1,12 @@
|
||||
extends: existence
|
||||
message: "Don't use plurals in parentheses such as in '%s'."
|
||||
link: "https://developers.google.com/style/plurals-parentheses"
|
||||
level: error
|
||||
nonword: true
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- trim_right
|
||||
- "(s)"
|
||||
tokens:
|
||||
- '\b\w+\(s\)'
|
||||
7
.vale/styles/Google/Ordinal.yml
Normal file
7
.vale/styles/Google/Ordinal.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Spell out all ordinal numbers ('%s') in text."
|
||||
link: 'https://developers.google.com/style/numbers'
|
||||
level: error
|
||||
nonword: true
|
||||
tokens:
|
||||
- \d+(?:st|nd|rd|th)
|
||||
7
.vale/styles/Google/OxfordComma.yml
Normal file
7
.vale/styles/Google/OxfordComma.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Use the Oxford comma in '%s'."
|
||||
link: 'https://developers.google.com/style/commas'
|
||||
scope: sentence
|
||||
level: warning
|
||||
tokens:
|
||||
- '(?:[^,]+,){1,}\s\w+\s(?:and|or)'
|
||||
7
.vale/styles/Google/Parens.yml
Normal file
7
.vale/styles/Google/Parens.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Use parentheses judiciously."
|
||||
link: 'https://developers.google.com/style/parentheses'
|
||||
nonword: true
|
||||
level: suggestion
|
||||
tokens:
|
||||
- '\(.+\)'
|
||||
184
.vale/styles/Google/Passive.yml
Normal file
184
.vale/styles/Google/Passive.yml
Normal file
@ -0,0 +1,184 @@
|
||||
extends: existence
|
||||
link: 'https://developers.google.com/style/voice'
|
||||
message: "In general, use active voice instead of passive voice ('%s')."
|
||||
ignorecase: true
|
||||
level: suggestion
|
||||
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
|
||||
7
.vale/styles/Google/Periods.yml
Normal file
7
.vale/styles/Google/Periods.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Don't use periods with acronyms or initialisms such as '%s'."
|
||||
link: 'https://developers.google.com/style/abbreviations'
|
||||
level: error
|
||||
nonword: true
|
||||
tokens:
|
||||
- '\b(?:[A-Z]\.){3,}'
|
||||
7
.vale/styles/Google/Quotes.yml
Normal file
7
.vale/styles/Google/Quotes.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Commas and periods go inside quotation marks."
|
||||
link: 'https://developers.google.com/style/quotation-marks'
|
||||
level: error
|
||||
nonword: true
|
||||
tokens:
|
||||
- '"[^"]+"[.,?]'
|
||||
7
.vale/styles/Google/Ranges.yml
Normal file
7
.vale/styles/Google/Ranges.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Don't add words such as 'from' or 'between' to describe a range of numbers."
|
||||
link: 'https://developers.google.com/style/hyphens'
|
||||
nonword: true
|
||||
level: warning
|
||||
tokens:
|
||||
- '(?:from|between)\s\d+\s?-\s?\d+'
|
||||
8
.vale/styles/Google/Semicolons.yml
Normal file
8
.vale/styles/Google/Semicolons.yml
Normal file
@ -0,0 +1,8 @@
|
||||
extends: existence
|
||||
message: "Use semicolons judiciously."
|
||||
link: 'https://developers.google.com/style/semicolons'
|
||||
nonword: true
|
||||
scope: sentence
|
||||
level: suggestion
|
||||
tokens:
|
||||
- ';'
|
||||
11
.vale/styles/Google/Slang.yml
Normal file
11
.vale/styles/Google/Slang.yml
Normal file
@ -0,0 +1,11 @@
|
||||
extends: existence
|
||||
message: "Don't use internet slang abbreviations such as '%s'."
|
||||
link: 'https://developers.google.com/style/abbreviations'
|
||||
ignorecase: true
|
||||
level: error
|
||||
tokens:
|
||||
- 'tl;dr'
|
||||
- ymmv
|
||||
- rtfm
|
||||
- imo
|
||||
- fwiw
|
||||
10
.vale/styles/Google/Spacing.yml
Normal file
10
.vale/styles/Google/Spacing.yml
Normal file
@ -0,0 +1,10 @@
|
||||
extends: existence
|
||||
message: "'%s' should have one space."
|
||||
link: 'https://developers.google.com/style/sentence-spacing'
|
||||
level: error
|
||||
nonword: true
|
||||
action:
|
||||
name: remove
|
||||
tokens:
|
||||
- '[a-z][.?!] {2,}[A-Z]'
|
||||
- '[a-z][.?!][A-Z]'
|
||||
10
.vale/styles/Google/Spelling.yml
Normal file
10
.vale/styles/Google/Spelling.yml
Normal file
@ -0,0 +1,10 @@
|
||||
extends: existence
|
||||
message: "In general, use American spelling instead of '%s'."
|
||||
link: 'https://developers.google.com/style/spelling'
|
||||
ignorecase: true
|
||||
level: warning
|
||||
tokens:
|
||||
- '(?:\w+)nised?'
|
||||
- 'colour'
|
||||
- 'labour'
|
||||
- 'centre'
|
||||
8
.vale/styles/Google/Units.yml
Normal file
8
.vale/styles/Google/Units.yml
Normal file
@ -0,0 +1,8 @@
|
||||
extends: existence
|
||||
message: "Put a nonbreaking space between the number and the unit in '%s'."
|
||||
link: "https://developers.google.com/style/units-of-measure"
|
||||
nonword: true
|
||||
level: error
|
||||
tokens:
|
||||
- \b\d+(?:B|kB|MB|GB|TB)
|
||||
- \b\d+(?:ns|ms|s|min|h|d)
|
||||
11
.vale/styles/Google/We.yml
Normal file
11
.vale/styles/Google/We.yml
Normal file
@ -0,0 +1,11 @@
|
||||
extends: existence
|
||||
message: "Try to avoid using first-person plural like '%s'."
|
||||
link: 'https://developers.google.com/style/pronouns#personal-pronouns'
|
||||
level: warning
|
||||
ignorecase: true
|
||||
tokens:
|
||||
- we
|
||||
- we'(?:ve|re)
|
||||
- ours?
|
||||
- us
|
||||
- let's
|
||||
7
.vale/styles/Google/Will.yml
Normal file
7
.vale/styles/Google/Will.yml
Normal file
@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Avoid using '%s'."
|
||||
link: 'https://developers.google.com/style/tense'
|
||||
ignorecase: true
|
||||
level: warning
|
||||
tokens:
|
||||
- will
|
||||
80
.vale/styles/Google/WordList.yml
Normal file
80
.vale/styles/Google/WordList.yml
Normal file
@ -0,0 +1,80 @@
|
||||
extends: substitution
|
||||
message: "Use '%s' instead of '%s'."
|
||||
link: "https://developers.google.com/style/word-list"
|
||||
level: warning
|
||||
ignorecase: false
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
"(?:API Console|dev|developer) key": API key
|
||||
"(?:cell ?phone|smart ?phone)": phone|mobile phone
|
||||
"(?:dev|developer|APIs) console": API console
|
||||
"(?:e-mail|Email|E-mail)": email
|
||||
"(?:file ?path|path ?name)": path
|
||||
"(?:kill|terminate|abort)": stop|exit|cancel|end
|
||||
"(?:OAuth ?2|Oauth)": OAuth 2.0
|
||||
"(?:ok|Okay)": OK|okay
|
||||
"(?:WiFi|wifi)": Wi-Fi
|
||||
'[\.]+apk': APK
|
||||
'3\-D': 3D
|
||||
'Google (?:I\-O|IO)': Google I/O
|
||||
"tap (?:&|and) hold": touch & hold
|
||||
"un(?:check|select)": clear
|
||||
above: preceding
|
||||
account name: username
|
||||
action bar: app bar
|
||||
admin: administrator
|
||||
Ajax: AJAX
|
||||
a\.k\.a|aka: or|also known as
|
||||
Android device: Android-powered device
|
||||
android: Android
|
||||
API explorer: APIs Explorer
|
||||
application: app
|
||||
approx\.: approximately
|
||||
authN: authentication
|
||||
authZ: authorization
|
||||
autoupdate: automatically update
|
||||
cellular data: mobile data
|
||||
cellular network: mobile network
|
||||
chapter: documents|pages|sections
|
||||
check box: checkbox
|
||||
CLI: command-line tool
|
||||
click on: click|click in
|
||||
Cloud: Google Cloud Platform|GCP
|
||||
Container Engine: Kubernetes Engine
|
||||
content type: media type
|
||||
curated roles: predefined roles
|
||||
data are: data is
|
||||
Developers Console: Google API Console|API Console
|
||||
disabled?: turn off|off
|
||||
ephemeral IP address: ephemeral external IP address
|
||||
fewer data: less data
|
||||
file name: filename
|
||||
firewalls: firewall rules
|
||||
functionality: capability|feature
|
||||
Google account: Google Account
|
||||
Google accounts: Google Accounts
|
||||
Googling: search with Google
|
||||
grayed-out: unavailable
|
||||
HTTPs: HTTPS
|
||||
in order to: to
|
||||
ingest: import|load
|
||||
k8s: Kubernetes
|
||||
long press: touch & hold
|
||||
network IP address: internal IP address
|
||||
omnibox: address bar
|
||||
open-source: open source
|
||||
overview screen: recents screen
|
||||
regex: regular expression
|
||||
SHA1: SHA-1|HAS-SHA1
|
||||
sign into: sign in to
|
||||
sign-?on: single sign-on
|
||||
static IP address: static external IP address
|
||||
stylesheet: style sheet
|
||||
synch: sync
|
||||
tablename: table name
|
||||
tablet: device
|
||||
touch: tap
|
||||
url: URL
|
||||
vs\.: versus
|
||||
World Wide Web: web
|
||||
4
.vale/styles/Google/meta.json
Normal file
4
.vale/styles/Google/meta.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"feed": "https://github.com/errata-ai/Google/releases.atom",
|
||||
"vale_version": ">=1.0.0"
|
||||
}
|
||||
0
.vale/styles/Google/vocab.txt
Normal file
0
.vale/styles/Google/vocab.txt
Normal file
702
.vale/styles/write-good/Cliches.yml
Normal file
702
.vale/styles/write-good/Cliches.yml
Normal file
@ -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
|
||||
32
.vale/styles/write-good/E-Prime.yml
Normal file
32
.vale/styles/write-good/E-Prime.yml
Normal file
@ -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
|
||||
11
.vale/styles/write-good/Illusions.yml
Normal file
11
.vale/styles/write-good/Illusions.yml
Normal file
@ -0,0 +1,11 @@
|
||||
extends: repetition
|
||||
message: "'%s' is repeated!"
|
||||
level: warning
|
||||
alpha: true
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- truncate
|
||||
- " "
|
||||
tokens:
|
||||
- '[^\s]+'
|
||||
183
.vale/styles/write-good/Passive.yml
Normal file
183
.vale/styles/write-good/Passive.yml
Normal file
@ -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
|
||||
27
.vale/styles/write-good/README.md
Normal file
27
.vale/styles/write-good/README.md
Normal file
@ -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.
|
||||
```
|
||||
5
.vale/styles/write-good/So.yml
Normal file
5
.vale/styles/write-good/So.yml
Normal file
@ -0,0 +1,5 @@
|
||||
extends: existence
|
||||
message: "Don't start a sentence with '%s'."
|
||||
level: error
|
||||
raw:
|
||||
- '(?:[;-]\s)so[\s,]|\bSo[\s,]'
|
||||
6
.vale/styles/write-good/ThereIs.yml
Normal file
6
.vale/styles/write-good/ThereIs.yml
Normal file
@ -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'
|
||||
221
.vale/styles/write-good/TooWordy.yml
Normal file
221
.vale/styles/write-good/TooWordy.yml
Normal file
@ -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
|
||||
29
.vale/styles/write-good/Weasel.yml
Normal file
29
.vale/styles/write-good/Weasel.yml
Normal file
@ -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
|
||||
4
.vale/styles/write-good/meta.json
Normal file
4
.vale/styles/write-good/meta.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"feed": "https://github.com/errata-ai/write-good/releases.atom",
|
||||
"vale_version": ">=1.0.0"
|
||||
}
|
||||
45
.woodpecker/Dockerfile
Normal file
45
.woodpecker/Dockerfile
Normal file
@ -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"]
|
||||
42
.woodpecker/Dockerfile.cross
Normal file
42
.woodpecker/Dockerfile.cross
Normal file
@ -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"]
|
||||
78
.woodpecker/README.md
Normal file
78
.woodpecker/README.md
Normal file
@ -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
|
||||
168
.woodpecker/ci-advanced.yml
Normal file
168
.woodpecker/ci-advanced.yml
Normal file
@ -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]
|
||||
84
.woodpecker/ci.yml
Normal file
84
.woodpecker/ci.yml
Normal file
@ -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
|
||||
18
.yamllint-ci.yml
Normal file
18
.yamllint-ci.yml
Normal file
@ -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/**
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user