diff --git a/skills/ci-cd-pipeline/SKILL.md b/skills/ci-cd-pipeline/SKILL.md new file mode 100644 index 0000000..9bbce0f --- /dev/null +++ b/skills/ci-cd-pipeline/SKILL.md @@ -0,0 +1,139 @@ +# CI/CD Pipeline Setup + +Blueprint for setting up a GitHub Actions CI/CD pipeline with checks, +builds, draft releases, and supply-chain provenance. + +## Overview + +The pipeline is organized as a single workflow file (`.github/workflows/ci.yml`) +with jobs that run in dependency order. Tag pushes trigger the build+release +path; branch pushes and PRs trigger only the check path. + +## Job Structure + +``` +check (every push) + ├── unit tests + ├── linter + ├── dependency audit + └── documentation + │ +pages (master only) — deploy API docs + │ +build (tags only) + ├── compile for all targets + ├── package into archives + └── upload as workflow artifacts + │ +provenance (tags only) — SLSA attestation + │ +release (tags only) — create draft release with all artifacts +``` + +## Check Job + +Runs on every push and pull request. Should include: + +- **Check** — verify the project compiles +- **Tests** — run the full test suite +- **Linter** — enforce zero warnings +- **Dependency audit** — check for known vulnerabilities +- **Documentation** — generate and upload API docs (master only) + +```yaml +check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo check --workspace + - run: cargo test --workspace + - run: cargo clippy --workspace -- -D warnings + - run: cargo doc --no-deps +``` + +## Build & Release Job + +Only runs on tag pushes matching a version pattern (e.g. `v*`). + +- Builds for all target platforms +- Creates release archives (tar.gz, zip) +- Generates SHA256 hashes of all artifacts +- Uploads archives as workflow artifacts +- Sets `draft: true` so releases require manual publishing + +```yaml +build: + needs: check + if: startsWith(github.ref, 'refs/tags/v') + outputs: + hashes: ${{ steps.hash.outputs.hashes }} + steps: + - uses: actions/checkout@v4 + - run: + - name: Package + run: + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + path: builds/ +``` + +## Provenance (SLSA) + +Uses the SLSA v3 generator to attest that release artifacts were built +by the CI pipeline from a specific commit. + +```yaml +provenance: + needs: build + if: startsWith(github.ref, 'refs/tags/v') + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 + with: + base64-subjects: "${{ needs.build.outputs.hashes }}" + upload-assets: false +``` + +## Draft Release Job + +Creates a draft release after build + provenance both complete. Downloads +the binary artifacts and provenance attestation, then uploads them together. + +```yaml +release: + needs: [build, provenance] + if: startsWith(github.ref, 'refs/tags/v') + steps: + - uses: actions/download-artifact@v4 + - uses: softprops/action-gh-release@v2 + with: + files: + body_path: _release.md + draft: true +``` + +## Guardrails + +- Releases are always **drafts** — the maintainer tests before publishing +- Provenance runs as a separate job to avoid interfering with the release +- `upload-assets: false` on the SLSA generator — let the release job handle all uploads +- SHA256 hashes are generated in the build job and passed to provenance + +## Key Actions + +| Action | Purpose | +|--------|---------| +| `actions/checkout@v4` | Check out source code | +| `actions/upload-artifact@v4` | Store build artifacts between jobs | +| `actions/download-artifact@v4` | Retrieve artifacts in downstream jobs | +| `softprops/action-gh-release@v2` | Create releases (supports `draft: true`) | +| `slsa-framework/slsa-github-generator` | Generate SLSA v3 provenance | +| `dtolnay/rust-toolchain@stable` | Install the language toolchain | + +## First-Time Setup + +1. Create `.github/workflows/ci.yml` with the job structure above +2. Create `_release.md` with the initial release notes template +3. Enable GitHub Pages if using API docs (Settings → Pages → GitHub Actions) +4. Create a signed tag and push to verify the pipeline +5. Test the draft → publish cycle end-to-end diff --git a/skills/documentation/SKILL.md b/skills/documentation/SKILL.md new file mode 100644 index 0000000..60422f8 --- /dev/null +++ b/skills/documentation/SKILL.md @@ -0,0 +1,50 @@ +# Documentation + +When to update each documentation file in the project. + +## Hierarchy + +| File | Purpose | When to update | +|------|---------|----------------| +| `src/*` | Doc comments on every function | Every change to the function | +| `CHANGELOG.md` | What changed, version, date | Every commit | +| `GOVERNANCE.md` | Roadmap, release process, checklist | When process or plans change | +| `KNOWN_ISSUES.md` | Bugs and limitations users might encounter | When a new issue surfaces or is resolved | +| `DECISIONS.md` | Rationale behind architecture choices | When a significant decision is made | +| `_release.md` | What's new in the current release | Every release | +| `README.md` | User-facing features, build instructions | When features or setup change | +| CI workflow file | Pipeline configuration | When pipeline logic changes | + +## Doc Comment Standards + +- Every public function must have a doc comment +- Each comment explains *what* the function does, *why* it exists, and + *what edge cases* it handles +- No "Internal helper" or "see module-level docs" placeholders +- Language-standard doc format (e.g. `///` in Rust, `///` in C#, `/** */` in JS) + +## Changelog Format + +``` +## [v0.x.y] — YYYY-MM-DD + +### Added +- New features + +### Fixed +- Bug fixes + +### Changed +- Behavior changes, refactors + +### Removed +- Features removed + +### Notes +- Operational notes (git resets, CI issues, etc.) +``` + +## Release Notes + +- Contains only the current version's changes — no history from older versions +- Replaced entirely for each new release, not appended diff --git a/skills/privacy-security/SKILL.md b/skills/privacy-security/SKILL.md new file mode 100644 index 0000000..df3efa1 --- /dev/null +++ b/skills/privacy-security/SKILL.md @@ -0,0 +1,29 @@ +# Privacy & Security + +Privacy-first design principles and security practices. + +## Privacy Principles + +- **No sensitive paths written to disk** — user data is session-only when possible +- **No scanning of user profiles or system directories** beyond the current user +- **All logged paths sanitized** to strip user-identifiable prefixes +- **User consent tracked via sentinel file**, not a config file with user data + +## Input Handling + +- Strip control characters from user-provided input before it reaches + config files, logs, or the filesystem — prevents injection and log forgery +- Validate and sanitize all external input before processing + +## Security Practices + +- `deny(unsafe_code)` enabled where the language supports it — zero unsafe +- Dependency auditing and license checks in CI for every commit +- GPG-signed release tags with build provenance attestation +- Vulnerability disclosure policy documented in the repository + +## What We Avoid + +- No telemetry, no network connections, no auto-updater +- No admin or root privileges required — runs in user context +- No third-party services in the shipped binary diff --git a/skills/release-workflow/SKILL.md b/skills/release-workflow/SKILL.md new file mode 100644 index 0000000..477fe8e --- /dev/null +++ b/skills/release-workflow/SKILL.md @@ -0,0 +1,53 @@ +# Release Workflow + +Versioning, release checklist, signing, and push conventions. + +## Versioning + +| Bump | When | Example | +|------|------|---------| +| PATCH | Bug fix or small polish after a release | v0.3.1 → v0.3.2 | +| MINOR | New feature or significant restructure | v0.3.x → v0.4.0 | +| MAJOR | Breaking change (1.0+ only) | 1.0.0 → 2.0.0 | + +- Version in the project manifest matches the latest release tag +- Tags are created at release time, not per-commit +- Multiple commits can happen between tags + +## Draft Release Cycle + +``` +commit → push → tag v0.x.y → CI builds draft → user tests → publish +``` + +No release goes live without the user testing the draft first. + +## Release Checklist + +Before signing a release tag: + +- [ ] Impact analysis completed — all call sites for new/changed functions +- [ ] All tests pass +- [ ] Linter passes with zero warnings +- [ ] CHANGELOG.md has an entry for the new version +- [ ] Working tree is clean — no uncommitted changes +- [ ] Release notes file is updated for the new version + +After CI completes: + +- [ ] Download draft binaries from the releases page +- [ ] Test on target platform — basic workflow, key features +- [ ] Click **Publish release** on the hosting platform when satisfied + +## Signing & Push + +- Commit with `--no-gpg-sign` (avoids GPG passphrase hang in non-interactive terminals) +- Maintainer amends with `--gpg-sign` before push +- Normal push for fast-forward commits +- `--force-with-lease` for amended commits or tag refreshes +- If force-pushing, delete old tag and re-tag after the new commit lands + +## Release Notes + +- Release notes file contains only the current version's changes +- Historical release notes on the platform are cleaned per-release diff --git a/skills/rust-standards/SKILL.md b/skills/rust-standards/SKILL.md new file mode 100644 index 0000000..9b40774 --- /dev/null +++ b/skills/rust-standards/SKILL.md @@ -0,0 +1,78 @@ +# Rust Standards + +Coding conventions and patterns for the NotAlterra project. + +## Error Handling + +- Use `anyhow::Result` for fallible functions — no custom error types +- `anyhow::bail!` for early returns with context +- `.with_context(|| format!(...))` on `Result` from external crates +- Avoid `unwrap()` and `expect()` outside of tests and examples +- Use `let _ = fallible_fn()` when deliberately ignoring errors + +## File I/O + +- Prefer `std::fs` convenience functions for simple operations + (`fs::read()`, `fs::write()`, `fs::read_dir()`) +- Use `PathBuf` for owned paths, `&Path` for borrowed references +- Validate paths early with `path.exists()` before operations +- Use `saturating_sub` for all arithmetic that could underflow + +## String Handling + +- Use `format!()` for construction, avoid `+` concatenation +- Use `to_string_lossy()` for OsStr → String conversion +- Strip control characters from user input before storage or logging + +## Data Structures + +- Prefer `Vec` over linked lists or custom containers +- Use `HashSet` for deduplication +- Use `Option` for nullable values — never `null` or sentinel values +- Use `struct` with named fields for complex return types +- Derive `Debug, Clone` on all data structures, `Default` where meaningful + +## Pattern: Property Extraction (GVAS parser) + +All four extractors follow the same pattern: +1. Scan for property name using `windows(target.len()).position()` +2. Validate the FName header (length dword + null terminator) +3. Skip past the property type name +4. Validate bounds before every index access +5. Return `Option` or `Result` — never panic + +When adding a new property type, follow this exact pattern and add a bounds +check on every array access. + +## Pattern: TUI Dialogs + +All dialogs follow the same structure: +1. Define popup area with `centered_rect_size()` or `centered_rect()` +2. Render `Clear` widget, then a bordered `Block` +3. Compute `inner` area with margin +4. Render title, body, buttons in sequence +5. Call `draw_whale_separator(f, bar, app)` at the bottom + +## Pattern: Menu Actions + +All menu actions: +1. Validate preconditions (save folder set, backup exists) +2. Show status/spinner if the operation takes time +3. Call through to `ops::*` for actual file operations +4. Log via `guard::log_action()` with sanitized paths +5. Show result dialog (success or error) +6. Refresh dashboard stats + +## Clippy + +- `-D warnings` enforced in CI — no exceptions +- Fix lints immediately when CI catches new ones +- Common lints that have fired: `collapsible_match`, `manual_is_multiple_of`, + `empty_line_after_doc_comments`, `needless_borrows_for_generic_args` + +## Dependencies + +- Prefer crates with 50M+ downloads for core functionality +- Avoid platform-specific FFI — prefer pure Rust where possible +- Keep dependency count minimal — each new crate is a review point +- Run `cargo audit` and `cargo deny` before each release diff --git a/skills/session-protocol/SKILL.md b/skills/session-protocol/SKILL.md new file mode 100644 index 0000000..f242961 --- /dev/null +++ b/skills/session-protocol/SKILL.md @@ -0,0 +1,23 @@ +# Session Protocol + +How to structure and execute each development session efficiently. + +## Initialization + +1. **Full project scan first** — read the build file, all source files, + tests, docs. Ensures the full codebase is understood before making changes. +2. **Check version control status** — identify any uncommitted work from + prior sessions. +3. **Load companion skills** — `documentation`, `release-workflow`, + `testing-fuzzing`, `privacy-security`, `ci-cd-pipeline`. + +## Task Protocol + +1. **Impact analysis before code** — list every file and call site that needs + to change. Present for validation before writing code. +2. **One feature per cycle** — one logical change per commit. Batch docs, + changelog, and version metadata with the feature. +3. **Call site audit on completion** — verify every reference is updated. + Build + test + lint before declaring done. +4. **Draft release cycle** — commit → push → tag → CI builds draft → + user tests → publish. Never ship without draft testing. diff --git a/skills/testing-fuzzing/SKILL.md b/skills/testing-fuzzing/SKILL.md new file mode 100644 index 0000000..0d3948c --- /dev/null +++ b/skills/testing-fuzzing/SKILL.md @@ -0,0 +1,37 @@ +# Testing & Fuzzing + +Testing conventions and fuzzing strategy. + +## Integration Tests + +**Test patterns to follow:** +- Use temporary directories for all file-based tests +- Test both success and failure paths +- Test round-trips: create → process → verify content matches +- Test edge cases: empty inputs, truncated data, missing files + +**Where tests live:** +- `tests/` — cross-module integration tests +- `src/` — unit tests in language-standard test modules +- `fuzz/fuzz_targets/` — fuzz targets + +## Fuzz Targets + +Fuzzing is for code that parses **untrusted binary input**. + +**When to add a fuzz target:** +- Custom binary format parsers +- Archive round-trips (create archive from fuzzed inputs → restore → compare) +- Not needed for deterministic operations or wrapping established libraries + +**Requirements:** +- Fuzzing requires a nightly toolchain for sanitizer instrumentation +- The project must have a fuzz harness (e.g. cargo-fuzz, libfuzzer, oss-fuzz) + +## Coverage Requirements + +- Every new feature ships with integration or unit tests +- Fuzz targets for binary parsers and archive round-trips only +- All tests must pass before every commit +- Linter must pass with zero warnings +- Doc coverage check must pass (if implemented)