diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 0000000..b965267 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,37 @@ +# Generated by dev-system/ci +# cargo-audit configuration for security vulnerability scanning + +# Database configuration +[advisories] +# The database path +db-path = "~/.cargo/advisory-db" + +# Advisory database URLs +db-urls = ["https://github.com/rustsec/advisory-db"] + +# How to handle different kinds of advisories +# "allow" - Pass the check despite the warning +# "warn" - Pass the check but warn about the issue +# "deny" - Fail the check +deny = ["unmaintained", "unsound", "yanked"] + +# Specific vulnerability IDs to ignore (in case of false positives) +# You can use: https://rustsec.org/ +ignore = [ + # Example: { id = "RUSTSEC-2023-XXXX", reason = "Not applicable to our use case" } +] + +# How to handle vulnerabilities based on severity +[output] +# Deny on high severity vulnerabilities +deny = ["high", "critical"] +# Warn on medium severity vulnerabilities +warn = ["medium", "low"] +# Advisory format: "terminal", "json" +format = "terminal" + +# Target configuration +[target] +# Check only specific targets +# Uncomment to restrict to specific target triples +# triple = "x86_64-unknown-linux-gnu" diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..8f53d51 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,73 @@ +# 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" +doc-json = "doc --no-deps -- -Z unstable-options --output-format json" diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 0000000..5da36da --- /dev/null +++ b/.clippy.toml @@ -0,0 +1,17 @@ +# Generated by dev-system/ci +# Clippy configuration for Rust linting + +# Lint level thresholds +cognitive-complexity-threshold = 25 +type-complexity-threshold = 500 +excessive-nesting-threshold = 5 + +# Allowed patterns (prevent lints on specific code) +# allow-expect-in-tests = true +# allow-unwrap-in-tests = true + +# Single-character variable name threshold +single-char-binding-names-threshold = 4 + +# Note: Lint configurations belong in Cargo.toml under [lints.clippy] or [workspace.lints.clippy] +# This file only contains clippy configuration parameters, not lint levels diff --git a/.github/workflows/nickel-typecheck.yml b/.github/workflows/nickel-typecheck.yml new file mode 100644 index 0000000..325a550 --- /dev/null +++ b/.github/workflows/nickel-typecheck.yml @@ -0,0 +1,116 @@ +# GitHub Actions Nickel Type Checking Workflow +# Generated by dev-system/ci +# Validates all Nickel schemas with nickel typecheck + +name: Nickel Type Check + +on: + push: + branches: [main, develop] + paths: ['**.ncl'] + pull_request: + branches: [main] + paths: ['**.ncl'] + +jobs: + typecheck: + name: Nickel Type Checking + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nickel + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ“¦ Installing Nickel..." + + if command -v nickel &> /dev/null; then + echo "βœ“ Nickel already installed" + nickel --version + else + echo "Installing via homebrew..." + brew install nickel || { + echo "Homebrew installation failed, trying from source..." + curl --proto '=https' --tlsv1.2 -sSf https://install.nickel-lang.org | bash || exit 1 + } + fi + + nickel --version + + - name: Setup environment + run: | + #!/usr/bin/env bash + # Set NICKEL_IMPORT_PATH for schema imports + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults" + echo "NICKEL_IMPORT_PATH=$NICKEL_IMPORT_PATH" >> $GITHUB_ENV + + - name: Type check schemas + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ” Type checking Nickel schemas..." + + # Find all .ncl files + SCHEMAS=$(find . -name "*.ncl" -type f \ + ! -path "./target/*" \ + ! -path "./.git/*" \ + ! -path "./node_modules/*" \ + | sort) + + if [ -z "$SCHEMAS" ]; then + echo "⚠️ No Nickel schemas found" + exit 0 + fi + + FAILED=0 + PASSED=0 + + # Set import path + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:." + + for schema in $SCHEMAS; do + echo "Checking: $schema" + if nickel typecheck "$schema" > /dev/null 2>&1; then + echo " βœ“ Valid" + ((PASSED++)) + else + echo " ❌ Type error" + nickel typecheck "$schema" || true + ((FAILED++)) + fi + done + + echo "" + echo "Summary: $PASSED passed, $FAILED failed" + + if [ $FAILED -gt 0 ]; then + exit 1 + fi + + - name: Export and validate + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ“Š Exporting Nickel configurations..." + + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:." + + # Export main configs if they exist + if [ -f ".typedialog/ci/schemas/ci-local.ncl" ]; then + echo "Exporting CI config..." + nickel export .typedialog/ci/schemas/ci-local.ncl > /tmp/ci-export.json + if [ $? -eq 0 ]; then + echo " βœ“ Successfully exported" + else + echo " ❌ Export failed" + exit 1 + fi + fi + + echo "βœ“ All exports successful" diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml new file mode 100644 index 0000000..73c2af1 --- /dev/null +++ b/.github/workflows/rust-ci.yml @@ -0,0 +1,47 @@ +jobs: + audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + - name: Audit + run: cargo audit --deny warnings + - name: Deny Check + run: cargo deny check licenses advisories + check: + name: Check + Test + Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust-version }} + - name: Cache + uses: Swatinem/rust-cache@v2 + - name: Check + run: cargo check --all-targets + - name: Format Check + run: cargo fmt --all -- --check + - name: Clippy + run: cargo clippy --all-targets -- -D warnings + - name: Tests + run: cargo test --workspace + strategy: + matrix: + rust-version: + - stable + - nightly +name: Rust CI +on: + pull_request: + branches: + - main + push: + branches: + - main + - develop diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96550bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,69 @@ +CLAUDE.md +.claude +utils/save*sh +.fastembed_cache +presentaciones +COMMIT_MESSAGE.md +.wrks +nushell +nushell-* +*.tar.gz +#*-nushell-plugins.tar.gz +github-com +.coder +target +distribution +.qodo +# enviroment to load on bin/build +.env +# OSX trash +.DS_Store + +# Vscode files +.vscode + +# Emacs save files +*~ +\#*\# +.\#* + +# Vim-related files +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist + +# cscope-related files +cscope.* + +# User cluster configs +.kubeconfig + +.tags* + +# direnv .envrc files +.envrc + +# make-related metadata +/.make/ + +# Just in time generated data in the source, should never be committed +/test/e2e/generated/bindata.go + +# This file used by some vendor repos (e.g. github.com/go-openapi/...) to store secret variables and should not be ignored +!\.drone\.sec + +# Godeps workspace +/Godeps/_workspace + +/bazel-* +*.pyc + +# generated by verify-vendor.sh +vendordiff.patch +.claude/settings.local.json + +# Generated SBOM files +SBOM.*.json +*.sbom.json diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..8bd3887 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,53 @@ +# Generated by dev-system/ci +# Rustfmt configuration for consistent Rust code formatting +# Configured for cargo +nightly fmt with advanced features enabled + +# Basic formatting options +edition = "2021" +max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Unix" + +# Code structure +use_small_heuristics = "Default" + +# Imports +reorder_imports = true +reorder_modules = true +remove_nested_parens = true +group_imports = "StdExternalCrate" + +# Match expressions +match_block_trailing_comma = false + +# Chains +chain_width = 60 + +# Comment formatting (nightly) +comment_width = 80 +wrap_comments = true +normalize_comments = true +normalize_doc_attributes = true + +# Spaces and indentation (nightly) +fn_single_line = false +fn_params_layout = "Tall" +where_single_line = false + +# Formatting (nightly) +format_strings = true +format_code_in_doc_comments = false + +# Spaces (nightly) +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false + +# Line breaks (nightly) +match_arm_blocks = true +blank_lines_lower_bound = 0 +blank_lines_upper_bound = 1 + +# Enable nightly features +unstable_features = true diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..5eaa967 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,40 @@ +# ShellCheck Configuration Template +# Bash/shell script linting configuration +# Generated by dev-system/ci +# Location: .shellcheckrc + + +# Generated by dev-system/ci +# ShellCheck configuration for Bash script validation + +# Enable all optional checks +enable=all + +# Disable specific checks that are too strict +# SC1091 - Not following sourced files (noisy in monorepos) +# disable=SC1091 + +# Source path for sourced files +source-path=SCRIPTDIR + +# Severity levels: error, warning, info, style +severity=warning + +# Format: gcc, json, json1, quiet +format=gcc + +# Exit status thresholds +# 0: All checks passed +# 1: Warning found +# 2: Error found + +# Shell dialect (bash, sh, ksh, etc) +# shell=bash + +# Check style guide compliance +# These are considered good practices but optional + +# Common problematic patterns +# SC2086 - Double quote to prevent globbing +# SC2181 - Check exit code explicitly +# SC2207 - Array from command substitution diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 0000000..5d20bf8 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,49 @@ +# Taplo configuration for TOML formatting and linting +# https://taplo.tamasfe.dev/configuration/ + +[formatting] +# Indent tables with 2 spaces +indent_string = " " +indent_tables = true + +# Reorder keys alphabetically within tables +reorder_keys = true + +# Reorder arrays to be more readable +reorder_arrays = false + +# Align entries vertically in inline tables +align_entries = false + +# Allow compact inline tables +allowed_blank_lines = 1 + +# Trailing newline +trailing_newline = true + +# Column width for wrapping +column_width = 100 + +# Compact arrays +compact_arrays = true + +# Compact inline tables +compact_inline_tables = false + +# === INCLUDE/EXCLUDE PATTERNS === + +include = ["Cargo.toml", "*/Cargo.toml", "config/**/*.toml", "**/*.toml"] + +exclude = ["target/**", "node_modules/**", ".git/**"] + +# === SCHEMA VALIDATION === + +# Cargo.toml schema validation +[[rule]] +include = ["**/Cargo.toml"] +# Taplo includes built-in Cargo.toml schema + +# TypeDialog form definition TOML files +[[rule]] +include = ["**/.typedialog/**/*.toml", "config/**/forms/*.toml", "tests/fixtures/**/*.toml"] +keys = ["name", "description", "fields", "items", "elements"] diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000..6289603 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,41 @@ +# Vale configuration for TypeDialog documentation +# https://vale.sh/docs/topics/config/ + +StylesPath = .vale/styles +MinAlertLevel = warning + +# Global settings +[*] +Packages = Google, write-good +Vocab = TypeDialog + +# Markdown files: docs/**/*.md and root *.md (excluding .claude, .coder, CLAUDE.md) +[*.md] +BasedOnStyles = write-good, Google + +# Ignore code blocks and specific patterns +TokenIgnores = (\$\{[^\}]+\}), (`[^`]+`), (\*\*[^\*]+\*\*) + +# Disable noisy rules for technical documentation +Google.Headings = NO +Google.Parens = NO +Google.Acronyms = NO +Google.Passive = NO +Google.We = NO +Google.Will = NO +Google.WordList = NO +Google.Colons = NO + +write-good.E-Prime = NO +write-good.TooWordy = NO +write-good.Passive = NO + +Vale.Spelling = NO + +# Keep enabled (useful for technical docs): +# - write-good.Weasel (vague words like "various") +# - Google.Contractions (maintain formal tone) +# - Google.FirstPerson (avoid "we/our") +# - Google.Exclamation +# - Google.Slang +# - Google.Units diff --git a/.vale/Vocab/TypeDialog/accept.txt b/.vale/Vocab/TypeDialog/accept.txt new file mode 100644 index 0000000..ffc7ad8 --- /dev/null +++ b/.vale/Vocab/TypeDialog/accept.txt @@ -0,0 +1,25 @@ +# TypeDialog accepted terms (case-insensitive) +# Technical acronyms and abbreviations +API +CLI +TUI +JSON +YAML +TOML +REST +HTTP +HTTPS +TLS +SSL +CORS +URL +URI +NPM +SDK +HTML +CSS +JWT +WASM +WebAssembly +README +CHANGELOG diff --git a/.vale/Vocab/TypeDialog/reject.txt b/.vale/Vocab/TypeDialog/reject.txt new file mode 100644 index 0000000..a7f5a8f --- /dev/null +++ b/.vale/Vocab/TypeDialog/reject.txt @@ -0,0 +1,2 @@ +# TypeDialog rejected terms +# Add terms that should never be used diff --git a/.vale/styles/Google/AMPM.yml b/.vale/styles/Google/AMPM.yml new file mode 100644 index 0000000..37b49ed --- /dev/null +++ b/.vale/styles/Google/AMPM.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'AM' or 'PM' (preceded by a space)." +link: "https://developers.google.com/style/word-list" +level: error +nonword: true +tokens: + - '\d{1,2}[AP]M\b' + - '\d{1,2} ?[ap]m\b' + - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/.vale/styles/Google/Acronyms.yml b/.vale/styles/Google/Acronyms.yml new file mode 100644 index 0000000..f41af01 --- /dev/null +++ b/.vale/styles/Google/Acronyms.yml @@ -0,0 +1,64 @@ +extends: conditional +message: "Spell out '%s', if it's unfamiliar to the audience." +link: 'https://developers.google.com/style/abbreviations' +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP diff --git a/.vale/styles/Google/Colons.yml b/.vale/styles/Google/Colons.yml new file mode 100644 index 0000000..4a027c3 --- /dev/null +++ b/.vale/styles/Google/Colons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' should be in lowercase." +link: 'https://developers.google.com/style/colons' +nonword: true +level: warning +scope: sentence +tokens: + - '(?=1.0.0" +} diff --git a/.vale/styles/Google/vocab.txt b/.vale/styles/Google/vocab.txt new file mode 100644 index 0000000..e69de29 diff --git a/.vale/styles/write-good/Cliches.yml b/.vale/styles/write-good/Cliches.yml new file mode 100644 index 0000000..c953143 --- /dev/null +++ b/.vale/styles/write-good/Cliches.yml @@ -0,0 +1,702 @@ +extends: existence +message: "Try to avoid using clichΓ©s like '%s'." +ignorecase: true +level: warning +tokens: + - a chip off the old block + - a clean slate + - a dark and stormy night + - a far cry + - a fine kettle of fish + - a loose cannon + - a penny saved is a penny earned + - a tough row to hoe + - a word to the wise + - ace in the hole + - acid test + - add insult to injury + - against all odds + - air your dirty laundry + - all fun and games + - all in a day's work + - all talk, no action + - all thumbs + - all your eggs in one basket + - all's fair in love and war + - all's well that ends well + - almighty dollar + - American as apple pie + - an axe to grind + - another day, another dollar + - armed to the teeth + - as luck would have it + - as old as time + - as the crow flies + - at loose ends + - at my wits end + - avoid like the plague + - babe in the woods + - back against the wall + - back in the saddle + - back to square one + - back to the drawing board + - bad to the bone + - badge of honor + - bald faced liar + - ballpark figure + - banging your head against a brick wall + - baptism by fire + - barking up the wrong tree + - bat out of hell + - be all and end all + - beat a dead horse + - beat around the bush + - been there, done that + - beggars can't be choosers + - behind the eight ball + - bend over backwards + - benefit of the doubt + - bent out of shape + - best thing since sliced bread + - bet your bottom dollar + - better half + - better late than never + - better mousetrap + - better safe than sorry + - between a rock and a hard place + - beyond the pale + - bide your time + - big as life + - big cheese + - big fish in a small pond + - big man on campus + - bigger they are the harder they fall + - bird in the hand + - bird's eye view + - birds and the bees + - birds of a feather flock together + - bit the hand that feeds you + - bite the bullet + - bite the dust + - bitten off more than he can chew + - black as coal + - black as pitch + - black as the ace of spades + - blast from the past + - bleeding heart + - blessing in disguise + - blind ambition + - blind as a bat + - blind leading the blind + - blood is thicker than water + - blood sweat and tears + - blow off steam + - blow your own horn + - blushing bride + - boils down to + - bolt from the blue + - bone to pick + - bored stiff + - bored to tears + - bottomless pit + - boys will be boys + - bright and early + - brings home the bacon + - broad across the beam + - broken record + - brought back to reality + - bull by the horns + - bull in a china shop + - burn the midnight oil + - burning question + - burning the candle at both ends + - burst your bubble + - bury the hatchet + - busy as a bee + - by hook or by crook + - call a spade a spade + - called onto the carpet + - calm before the storm + - can of worms + - can't cut the mustard + - can't hold a candle to + - case of mistaken identity + - cat got your tongue + - cat's meow + - caught in the crossfire + - caught red-handed + - checkered past + - chomping at the bit + - cleanliness is next to godliness + - clear as a bell + - clear as mud + - close to the vest + - cock and bull story + - cold shoulder + - come hell or high water + - cool as a cucumber + - cool, calm, and collected + - cost a king's ransom + - count your blessings + - crack of dawn + - crash course + - creature comforts + - cross that bridge when you come to it + - crushing blow + - cry like a baby + - cry me a river + - cry over spilt milk + - crystal clear + - curiosity killed the cat + - cut and dried + - cut through the red tape + - cut to the chase + - cute as a bugs ear + - cute as a button + - cute as a puppy + - cuts to the quick + - dark before the dawn + - day in, day out + - dead as a doornail + - devil is in the details + - dime a dozen + - divide and conquer + - dog and pony show + - dog days + - dog eat dog + - dog tired + - don't burn your bridges + - don't count your chickens + - don't look a gift horse in the mouth + - don't rock the boat + - don't step on anyone's toes + - don't take any wooden nickels + - down and out + - down at the heels + - down in the dumps + - down the hatch + - down to earth + - draw the line + - dressed to kill + - dressed to the nines + - drives me up the wall + - dull as dishwater + - dyed in the wool + - eagle eye + - ear to the ground + - early bird catches the worm + - easier said than done + - easy as pie + - eat your heart out + - eat your words + - eleventh hour + - even the playing field + - every dog has its day + - every fiber of my being + - everything but the kitchen sink + - eye for an eye + - face the music + - facts of life + - fair weather friend + - fall by the wayside + - fan the flames + - feast or famine + - feather your nest + - feathered friends + - few and far between + - fifteen minutes of fame + - filthy vermin + - fine kettle of fish + - fish out of water + - fishing for a compliment + - fit as a fiddle + - fit the bill + - fit to be tied + - flash in the pan + - flat as a pancake + - flip your lid + - flog a dead horse + - fly by night + - fly the coop + - follow your heart + - for all intents and purposes + - for the birds + - for what it's worth + - force of nature + - force to be reckoned with + - forgive and forget + - fox in the henhouse + - free and easy + - free as a bird + - fresh as a daisy + - full steam ahead + - fun in the sun + - garbage in, garbage out + - gentle as a lamb + - get a kick out of + - get a leg up + - get down and dirty + - get the lead out + - get to the bottom of + - get your feet wet + - gets my goat + - gilding the lily + - give and take + - go against the grain + - go at it tooth and nail + - go for broke + - go him one better + - go the extra mile + - go with the flow + - goes without saying + - good as gold + - good deed for the day + - good things come to those who wait + - good time was had by all + - good times were had by all + - greased lightning + - greek to me + - green thumb + - green-eyed monster + - grist for the mill + - growing like a weed + - hair of the dog + - hand to mouth + - happy as a clam + - happy as a lark + - hasn't a clue + - have a nice day + - have high hopes + - have the last laugh + - haven't got a row to hoe + - head honcho + - head over heels + - hear a pin drop + - heard it through the grapevine + - heart's content + - heavy as lead + - hem and haw + - high and dry + - high and mighty + - high as a kite + - hit paydirt + - hold your head up high + - hold your horses + - hold your own + - hold your tongue + - honest as the day is long + - horns of a dilemma + - horse of a different color + - hot under the collar + - hour of need + - I beg to differ + - icing on the cake + - if the shoe fits + - if the shoe were on the other foot + - in a jam + - in a jiffy + - in a nutshell + - in a pig's eye + - in a pinch + - in a word + - in hot water + - in the gutter + - in the nick of time + - in the thick of it + - in your dreams + - it ain't over till the fat lady sings + - it goes without saying + - it takes all kinds + - it takes one to know one + - it's a small world + - it's only a matter of time + - ivory tower + - Jack of all trades + - jockey for position + - jog your memory + - joined at the hip + - judge a book by its cover + - jump down your throat + - jump in with both feet + - jump on the bandwagon + - jump the gun + - jump to conclusions + - just a hop, skip, and a jump + - just the ticket + - justice is blind + - keep a stiff upper lip + - keep an eye on + - keep it simple, stupid + - keep the home fires burning + - keep up with the Joneses + - keep your chin up + - keep your fingers crossed + - kick the bucket + - kick up your heels + - kick your feet up + - kid in a candy store + - kill two birds with one stone + - kiss of death + - knock it out of the park + - knock on wood + - knock your socks off + - know him from Adam + - know the ropes + - know the score + - knuckle down + - knuckle sandwich + - knuckle under + - labor of love + - ladder of success + - land on your feet + - lap of luxury + - last but not least + - last hurrah + - last-ditch effort + - law of the jungle + - law of the land + - lay down the law + - leaps and bounds + - let sleeping dogs lie + - let the cat out of the bag + - let the good times roll + - let your hair down + - let's talk turkey + - letter perfect + - lick your wounds + - lies like a rug + - life's a bitch + - life's a grind + - light at the end of the tunnel + - lighter than a feather + - lighter than air + - like clockwork + - like father like son + - like taking candy from a baby + - like there's no tomorrow + - lion's share + - live and learn + - live and let live + - long and short of it + - long lost love + - look before you leap + - look down your nose + - look what the cat dragged in + - looking a gift horse in the mouth + - looks like death warmed over + - loose cannon + - lose your head + - lose your temper + - loud as a horn + - lounge lizard + - loved and lost + - low man on the totem pole + - luck of the draw + - luck of the Irish + - make hay while the sun shines + - make money hand over fist + - make my day + - make the best of a bad situation + - make the best of it + - make your blood boil + - man of few words + - man's best friend + - mark my words + - meaningful dialogue + - missed the boat on that one + - moment in the sun + - moment of glory + - moment of truth + - money to burn + - more power to you + - more than one way to skin a cat + - movers and shakers + - moving experience + - naked as a jaybird + - naked truth + - neat as a pin + - needle in a haystack + - needless to say + - neither here nor there + - never look back + - never say never + - nip and tuck + - nip it in the bud + - no guts, no glory + - no love lost + - no pain, no gain + - no skin off my back + - no stone unturned + - no time like the present + - no use crying over spilled milk + - nose to the grindstone + - not a hope in hell + - not a minute's peace + - not in my backyard + - not playing with a full deck + - not the end of the world + - not written in stone + - nothing to sneeze at + - nothing ventured nothing gained + - now we're cooking + - off the top of my head + - off the wagon + - off the wall + - old hat + - older and wiser + - older than dirt + - older than Methuselah + - on a roll + - on cloud nine + - on pins and needles + - on the bandwagon + - on the money + - on the nose + - on the rocks + - on the spot + - on the tip of my tongue + - on the wagon + - on thin ice + - once bitten, twice shy + - one bad apple doesn't spoil the bushel + - one born every minute + - one brick short + - one foot in the grave + - one in a million + - one red cent + - only game in town + - open a can of worms + - open and shut case + - open the flood gates + - opportunity doesn't knock twice + - out of pocket + - out of sight, out of mind + - out of the frying pan into the fire + - out of the woods + - out on a limb + - over a barrel + - over the hump + - pain and suffering + - pain in the + - panic button + - par for the course + - part and parcel + - party pooper + - pass the buck + - patience is a virtue + - pay through the nose + - penny pincher + - perfect storm + - pig in a poke + - pile it on + - pillar of the community + - pin your hopes on + - pitter patter of little feet + - plain as day + - plain as the nose on your face + - play by the rules + - play your cards right + - playing the field + - playing with fire + - pleased as punch + - plenty of fish in the sea + - point with pride + - poor as a church mouse + - pot calling the kettle black + - pretty as a picture + - pull a fast one + - pull your punches + - pulling your leg + - pure as the driven snow + - put it in a nutshell + - put one over on you + - put the cart before the horse + - put the pedal to the metal + - put your best foot forward + - put your foot down + - quick as a bunny + - quick as a lick + - quick as a wink + - quick as lightning + - quiet as a dormouse + - rags to riches + - raining buckets + - raining cats and dogs + - rank and file + - rat race + - reap what you sow + - red as a beet + - red herring + - reinvent the wheel + - rich and famous + - rings a bell + - ripe old age + - ripped me off + - rise and shine + - road to hell is paved with good intentions + - rob Peter to pay Paul + - roll over in the grave + - rub the wrong way + - ruled the roost + - running in circles + - sad but true + - sadder but wiser + - salt of the earth + - scared stiff + - scared to death + - sealed with a kiss + - second to none + - see eye to eye + - seen the light + - seize the day + - set the record straight + - set the world on fire + - set your teeth on edge + - sharp as a tack + - shoot for the moon + - shoot the breeze + - shot in the dark + - shoulder to the wheel + - sick as a dog + - sigh of relief + - signed, sealed, and delivered + - sink or swim + - six of one, half a dozen of another + - skating on thin ice + - slept like a log + - slinging mud + - slippery as an eel + - slow as molasses + - smart as a whip + - smooth as a baby's bottom + - sneaking suspicion + - snug as a bug in a rug + - sow wild oats + - spare the rod, spoil the child + - speak of the devil + - spilled the beans + - spinning your wheels + - spitting image of + - spoke with relish + - spread like wildfire + - spring to life + - squeaky wheel gets the grease + - stands out like a sore thumb + - start from scratch + - stick in the mud + - still waters run deep + - stitch in time + - stop and smell the roses + - straight as an arrow + - straw that broke the camel's back + - strong as an ox + - stubborn as a mule + - stuff that dreams are made of + - stuffed shirt + - sweating blood + - sweating bullets + - take a load off + - take one for the team + - take the bait + - take the bull by the horns + - take the plunge + - takes one to know one + - takes two to tango + - the more the merrier + - the real deal + - the real McCoy + - the red carpet treatment + - the same old story + - there is no accounting for taste + - thick as a brick + - thick as thieves + - thin as a rail + - think outside of the box + - third time's the charm + - this day and age + - this hurts me worse than it hurts you + - this point in time + - three sheets to the wind + - through thick and thin + - throw in the towel + - tie one on + - tighter than a drum + - time and time again + - time is of the essence + - tip of the iceberg + - tired but happy + - to coin a phrase + - to each his own + - to make a long story short + - to the best of my knowledge + - toe the line + - tongue in cheek + - too good to be true + - too hot to handle + - too numerous to mention + - touch with a ten foot pole + - tough as nails + - trial and error + - trials and tribulations + - tried and true + - trip down memory lane + - twist of fate + - two cents worth + - two peas in a pod + - ugly as sin + - under the counter + - under the gun + - under the same roof + - under the weather + - until the cows come home + - unvarnished truth + - up the creek + - uphill battle + - upper crust + - upset the applecart + - vain attempt + - vain effort + - vanquish the enemy + - vested interest + - waiting for the other shoe to drop + - wakeup call + - warm welcome + - watch your p's and q's + - watch your tongue + - watching the clock + - water under the bridge + - weather the storm + - weed them out + - week of Sundays + - went belly up + - wet behind the ears + - what goes around comes around + - what you see is what you get + - when it rains, it pours + - when push comes to shove + - when the cat's away + - when the going gets tough, the tough get going + - white as a sheet + - whole ball of wax + - whole hog + - whole nine yards + - wild goose chase + - will wonders never cease? + - wisdom of the ages + - wise as an owl + - wolf at the door + - words fail me + - work like a dog + - world weary + - worst nightmare + - worth its weight in gold + - wrong side of the bed + - yanking your chain + - yappy as a dog + - years young + - you are what you eat + - you can run but you can't hide + - you only live once + - you're the boss + - young and foolish + - young and vibrant diff --git a/.vale/styles/write-good/E-Prime.yml b/.vale/styles/write-good/E-Prime.yml new file mode 100644 index 0000000..074a102 --- /dev/null +++ b/.vale/styles/write-good/E-Prime.yml @@ -0,0 +1,32 @@ +extends: existence +message: "Try to avoid using '%s'." +ignorecase: true +level: suggestion +tokens: + - am + - are + - aren't + - be + - been + - being + - he's + - here's + - here's + - how's + - i'm + - is + - isn't + - it's + - she's + - that's + - there's + - they're + - was + - wasn't + - we're + - were + - weren't + - what's + - where's + - who's + - you're diff --git a/.vale/styles/write-good/Illusions.yml b/.vale/styles/write-good/Illusions.yml new file mode 100644 index 0000000..b4f1321 --- /dev/null +++ b/.vale/styles/write-good/Illusions.yml @@ -0,0 +1,11 @@ +extends: repetition +message: "'%s' is repeated!" +level: warning +alpha: true +action: + name: edit + params: + - truncate + - " " +tokens: + - '[^\s]+' diff --git a/.vale/styles/write-good/Passive.yml b/.vale/styles/write-good/Passive.yml new file mode 100644 index 0000000..f472cb9 --- /dev/null +++ b/.vale/styles/write-good/Passive.yml @@ -0,0 +1,183 @@ +extends: existence +message: "'%s' may be passive voice. Use active voice if you can." +ignorecase: true +level: warning +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/.vale/styles/write-good/README.md b/.vale/styles/write-good/README.md new file mode 100644 index 0000000..3edcc9b --- /dev/null +++ b/.vale/styles/write-good/README.md @@ -0,0 +1,27 @@ +Based on [write-good](https://github.com/btford/write-good). + +> Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too. + +``` +The MIT License (MIT) + +Copyright (c) 2014 Brian Ford + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` diff --git a/.vale/styles/write-good/So.yml b/.vale/styles/write-good/So.yml new file mode 100644 index 0000000..e57f099 --- /dev/null +++ b/.vale/styles/write-good/So.yml @@ -0,0 +1,5 @@ +extends: existence +message: "Don't start a sentence with '%s'." +level: error +raw: + - '(?:[;-]\s)so[\s,]|\bSo[\s,]' diff --git a/.vale/styles/write-good/ThereIs.yml b/.vale/styles/write-good/ThereIs.yml new file mode 100644 index 0000000..8b82e8f --- /dev/null +++ b/.vale/styles/write-good/ThereIs.yml @@ -0,0 +1,6 @@ +extends: existence +message: "Don't start a sentence with '%s'." +ignorecase: false +level: error +raw: + - '(?:[;-]\s)There\s(is|are)|\bThere\s(is|are)\b' diff --git a/.vale/styles/write-good/TooWordy.yml b/.vale/styles/write-good/TooWordy.yml new file mode 100644 index 0000000..275701b --- /dev/null +++ b/.vale/styles/write-good/TooWordy.yml @@ -0,0 +1,221 @@ +extends: existence +message: "'%s' is too wordy." +ignorecase: true +level: warning +tokens: + - a number of + - abundance + - accede to + - accelerate + - accentuate + - accompany + - accomplish + - accorded + - accrue + - acquiesce + - acquire + - additional + - adjacent to + - adjustment + - admissible + - advantageous + - adversely impact + - advise + - aforementioned + - aggregate + - aircraft + - all of + - all things considered + - alleviate + - allocate + - along the lines of + - already existing + - alternatively + - amazing + - ameliorate + - anticipate + - apparent + - appreciable + - as a matter of fact + - as a means of + - as far as I'm concerned + - as of yet + - as to + - as yet + - ascertain + - assistance + - at the present time + - at this time + - attain + - attributable to + - authorize + - because of the fact that + - belated + - benefit from + - bestow + - by means of + - by virtue of + - by virtue of the fact that + - cease + - close proximity + - commence + - comply with + - concerning + - consequently + - consolidate + - constitutes + - demonstrate + - depart + - designate + - discontinue + - due to the fact that + - each and every + - economical + - eliminate + - elucidate + - employ + - endeavor + - enumerate + - equitable + - equivalent + - evaluate + - evidenced + - exclusively + - expedite + - expend + - expiration + - facilitate + - factual evidence + - feasible + - finalize + - first and foremost + - for all intents and purposes + - for the most part + - for the purpose of + - forfeit + - formulate + - have a tendency to + - honest truth + - however + - if and when + - impacted + - implement + - in a manner of speaking + - in a timely manner + - in a very real sense + - in accordance with + - in addition + - in all likelihood + - in an effort to + - in between + - in excess of + - in lieu of + - in light of the fact that + - in many cases + - in my opinion + - in order to + - in regard to + - in some instances + - in terms of + - in the case of + - in the event that + - in the final analysis + - in the nature of + - in the near future + - in the process of + - inception + - incumbent upon + - indicate + - indication + - initiate + - irregardless + - is applicable to + - is authorized to + - is responsible for + - it is + - it is essential + - it seems that + - it was + - magnitude + - maximum + - methodology + - minimize + - minimum + - modify + - monitor + - multiple + - necessitate + - nevertheless + - not certain + - not many + - not often + - not unless + - not unlike + - notwithstanding + - null and void + - numerous + - objective + - obligate + - obtain + - on the contrary + - on the other hand + - one particular + - optimum + - overall + - owing to the fact that + - participate + - particulars + - pass away + - pertaining to + - point in time + - portion + - possess + - preclude + - previously + - prior to + - prioritize + - procure + - proficiency + - provided that + - purchase + - put simply + - readily apparent + - refer back + - regarding + - relocate + - remainder + - remuneration + - requirement + - reside + - residence + - retain + - satisfy + - shall + - should you wish + - similar to + - solicit + - span across + - strategize + - subsequent + - substantial + - successfully complete + - sufficient + - terminate + - the month of + - the point I am trying to make + - therefore + - time period + - took advantage of + - transmit + - transpire + - type of + - until such time as + - utilization + - utilize + - validate + - various different + - what I mean to say is + - whether or not + - with respect to + - with the exception of + - witnessed diff --git a/.vale/styles/write-good/Weasel.yml b/.vale/styles/write-good/Weasel.yml new file mode 100644 index 0000000..d1d90a7 --- /dev/null +++ b/.vale/styles/write-good/Weasel.yml @@ -0,0 +1,29 @@ +extends: existence +message: "'%s' is a weasel word!" +ignorecase: true +level: warning +tokens: + - clearly + - completely + - exceedingly + - excellent + - extremely + - fairly + - huge + - interestingly + - is a number + - largely + - mostly + - obviously + - quite + - relatively + - remarkably + - several + - significantly + - substantially + - surprisingly + - tiny + - usually + - various + - vast + - very diff --git a/.vale/styles/write-good/meta.json b/.vale/styles/write-good/meta.json new file mode 100644 index 0000000..a115d28 --- /dev/null +++ b/.vale/styles/write-good/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/errata-ai/write-good/releases.atom", + "vale_version": ">=1.0.0" +} diff --git a/.woodpecker/Dockerfile b/.woodpecker/Dockerfile new file mode 100644 index 0000000..5086c87 --- /dev/null +++ b/.woodpecker/Dockerfile @@ -0,0 +1,45 @@ +# Custom Docker image for Woodpecker CI +# Pre-installs common tools to speed up CI runs +# +# Build: docker build -t your-registry/ci:latest -f .woodpecker/Dockerfile . +# Push: docker push your-registry/ci:latest +# +# Then update .woodpecker/ci.yml to use: image: your-registry/ci:latest + +FROM rust:latest + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + shellcheck \ + curl \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Install just +RUN curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + +# Install Rust components +RUN rustup component add clippy rustfmt + +# Install Rust tools (pre-compiled to speed up CI) +RUN cargo install \ + cargo-audit \ + cargo-deny \ + cargo-sbom \ + nickel-lang-cli \ + nu \ + --locked + +# Set working directory +WORKDIR /workspace + +# Verify installations +RUN just --version && \ + cargo --version && \ + cargo audit --version && \ + cargo deny --version && \ + cargo sbom --version && \ + nickel --version && \ + nu --version + +CMD ["/bin/bash"] diff --git a/.woodpecker/Dockerfile.cross b/.woodpecker/Dockerfile.cross new file mode 100644 index 0000000..2b56cd8 --- /dev/null +++ b/.woodpecker/Dockerfile.cross @@ -0,0 +1,42 @@ +# Dockerfile for cross-platform compilation +# Supports building for multiple targets using docker + +FROM ubuntu:22.04 + +# Install build essentials +RUN apt-get update && apt-get install -y \ + build-essential \ + curl \ + git \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Install Rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install cross tool for cross-compilation +RUN cargo install cross --locked + +# Create workspace directory +WORKDIR /workspace + +# Copy entire project +COPY . . + +# Default build target +ARG TARGET=x86_64-unknown-linux-gnu +ENV BUILD_TARGET="${TARGET}" + +# Build command +RUN cross build --target "${BUILD_TARGET}" --release + +# Extract binaries to output directory +RUN mkdir -p /output/bin && \ + find target/"${BUILD_TARGET}"/release -maxdepth 1 -type f -executable -exec cp {} /output/bin/ \; + +# Create manifest +RUN echo "{ \"target\": \"${BUILD_TARGET}\", \"built\": \"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\" }" > /output/BUILD_INFO.json + +# Default command +CMD ["/bin/bash"] diff --git a/.woodpecker/README.md b/.woodpecker/README.md new file mode 100644 index 0000000..58b4853 --- /dev/null +++ b/.woodpecker/README.md @@ -0,0 +1,78 @@ +# Woodpecker CI Configuration + +Pipelines for Gitea/Forgejo + Woodpecker CI. + +## Files + +- **`ci.yml`** - Main CI pipeline (push, pull requests) +- **`Dockerfile`** - Custom CI image with pre-installed tools +- **`Dockerfile.cross`** - Cross-compilation image for multi-platform builds + +## Setup + +### 1. Activate Woodpecker CI + +Enable Woodpecker CI in your Gitea/Forgejo repository settings. + +### 2. (Optional) Build Custom Image + +Speeds up CI by pre-installing tools (~5 min faster per run). + +```bash +# Build CI image +docker build -t your-registry/ci:latest -f .woodpecker/Dockerfile . + +# Push to your registry +docker push your-registry/ci:latest + +# Update .woodpecker/ci.yml +# Change: image: rust:latest +# To: image: your-registry/ci:latest +``` + +### 3. Cross-Compilation Setup + +For multi-platform builds: + +```bash +# Build cross-compilation image +docker build -t your-registry/ci-cross:latest -f .woodpecker/Dockerfile.cross . + +# Push to registry +docker push your-registry/ci-cross:latest +``` + +## CI Pipeline (`ci.yml`) + +**Triggers**: Push to `main`/`develop`, Pull Requests + +**Jobs**: +1. Lint (Rust, Bash, Nickel, Nushell, Markdown) - Parallel +2. Test (all features) +3. Build (release) +4. Security audit +5. License compliance check + +**Duration**: ~15-20 minutes (without custom image), ~10-15 minutes (with custom image) + +## Triggering Pipelines + +```bash +# CI pipeline (automatic on push/PR) +git push origin main +``` + +## Viewing Results + +- **Gitea/Forgejo**: Repository β†’ Actions β†’ Pipeline runs +- **Woodpecker UI**: https://your-woodpecker.instance/repos/{user}/{repo} + +## Differences from GitHub Actions + +| Feature | GitHub Actions | Woodpecker CI | +|---------|---------------|---------------| +| Matrix builds | βœ… 3 OS | ❌ Linux only* | +| Caching | βœ… Built-in | ⚠️ Server-side** | + +\* Multi-OS builds require multiple Woodpecker agents +\*\* Configure in Woodpecker server settings diff --git a/.woodpecker/ci-advanced.yml b/.woodpecker/ci-advanced.yml new file mode 100644 index 0000000..3bda3c4 --- /dev/null +++ b/.woodpecker/ci-advanced.yml @@ -0,0 +1,168 @@ +# Woodpecker CI - Advanced Pipeline +# Multi-platform builds, coverage, benchmarks, and security scanning + +when: + event: [push, pull_request, manual] + branch: + - main + - develop + +matrix: + PLATFORM: + - linux/amd64 + - linux/arm64 + +steps: + # === LINTING (Parallel) === + + lint-rust: + image: rust:latest + commands: + - curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + - rustup component add clippy rustfmt + - cargo fmt --all -- --check + - cargo clippy --all-targets --all-features -- -D warnings + environment: + CARGO_TERM_COLOR: always + + lint-bash: + image: koalaman/shellcheck-alpine:stable + commands: + - apk add --no-cache curl bash + - find . -name '*.sh' -type f ! -path './target/*' -exec shellcheck {} + + + lint-nickel: + image: rust:latest + commands: + - cargo install nickel-lang-cli --locked + - find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \; + + lint-nushell: + image: rust:latest + commands: + - cargo install nu --locked + - find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \; + + lint-markdown: + image: node:alpine + commands: + - npm install -g markdownlint-cli2 + - markdownlint-cli2 '**/*.md' '#node_modules' '#target' + + # === TESTING === + + test: + image: rust:latest + commands: + - cargo test --workspace --all-features --no-fail-fast + depends_on: + - lint-rust + - lint-bash + - lint-nickel + - lint-nushell + - lint-markdown + environment: + RUST_BACKTRACE: 1 + + # === CODE COVERAGE === + + coverage: + image: rust:latest + commands: + - cargo install cargo-tarpaulin --locked + - cargo tarpaulin --workspace --all-features --out Xml --output-dir coverage + - | + if [ -f coverage/cobertura.xml ]; then + echo "Coverage report generated successfully" + fi + depends_on: + - test + when: + event: [push, pull_request] + branch: [main, develop] + + # === BUILD (Multi-platform) === + + build-native: + image: rust:latest + commands: + - cargo build --release --workspace + - ls -lh target/release/ + depends_on: + - test + + build-cross: + image: rust:latest + commands: + - cargo install cross --locked + - cross build --target x86_64-unknown-linux-musl --release + - cross build --target aarch64-unknown-linux-musl --release + depends_on: + - test + when: + matrix: + PLATFORM: linux/amd64 + + # === BENCHMARKS === + + benchmark: + image: rust:latest + commands: + - rustup toolchain install nightly + - cargo +nightly bench --workspace --no-fail-fast + - | + if [ -d target/criterion ]; then + echo "Benchmark results available in target/criterion" + fi + depends_on: + - build-native + when: + event: pull_request + + # === SECURITY AUDITS === + + security-audit: + image: rust:latest + commands: + - cargo install cargo-audit --locked + - cargo audit --deny warnings --deny unmaintained --deny unsound + depends_on: + - lint-rust + + license-check: + image: rust:latest + commands: + - cargo install cargo-deny --locked + - cargo deny check licenses advisories sources bans + depends_on: + - lint-rust + + dependency-check: + image: rust:latest + commands: + - cargo install cargo-outdated --locked + - cargo outdated --exit-code 1 --root-deps-only + depends_on: + - lint-rust + when: + event: manual + + # === SONARQUBE ANALYSIS === + + sonarqube: + image: sonarsource/sonar-scanner-cli:latest + commands: + - | + sonar-scanner \ + -Dsonar.projectKey=${CI_REPO_NAME} \ + -Dsonar.sources=. \ + -Dsonar.host.url=${SONAR_HOST_URL} \ + -Dsonar.token=${SONAR_TOKEN} \ + -Dsonar.rust.clippy.reportPaths=clippy-report.json \ + -Dsonar.coverageReportPaths=coverage/cobertura.xml + depends_on: + - coverage + secrets: [sonar_host_url, sonar_token] + when: + event: [push, pull_request] + branch: [main, develop] diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml new file mode 100644 index 0000000..be8aba9 --- /dev/null +++ b/.woodpecker/ci.yml @@ -0,0 +1,84 @@ +# Woodpecker CI Pipeline +# Equivalent to GitHub Actions CI workflow +# Generated by dev-system/ci + +when: + event: [push, pull_request, manual] + branch: + - main + - develop + +steps: + # === LINTING === + + lint-rust: + image: rust:latest + commands: + - curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + - rustup component add clippy + - cargo fmt --all -- --check + - cargo clippy --all-targets -- -D warnings + + lint-bash: + image: koalaman/shellcheck-alpine:stable + commands: + - apk add --no-cache curl bash + - find . -name '*.sh' -type f ! -path './target/*' -exec shellcheck {} + + + lint-nickel: + image: rust:latest + commands: + - cargo install nickel-lang-cli --locked + - find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \; + + lint-nushell: + image: rust:latest + commands: + - cargo install nu --locked + - find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \; + + lint-markdown: + image: node:alpine + commands: + - npm install -g markdownlint-cli2 + - markdownlint-cli2 '**/*.md' '#node_modules' '#target' + + # === TESTING === + + test: + image: rust:latest + commands: + - cargo test --workspace --all-features + depends_on: + - lint-rust + - lint-bash + - lint-nickel + - lint-nushell + - lint-markdown + + # === BUILD === + + build: + image: rust:latest + commands: + - cargo build --release + depends_on: + - test + + # === SECURITY === + + security-audit: + image: rust:latest + commands: + - cargo install cargo-audit --locked + - cargo audit --deny warnings + depends_on: + - lint-rust + + license-check: + image: rust:latest + commands: + - cargo install cargo-deny --locked + - cargo deny check licenses advisories + depends_on: + - lint-rust diff --git a/.yamllint-ci.yml b/.yamllint-ci.yml new file mode 100644 index 0000000..3575afe --- /dev/null +++ b/.yamllint-ci.yml @@ -0,0 +1,18 @@ +extends: default + +rules: + line-length: + max: 200 # More reasonable for infrastructure code + comments: + min-spaces-from-content: 1 # Allow single space before comments + document-start: disable # Cloud-init files don't need --- start + truthy: + allowed-values: ["true", "false", "yes", "no", "on", "off"] # Allow cloud-init and GitHub Actions common values + +# Ignore cloud-init files for comment spacing since #cloud-config is a special directive +# Ignore directories with generated/runtime files +ignore: | + **/cloud-init.yml + build/** + data/** + envs/** diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7d990d3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,108 @@ +# Changelog + +All notable changes to ontoref are documented here. +ADRs referenced below live in `adrs/` as typed Nickel records. + +--- + +## [Unreleased] + +### Protocol + +- ADR-001 accepted: ontoref extracted as a standalone protocol project, independent of + stratumiops versioning and release cycle. Consumer projects adopt via `scripts/ontoref` + wrapper + `.ontoref/config.ncl`. + ([adr-001](adrs/adr-001-protocol-as-standalone-project.ncl)) +- ADR-002 accepted: `ontoref-daemon` introduced as optional persistent daemon for NCL export + caching (keyed by path+mtime), actor registry (developer/agent/CI), and notification barrier + (pre-commit hook, fail-open). Supersedes stratumiops ADR-007. + ([adr-002](adrs/adr-002-daemon-for-caching-and-notification-barrier.ncl)) +- ADR-003 accepted: Q&A and accumulated operational knowledge persist to `reflection/qa.ncl` + β€” typed NCL, git-versioned, accessible via MCP tools and HTTP endpoints. localStorage + eliminated. Q&A entries survive session boundaries and are queryable by any actor. + ([adr-003](adrs/adr-003-qa-and-knowledge-persistence-as-ncl.ncl)) + +### Crates + +- `ontoref-ontology`: Rust crate for loading `.ontology/*.ncl` as typed structs (`Core`, `Gate`, `State`). Zero stratumiops dependencies. +- `ontoref-reflection`: Rust crate for loading, validating, and executing Reflection modes as NCL DAG contracts. Optional `nats` feature (path dep: `platform-nats`). +- `ontoref-daemon`: Rust crate providing HTTP API (axum), DashMap-backed NCL export cache, + notify-based file watcher, and actor registry. Optional `db` feature (path dep: `stratum-db`) + and `nats` feature (path dep: `platform-nats`). + +### Daemon β€” Q&A NCL Persistence (`crates/ontoref-daemon/src/ui/qa_ncl.rs`) + +Line-level NCL surgery for `reflection/qa.ncl` β€” same pattern as `backlog_ncl.rs`. No AST parsing, no nickel-lang-core dependency. + +- `add_entry` β€” appends a typed `QaEntry` block before `],` array close; generates sequential `qa-NNN` ids +- `update_entry` β€” in-place field mutation via bidirectional scan (question + answer fields) +- `remove_entry` β€” removes the full block by id using backward scan for `{` and forward scan for `},` + +HTTP endpoints (all under `#[cfg(feature = "ui")]` except read-only GET): +- `GET /qa-json` β€” export all Q&A entries as JSON (read-only, always enabled) +- `POST /qa/add` β€” append new entry; returns generated id +- `POST /qa/delete` β€” remove entry by id; invalidates NCL cache +- `POST /qa/update` β€” mutate question + answer fields by id; invalidates NCL cache +- `GET /actions/run` / `POST /actions/run` β€” execute a quick action by id; spawns `./ontoref ` + +Server-side hydration: `qa.html` receives `entries` as Tera context variable, embeds +`SERVER_ENTRIES` JSON literal in the page `