diff --git a/.agents/skills/process-issues/SKILL.md b/.agents/skills/process-issues/SKILL.md index 34ea0ffbe..72e32913d 100644 --- a/.agents/skills/process-issues/SKILL.md +++ b/.agents/skills/process-issues/SKILL.md @@ -43,8 +43,8 @@ For each qualifying issue (ordered by issue number), achieve ALL of these before - Minimal, focused changes - Positive and negative tests pass -- Security tests added if change touches parser, interpreter, VFS, network, git, or user input (per `specs/security-testing.md`) -- Threat model updated if new attack surface (per `specs/threat-model.md`) +- Security tests added if change touches parser, interpreter, VFS, network, git, or user input (per `knowledge/security-testing.md`) +- Threat model updated if new attack surface (per `knowledge/threat-model.md`) ### 4. Ship via `/ship` diff --git a/.agents/skills/ship/SKILL.md b/.agents/skills/ship/SKILL.md index 3b905f4ae..e040e54e2 100644 --- a/.agents/skills/ship/SKILL.md +++ b/.agents/skills/ship/SKILL.md @@ -33,7 +33,7 @@ Review the changes on this branch (use `git diff origin/main...HEAD` and `git lo 3. **Write missing tests** for any uncovered code paths: - **Positive tests**: happy path, valid inputs, expected state transitions - **Negative tests**: invalid inputs, error conditions, boundary cases, permission failures, missing resources - - **Security tests**: if change touches parser, interpreter, VFS, network, git, or user input — add tests per `specs/security-testing.md` + - **Security tests**: if change touches parser, interpreter, VFS, network, git, or user input — add tests per `knowledge/security-testing.md` - **Compatibility tests**: if change affects Bash behavior parity — add differential tests comparing against real Bash 4. **Run all tests** to confirm green: `just test` 5. If any test fails, fix the code or test until green @@ -42,10 +42,10 @@ Review the changes on this branch (use `git diff origin/main...HEAD` and `git lo Review the changes and update project artifacts where applicable. Skip items that aren't affected. -1. **Specs** (`specs/`): if the change adds/modifies behavior covered by a spec, update the relevant spec file to stay in sync -2. **Threat model** (`specs/threat-model.md`): if the change introduces new attack surfaces, external inputs, authentication/authorization changes, or data handling — add or update threat entries using the `TM--` format and add `// THREAT[TM-XXX-NNN]` code comments at mitigation points -3. **AGENTS.md**: if the change adds new specs, commands, or modifies development workflows — update the relevant section -4. **Limitations** (`specs/limitations.md`): if a limitation was added or lifted, update the table; if builtins changed, run `just regen-builtins` and commit the JSON +1. **Knowledge** (`knowledge/`): if the change affects durable behavior, decisions, constraints, threats, tests, or operations, update the relevant OKF knowledge in the same change +2. **Threat model** (`knowledge/threat-model.md`): if the change introduces new attack surfaces, external inputs, authentication/authorization changes, or data handling — add or update threat entries using the `TM--` format and add `// THREAT[TM-XXX-NNN]` code comments at mitigation points +3. **AGENTS.md**: if the change adds new knowledge, commands, or modifies development workflows — update the relevant section +4. **Limitations** (`knowledge/limitations.md`): if a limitation was added or lifted, update the table; if builtins changed, run `just regen-builtins` and commit the JSON 5. **Documentation** (`crates/bashkit/docs/`): if the change affects public APIs, tools, or features — update the relevant guide markdown files ### Phase 3b: Code Simplification @@ -66,12 +66,12 @@ Analyze all changed code for security vulnerabilities: 1. **Input validation** — check that user-supplied data (script input, file paths, environment variables, command arguments) is validated before use 2. **Injection risks** — look for command injection, path traversal, environment variable injection, or shell metacharacter issues -3. **Sandbox escapes** — if changes touch VFS, builtins, or process execution, verify they cannot escape the sandbox (see `specs/threat-model.md`) +3. **Sandbox escapes** — if changes touch VFS, builtins, or process execution, verify they cannot escape the sandbox (see `knowledge/threat-model.md`) 4. **Resource exhaustion** — check for unbounded loops, unbounded allocations, or missing limits on user-controlled sizes 5. **Error handling** — ensure errors don't leak internal state, file paths, or sensitive information 6. **Unsafe code** — review any `unsafe` blocks for soundness; prefer safe alternatives -If security issues are found, fix them, add regression tests, and update `specs/threat-model.md` if a new threat category is identified. +If security issues are found, fix them, add regression tests, and update `knowledge/threat-model.md` if a new threat category is identified. ### Phase 3d: Design Quality Review diff --git a/.claude/commands/maintain.md b/.claude/commands/maintain.md index fe3b99b23..bfc024ad1 100644 --- a/.claude/commands/maintain.md +++ b/.claude/commands/maintain.md @@ -1,4 +1,4 @@ -Run the pre-release maintenance checklist from `specs/maintenance.md`. Find and fix all issues before reporting. +Run the pre-release maintenance checklist from `knowledge/maintenance.md`. Find and fix all issues before reporting. ## Arguments @@ -28,7 +28,7 @@ Key tools: `cargo update`, `cargo outdated`, `cargo audit`, `cargo deny check`, Ensure the threat model covers all features, security tests exist for all mitigated threats, and no OWASP-style issues exist in the codebase. -Key references: `specs/threat-model.md`, `specs/security-testing.md`, `crates/bashkit/docs/threat-model.md` +Key references: `knowledge/threat-model.md`, `knowledge/security-testing.md`, `crates/bashkit/docs/threat-model.md` ### 3. Tests are comprehensive and green @@ -94,7 +94,7 @@ Key tools: - `gh run list --workflow=fuzz.yml --limit 7` (fuzz) - `gh api repos/OWNER/REPO/actions/runs/RUN_ID/jobs` (inspect failed jobs) -If failures persist >2 days, escalate per `specs/maintenance.md`. +If failures persist >2 days, escalate per `knowledge/maintenance.md`. If the agent cannot fix a failure, it MUST open a GitHub issue and report the pass as blocked — never silently skip. @@ -108,6 +108,6 @@ pass as blocked — never silently skip. ## Notes -- This is a goal-based checklist. The spec (`specs/maintenance.md`) defines *what* must be true. This skill defines *how* to verify and fix. +- This is a goal-based checklist. The spec (`knowledge/maintenance.md`) defines *what* must be true. This skill defines *how* to verify and fix. - Use parallel agents for independent sections when possible. - For scoped runs, still verify that fixes don't break other areas (`just test` at minimum). diff --git a/.deepsec/data/bashkit/INFO.md b/.deepsec/data/bashkit/INFO.md index d41d6a7de..74ca640f4 100644 --- a/.deepsec/data/bashkit/INFO.md +++ b/.deepsec/data/bashkit/INFO.md @@ -54,7 +54,7 @@ shown directly to LLMs or users. - Tests and fuzz targets intentionally contain hostile scripts, fake secrets, host canaries, traversal strings, malformed archives, and allowlist bypass attempts. -- `specs/` and `crates/bashkit/docs/` describe vulnerabilities and mitigations; +- `knowledge/` and `crates/bashkit/docs/` describe vulnerabilities and mitigations; treat them as design docs unless the same pattern appears in executable code. - Optional features named `realfs`, `http_client`, `ssh`, `git`, `python`, `typescript`, `sqlite`, and `bot-auth` are intended capability gates, not diff --git a/.github/workflows/apidocs-drift.yml b/.github/workflows/apidocs-drift.yml index c81b728df..939b55764 100644 --- a/.github/workflows/apidocs-drift.yml +++ b/.github/workflows/apidocs-drift.yml @@ -5,7 +5,7 @@ name: API Reference Drift # site/src/content/apidocs/*.md and feeds the /api/{python,typescript} pages; # the node-only site build just renders it, so it must be regenerated and # committed on release — fix drift by running `just apidocs` and committing. -# See specs/documentation.md ("API reference hosting"). +# See knowledge/documentation.md ("API reference hosting"). # # Per AGENTS.md commit-attribution rules this workflow never auto-commits; it # only fails so a human regenerates and commits under a real identity. diff --git a/.github/workflows/builtins-drift.yml b/.github/workflows/builtins-drift.yml index 281948060..3c9abcbb3 100644 --- a/.github/workflows/builtins-drift.yml +++ b/.github/workflows/builtins-drift.yml @@ -1,6 +1,6 @@ name: Builtins Inventory Drift -# Fails when specs/status/builtins.json no longer matches what the code +# Fails when knowledge/status/builtins.json no longer matches what the code # registers (see `Bash::builtin_names`). The JSON is generated by # `just regen-builtins` and is the data source for the site's builtins # page and homepage counts — fix drift by regenerating and committing. @@ -15,7 +15,7 @@ on: - 'crates/bashkit/src/builtins/**' - 'crates/bashkit/src/lib.rs' - 'crates/bashkit/examples/dump_builtins.rs' - - 'specs/status/builtins.json' + - 'knowledge/status/builtins.json' - '.github/workflows/builtins-drift.yml' schedule: # Weekly Mondays 05:30 UTC, after the coreutils drift run. @@ -49,11 +49,11 @@ jobs: run: | cargo run -q --example dump_builtins \ --features jq,git,ssh,http_client,python,typescript,sqlite \ - > specs/status/builtins.json + > knowledge/status/builtins.json - name: Fail on drift run: | - if ! git diff --exit-code -- specs/status/builtins.json; then - echo "::error::specs/status/builtins.json is stale — run 'just regen-builtins' and commit the result" + if ! git diff --exit-code -- knowledge/status/builtins.json; then + echo "::error::knowledge/status/builtins.json is stale — run 'just regen-builtins' and commit the result" exit 1 fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 851189dba..8fee02410 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: # Build the browser package (@everruns/bashkit-wasm) and run its headless # integration tests, proving the single-threaded bundle loads with no # COOP/COEP headers and that sync + async execution both work. See - # specs/browser-package.md. Keep wasm-bindgen-cli in lockstep with the + # knowledge/browser-package.md. Keep wasm-bindgen-cli in lockstep with the # wasm-bindgen version in Cargo.lock. name: WASM web package runs-on: ubuntu-latest diff --git a/.github/workflows/coreutils-args-drift.yml b/.github/workflows/coreutils-args-drift.yml index d42278f35..fea9c3a91 100644 --- a/.github/workflows/coreutils-args-drift.yml +++ b/.github/workflows/coreutils-args-drift.yml @@ -2,7 +2,7 @@ name: Coreutils Args Drift # Detects upstream uutils/coreutils argument-surface AND vendored-module # drift, and proposes both as a single PR. See -# specs/coreutils-args-port.md for the design (args mode + module mode). +# knowledge/coreutils-args-port.md for the design (args mode + module mode). # # Module set is read from `crates/bashkit-coreutils-port/vendored.toml`; # adding a vendored module is one TOML stanza there and the drift run @@ -324,7 +324,7 @@ jobs: correctly per \`AGENTS.md\`. Intermediate bot commits in this PR are discarded by squash. - Design: [\`specs/coreutils-args-port.md\`](../tree/main/specs/coreutils-args-port.md). + Design: [\`knowledge/coreutils-args-port.md\`](../tree/main/knowledge/coreutils-args-port.md). EOF if gh pr view "$branch" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then diff --git a/.github/workflows/publish-python.yml b/.github/workflows/publish-python.yml index dbc1758a0..fd71b7ace 100644 --- a/.github/workflows/publish-python.yml +++ b/.github/workflows/publish-python.yml @@ -21,7 +21,7 @@ env: CARGO_TERM_COLOR: always # abi3 (stable ABI): one interpreter builds a single cp39-abi3 wheel per # platform that runs on Python 3.9+. No per-minor-version matrix. See - # specs/python-package.md § abi3. + # knowledge/python-package.md § abi3. BUILD_PYTHON: "3.12" jobs: @@ -119,14 +119,14 @@ jobs: # Reduced-feature Pyodide/Emscripten wheel (browser / JupyterLite). # Separate job: distinct toolchain (nightly Rust + emsdk + pyodide-build) and a # single Python version dictated by the pyodide-build ABI lockstep. - # See specs/emscripten-wheels.md. + # See knowledge/emscripten-wheels.md. build-emscripten: name: Build wheel - emscripten (Pyodide) runs-on: ubuntu-latest env: # Keep in lockstep with the `wasm` job in python.yml: the nightly's LLVM, # pyodide-build's Emscripten/binaryen, and Pyodide's EH ABI must agree. - # See specs/emscripten-wheels.md "version triangle". Bump together. + # See knowledge/emscripten-wheels.md "version triangle". Bump together. RUST_NIGHTLY: "nightly-2026-05-29" PYODIDE_BUILD_VERSION: "0.34.4" steps: @@ -134,7 +134,7 @@ jobs: # Python 3.13 -> pyodide-build's modern config (Pyodide 0.29.x, Emscripten # 4.0.9), whose binaryen understands modern LLVM's wasm target-features and - # whose runtime supports wasm exception handling. See specs/emscripten-wheels.md. + # whose runtime supports wasm exception handling. See knowledge/emscripten-wheels.md. - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.13" diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 8c560b39e..b1407fccc 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -193,14 +193,14 @@ jobs: retention-days: 5 # Build the reduced-feature Pyodide/Emscripten wheel and smoke-test it in a - # Pyodide venv. See specs/emscripten-wheels.md for the feature matrix and the + # Pyodide venv. See knowledge/emscripten-wheels.md for the feature matrix and the # pyodide-build <-> Emscripten <-> Python <-> Rust version lockstep. wasm: name: Build wheel (Pyodide/Emscripten) runs-on: ubuntu-latest env: # Pinned for reproducibility: this trio must stay aligned on the wasm - # feature set + exception-handling ABI (see specs/emscripten-wheels.md + # feature set + exception-handling ABI (see knowledge/emscripten-wheels.md # "version triangle"). pyodide-build 0.34.x (under Python 3.13) selects # Pyodide 0.29.x / Emscripten 4.0.9; the nightly's LLVM must match that # binaryen. Bump all three together and re-verify the wheel imports. @@ -220,7 +220,7 @@ jobs: # must satisfy our deps' MSRV (monty needs rustc 1.95) and edition 2024, # so it has to be recent; its LLVM (19+) matches Emscripten 4.0.9's # binaryen, which is what avoids the wasm-opt target-feature skew that - # older Emscripten (3.1.x) hit. See specs/emscripten-wheels.md. + # older Emscripten (3.1.x) hit. See knowledge/emscripten-wheels.md. - name: Install nightly Rust with the Emscripten target # @nightly matches the repo's other nightly jobs (fuzz.yml, nightly.yml, # ci.yml); the exact nightly is pinned via the toolchain: input below. diff --git a/AGENTS.md b/AGENTS.md index 90d500eab..651b0b3aa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,11 +17,11 @@ Fix root cause. Unsure: read more code; if stuck, ask w/ short options. Unrecogn - No backward compat needed (internal code) - Write failing test before fixing bug -### Specs +### Knowledge -`specs/` contains feature specifications. New code should comply with these or propose changes. +`knowledge/` is the canonical OKF bundle and persistent project memory. Read relevant knowledge before changing behavior, and update it in the same change when decisions, behavior, constraints, threats, tests, or operations change. New durable engineering knowledge belongs there; see `knowledge/index.md` for the maintenance contract. -| Spec | Description | +| Knowledge | Description | |------|-------------| | architecture | Core interpreter architecture, module structure | | parser | Bash syntax parser design | @@ -57,14 +57,14 @@ Fix root cause. Unsure: read more code; if stuck, ask w/ short options. Unrecogn - **Public docs** live in `docs/` — user-facing articles (security, guides, etc.) - **Rustdoc guides** live in `crates/bashkit/docs/` as markdown files -- Rustdoc guides embedded via `include_str!` (see `specs/documentation.md`) +- Rustdoc guides embedded via `include_str!` (see `knowledge/documentation.md`) - Edit `crates/bashkit/docs/*.md`, not the doc modules in `lib.rs` - Add "See also" cross-links when creating new guides - Run `cargo doc --open` to preview rustdoc changes ### Bashkit Principles -- All design decisions in `specs/` - no undocumented choices +- All design decisions in `knowledge/` - no undocumented choices - Everything runnable and testable - no theoretical code - Don't stop until e2e works - verify before declaring done - Examples tested in CI - must pass @@ -130,7 +130,7 @@ and are aggregated by `crates/bashkit/tests/integration/main.rs` into a single b New behavioral tests go there. A small number of files stay as top-level `tests/*.rs` because they need their own binary (process-global env mutation, `--test-threads=1`, ssh-only feature isolation) — the list and -criteria live in `specs/testing.md`. +criteria live in `knowledge/testing.md`. ### Rust @@ -142,7 +142,7 @@ criteria live in `specs/testing.md`. ### Stderr from builtins must not leak internal Debug shapes -**TM-INF-022** in `specs/threat-model.md`. No `{:?}`/`{:#?}` in +**TM-INF-022** in `knowledge/threat-model.md`. No `{:?}`/`{:#?}` in `crates/bashkit/src/builtins/`; use `Display` or a domain formatter (reference: `format_compile_errors` in `builtins/jq/errors.rs`); cap diagnostics ≤ 1 KB; test-only Debug needs `// debug-ok: `. @@ -184,14 +184,14 @@ Do not mix criterion `.md` files into `crates/bashkit-bench/results/`. 3. `cargo clippy --all-targets --all-features -- -D warnings` 4. `just test` (feature-sliced; never `cargo test --all-features` in one invocation — see Local Dev) 5. Unit tests cover both positive (expected behavior) and negative (error handling, edge cases) scenarios -6. Security tests if change touches user input, parsing, sandboxing, or permissions (see `specs/security-testing.md`) +6. Security tests if change touches user input, parsing, sandboxing, or permissions (see `knowledge/security-testing.md`) 7. Compatibility/differential tests if change affects Bash behavior parity (compare against real Bash) 8. Rebase on main: `git fetch origin main && git rebase origin/main` (for worktrees: verify the worktree `HEAD` is on latest `origin/main` before editing) -9. Update specs if behavior changes +9. Update knowledge if behavior or durable project facts change 10. CI green before merge 11. Resolve all PR comments -12. `cargo bench --bench parallel_execution` if touching Arc/async/Interpreter/builtins (see `specs/parallel-execution.md`) -13. `just bench-sqlite` if touching the sqlite builtin or its VFS/IO bridge (see `specs/sqlite-builtin.md`) +12. `cargo bench --bench parallel_execution` if touching Arc/async/Interpreter/builtins (see `knowledge/parallel-execution.md`) +13. `just bench-sqlite` if touching the sqlite builtin or its VFS/IO bridge (see `knowledge/sqlite-builtin.md`) 14. `just bench` if changes might impact performance (interpreter, builtins, tools) 15. `ruff check crates/bashkit-python && ruff format --check crates/bashkit-python` if touching Python code @@ -206,7 +206,7 @@ Do not mix criterion `.md` files into `crates/bashkit-bench/results/`. Types: feat, fix, docs, refactor, test, chore -- Updates to `specs/` and `AGENTS.md`: use `chore` type +- Updates to `knowledge/` and `AGENTS.md`: use `chore` type - NEVER add links to Claude sessions in PR body or commits ### Commit Attribution diff --git a/CHANGELOG.md b/CHANGELOG.md index 8548d7e5b..4b44f9752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -113,7 +113,7 @@ addresses, and the response size cap, and returns typed errors (`Denied`/`Timeout`/`TooLarge`/`Transport`) that map onto curl exit codes (7/28/63/1). Mirrors fetchkit's transport injection so one host egress - implementation can back both libraries. See `specs/http-transport.md` + implementation can back both libraries. See `knowledge/http-transport.md` ([#2147](https://github.com/everruns/bashkit/pull/2147)). - **`xargs -P` parallel execution** — `-P/--max-procs` runs command batches concurrently, with `--process-slot-var` exposing the slot index to each child diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87968644b..7e61ad210 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,11 +63,11 @@ test: add array edge case tests ## Adding Features -1. Check if the feature is documented in `specs/` +1. Check if the feature is documented in `knowledge/` 2. Add spec tests in `crates/bashkit/tests/spec_cases/` 3. Implement the feature 4. Update `crates/bashkit/docs/compatibility.md` if applicable -5. Update `specs/limitations.md` if removing a limitation +5. Update `knowledge/limitations.md` if removing a limitation ## Spec Test Format @@ -93,12 +93,12 @@ expected - [ ] `just pre-pr` passes - [ ] Rebased on main -- [ ] Specs updated if behavior changes +- [ ] Knowledge updated if behavior changes - [ ] CI green ## Architecture -See `specs/` for design documents: +See `knowledge/` for persistent design and engineering knowledge: - `architecture.md` - Overall design - `parser.md` - Parser/lexer details diff --git a/Cargo.toml b/Cargo.toml index 720369e72..6d6e12823 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ # Bashkit - Awesomely fast virtual sandbox with bash and file system # Part of the Everruns ecosystem -# See specs/ for design decisions +# See knowledge/ for design decisions [workspace] resolver = "2" @@ -110,7 +110,7 @@ tower = { version = "0.5", features = ["util"] } # SSH client (for ssh/scp/sftp builtins) russh = "0.62" # Embedded SQLite engine (Turso, pure Rust). Upstream is BETA — gated behind -# the `sqlite` feature and disabled by default; see specs/sqlite-builtin.md. +# the `sqlite` feature and disabled by default; see knowledge/sqlite-builtin.md. turso_core = "0.8.0-pre.1" # Serial test execution @@ -122,7 +122,7 @@ serial_test = "3" # separate binary per minor version. Collapses the 6-version × 7-platform matrix # (42 native wheels/release, ~12 MB each) to 7, and future Python releases need # no rebuild. `generate-import-lib` kept for the Windows abi3 import lib. -# See specs/python-package.md § abi3. +# See knowledge/python-package.md § abi3. pyo3 = { version = "0.29", features = ["extension-module", "generate-import-lib", "abi3-py39"] } pyo3-async-runtimes = { version = "0.29", features = ["tokio-runtime"] } diff --git a/README.md b/README.md index 2865881b5..592371289 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Homepage: [bashkit.sh](https://bashkit.sh) ## Features -- **Secure by default** - No process spawning, no filesystem access, no network access unless explicitly enabled. [280+ threats](specs/threat-model.md) analyzed and mitigated +- **Secure by default** - No process spawning, no filesystem access, no network access unless explicitly enabled. [280+ threats](knowledge/threat-model.md) analyzed and mitigated - **POSIX compliant** - Substantial IEEE 1003.1-2024 Shell Command Language compliance - **Sandboxed, in-process execution** - All 164 commands reimplemented in Rust, no `fork`/`exec` - **Virtual filesystem** - InMemoryFs, OverlayFs, MountableFs with optional RealFs backend (`realfs` feature) @@ -318,7 +318,7 @@ let mut bash = Bash::builder() // Remote operations: remote add/remove, clone/push/pull/fetch (virtual mode) ``` -See [specs/git-support.md](specs/git-support.md) for the full specification. +See [knowledge/git-support.md](knowledge/git-support.md) for the full specification. ## Experimental: Python Support @@ -581,7 +581,7 @@ Bashkit is built for running untrusted scripts from AI agents and users. Securit 280+ identified threats across 17 categories (DoS, sandbox escape, info disclosure, injection, network, isolation, internal errors, git, SSH, logging, crypto, Python, TypeScript, SQLite, Unicode, filesystem, snapshots) — each with a stable ID, mitigation status, and test coverage. -See the [threat model](specs/threat-model.md) for the full analysis and [security policy](SECURITY.md) for reporting vulnerabilities. +See the [threat model](knowledge/threat-model.md) for the full analysis and [security policy](SECURITY.md) for reporting vulnerabilities. ## Other Virtual Bash Implementations diff --git a/SECURITY.md b/SECURITY.md index 479d55464..d4635d60a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -40,7 +40,7 @@ Bashkit is designed as a virtual interpreter. Key security boundaries: ### Known Limitations -See [specs/limitations.md](specs/limitations.md) for documented gaps and limitations. +See [knowledge/limitations.md](knowledge/limitations.md) for documented gaps and limitations. ## Supported Versions diff --git a/crates/bashkit-bench/README.md b/crates/bashkit-bench/README.md index 963c27fea..5061ab52e 100644 --- a/crates/bashkit-bench/README.md +++ b/crates/bashkit-bench/README.md @@ -128,7 +128,7 @@ cargo run -p bashkit-bench --release -- --list | `--list` | List available benchmarks | Saved JSON/Markdown reports in `crates/bashkit-bench/results/` feed the site -`/benches` page. See `specs/performance-results.md` for the aggregation +`/benches` page. See `knowledge/performance-results.md` for the aggregation contract. ## Prerequisites diff --git a/crates/bashkit-cli/src/interactive.rs b/crates/bashkit-cli/src/interactive.rs index 362b2ecec..513011ade 100644 --- a/crates/bashkit-cli/src/interactive.rs +++ b/crates/bashkit-cli/src/interactive.rs @@ -6,7 +6,7 @@ // Decision: PS1 prompt with bash-compatible escapes (\u, \h, \w, \$). // Decision: exit via ExitSignal event fired by the interpreter — REPL polls // the signal after each exec() call. -// See specs/interactive-shell.md +// See knowledge/interactive-shell.md use anyhow::Result; use rustyline::completion::Completer; diff --git a/crates/bashkit-cli/src/main.rs b/crates/bashkit-cli/src/main.rs index 84c2ad25f..7ed5310a7 100644 --- a/crates/bashkit-cli/src/main.rs +++ b/crates/bashkit-cli/src/main.rs @@ -8,7 +8,7 @@ // by flags to avoid unbounded hangs for wrapper/automation usage. // Decision: interactive mode uses rustyline for line editing — lightweight, MIT, // no heavy deps (no SQLite, no crossterm). Multiline via parse error detection. -// See specs/interactive-shell.md +// See knowledge/interactive-shell.md // Decision: CLI enables embedded Python by default when compiled in. This is an // explicit CLI builder opt-in, not ambient process environment inheritance. diff --git a/crates/bashkit-coreutils-port/Cargo.toml b/crates/bashkit-coreutils-port/Cargo.toml index 74fde8bed..c66d97dd9 100644 --- a/crates/bashkit-coreutils-port/Cargo.toml +++ b/crates/bashkit-coreutils-port/Cargo.toml @@ -8,7 +8,7 @@ # manifest (`vendored.toml`) declaring per-import substitution policy. # # Run manually when bumping the pinned uutils revision; output is committed. -# See specs/coreutils-args-port.md for both modes. +# See knowledge/coreutils-args-port.md for both modes. [package] name = "bashkit-coreutils-port" diff --git a/crates/bashkit-coreutils-port/src/main.rs b/crates/bashkit-coreutils-port/src/main.rs index eadb29368..8acd78729 100644 --- a/crates/bashkit-coreutils-port/src/main.rs +++ b/crates/bashkit-coreutils-port/src/main.rs @@ -33,7 +33,7 @@ //! command + MIT attribution). //! //! Run manually when bumping the pinned uutils revision; output is -//! committed. See `specs/coreutils-args-port.md`. +//! committed. See `knowledge/coreutils-args-port.md`. use std::path::PathBuf; use std::process::ExitCode; diff --git a/crates/bashkit-eval/Cargo.toml b/crates/bashkit-eval/Cargo.toml index aef34519b..7500dac2a 100644 --- a/crates/bashkit-eval/Cargo.toml +++ b/crates/bashkit-eval/Cargo.toml @@ -4,7 +4,7 @@ # bashkit drives the agent loop as a mira `Subject`; tasks are mira `Sample`s; # the bashkit expectation checks run as a mira `Scorer`. The `mira` CLI hosts # this binary over stdio and owns the model matrix, scheduling, and reporting. -# See specs/eval.md for design decisions. +# See knowledge/eval.md for design decisions. [package] name = "bashkit-eval" diff --git a/crates/bashkit-eval/README.md b/crates/bashkit-eval/README.md index a80860f27..f1e652284 100644 --- a/crates/bashkit-eval/README.md +++ b/crates/bashkit-eval/README.md @@ -6,7 +6,7 @@ Measures how well models use bashkit's bash tool in agentic workloads. bashkit-eval is a **study binary** the `mira` host CLI spawns over stdio; mira owns the model matrix, scheduling, retries, resume, and reporting. bashkit supplies the subject (its agent loop over a persistent VFS) and the scorer (the -deterministic expectation checks). See [`specs/eval.md`](../../specs/eval.md). +deterministic expectation checks). See [`knowledge/eval.md`](../../knowledge/eval.md). ## Usage diff --git a/crates/bashkit-eval/src/checks.rs b/crates/bashkit-eval/src/checks.rs index 420d5c417..cb36fca5a 100644 --- a/crates/bashkit-eval/src/checks.rs +++ b/crates/bashkit-eval/src/checks.rs @@ -6,7 +6,7 @@ // `AgentTrace` + `&dyn FileSystem`. This keeps scoring synchronous and lets it // run inside a mira `Scorer`, which only sees `&Sample` + `&Transcript`. // -// Check reference (see specs/eval.md): +// Check reference (see knowledge/eval.md): // exit_code:N stdout_contains:text stdout_regex:pattern // stderr_empty file_exists:/path dir_exists:/path // file_contains:/path:text file_line_regex:/path:pattern llm_judge:prompt diff --git a/crates/bashkit-eval/src/dataset.rs b/crates/bashkit-eval/src/dataset.rs index 65656efce..cd67b5c4a 100644 --- a/crates/bashkit-eval/src/dataset.rs +++ b/crates/bashkit-eval/src/dataset.rs @@ -1,6 +1,6 @@ // Dataset types and JSONL loader // Each line in the JSONL file is one EvalTask -// See specs/eval.md for format specification +// See knowledge/eval.md for format specification use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; diff --git a/crates/bashkit-eval/src/lib.rs b/crates/bashkit-eval/src/lib.rs index 1d25509ff..5b4b35f6a 100644 --- a/crates/bashkit-eval/src/lib.rs +++ b/crates/bashkit-eval/src/lib.rs @@ -1,5 +1,5 @@ // bashkit-eval: a mira eval study for bashkit tool usage. -// See specs/eval.md for design decisions. +// See knowledge/eval.md for design decisions. // // The transport + execution layer (providers, agent loops, dataset types) is // reused as-is; the mira integration (samples, subjects, scorer, eval builders) diff --git a/crates/bashkit-eval/src/main.rs b/crates/bashkit-eval/src/main.rs index b2d52faca..2651d03a9 100644 --- a/crates/bashkit-eval/src/main.rs +++ b/crates/bashkit-eval/src/main.rs @@ -9,7 +9,7 @@ // // The `#[eval]` wrappers live here (in the bin crate) so their inventory // registrations are guaranteed to link into this binary; the heavy lifting is -// in `bashkit_eval::mira_study`. See specs/eval.md. +// in `bashkit_eval::mira_study`. See knowledge/eval.md. use bashkit_eval::mira_study; use mira::{Eval, eval}; diff --git a/crates/bashkit-eval/src/mira_study.rs b/crates/bashkit-eval/src/mira_study.rs index 040aeee5e..ec92bbb8d 100644 --- a/crates/bashkit-eval/src/mira_study.rs +++ b/crates/bashkit-eval/src/mira_study.rs @@ -14,7 +14,7 @@ // old `TaskScore::all_passed`); the score value is the weighted pass rate. // // The model matrix, scheduling, retries, and reporting are owned by the `mira` -// host CLI. See specs/eval.md. +// host CLI. See knowledge/eval.md. use mira::subject::{Subject, subject_fn}; use mira::{Eval, Sample, Score, Target, Transcript}; diff --git a/crates/bashkit-eval/src/snapshot.rs b/crates/bashkit-eval/src/snapshot.rs index 93a00fa9b..d1aecc5fc 100644 --- a/crates/bashkit-eval/src/snapshot.rs +++ b/crates/bashkit-eval/src/snapshot.rs @@ -8,7 +8,7 @@ // `transcript.metadata["bashkit"]` as this `Snapshot` (kept out of `files` // so the file map stays a clean view of the workspace). // -// See specs/eval.md ("Scoring") for why the snapshot, not a live filesystem +// See knowledge/eval.md ("Scoring") for why the snapshot, not a live filesystem // handle, is the scoring substrate. use std::collections::{BTreeMap, BTreeSet}; diff --git a/crates/bashkit-js/__test__/security.spec.ts b/crates/bashkit-js/__test__/security.spec.ts index 09de669e4..372db6095 100644 --- a/crates/bashkit-js/__test__/security.spec.ts +++ b/crates/bashkit-js/__test__/security.spec.ts @@ -5,7 +5,7 @@ * error sanitization) and black-box tests (adversarial inputs an attacker * would try without source knowledge). * - * Threat-model IDs reference specs/threat-model.md. + * Threat-model IDs reference knowledge/threat-model.md. * * Run: pnpm exec ava __test__/security.spec.ts */ diff --git a/crates/bashkit-python/Cargo.toml b/crates/bashkit-python/Cargo.toml index baff9c523..5adbba9ae 100644 --- a/crates/bashkit-python/Cargo.toml +++ b/crates/bashkit-python/Cargo.toml @@ -33,7 +33,7 @@ num-bigint = "^0.4.6" # realfs: always-on so Python callers can use mount_real_* APIs. # http_client/sqlite/interop pull mio/tokio-net/rt-multi-thread/tokio::fs, # none of which compile on wasm32-unknown-emscripten — see the wasm block -# below and specs/emscripten-wheels.md. +# below and knowledge/emscripten-wheels.md. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] bashkit = { path = "../bashkit", features = ["scripted_tool", "python", "realfs", "jq", "interop", "http_client", "sqlite"] } tokio = { workspace = true, features = ["rt-multi-thread"] } @@ -47,7 +47,7 @@ pyo3-async-runtimes = { workspace = true } # or host filesystem access that Pyodide does not provide. Keeps the in-VFS # shell plus the embedded jq and Monty Python interpreters. tokio stays on its # wasm-safe base features (sync, macros, io-util, rt, time) — current-thread -# runtime only. See specs/emscripten-wheels.md. +# runtime only. See knowledge/emscripten-wheels.md. [target.'cfg(target_arch = "wasm32")'.dependencies] bashkit = { path = "../bashkit", features = ["scripted_tool", "python", "jq"] } tokio = { workspace = true } diff --git a/crates/bashkit-python/src/lib.rs b/crates/bashkit-python/src/lib.rs index 137e073c8..e6c576508 100644 --- a/crates/bashkit-python/src/lib.rs +++ b/crates/bashkit-python/src/lib.rs @@ -8,7 +8,7 @@ // The WebAssembly (Pyodide/Emscripten) build is a reduced-feature variant: the // async `execute()` family, network/credential config, host-FS mounts, the capsule // interop bridge, sqlite, and external_handler are all native-only (they need -// threads, sockets, or host FS that Pyodide lacks — see specs/emscripten-wheels.md). +// threads, sockets, or host FS that Pyodide lacks — see knowledge/emscripten-wheels.md). // That leaves a handful of imports and helper functions referenced only from the // native-gated code paths; silence the resulting dead-code/unused-import lints on // wasm rather than scattering per-item cfgs through shared conversion helpers. @@ -16,7 +16,7 @@ // interop (capsule FS handoff), realfs (host mounts) and the credential-injection // network config require threads / host FS / sockets that wasm32-unknown-emscripten -// (Pyodide) does not provide — see specs/emscripten-wheels.md. They are native-only. +// (Pyodide) does not provide — see knowledge/emscripten-wheels.md. They are native-only. #[cfg(not(target_arch = "wasm32"))] use bashkit::interop::fs::{BashkitFsAbiOwnedHandleV1, export_filesystem, import_owned_filesystem}; use bashkit::tool::VERSION; @@ -41,7 +41,7 @@ use pyo3::types::{ // pyo3-async-runtimes bridges Rust futures to a Python asyncio loop; it hard-pulls // multi-threaded tokio + mio sockets, which do not build on wasm. The async // `execute()` family and caller-loop callback scheduling are therefore native-only; -// wasm exposes the blocking `execute_sync()` API. See specs/emscripten-wheels.md. +// wasm exposes the blocking `execute_sync()` API. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] use pyo3_async_runtimes::TaskLocals; #[cfg(not(target_arch = "wasm32"))] @@ -390,7 +390,7 @@ impl PyNetworkConfig { /// default. Unknown keys raise `ValueError` so typos surface immediately. // The Pyodide/Emscripten build has no outbound HTTP client (no sockets in the // browser sandbox), so accepting a network allowlist would silently do nothing. -// Fail loudly instead. See specs/emscripten-wheels.md. +// Fail loudly instead. See knowledge/emscripten-wheels.md. #[cfg(target_arch = "wasm32")] fn parse_network_config(network: Option<&Bound<'_, PyDict>>) -> PyResult> { if network.is_some() { @@ -985,7 +985,7 @@ fn apply_fs_config( // Host-directory mounts require the `realfs` backend (tokio::fs), unavailable // on wasm. `parse_mounts` already rejects a non-empty `mounts` list on wasm, - // so this loop is native-only. See specs/emscripten-wheels.md. + // so this loop is native-only. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] for mount in real_mounts { builder = match (mount.writable, &mount.vfs_mount) { @@ -1749,7 +1749,7 @@ impl PyFileSystem { // `FileSystem.real()` needs the realfs backend (host FS), and the capsule // bridge (`from_capsule`/`to_capsule`) needs the `interop` ABI — both pull // threads/host-FS deps absent on wasm, so these constructors are native-only. - // See specs/emscripten-wheels.md. + // See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] #[staticmethod] #[pyo3(signature = (host_path, writable=false))] @@ -3649,7 +3649,7 @@ fn apply_sqlite_config( ) -> PyResult { // The embedded SQLite (Turso) backend needs the multi-threaded tokio runtime to // bridge its sync IO trait back to the async VFS, so the core `sqlite` feature is - // off on wasm. Reject `sqlite=True` loudly there. See specs/emscripten-wheels.md. + // off on wasm. Reject `sqlite=True` loudly there. See knowledge/emscripten-wheels.md. #[cfg(target_arch = "wasm32")] { let _ = (timeout_seconds, max_memory); @@ -3801,7 +3801,7 @@ impl PyBash { ); builder = apply_sqlite_config(builder, self.sqlite, self.timeout_seconds, self.max_memory)?; // network (http_client) and allowed_mount_paths (realfs) are native-only; - // both kwargs are rejected at construction on wasm. See specs/emscripten-wheels.md. + // both kwargs are rejected at construction on wasm. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] { if let Some(ref net) = self.network { @@ -3947,7 +3947,7 @@ impl PyBash { ); builder = apply_sqlite_config(builder, sqlite, timeout_seconds, max_memory)?; // network (http_client) and allowed_mount_paths (realfs) are native-only; - // both kwargs are rejected at construction on wasm. See specs/emscripten-wheels.md. + // both kwargs are rejected at construction on wasm. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] { if let Some(ref net) = network { @@ -4028,7 +4028,7 @@ impl PyBash { /// /// Native-only: the async API bridges to a Python asyncio loop via /// pyo3-async-runtimes, which the WebAssembly (Pyodide) build omits. On wasm, - /// use `execute_sync()`. See specs/emscripten-wheels.md. + /// use `execute_sync()`. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] #[pyo3(signature = (commands, on_output=None))] fn execute<'py>( @@ -4681,7 +4681,7 @@ impl BashTool { } // network (http_client) and allowed_mount_paths (realfs) are native-only; - // both kwargs are rejected at construction on wasm. See specs/emscripten-wheels.md. + // both kwargs are rejected at construction on wasm. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] { if let Some(ref net) = self.network { @@ -4822,7 +4822,7 @@ impl BashTool { let custom_builtins = parse_custom_builtins(py, custom_builtins)?; let network = parse_network_config(network)?; // network (http_client) and allowed_mount_paths (realfs) are native-only; - // both kwargs are rejected at construction on wasm. See specs/emscripten-wheels.md. + // both kwargs are rejected at construction on wasm. See knowledge/emscripten-wheels.md. #[cfg(not(target_arch = "wasm32"))] { if let Some(ref net) = network { diff --git a/crates/bashkit-python/tests/_security_core.py b/crates/bashkit-python/tests/_security_core.py index c80258c76..6b2c62de2 100644 --- a/crates/bashkit-python/tests/_security_core.py +++ b/crates/bashkit-python/tests/_security_core.py @@ -13,7 +13,7 @@ # Decision: keep the issue-1264 parity cases in this hidden core module while # the public `test_security.py` module re-exports the merged security suite. # New threat-model-traceable cases use `test_tm_*` names so they can map back -# to `specs/threat-model.md`. +# to `knowledge/threat-model.md`. def _assert_sanitized_error(text: str) -> None: diff --git a/crates/bashkit-python/tests/test_security.py b/crates/bashkit-python/tests/test_security.py index 39dc21191..d33292e67 100644 --- a/crates/bashkit-python/tests/test_security.py +++ b/crates/bashkit-python/tests/test_security.py @@ -4,7 +4,7 @@ # file layout matches the JS parity target while keeping the original white-box # and black-box implementations readable in hidden source modules. # Naming: `test_tm___` maps directly to -# `specs/threat-model.md` so grepable Python test names line up with the +# `knowledge/threat-model.md` so grepable Python test names line up with the # documented threat model. import sys diff --git a/crates/bashkit-wasm/Cargo.toml b/crates/bashkit-wasm/Cargo.toml index 28a5c8db3..ff1335765 100644 --- a/crates/bashkit-wasm/Cargo.toml +++ b/crates/bashkit-wasm/Cargo.toml @@ -5,7 +5,7 @@ # `wasm32-unknown-unknown` (pure wasm-bindgen, no WASI, no threads), so it needs # NO `SharedArrayBuffer` and NO cross-origin isolation (COOP/COEP) headers — # unlike the wasm32-wasip1-threads example. That makes it drop-in for any web -# app, including embedded/iframe contexts. See specs/browser-package.md. +# app, including embedded/iframe contexts. See knowledge/browser-package.md. # # Feature surface mirrors the `wasm` CI job (scripted_tool + jq). http_client, # ssh, sqlite, python, realfs, and interop are intentionally excluded: they need diff --git a/crates/bashkit-wasm/__test__/bashkit-wasm.test.mjs b/crates/bashkit-wasm/__test__/bashkit-wasm.test.mjs index 49a2025a8..4143c87b7 100644 --- a/crates/bashkit-wasm/__test__/bashkit-wasm.test.mjs +++ b/crates/bashkit-wasm/__test__/bashkit-wasm.test.mjs @@ -103,7 +103,7 @@ test("child shell: piping a script into bash", async () => { // Each of these used to panic and poison the whole module on wasm32: they // reached for a tokio timer (sleep/timeout), tokio::spawn (background jobs), or // std::thread::spawn (awk file redirects). On single-threaded wasm they must -// run inline instead. See specs/browser-package.md. +// run inline instead. See knowledge/browser-package.md. test("sleep returns immediately (no timer driver on wasm)", async () => { const bash = new Bash(); diff --git a/crates/bashkit-wasm/src/lib.rs b/crates/bashkit-wasm/src/lib.rs index 987366567..70d6fe1e6 100644 --- a/crates/bashkit-wasm/src/lib.rs +++ b/crates/bashkit-wasm/src/lib.rs @@ -1,7 +1,7 @@ //! Browser (WebAssembly) bindings for the Bashkit sandboxed bash interpreter. //! //! Important decisions (see also the crate-level notes in `Cargo.toml` and -//! `specs/browser-package.md`): +//! `knowledge/browser-package.md`): //! //! - **Single-threaded, no cross-origin isolation.** Target is //! `wasm32-unknown-unknown`. There is no `SharedArrayBuffer`, no thread pool, diff --git a/crates/bashkit/Cargo.toml b/crates/bashkit/Cargo.toml index f7adad95c..3ce1f13d5 100644 --- a/crates/bashkit/Cargo.toml +++ b/crates/bashkit/Cargo.toml @@ -87,7 +87,7 @@ hmac = "0.13" tracing = { workspace = true, optional = true } # CLI-style argument parsing for custom builtins and ported coreutils -# argument surfaces. Always on — see specs/coreutils-args-port.md. +# argument surfaces. Always on — see knowledge/coreutils-args-port.md. clap = { workspace = true } # Pinned to uutils' workspace versions. Used by the vendored @@ -155,7 +155,7 @@ typescript = ["dep:zapcode-core"] # engine). Phase 1 uses turso's `MemoryIO` with a load/flush against the VFS # at command boundaries; Phase 2 plugs the bashkit VFS in via a custom `IO` # implementation. Both paths share the same builtin and dot-command surface. -# See specs/sqlite-builtin.md. +# See knowledge/sqlite-builtin.md. # # Turso is BETA upstream — keep this off by default and document the risk. # Requires the multi-threaded tokio runtime so the sync `IO` trait can bridge @@ -189,7 +189,7 @@ serial_test = { workspace = true } # This single `[[test]]` rolls them up. Tests that need their own binary # (process-global env mutation, `--test-threads=1`, ssh-only feature # isolation) remain as siblings at `tests/.rs`. See -# `specs/testing.md` for the convention. +# `knowledge/testing.md` for the convention. [[test]] name = "integration" path = "tests/integration/main.rs" @@ -278,6 +278,6 @@ web-time = { workspace = true } # the port tool hard-errors on Fluent/translate imports — so this feature # is never defined here and the gated branch is always compiled out. Declare # it as a known cfg so `unexpected_cfgs` (denied via -D warnings in CI) does -# not flag the vendored code. See specs/coreutils-args-port.md. +# not flag the vendored code. See knowledge/coreutils-args-port.md. [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("i18n-decimal"))'] } diff --git a/crates/bashkit/benches/sqlite.rs b/crates/bashkit/benches/sqlite.rs index df9e52cfc..cf97faf5b 100644 --- a/crates/bashkit/benches/sqlite.rs +++ b/crates/bashkit/benches/sqlite.rs @@ -161,7 +161,7 @@ async fn bench_in_memory_only(n: usize) { async fn bench_parallel_sessions(sessions: usize, rows: usize, backend: SqliteBackend) { // Shared VFS, distinct DB file per session — tests the cooperative-IO // path without contending on a single sqlite file (which the builtin - // doesn't try to coordinate; see `specs/sqlite-builtin.md`). + // doesn't try to coordinate; see `knowledge/sqlite-builtin.md`). let fs: Arc = Arc::new(InMemoryFs::new()); let handles: Vec<_> = (0..sessions) .map(|i| { diff --git a/crates/bashkit/docs/compatibility.md b/crates/bashkit/docs/compatibility.md index 55ee4cbd1..e9d892e01 100644 --- a/crates/bashkit/docs/compatibility.md +++ b/crates/bashkit/docs/compatibility.md @@ -12,7 +12,7 @@ ## POSIX Shell Compliance Bashkit provides substantial compliance with IEEE Std 1003.1-2024 (POSIX.1-2024) -Shell Command Language. See [specs/limitations.md](../specs/limitations.md) +Shell Command Language. See [knowledge/limitations.md](../../../knowledge/limitations.md) for detailed compliance status. | POSIX Category | Status | @@ -396,7 +396,7 @@ let bash = Bash::builder() .build(); ``` -See [specs/threat-model.md](../specs/threat-model.md) for HTTP security details. +See [knowledge/threat-model.md](../../../knowledge/threat-model.md) for HTTP security details. --- @@ -479,5 +479,5 @@ Identified from eval analysis — all items now implemented: ## See Also -- [specs/limitations.md](../../../specs/limitations.md) - Intentional gaps and partial features -- [specs/](../../../specs/) - Design specifications +- [knowledge/limitations.md](../../../knowledge/limitations.md) - Intentional gaps and partial features +- [Bashkit knowledge](../../../knowledge/) - Persistent design and engineering knowledge diff --git a/crates/bashkit/docs/credential-injection.md b/crates/bashkit/docs/credential-injection.md index 412aa2aca..d368e5a6a 100644 --- a/crates/bashkit/docs/credential-injection.md +++ b/crates/bashkit/docs/credential-injection.md @@ -7,7 +7,7 @@ real credentials, preventing exfiltration. **See also:** - [Threat Model](./threat-model.md) - Security properties - [Custom Builtins](./custom_builtins.md) - Extending the shell -- [Credential Injection Spec](https://github.com/everruns/bashkit/blob/main/specs/credential-injection.md) - Design decisions +- [Credential Injection Spec](https://github.com/everruns/bashkit/blob/main/knowledge/credential-injection.md) - Design decisions ## Two Modes diff --git a/crates/bashkit/docs/live_mounts.md b/crates/bashkit/docs/live_mounts.md index 5a99fb035..dda6a3b54 100644 --- a/crates/bashkit/docs/live_mounts.md +++ b/crates/bashkit/docs/live_mounts.md @@ -200,4 +200,4 @@ assert_eq!(result.stdout, "2.0"); - [`BashBuilder::readonly_filesystem`] — deny all VFS mutations after setup - [`BashBuilder::fs`] — custom filesystem injection - [`Bash::fs`] — direct filesystem access -- [VFS specification](https://github.com/everruns/bashkit/blob/main/specs/vfs.md) +- [VFS specification](https://github.com/everruns/bashkit/blob/main/knowledge/vfs.md) diff --git a/crates/bashkit/docs/namespace_filesystems.md b/crates/bashkit/docs/namespace_filesystems.md index a022f4a14..1648f535b 100644 --- a/crates/bashkit/docs/namespace_filesystems.md +++ b/crates/bashkit/docs/namespace_filesystems.md @@ -86,4 +86,4 @@ access. - [`MountableFs`] — dynamic live mounts with a fallback root filesystem. - [`ReadOnlyFs`] — deny mutations for an entire filesystem. - [Live mounts](live-mounts.md) — attach and detach filesystems after build. -- [VFS specification](https://github.com/everruns/bashkit/blob/main/specs/vfs.md). +- [VFS specification](https://github.com/everruns/bashkit/blob/main/knowledge/vfs.md). diff --git a/crates/bashkit/docs/python.md b/crates/bashkit/docs/python.md index b6fbe9a29..4e6477ab2 100644 --- a/crates/bashkit/docs/python.md +++ b/crates/bashkit/docs/python.md @@ -12,7 +12,7 @@ configurable resource limits and no host access. - [Threat Model](./threat-model.md) - Security considerations (TM-PY-*) - [Custom Builtins](./custom_builtins.md) - Writing your own builtins - [Compatibility Reference](./compatibility.md) - Bash feature support -- [`specs/python-builtin.md`][spec] - Full specification +- [`knowledge/python-builtin.md`][spec] - Full specification ## Quick Start @@ -211,4 +211,4 @@ All Python execution runs in a virtual environment: See threat IDs TM-PY-001 through TM-PY-029 in the [threat model](./threat-model.md). -[spec]: https://github.com/everruns/bashkit/blob/main/specs/python-builtin.md +[spec]: https://github.com/everruns/bashkit/blob/main/knowledge/python-builtin.md diff --git a/crates/bashkit/docs/sqlite.md b/crates/bashkit/docs/sqlite.md index a4fab03d7..22dd04788 100644 --- a/crates/bashkit/docs/sqlite.md +++ b/crates/bashkit/docs/sqlite.md @@ -132,7 +132,7 @@ Tune per workload via `SqliteLimits::default().max_*(...)`. ## Security -See `specs/sqlite-builtin.md` § "Trust Model & Threats" for the full +See `knowledge/sqlite-builtin.md` § "Trust Model & Threats" for the full threat table. Highlights: - **No host filesystem access.** All paths resolve through the bashkit diff --git a/crates/bashkit/docs/ssh.md b/crates/bashkit/docs/ssh.md index 451d6ed8b..9630dcf43 100644 --- a/crates/bashkit/docs/ssh.md +++ b/crates/bashkit/docs/ssh.md @@ -3,7 +3,7 @@ Bashkit provides `ssh`, `scp`, and `sftp` builtins for remote command execution and file transfer over SSH. The default transport uses [russh](https://crates.io/crates/russh). -**See also:** [`specs/ssh-support.md`][spec] +**See also:** [`knowledge/ssh-support.md`][spec] ## Quick Start @@ -74,4 +74,4 @@ Tried in order: none (public services) → public key (`-i` flag or `default_pri - Remote paths shell-escaped (TM-SSH-008) - Response size and session count limits -[spec]: https://github.com/everruns/bashkit/blob/main/specs/ssh-support.md +[spec]: https://github.com/everruns/bashkit/blob/main/knowledge/ssh-support.md diff --git a/crates/bashkit/docs/threat-model.md b/crates/bashkit/docs/threat-model.md index eb6841545..4bc70773b 100644 --- a/crates/bashkit/docs/threat-model.md +++ b/crates/bashkit/docs/threat-model.md @@ -348,7 +348,7 @@ Network access is disabled by default. When enabled, strict controls apply. **Credential Injection (TM-NET-024–027):** Per-host HTTP credentials injected by the embedding host without exposing the -secret to the script (see `specs/credential-injection.md`). +secret to the script (see `knowledge/credential-injection.md`). | Threat | Attack Example | Mitigation | Status | |--------|---------------|------------|--------| @@ -945,7 +945,7 @@ All threats use stable IDs in the format `TM--`: | TM-FS | RealFs Mount Security | | TM-UNI | Unicode Security | -Full threat analysis: [`specs/threat-model.md`][spec] +Full threat analysis: [`knowledge/threat-model.md`][spec] [limits]: https://docs.rs/bashkit/latest/bashkit/struct.ExecutionLimits.html [fslimits]: https://docs.rs/bashkit/latest/bashkit/struct.FsLimits.html @@ -957,7 +957,7 @@ Full threat analysis: [`specs/threat-model.md`][spec] [failpoint_tests]: https://github.com/everruns/bashkit/blob/main/crates/bashkit/tests/security_failpoint_tests.rs [network_tests]: https://github.com/everruns/bashkit/blob/main/crates/bashkit/tests/network_security_tests.rs [fuzz]: https://github.com/everruns/bashkit/tree/main/crates/bashkit/fuzz -[spec]: https://github.com/everruns/bashkit/blob/main/specs/threat-model.md +[spec]: https://github.com/everruns/bashkit/blob/main/knowledge/threat-model.md [parser]: https://github.com/everruns/bashkit/blob/main/crates/bashkit/src/parser/mod.rs [interp]: https://github.com/everruns/bashkit/blob/main/crates/bashkit/src/interpreter/mod.rs [date]: https://github.com/everruns/bashkit/blob/main/crates/bashkit/src/builtins/date.rs diff --git a/crates/bashkit/docs/typescript.md b/crates/bashkit/docs/typescript.md index 0d464f163..b3a1d4565 100644 --- a/crates/bashkit/docs/typescript.md +++ b/crates/bashkit/docs/typescript.md @@ -13,7 +13,7 @@ resource limits and no host access. - [Threat Model](./threat-model.md) - Security considerations (TM-TS-*) - [Custom Builtins](./custom_builtins.md) - Writing your own builtins - [Compatibility Reference](./compatibility.md) - Bash feature support -- [`specs/zapcode-runtime.md`][spec] - Full specification +- [`knowledge/zapcode-runtime.md`][spec] - Full specification ## Quick Start @@ -259,4 +259,4 @@ All TypeScript execution runs in a virtual environment: See threat IDs TM-TS-001 through TM-TS-023 in the [threat model](./threat-model.md). -[spec]: https://github.com/everruns/bashkit/blob/main/specs/zapcode-runtime.md +[spec]: https://github.com/everruns/bashkit/blob/main/knowledge/zapcode-runtime.md diff --git a/crates/bashkit/examples/dump_builtins.rs b/crates/bashkit/examples/dump_builtins.rs index ca668d739..3ffdb3512 100644 --- a/crates/bashkit/examples/dump_builtins.rs +++ b/crates/bashkit/examples/dump_builtins.rs @@ -1,6 +1,6 @@ //! Dump the canonical builtin inventory as JSON. //! -//! Source generator for `specs/status/builtins.json` (the data behind the +//! Source generator for `knowledge/status/builtins.json` (the data behind the //! site's builtins page). Run via `just regen-builtins`, which enables every //! builtin-affecting feature so the inventory is complete; the //! `builtins-drift` workflow regenerates and fails on diff. diff --git a/crates/bashkit/fuzz/Cargo.toml b/crates/bashkit/fuzz/Cargo.toml index db0583444..53e1fbcd1 100644 --- a/crates/bashkit/fuzz/Cargo.toml +++ b/crates/bashkit/fuzz/Cargo.toml @@ -1,6 +1,6 @@ # Fuzz testing for Bashkit parser # Run with: cargo +nightly fuzz run parser_fuzz -# See specs/threat-model.md for security context +# See knowledge/threat-model.md for security context [package] name = "bashkit-fuzz" diff --git a/crates/bashkit/src/builtins/git/cmd.rs b/crates/bashkit/src/builtins/git/cmd.rs index 2aebe5575..d703f878a 100644 --- a/crates/bashkit/src/builtins/git/cmd.rs +++ b/crates/bashkit/src/builtins/git/cmd.rs @@ -14,7 +14,7 @@ //! # Security //! //! All operations are confined to the virtual filesystem and use -//! the configured author identity. See `specs/threat-model.md` +//! the configured author identity. See `knowledge/threat-model.md` //! Section 9: Git Security (TM-GIT-*). //! //! # Example diff --git a/crates/bashkit/src/builtins/git/config.rs b/crates/bashkit/src/builtins/git/config.rs index 3dd6d5068..1d929cc47 100644 --- a/crates/bashkit/src/builtins/git/config.rs +++ b/crates/bashkit/src/builtins/git/config.rs @@ -2,7 +2,7 @@ //! //! # Security Mitigations //! -//! This module mitigates the following threats (see `specs/threat-model.md`): +//! This module mitigates the following threats (see `knowledge/threat-model.md`): //! //! - **TM-GIT-001**: Unauthorized clone → remote URL allowlist (Phase 2) //! - **TM-GIT-002**: Host identity leak → configurable virtual identity diff --git a/crates/bashkit/src/builtins/git/mod.rs b/crates/bashkit/src/builtins/git/mod.rs index 9a414ef3f..21efbc537 100644 --- a/crates/bashkit/src/builtins/git/mod.rs +++ b/crates/bashkit/src/builtins/git/mod.rs @@ -42,7 +42,7 @@ //! //! # Security Threats //! -//! See `specs/threat-model.md` Section 9: Git Security (TM-GIT-*) +//! See `knowledge/threat-model.md` Section 9: Git Security (TM-GIT-*) mod config; diff --git a/crates/bashkit/src/builtins/path.rs b/crates/bashkit/src/builtins/path.rs index 94d832eec..c7f5bc0df 100644 --- a/crates/bashkit/src/builtins/path.rs +++ b/crates/bashkit/src/builtins/path.rs @@ -139,7 +139,7 @@ impl Builtin for Dirname { /// `generated/realpath_args.rs`. Behaviour is implemented locally /// against the bashkit VFS. /// -/// Symlink resolution stays disabled per L-FS-001 in `specs/limitations.md`'s +/// Symlink resolution stays disabled per L-FS-001 in `knowledge/limitations.md`'s /// "Intentionally Unimplemented" entry: bashkit's VFS does not model /// symlinks, so `-e`/`-m` only differ on existence checks, and /// `-L`/`-P`/`--strip` collapse to the same lexical canonicalisation. diff --git a/crates/bashkit/src/builtins/pipeline.rs b/crates/bashkit/src/builtins/pipeline.rs index 69a0e3224..f0f8cc579 100644 --- a/crates/bashkit/src/builtins/pipeline.rs +++ b/crates/bashkit/src/builtins/pipeline.rs @@ -21,7 +21,7 @@ use crate::interpreter::ExecResult; /// /// Important decision (parallelism): bashkit runs a single `Bash` interpreter /// sequentially — even background `&` jobs execute synchronously for -/// deterministic output (see `specs/parallel-execution.md` and +/// deterministic output (see `knowledge/parallel-execution.md` and /// `interpreter/jobs.rs`). So `-P N` does NOT spawn N OS processes for /// wall-clock speedup; instead it allocates N round-robin *slots*, and the /// commands still run in order. The slot index is exposed via diff --git a/crates/bashkit/src/builtins/sleep.rs b/crates/bashkit/src/builtins/sleep.rs index f738aa275..5b2df73ef 100644 --- a/crates/bashkit/src/builtins/sleep.rs +++ b/crates/bashkit/src/builtins/sleep.rs @@ -54,7 +54,7 @@ impl Builtin for Sleep { if seconds > 0.0 { // wasm32-unknown-unknown has no timer driver, so tokio::time::sleep // panics ("time not implemented"). The single-threaded sandbox has - // no wall-clock semantics anyway (see specs/browser-package.md), so + // no wall-clock semantics anyway (see knowledge/browser-package.md), so // on wasm the sleep elapses instantly. #[cfg(not(target_family = "wasm"))] tokio::time::sleep(Duration::from_secs_f64(seconds)).await; diff --git a/crates/bashkit/src/builtins/sqlite/engine.rs b/crates/bashkit/src/builtins/sqlite/engine.rs index c5bb5fbdb..e1aea2de9 100644 --- a/crates/bashkit/src/builtins/sqlite/engine.rs +++ b/crates/bashkit/src/builtins/sqlite/engine.rs @@ -1,7 +1,7 @@ //! Thin wrapper around `turso_core` that hides the choice of `IO` backend. //! //! The two backends correspond to the two phases described in -//! `specs/sqlite-builtin.md`: +//! `knowledge/sqlite-builtin.md`: //! //! - **Phase 1** ([`Backend::Memory`]): use turso's `MemoryIO` and snapshot the //! raw database bytes for caller-driven persistence. This is what the diff --git a/crates/bashkit/src/builtins/sqlite/mod.rs b/crates/bashkit/src/builtins/sqlite/mod.rs index 32491737e..1e9afb196 100644 --- a/crates/bashkit/src/builtins/sqlite/mod.rs +++ b/crates/bashkit/src/builtins/sqlite/mod.rs @@ -1,6 +1,6 @@ //! `sqlite` / `sqlite3` builtin — embedded SQLite via [`turso_core`]. //! -//! See `specs/sqlite-builtin.md` for the design rationale, threat model, and +//! See `knowledge/sqlite-builtin.md` for the design rationale, threat model, and //! test plan. At a glance: //! //! - A single invocation opens a fresh database connection, runs every SQL diff --git a/crates/bashkit/src/builtins/sqlite/tests.rs b/crates/bashkit/src/builtins/sqlite/tests.rs index e220a99a3..a998e65e9 100644 --- a/crates/bashkit/src/builtins/sqlite/tests.rs +++ b/crates/bashkit/src/builtins/sqlite/tests.rs @@ -1,6 +1,6 @@ //! Unit tests for the `sqlite` builtin. //! -//! Coverage matrix (mirrors `specs/sqlite-builtin.md` § Test plan): +//! Coverage matrix (mirrors `knowledge/sqlite-builtin.md` § Test plan): //! //! - **Positive** — basic CRUD, transactions, dot-commands, output modes, //! `:memory:`, persistence to VFS, `--version`/`--help`. diff --git a/crates/bashkit/src/builtins/ssh/mod.rs b/crates/bashkit/src/builtins/ssh/mod.rs index 1192215a5..258b64b44 100644 --- a/crates/bashkit/src/builtins/ssh/mod.rs +++ b/crates/bashkit/src/builtins/ssh/mod.rs @@ -26,7 +26,7 @@ //! //! # Security Threats //! -//! See `specs/ssh-support.md` and `specs/threat-model.md` (TM-SSH-*) +//! See `knowledge/ssh-support.md` and `knowledge/threat-model.md` (TM-SSH-*) mod allowlist; mod config; diff --git a/crates/bashkit/src/credential.rs b/crates/bashkit/src/credential.rs index acc0df026..2a33f4868 100644 --- a/crates/bashkit/src/credential.rs +++ b/crates/bashkit/src/credential.rs @@ -3,7 +3,7 @@ // Decision: Overwrite semantics — injected headers replace existing headers with same name. // Decision: Non-blocking — injection failures don't block the request. // Decision: Built on before_http hooks — no new interception points. -// See specs/credential-injection.md +// See knowledge/credential-injection.md //! Generic credential injection for outbound HTTP requests. //! diff --git a/crates/bashkit/src/fs/limits.rs b/crates/bashkit/src/fs/limits.rs index 08ecb8fa4..a5695dd79 100644 --- a/crates/bashkit/src/fs/limits.rs +++ b/crates/bashkit/src/fs/limits.rs @@ -4,7 +4,7 @@ //! //! # Security Mitigations //! -//! This module mitigates the following threats (see `specs/threat-model.md`): +//! This module mitigates the following threats (see `knowledge/threat-model.md`): //! //! - **TM-DOS-005**: Large file creation → `max_file_size` //! - **TM-DOS-006**: Many small files → `max_file_count` diff --git a/crates/bashkit/src/fs/memory.rs b/crates/bashkit/src/fs/memory.rs index b719282a2..6a8a0b2c5 100644 --- a/crates/bashkit/src/fs/memory.rs +++ b/crates/bashkit/src/fs/memory.rs @@ -5,7 +5,7 @@ //! //! # Security Mitigations //! -//! This module mitigates the following threats (see `specs/threat-model.md`): +//! This module mitigates the following threats (see `knowledge/threat-model.md`): //! //! - **TM-ESC-001**: Path traversal → `normalize_path()` collapses `..` safely //! - **TM-ESC-002**: Symlink escape → symlinks stored but not followed diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index 08c147004..5c5c4a13d 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -8132,7 +8132,7 @@ impl Interpreter { // panics ("time not implemented"). Run the command without wall-clock // enforcement — the parser fuel budget, maxCommands and // maxLoopIterations still bound runaway work. This matches the - // "no preemptive timeout" stance in specs/browser-package.md. + // "no preemptive timeout" stance in knowledge/browser-package.md. #[cfg(target_family = "wasm")] let outcome = { let _ = (duration, preserve_status); diff --git a/crates/bashkit/src/lib.rs b/crates/bashkit/src/lib.rs index fb8f9553c..7bcc440dd 100644 --- a/crates/bashkit/src/lib.rs +++ b/crates/bashkit/src/lib.rs @@ -439,7 +439,7 @@ pub mod scripted_tool; mod snapshot; /// Test-only helpers shared between internal `#[cfg(test)]` modules, /// integration tests in `tests/*.rs`, and cargo-fuzz targets in -/// `fuzz/fuzz_targets/*.rs`. See `specs/threat-model.md` for the +/// `fuzz/fuzz_targets/*.rs`. See `knowledge/threat-model.md` for the /// invariants enforced (TM-INF-013, TM-INF-016, TM-INF-022). #[doc(hidden)] pub mod testing; @@ -1353,7 +1353,7 @@ impl Bash { /// `git`, `ssh`), interpreter-special builtins like `exec`, custom /// builtins registered at construction, and host-registry builtins. /// Canonical source for the generated builtins - /// status (`just regen-builtins`, `specs/status/builtins.json`). + /// status (`just regen-builtins`, `knowledge/status/builtins.json`). pub fn builtin_names(&self) -> Vec { self.interpreter.builtin_names() } @@ -3152,7 +3152,7 @@ impl BashBuilder { // ============================================================================= // These modules embed external markdown guides into rustdoc. // Source files live in crates/bashkit/docs/ - edit there, not here. -// See specs/documentation.md for the documentation approach. +// See knowledge/documentation.md for the documentation approach. /// Guide for transparent credential injection in outbound HTTP requests. /// diff --git a/crates/bashkit/src/limits.rs b/crates/bashkit/src/limits.rs index 7659623bf..64b72891d 100644 --- a/crates/bashkit/src/limits.rs +++ b/crates/bashkit/src/limits.rs @@ -4,7 +4,7 @@ //! //! # Security Mitigations //! -//! This module mitigates the following threats (see `specs/threat-model.md`): +//! This module mitigates the following threats (see `knowledge/threat-model.md`): //! //! - **TM-DOS-001**: Large script input → `max_input_bytes` //! - **TM-DOS-002, TM-DOS-004, TM-DOS-019**: Command flooding → `max_commands` diff --git a/crates/bashkit/src/network/allowlist.rs b/crates/bashkit/src/network/allowlist.rs index c3a6d2f3f..0f27291bd 100644 --- a/crates/bashkit/src/network/allowlist.rs +++ b/crates/bashkit/src/network/allowlist.rs @@ -4,7 +4,7 @@ //! //! # Security Mitigations //! -//! This module mitigates the following threats (see `specs/threat-model.md`): +//! This module mitigates the following threats (see `knowledge/threat-model.md`): //! //! - **TM-NET-001**: DNS spoofing → literal host matching, no DNS resolution //! - **TM-NET-002**: DNS rebinding → allowlist uses literal strings; the diff --git a/crates/bashkit/src/network/client.rs b/crates/bashkit/src/network/client.rs index 0a9452dbe..78c834a94 100644 --- a/crates/bashkit/src/network/client.rs +++ b/crates/bashkit/src/network/client.rs @@ -5,7 +5,7 @@ //! //! # Security Mitigations //! -//! This module mitigates the following threats (see `specs/threat-model.md`): +//! This module mitigates the following threats (see `knowledge/threat-model.md`): //! //! - **TM-NET-008**: Large response DoS → `max_response_bytes` limit (10MB default) //! - **TM-NET-009**: Connection hang → connect timeout (10s) diff --git a/crates/bashkit/src/network/transport.rs b/crates/bashkit/src/network/transport.rs index 72b7d9410..bc90a9b90 100644 --- a/crates/bashkit/src/network/transport.rs +++ b/crates/bashkit/src/network/transport.rs @@ -1,6 +1,6 @@ //! Pluggable HTTP transport for the curl/wget/http builtins. //! -//! Design decision (see `specs/http-transport.md`): bashkit owns HTTP +//! Design decision (see `knowledge/http-transport.md`): bashkit owns HTTP //! *policy* — URL allowlist, DNS/private-IP SSRF precheck, `before_http` / //! `after_http` hooks, credential injection, bot-auth signing, and response //! size caps — while an injected [`HttpTransport`] owns *connectivity*. diff --git a/crates/bashkit/src/testing.rs b/crates/bashkit/src/testing.rs index 19baca227..bc6a76e24 100644 --- a/crates/bashkit/src/testing.rs +++ b/crates/bashkit/src/testing.rs @@ -6,7 +6,7 @@ //! cross-tool invariants as the inline `#[cfg(test)]` modules without us //! duplicating the banned-substring list and the canary plumbing. //! -//! The invariants enforced here are documented in `specs/threat-model.md`: +//! The invariants enforced here are documented in `knowledge/threat-model.md`: //! - **TM-INF-022** — no Rust Debug shapes in stderr //! - **TM-INF-016** — no host paths (`/rustc/`, `~/.cargo/registry/`, //! `target/debug/deps/`) in stderr diff --git a/crates/bashkit/src/tool.rs b/crates/bashkit/src/tool.rs index 3ee96e07a..3a65a129d 100644 --- a/crates/bashkit/src/tool.rs +++ b/crates/bashkit/src/tool.rs @@ -489,7 +489,7 @@ impl ToolStatus { /// # Public Contract /// /// This trait is a **public library contract**. Breaking changes require a major version bump. -/// See `specs/tool-contract.md` for the full specification. +/// See `knowledge/tool-contract.md` for the full specification. /// /// All tools must implement this trait to be usable by LLMs and agents. /// The trait provides introspection (schemas, docs) and execution methods. diff --git a/crates/bashkit/tests/integration/coreutils_differential_tests.rs b/crates/bashkit/tests/integration/coreutils_differential_tests.rs index 548eba943..77965772f 100644 --- a/crates/bashkit/tests/integration/coreutils_differential_tests.rs +++ b/crates/bashkit/tests/integration/coreutils_differential_tests.rs @@ -7,7 +7,7 @@ //! the args workflow only sees flag-signature changes; semantic //! divergence inside `cat.rs` / `textrev.rs` is invisible to it. //! -//! See `specs/coreutils-args-port.md` § Verification — Differential tests. +//! See `knowledge/coreutils-args-port.md` § Verification — Differential tests. //! //! Currently ported utils covered: //! - cat: flags `-n`, `-b`, `-E`, `-A`, `-T`, `-v`, `-s`, `-ns`, `-bs`, diff --git a/crates/bashkit/tests/integration/credential_injection_tests.rs b/crates/bashkit/tests/integration/credential_injection_tests.rs index 0bcca282e..946e73078 100644 --- a/crates/bashkit/tests/integration/credential_injection_tests.rs +++ b/crates/bashkit/tests/integration/credential_injection_tests.rs @@ -1,6 +1,6 @@ //! Credential Injection Integration Tests //! -//! Tests for generic credential injection (specs/credential-injection.md). +//! Tests for generic credential injection (knowledge/credential-injection.md). //! //! Tests verify: //! - Injection mode: headers added transparently diff --git a/crates/bashkit/tests/integration/git_remote_security_tests.rs b/crates/bashkit/tests/integration/git_remote_security_tests.rs index df974b0ac..a2070800c 100644 --- a/crates/bashkit/tests/integration/git_remote_security_tests.rs +++ b/crates/bashkit/tests/integration/git_remote_security_tests.rs @@ -1,6 +1,6 @@ //! Git Remote Security Tests //! -//! Tests for git remote-related threats documented in specs/threat-model.md +//! Tests for git remote-related threats documented in knowledge/threat-model.md //! Section 8: Git Security (TM-GIT-010 through TM-GIT-013) #![cfg(feature = "git")] diff --git a/crates/bashkit/tests/integration/git_security_tests.rs b/crates/bashkit/tests/integration/git_security_tests.rs index 49635c0c9..15ee2f1da 100644 --- a/crates/bashkit/tests/integration/git_security_tests.rs +++ b/crates/bashkit/tests/integration/git_security_tests.rs @@ -1,6 +1,6 @@ //! Git Security Tests //! -//! Tests for git-related threats documented in specs/threat-model.md +//! Tests for git-related threats documented in knowledge/threat-model.md //! Section 8: Git Security (TM-GIT-*) #![cfg(feature = "git")] diff --git a/crates/bashkit/tests/integration/limitations_doc_tests.rs b/crates/bashkit/tests/integration/limitations_doc_tests.rs index 98daadeec..099732cd4 100644 --- a/crates/bashkit/tests/integration/limitations_doc_tests.rs +++ b/crates/bashkit/tests/integration/limitations_doc_tests.rs @@ -1,4 +1,4 @@ -//! Lint for `specs/limitations.md` — the negative spec. +//! Lint for `knowledge/limitations.md` — the negative spec. //! //! Limitations record absences, which no code-level test can witness //! directly; the next-best enforcement is keeping the document machine @@ -10,7 +10,7 @@ use std::collections::HashSet; use std::path::Path; fn limitations_doc() -> String { - let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../specs/limitations.md"); + let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../knowledge/limitations.md"); std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display())) } @@ -129,7 +129,7 @@ fn limitation_ids_referenced_from_code_exist_in_doc() { for id in &cited { assert!( ids.contains(id), - "{id} cited in source but missing from specs/limitations.md" + "{id} cited in source but missing from knowledge/limitations.md" ); } } diff --git a/crates/bashkit/tests/integration/limitations_evidence_tests.rs b/crates/bashkit/tests/integration/limitations_evidence_tests.rs index d10e82dc9..f4ea96a31 100644 --- a/crates/bashkit/tests/integration/limitations_evidence_tests.rs +++ b/crates/bashkit/tests/integration/limitations_evidence_tests.rs @@ -1,4 +1,4 @@ -//! Evidence tests for `specs/limitations.md`. +//! Evidence tests for `knowledge/limitations.md`. //! //! Each test demonstrates one intentional limitation (L-* row) so the //! negative spec stays executable: if a limitation is ever lifted, the diff --git a/crates/bashkit/tests/integration/main.rs b/crates/bashkit/tests/integration/main.rs index 76c822055..1a65a3e16 100644 --- a/crates/bashkit/tests/integration/main.rs +++ b/crates/bashkit/tests/integration/main.rs @@ -6,7 +6,7 @@ //! step alone blew out CI disk on the hosted runner (`rustc-LLVM ERROR: IO //! failure on output stream: No space left on device`). //! -//! Per `specs/testing.md`, default integration tests live as `mod`s under +//! Per `knowledge/testing.md`, default integration tests live as `mod`s under //! `tests/integration/`, declared here. Tests that genuinely need their own //! binary (process-global env mutation, `--test-threads=1`, feature-isolation //! sweeps) stay as siblings at `tests/.rs`. diff --git a/crates/bashkit/tests/integration/network_security_tests.rs b/crates/bashkit/tests/integration/network_security_tests.rs index 0a8573dcd..ad64d7622 100644 --- a/crates/bashkit/tests/integration/network_security_tests.rs +++ b/crates/bashkit/tests/integration/network_security_tests.rs @@ -1,6 +1,6 @@ //! Network Security Tests //! -//! Tests for HTTP-related security threats documented in specs/threat-model.md +//! Tests for HTTP-related security threats documented in knowledge/threat-model.md //! Section 5.3: HTTP Attack Vectors //! //! These tests verify: diff --git a/crates/bashkit/tests/integration/parallel_sessions_tests.rs b/crates/bashkit/tests/integration/parallel_sessions_tests.rs index 37c37a080..e8a69589e 100644 --- a/crates/bashkit/tests/integration/parallel_sessions_tests.rs +++ b/crates/bashkit/tests/integration/parallel_sessions_tests.rs @@ -1,7 +1,7 @@ //! Large parallel fan-out tests. //! //! A bashkit session is a plain heap object + tokio task — no per-session OS -//! process or thread (see `specs/parallel-execution.md`, L-PROC-003). These +//! process or thread (see `knowledge/parallel-execution.md`, L-PROC-003). These //! tests confirm a large fan-out (1000 sessions) actually does real work and //! produces correct output, rather than spawning and returning instantly //! because every session errored out (e.g. hit a limit). The timing of this diff --git a/crates/bashkit/tests/integration/sqlite_compat_tests.rs b/crates/bashkit/tests/integration/sqlite_compat_tests.rs index 9132d0c8d..2a2f1e918 100644 --- a/crates/bashkit/tests/integration/sqlite_compat_tests.rs +++ b/crates/bashkit/tests/integration/sqlite_compat_tests.rs @@ -15,7 +15,7 @@ //! - `ORDER BY` / `LIMIT` / `OFFSET` syntax accepted. //! //! These are NOT exhaustive sqlite parity tests — they pin the shapes that -//! drive day-to-day usage. Add a row to `specs/sqlite-builtin.md` if you +//! drive day-to-day usage. Add a row to `knowledge/sqlite-builtin.md` if you //! intentionally diverge from sqlite3 here. #![cfg(feature = "sqlite")] diff --git a/crates/bashkit/tests/integration/sqlite_integration_tests.rs b/crates/bashkit/tests/integration/sqlite_integration_tests.rs index 373de44fb..5bf30b1d1 100644 --- a/crates/bashkit/tests/integration/sqlite_integration_tests.rs +++ b/crates/bashkit/tests/integration/sqlite_integration_tests.rs @@ -16,7 +16,7 @@ //! - JSON/CSV/markdown formatting //! - `:memory:` round-trip in a single invocation //! -//! See `specs/sqlite-builtin.md` for the test plan. +//! See `knowledge/sqlite-builtin.md` for the test plan. #![cfg(feature = "sqlite")] diff --git a/crates/bashkit/tests/integration/sqlite_security_tests.rs b/crates/bashkit/tests/integration/sqlite_security_tests.rs index 060b99511..998098240 100644 --- a/crates/bashkit/tests/integration/sqlite_security_tests.rs +++ b/crates/bashkit/tests/integration/sqlite_security_tests.rs @@ -1,7 +1,7 @@ //! Threat-model tests for the `sqlite` builtin. //! //! Each `#[test]` here covers a distinct adversarial scenario from -//! `specs/threat-model.md` (or the new entries in `specs/sqlite-builtin.md`). +//! `knowledge/threat-model.md` (or the new entries in `knowledge/sqlite-builtin.md`). //! Aside from confirming current mitigations, these tests act as //! regression guards: a future change that re-introduces an attack must //! flip a test red. diff --git a/crates/bashkit/tests/integration/threat_model_doc_tests.rs b/crates/bashkit/tests/integration/threat_model_doc_tests.rs index 760676f75..e49649bfe 100644 --- a/crates/bashkit/tests/integration/threat_model_doc_tests.rs +++ b/crates/bashkit/tests/integration/threat_model_doc_tests.rs @@ -2,14 +2,14 @@ //! //! Every `TM--` ID cited anywhere in this crate's source or //! tests (typically `// THREAT[TM-...]` mitigation anchors and threat-test -//! doc comments) must have an entry in `specs/threat-model.md`. This is the +//! doc comments) must have an entry in `knowledge/threat-model.md`. This is the //! same enforcement direction as `limitations_doc_tests`: code may not cite //! a ledger entry that does not exist, so restructuring the ledger can never //! silently orphan a mitigation anchor. //! //! A second test keeps the user-facing threat model //! (`crates/bashkit/docs/threat-model.md`) in one-to-one sync with the -//! canonical ledger (`specs/threat-model.md`): every spec threat must be +//! canonical ledger (`knowledge/threat-model.md`): every spec threat must be //! documented publicly, and the public doc may not invent IDs the ledger //! lacks. This closes the drift tracked in #2155. @@ -71,7 +71,7 @@ fn walk_rs_files(root: &Path, out: &mut Vec) { #[test] fn threat_ids_cited_in_code_exist_in_threat_model_doc() { let manifest = Path::new(env!("CARGO_MANIFEST_DIR")); - let doc_path = manifest.join("../../specs/threat-model.md"); + let doc_path = manifest.join("../../knowledge/threat-model.md"); let doc = std::fs::read_to_string(&doc_path) .unwrap_or_else(|e| panic!("read {}: {e}", doc_path.display())); @@ -105,7 +105,7 @@ fn threat_ids_cited_in_code_exist_in_threat_model_doc() { .collect(); assert!( missing.is_empty(), - "TM IDs cited in code but missing from specs/threat-model.md:\n{}", + "TM IDs cited in code but missing from knowledge/threat-model.md:\n{}", missing.join("\n") ); } @@ -113,7 +113,7 @@ fn threat_ids_cited_in_code_exist_in_threat_model_doc() { #[test] fn public_threat_model_doc_covers_every_spec_threat_id() { let manifest = Path::new(env!("CARGO_MANIFEST_DIR")); - let spec_path = manifest.join("../../specs/threat-model.md"); + let spec_path = manifest.join("../../knowledge/threat-model.md"); let public_path = manifest.join("docs/threat-model.md"); let spec = std::fs::read_to_string(&spec_path) .unwrap_or_else(|e| panic!("read {}: {e}", spec_path.display())); @@ -127,7 +127,7 @@ fn public_threat_model_doc_covers_every_spec_threat_id() { assert!( spec_ids.len() > 100, - "suspiciously few TM IDs in specs/threat-model.md ({}) — parsing broken?", + "suspiciously few TM IDs in knowledge/threat-model.md ({}) — parsing broken?", spec_ids.len() ); @@ -139,7 +139,7 @@ fn public_threat_model_doc_covers_every_spec_threat_id() { missing.sort_unstable(); assert!( missing.is_empty(), - "{} TM ID(s) in specs/threat-model.md but missing from \ + "{} TM ID(s) in knowledge/threat-model.md but missing from \ crates/bashkit/docs/threat-model.md — port them (see #2155):\n{}", missing.len(), missing.join("\n") @@ -154,7 +154,7 @@ fn public_threat_model_doc_covers_every_spec_threat_id() { assert!( stray.is_empty(), "{} TM ID(s) in crates/bashkit/docs/threat-model.md but absent from \ - specs/threat-model.md — fix the ID or add the ledger entry:\n{}", + knowledge/threat-model.md — fix the ID or add the ledger entry:\n{}", stray.len(), stray.join("\n") ); diff --git a/crates/bashkit/tests/integration/threat_model_tests.rs b/crates/bashkit/tests/integration/threat_model_tests.rs index 3a2accd5f..3b8ac879a 100644 --- a/crates/bashkit/tests/integration/threat_model_tests.rs +++ b/crates/bashkit/tests/integration/threat_model_tests.rs @@ -1,6 +1,6 @@ //! Threat Model Security Tests //! -//! Tests for threats identified in specs/threat-model.md +//! Tests for threats identified in knowledge/threat-model.md //! Each test category maps to a threat category in the threat model. //! //! Run with: `cargo test threat_` diff --git a/crates/bashkit/tests/integration/unicode_security_tests.rs b/crates/bashkit/tests/integration/unicode_security_tests.rs index 830223941..91bdd5dd3 100644 --- a/crates/bashkit/tests/integration/unicode_security_tests.rs +++ b/crates/bashkit/tests/integration/unicode_security_tests.rs @@ -1,6 +1,6 @@ //! Unicode Security Tests (TM-UNI-*) //! -//! Tests for Unicode-specific threats identified in specs/threat-model.md. +//! Tests for Unicode-specific threats identified in knowledge/threat-model.md. //! Covers byte-boundary safety, invisible characters, homoglyphs, normalization, //! and bidi attacks across parser, builtins, and VFS. //! diff --git a/crates/bashkit/tests/logging_security_tests.rs b/crates/bashkit/tests/logging_security_tests.rs index 447bce061..c0deec36d 100644 --- a/crates/bashkit/tests/logging_security_tests.rs +++ b/crates/bashkit/tests/logging_security_tests.rs @@ -3,7 +3,7 @@ //! Tests for TM-LOG-* threats to ensure sensitive data is properly redacted //! and log injection attacks are prevented. //! -//! These tests verify the security properties documented in specs/threat-model.md +//! These tests verify the security properties documented in knowledge/threat-model.md //! section 7 "Logging Security". #![cfg(feature = "logging")] diff --git a/docs/builtin_typescript.md b/docs/builtin_typescript.md index da5008b39..b4f01dacc 100644 --- a/docs/builtin_typescript.md +++ b/docs/builtin_typescript.md @@ -260,4 +260,4 @@ TypeScript execution is fully sandboxed: - Opt-in only: requires both `typescript` Cargo feature AND `.typescript()` builder call - Path traversal (`../../../etc/passwd`) is blocked by VFS normalization -See [TM-TS threat entries](../specs/threat-model.md) for the full security analysis. +See [TM-TS threat entries](../knowledge/threat-model.md) for the full security analysis. diff --git a/docs/filesystem.md b/docs/filesystem.md index e238d3c25..04c9eefa8 100644 --- a/docs/filesystem.md +++ b/docs/filesystem.md @@ -153,4 +153,4 @@ readonly_filesystem: bool # deny all VFS mutations after s - [Live mounts](live-mounts.md) — attach and detach filesystems at runtime. - [Filesystem namespaces](https://docs.rs/bashkit/latest/bashkit/namespace_filesystems_guide/) — compose and rebase static mount trees. - [Snapshotting](snapshotting.md) — serialise and restore VFS + shell state. -- Spec: [`specs/vfs.md`](https://github.com/everruns/bashkit/blob/main/specs/vfs.md). +- Spec: [`knowledge/vfs.md`](https://github.com/everruns/bashkit/blob/main/knowledge/vfs.md). diff --git a/docs/git.md b/docs/git.md index 92ecfc8d3..d3fe4b9c9 100644 --- a/docs/git.md +++ b/docs/git.md @@ -94,4 +94,4 @@ every builtin. - [Virtual filesystem](filesystem.md) — where the repository lives. - [Security](security.md) — sandbox boundaries and the `TM-GIT-*` threats. -- Spec: [`specs/git-support.md`](https://github.com/everruns/bashkit/blob/main/specs/git-support.md). +- Spec: [`knowledge/git-support.md`](https://github.com/everruns/bashkit/blob/main/knowledge/git-support.md). diff --git a/docs/request-signing.md b/docs/request-signing.md index 0542ea742..69ad0041d 100644 --- a/docs/request-signing.md +++ b/docs/request-signing.md @@ -117,7 +117,7 @@ The nonce defends against replay; the expiry window bounds signature validity. - [Networking & HTTP](networking.md) — the allowlist that gates every request. - [Credential injection](credential-injection.md) — attach bearer tokens without exposing them to scripts. -- Spec: [`specs/request-signing.md`](https://github.com/everruns/bashkit/blob/main/specs/request-signing.md). +- Spec: [`knowledge/request-signing.md`](https://github.com/everruns/bashkit/blob/main/knowledge/request-signing.md). - [RFC 9421](https://www.rfc-editor.org/rfc/rfc9421) · [RFC 7638](https://www.rfc-editor.org/rfc/rfc7638) · [web-bot-auth architecture](https://datatracker.ietf.org/doc/html/draft-meunier-web-bot-auth-architecture). diff --git a/docs/scripted-tools.md b/docs/scripted-tools.md index d49fcf57f..ff4c1995b 100644 --- a/docs/scripted-tools.md +++ b/docs/scripted-tools.md @@ -135,4 +135,4 @@ stack traces never reach script-visible stderr. - [Bashkit as an LLM tool](llm-tools.md) — the filesystem-backed `BashTool`. - [Virtual filesystem](filesystem.md) — why logic mode disables file access. -- Spec: [`specs/scripted-tool-orchestration.md`](https://github.com/everruns/bashkit/blob/main/specs/scripted-tool-orchestration.md). +- Spec: [`knowledge/scripted-tool-orchestration.md`](https://github.com/everruns/bashkit/blob/main/knowledge/scripted-tool-orchestration.md). diff --git a/docs/security.md b/docs/security.md index 435842ee6..26c918647 100644 --- a/docs/security.md +++ b/docs/security.md @@ -20,7 +20,7 @@ individual threat IDs and mitigation status, see the ## Threat model -Bashkit maintains a living threat model in [`specs/threat-model.md`](../specs/threat-model.md) +Bashkit maintains a living threat model in [`knowledge/threat-model.md`](../knowledge/threat-model.md) with stable threat IDs across these categories: | Category | ID prefix | Examples | @@ -50,7 +50,7 @@ the sandbox. Key exclusions: - **`trap`** — conflicts with the stateless execution model - **Real process spawning** — all subprocess commands stay within the virtual interpreter (`TM-ESC-015`) -These decisions are documented in [`specs/limitations.md`](../specs/limitations.md). +These decisions are documented in [`knowledge/limitations.md`](../knowledge/limitations.md). ## Security testing @@ -60,7 +60,7 @@ Bashkit uses multiple layers of security testing: validate mitigations against documented threat IDs. Each test maps to a specific `TM-*` threat. -**Fail-point injection** — A framework defined in [`specs/security-testing.md`](../specs/security-testing.md) +**Fail-point injection** — A framework defined in [`knowledge/security-testing.md`](../knowledge/security-testing.md) that injects failures at specific points to verify the interpreter handles them safely. 14+ tests in `security_failpoint_tests.rs`. diff --git a/examples/browser/.gitignore b/examples/browser/.gitignore index 3f88f50f5..6128dcff3 100644 --- a/examples/browser/.gitignore +++ b/examples/browser/.gitignore @@ -1,5 +1,5 @@ node_modules/ dist/ # Relaxed on purpose: no committed lockfile, so `pnpm install` always resolves -# the latest published @everruns/bashkit-wasm (see specs/maintenance.md). +# the latest published @everruns/bashkit-wasm (see knowledge/maintenance.md). pnpm-lock.yaml diff --git a/examples/browser/README.md b/examples/browser/README.md index fe5f05b32..dedc11eea 100644 --- a/examples/browser/README.md +++ b/examples/browser/README.md @@ -38,7 +38,7 @@ Present: full bash syntax, the text-tool builtins (`grep`, `sed`, `awk`, `find`, Absent (need sockets, threads, or a host FS the browser sandbox lacks): `http_client` (`curl`/`wget`), `ssh`, `sqlite`, embedded `python`, `realfs` mounts. Reach the network from a custom builtin that calls the app's own -`fetch`. See `crates/bashkit-wasm/` and `specs/browser-package.md` for details. +`fetch`. See `crates/bashkit-wasm/` and `knowledge/browser-package.md` for details. ## Scripts diff --git a/justfile b/justfile index 1e878ca70..7dc426e0d 100644 --- a/justfile +++ b/justfile @@ -78,14 +78,14 @@ clean: # Regenerate the self-hosted Python API reference (docs.rs analog for PyPI). # Output committed at site/src/content/apidocs/python.md; refresh on release. -# Needs griffe: pip install griffe. See specs/documentation.md. +# Needs griffe: pip install griffe. See knowledge/documentation.md. apidocs-python: python3 scripts/gen_python_apidocs.py # Regenerate the self-hosted TypeScript API reference (docs.rs analog for npm). # Output committed at site/src/content/apidocs/typescript.md; refresh on release. # Requires `napi build` first (generates index.d.ts the .ts wrappers import). -# Needs network for `npx typedoc`. See specs/documentation.md. +# Needs network for `npx typedoc`. See knowledge/documentation.md. apidocs-ts: cd crates/bashkit-js && pnpm exec napi build --platform cd crates/bashkit-js && pnpm run build:cjs @@ -99,7 +99,7 @@ apidocs: apidocs-python apidocs-ts regen-builtins: cargo run -q --example dump_builtins \ --features jq,git,ssh,http_client,python,typescript,sqlite \ - > specs/status/builtins.json + > knowledge/status/builtins.json # === uutils argument-surface port (POC) === @@ -205,7 +205,7 @@ bench-sqlite: # matrix, scheduling, and reporting. Install the host once: # cargo install mira-cli # provides the `mira` binary # Targets are gated on ANTHROPIC_API_KEY / OPENAI_API_KEY — set the keys for -# the models you want to run; unkeyed targets are skipped. See specs/eval.md. +# the models you want to run; unkeyed targets are skipped. See knowledge/eval.md. # List advertised evals, samples, scorers, and targets eval-list: diff --git a/specs/architecture.md b/knowledge/architecture.md similarity index 90% rename from specs/architecture.md rename to knowledge/architecture.md index 0d121bf36..fe0e7db39 100644 --- a/specs/architecture.md +++ b/knowledge/architecture.md @@ -1,3 +1,8 @@ +--- +title: Bashkit Architecture +summary: Core interpreter architecture, module boundaries, execution flow, and design principles. +--- + # Architecture ## Status diff --git a/specs/browser-package.md b/knowledge/browser-package.md similarity index 97% rename from specs/browser-package.md rename to knowledge/browser-package.md index 31ecf73d8..73b78bd69 100644 --- a/specs/browser-package.md +++ b/knowledge/browser-package.md @@ -1,3 +1,8 @@ +--- +title: Browser Package +summary: Slim single-threaded WebAssembly package design for browsers and JavaScript runtimes. +--- + # WebAssembly Package (`@everruns/bashkit-wasm`) > Naming: the crate is `bashkit-wasm` and the npm package is @@ -121,7 +126,7 @@ pattern as `publish-js.yml`. Browser example smoke testing writes a file under `/home/user`, reloads the page, and verifies `browserLocal` restores it from `localStorage`. -## Limitations (see `specs/limitations.md`) +## Limitations (see `knowledge/limitations.md`) - No wall-clock time on `wasm32-unknown-unknown` (no timer driver). This is a hard platform constraint, so time-based behaviour degrades rather than diff --git a/specs/builtins.md b/knowledge/builtins.md similarity index 94% rename from specs/builtins.md rename to knowledge/builtins.md index 9b96b3e11..e0f8daba3 100644 --- a/specs/builtins.md +++ b/knowledge/builtins.md @@ -1,3 +1,8 @@ +--- +title: Builtin Commands +summary: Builtin command trait, execution planning, registration, and implementation conventions. +--- + # Builtin Commands ## Status @@ -7,7 +12,7 @@ Implemented Bashkit provides built-in commands for script execution in a virtual environment. All builtins operate on the virtual filesystem. For the complete list, see -the generated `specs/status/builtins.json`; for known gaps, `specs/limitations.md`. +the generated `knowledge/status/builtins.json`; for known gaps, `knowledge/limitations.md`. ### Standard Flags @@ -38,7 +43,7 @@ Custom Rust builtins can implement `ClapBuiltin` instead of `Builtin` when their arguments are better represented as a `#[derive(clap::Parser)]` struct (see `builtins/mod.rs` / rustdoc for the trait and an example). `clap` is an unconditional dependency of `bashkit` (also used by ported coreutils argument -surfaces — see `specs/coreutils-args-port.md`), so this trait is always +surfaces — see `knowledge/coreutils-args-port.md`), so this trait is always available. Bashkit parses `Context::args` through clap, passes parsed args plus a mutable `BashkitContext` to the handler, maps `--help`/`--version` to successful stdout results, and maps clap parse failures to stderr with clap's @@ -176,7 +181,7 @@ per-invocation parallel-slot index. bashkit runs a single `Bash` interpreter sequentially — even background `&` jobs run synchronously for deterministic output (see -`specs/parallel-execution.md`). So `xargs -P N` / `--max-procs=N` does **not** +`knowledge/parallel-execution.md`). So `xargs -P N` / `--max-procs=N` does **not** spawn N OS processes for wall-clock speedup. Instead it allocates N round-robin *slots* and the commands still run in order, with the slot index (0..N-1, `idx % N`) surfaced via `--process-slot-var`. This is the behaviour @@ -196,10 +201,10 @@ macro in `interpreter/mod.rs`. To add a new one: 2. Add `mod mycommand;` and `pub use mycommand::MyCommand;` in `builtins/mod.rs` 3. Add one line to the `register_builtins!` table in `interpreter/mod.rs` 4. Add spec tests in `tests/spec_cases/` -5. Run `just regen-builtins`; record any gaps in `specs/limitations.md` +5. Run `just regen-builtins`; record any gaps in `knowledge/limitations.md` ### Network Builtins `curl`, `wget`, `http` require the `http_client` feature + URL allowlist. When `bot-auth` feature is enabled, all outbound HTTP requests are transparently -signed with Ed25519 per RFC 9421 (see `specs/request-signing.md`). +signed with Ed25519 per RFC 9421 (see `knowledge/request-signing.md`). diff --git a/specs/coreutils-args-port.md b/knowledge/coreutils-args-port.md similarity index 98% rename from specs/coreutils-args-port.md rename to knowledge/coreutils-args-port.md index 724cf9310..aee840286 100644 --- a/specs/coreutils-args-port.md +++ b/knowledge/coreutils-args-port.md @@ -1,3 +1,8 @@ +--- +title: Coreutils Argument Port +summary: Code generation design for porting uutils clap arguments and uucore modules. +--- + # Coreutils argument-surface port ## Status @@ -251,7 +256,7 @@ one TOML stanza and the next run picks it up. The PR's intermediate commits are bot-authored (automated drift detection, not a code change). Maintainers must **squash-merge as a human** so the merge commit is attributed correctly per `AGENTS.md`. Reviewing the auto-PR -is part of the maintenance checklist — see `specs/maintenance.md` +is part of the maintenance checklist — see `knowledge/maintenance.md` § Coreutils Argument-Surface Drift. ## Alternatives considered @@ -262,7 +267,7 @@ is part of the maintenance checklist — see `specs/maintenance.md` ## See also -- `specs/builtins.md` — `Builtin` trait, `ClapBuiltin`, command dispatch. +- `knowledge/builtins.md` — `Builtin` trait, `ClapBuiltin`, command dispatch. - `crates/bashkit-coreutils-port/src/main.rs` — codegen entry point; `args.rs` / `module.rs` host the two modes, `manifest.rs` the `vendored.toml` schema. - `crates/bashkit-coreutils-port/vendored.toml` — vendored-module manifest. - `crates/bashkit/src/builtins/cat.rs`, `textrev.rs` — port consumers. diff --git a/specs/credential-injection.md b/knowledge/credential-injection.md similarity index 97% rename from specs/credential-injection.md rename to knowledge/credential-injection.md index f58bfab45..6b179e9b6 100644 --- a/specs/credential-injection.md +++ b/knowledge/credential-injection.md @@ -1,3 +1,8 @@ +--- +title: Credential Injection +summary: Per-host HTTP credential injection without exposing secret values to sandboxed scripts. +--- + # Generic Credential Injection > Transparent per-host credential injection for outbound HTTP requests, without exposing secrets to sandboxed scripts. @@ -39,7 +44,7 @@ Request pipeline (unchanged from #1255; injection is step 3): 2. Private IP / SSRF check ← SSRF protection 3. before_http hooks ← credential injection lives here 4. Bot-auth signing ← Ed25519 headers -5. Custom HttpTransport OR reqwest (see specs/http-transport.md) +5. Custom HttpTransport OR reqwest (see knowledge/http-transport.md) 6. after_http hooks ← observational ``` diff --git a/specs/documentation.md b/knowledge/documentation.md similarity index 96% rename from specs/documentation.md rename to knowledge/documentation.md index c7b3237ab..020168149 100644 --- a/specs/documentation.md +++ b/knowledge/documentation.md @@ -1,3 +1,8 @@ +--- +title: Documentation Architecture +summary: User documentation and Rustdoc guide organization, embedding, and maintenance. +--- + # Documentation Approach ## Status @@ -127,7 +132,7 @@ bot commit would violate the AGENTS.md commit-attribution rule) — a human runs `just apidocs` and commits. The Python check is cheap (static `griffe` parse, pinned) so it runs on every PR touching the Python surface; the TypeScript check needs a Rust `napi build`, so it runs only on the weekly schedule and on -demand. Regenerate-and-commit is a release step (see `specs/release-process.md`). +demand. Regenerate-and-commit is a release step (see `knowledge/release-process.md`). ### Constraints diff --git a/specs/emscripten-wheels.md b/knowledge/emscripten-wheels.md similarity index 96% rename from specs/emscripten-wheels.md rename to knowledge/emscripten-wheels.md index 08250cecc..ff3792469 100644 --- a/specs/emscripten-wheels.md +++ b/knowledge/emscripten-wheels.md @@ -1,3 +1,8 @@ +--- +title: Emscripten Wheels +summary: Reduced-feature Pyodide and Emscripten Python wheel design and build constraints. +--- + # Emscripten / Pyodide Wheels ## Status @@ -161,5 +166,5 @@ the native wheels. ## See also -- `specs/python-package.md` — native wheel matrix, PyPI publishing, public API. -- `specs/architecture.md` — core interpreter, wasm-aware tokio gating. +- `knowledge/python-package.md` — native wheel matrix, PyPI publishing, public API. +- `knowledge/architecture.md` — core interpreter, wasm-aware tokio gating. diff --git a/specs/eval.md b/knowledge/eval.md similarity index 97% rename from specs/eval.md rename to knowledge/eval.md index a4d8d1fd2..7703a12dc 100644 --- a/specs/eval.md +++ b/knowledge/eval.md @@ -1,3 +1,8 @@ +--- +title: Evaluation Framework +summary: LLM evaluation study design, dataset format, execution, and scoring. +--- + # bashkit-eval: mira Eval Study ## Status @@ -162,7 +167,7 @@ and environment handling — each with task-appropriate pre-populated seed files ## Scripting-Tool Eval A second eval (`bashkit_scripting`) tests `ScriptedTool` orchestration (see -`specs/scripted-tool-orchestration.md`), measuring how well LLMs orchestrate +`knowledge/scripted-tool-orchestration.md`), measuring how well LLMs orchestrate multiple mock tools via bash scripts vs. calling each tool individually. ### Modes (the `mode` axis) diff --git a/specs/git-support.md b/knowledge/git-support.md similarity index 89% rename from specs/git-support.md rename to knowledge/git-support.md index ae5eff8c1..0b9e0103a 100644 --- a/specs/git-support.md +++ b/knowledge/git-support.md @@ -1,3 +1,8 @@ +--- +title: Git Support +summary: Sandboxed Git operations over the virtual filesystem. +--- + # Git Support ## Status @@ -21,7 +26,7 @@ on the virtual filesystem only. Configure via ### Security -See `specs/threat-model.md` Section 8: Git Security (TM-GIT-*) +See `knowledge/threat-model.md` Section 8: Git Security (TM-GIT-*) #### Key Mitigations @@ -70,6 +75,6 @@ Tests live under `crates/bashkit/tests/integration/`: ## See Also -- `specs/threat-model.md` - Security threats and mitigations -- `specs/builtins.md` - Builtin command reference +- `knowledge/threat-model.md` - Security threats and mitigations +- `knowledge/builtins.md` - Builtin command reference - `crates/bashkit/src/builtins/git/` - Implementation diff --git a/specs/http-transport.md b/knowledge/http-transport.md similarity index 92% rename from specs/http-transport.md rename to knowledge/http-transport.md index 3cc93f380..fd565ddde 100644 --- a/specs/http-transport.md +++ b/knowledge/http-transport.md @@ -1,3 +1,8 @@ +--- +title: HTTP Transport +summary: Pluggable host-controlled HTTP transport for curl and wget. +--- + # Pluggable HTTP Transport > Host-injectable transport for all outbound HTTP made by the `curl`/`wget`/`http` builtins, so embedders can direct sandbox traffic through their own boundary (egress gateway, proxy, audit layer) while bashkit keeps enforcing HTTP policy. @@ -45,7 +50,7 @@ Embedding hosts (reference consumer: [everruns](https://github.com/everruns/ever ## See also -- `specs/request-signing.md` — signing pipeline the transport inherits -- `specs/credential-injection.md` — header injection ahead of dispatch -- `specs/threat-model.md` — TM-NET-023 (SSRF responsibility of custom transports), TM-NET-015 (host proxy isolation on the built-in path) -- `specs/tool-contract.md` — LLM tool surface this feeds +- `knowledge/request-signing.md` — signing pipeline the transport inherits +- `knowledge/credential-injection.md` — header injection ahead of dispatch +- `knowledge/threat-model.md` — TM-NET-023 (SSRF responsibility of custom transports), TM-NET-015 (host proxy isolation on the built-in path) +- `knowledge/tool-contract.md` — LLM tool surface this feeds diff --git a/knowledge/index.md b/knowledge/index.md new file mode 100644 index 000000000..1f64f5c5d --- /dev/null +++ b/knowledge/index.md @@ -0,0 +1,39 @@ +--- +title: Bashkit Knowledge +summary: Persistent, agent-maintained product and engineering knowledge for Bashkit. +tags: + - bashkit + - engineering + - product + - security + - operations +--- + +# Bashkit Knowledge + +This directory is Bashkit's canonical [Open Knowledge Format (OKF)](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md) bundle and persistent project memory. + +## Contents + +The documents record architecture, behavior, constraints, security decisions, testing strategy, release procedures, and intentional limitations. Generated factual inventories live under [`status/`](status/). + +## Maintenance contract + +- Treat this knowledge as part of the implementation, not as historical documentation. +- Before changing behavior, read the relevant knowledge documents and follow their decisions or update them in the same change. +- When code changes a documented behavior, design decision, invariant, limitation, threat, test strategy, operational process, or generated fact, update the affected knowledge in the same pull request. +- Record important decisions that are not recoverable from code. Prefer links to source and tests over duplicating volatile implementation details. +- Keep stable identifiers such as `TM-*` and `L-*`; never renumber them. +- Add new durable project knowledge here. User-facing guides remain in `docs/`; embedded Rust guides remain in `crates/bashkit/docs/`. +- Every knowledge subdirectory must contain an OKF `index.md` with `title` and `summary` frontmatter. +- Run the relevant drift checks and tests after updating generated or machine-validated knowledge. + +## Knowledge map + +| Area | Documents | +|---|---| +| Foundations | [Architecture](architecture.md), [parser](parser.md), [virtual filesystem](vfs.md), [builtins](builtins.md), [parallel execution](parallel-execution.md) | +| Security | [Threat model](threat-model.md), [security testing](security-testing.md), [credential injection](credential-injection.md), [request signing](request-signing.md), [HTTP transport](http-transport.md) | +| Runtimes and packages | [Python builtin](python-builtin.md), [TypeScript runtime](zapcode-runtime.md), [SQLite builtin](sqlite-builtin.md), [Python package](python-package.md), [Emscripten wheels](emscripten-wheels.md), [WebAssembly package](browser-package.md) | +| Integrations | [Tool contract](tool-contract.md), [scripted orchestration](scripted-tool-orchestration.md), [Git](git-support.md), [SSH](ssh-support.md) | +| Quality and operations | [Testing](testing.md), [limitations](limitations.md), [documentation](documentation.md), [maintenance](maintenance.md), [release process](release-process.md), [performance results](performance-results.md), [eval](eval.md) | diff --git a/specs/interactive-shell.md b/knowledge/interactive-shell.md similarity index 94% rename from specs/interactive-shell.md rename to knowledge/interactive-shell.md index 404f3daaa..4cba496c9 100644 --- a/specs/interactive-shell.md +++ b/knowledge/interactive-shell.md @@ -1,3 +1,8 @@ +--- +title: Interactive Shell +summary: Interactive REPL design with rustyline-based line editing. +--- + # Interactive Shell Mode ## Status @@ -138,6 +143,6 @@ only with the `interactive` feature: `cargo test -p bashkit-cli` ## See Also -- `specs/architecture.md` - Core interpreter architecture -- `specs/builtins.md` - Builtin command reference -- `specs/limitations.md` - Intentional gaps and partial features +- `knowledge/architecture.md` - Core interpreter architecture +- `knowledge/builtins.md` - Builtin command reference +- `knowledge/limitations.md` - Intentional gaps and partial features diff --git a/specs/limitations.md b/knowledge/limitations.md similarity index 97% rename from specs/limitations.md rename to knowledge/limitations.md index 41ac652ea..90408160f 100644 --- a/specs/limitations.md +++ b/knowledge/limitations.md @@ -1,3 +1,8 @@ +--- +title: Known Limitations +summary: Intentional gaps, partial features, and Bash and POSIX compatibility stance. +--- + # Limitations ## Status @@ -9,7 +14,7 @@ The negative spec: what Bashkit deliberately does NOT do (and why), plus known partial implementations. Absences can't be recovered from code, so they're recorded here; everything positive is generated or tested instead: -- **Builtin inventory**: generated `specs/status/builtins.json` +- **Builtin inventory**: generated `knowledge/status/builtins.json` (`just regen-builtins`, drift-checked by `builtins-drift.yml`) - **Test counts / pass rates**: CI (`spec_tests::bash_spec_tests` suite); spec cases in `crates/bashkit/tests/spec_cases/` @@ -40,7 +45,7 @@ execution model. Evidence is a threat-model ID, a test, or `stance` | L-NET-001 | No raw network sockets; HTTP only via `curl`/`wget`/`http` builtins | Allowlist-mediated egress is the only network surface | `l_net_001_no_raw_sockets` | | L-NET-002 | No DNS resolution; hosts must appear in the allowlist | Resolution would bypass allowlist intent | `l_net_002_default_deny_no_resolution` | | L-SIG-001 | `trap` stores INT/TERM handlers but no signal delivery in virtual mode (EXIT, ERR fire) | No host signals exist inside the sandbox | `l_sig_001_signal_traps_not_delivered` | -| L-WASM-001 | Browser build (`@everruns/bashkit-wasm`, `wasm32-unknown-unknown`) has no wall-clock time: `sleep N` elapses instantly, and neither the `timeout N` builtin nor `timeoutMs` is enforced | No reliable timer driver on the target; parser fuel + `maxCommands`/`maxLoopIterations` still bound runaway scripts | `specs/browser-package.md`, stance | +| L-WASM-001 | Browser build (`@everruns/bashkit-wasm`, `wasm32-unknown-unknown`) has no wall-clock time: `sleep N` elapses instantly, and neither the `timeout N` builtin nor `timeoutMs` is enforced | No reliable timer driver on the target; parser fuel + `maxCommands`/`maxLoopIterations` still bound runaway scripts | `knowledge/browser-package.md`, stance | | L-WASM-002 | Browser build: `executeSync()` cannot run async custom builtins (fails with a clear message); use `execute()` | Single-threaded event loop can't settle a JS `Promise` without yielding | `crates/bashkit-wasm/__test__/bashkit-wasm.test.mjs` | | L-WASM-003 | Browser build: background jobs (`cmd &`) run synchronously and `awk` file redirects drive the VFS inline; no work runs on a separate thread | `wasm32-unknown-unknown` is single-threaded — `std::thread::spawn`/`tokio::spawn` are unavailable; safe because the in-memory VFS never suspends | `crates/bashkit-wasm/__test__/bashkit-wasm.test.mjs` | diff --git a/specs/maintenance.md b/knowledge/maintenance.md similarity index 93% rename from specs/maintenance.md rename to knowledge/maintenance.md index 317413946..5a4e12ae3 100644 --- a/specs/maintenance.md +++ b/knowledge/maintenance.md @@ -1,3 +1,8 @@ +--- +title: Maintenance +summary: Pre-release dependency, security, compatibility, and artifact maintenance requirements. +--- + # Pre-Release Maintenance ## Status @@ -37,7 +42,7 @@ dependency rot, or security gaps ship in a release. ### Security -- Threat model (`specs/threat-model.md`) covers all current features +- Threat model (`knowledge/threat-model.md`) covers all current features - Public threat model doc (`crates/bashkit/docs/threat-model.md`) in sync with spec - Every new builtin/feature has a corresponding TM-XXX entry - DeepSec is updated to the latest published version before scanning: @@ -55,7 +60,7 @@ dependency rot, or security gaps ship in a release. - All tests pass - No test gaps for recently added features -- `builtins-drift` workflow green (generated `specs/status/builtins.json` in sync) +- `builtins-drift` workflow green (generated `knowledge/status/builtins.json` in sync) - Bash compatibility — no new regressions against real bash - Coverage reviewed — no major uncovered paths @@ -68,7 +73,7 @@ dependency rot, or security gaps ship in a release. - Python docstrings match behavior - `README.md` feature list matches implemented builtins - Public docs (`docs/`) match current code: CLI flags, security boundaries, feature descriptions, test counts, and examples all reflect reality -- Agent surfaces (`/llms.txt`, `/llms-full.txt`, Markdown routes) regenerate and pass `verify-llms` (auto-enforced in CI); refresh the agent-skills tarball/`index.json` digest if `skills/bashkit/` changed (see `specs/documentation.md` § Agent-facing site surfaces) +- Agent surfaces (`/llms.txt`, `/llms-full.txt`, Markdown routes) regenerate and pass `verify-llms` (auto-enforced in CI); refresh the agent-skills tarball/`index.json` digest if `skills/bashkit/` changed (see `knowledge/documentation.md` § Agent-facing site surfaces) - `CONTRIBUTING.md` instructions accurate - `CHANGELOG.md` has entries for all changes since last release @@ -96,7 +101,7 @@ dependency rot, or security gaps ship in a release. ### Coreutils Argument-Surface and Module-Vendor Drift -See `specs/coreutils-args-port.md`. +See `knowledge/coreutils-args-port.md`. - Review any open `chore: sync uutils/coreutils argument surfaces and vendored modules` PR produced by the `coreutils-args-drift` workflow @@ -149,7 +154,7 @@ See `specs/coreutils-args-port.md`. - Core classes: `Bash`, `BashTool`, `ExecResult`, `ScriptedTool`, `BashError` - Execution methods: `execute`, `execute_sync`, `executeOrThrow`/`execute_or_throw` - Configuration: `username`, `hostname`, `max_commands`, `max_loop_iterations`, `python`, `external_functions`/`external_handler` - - Mount API: `files` dict, `mounts` list (read-only default), runtime `mount`/`unmount` (see `specs/vfs.md` § Binding API Parity) + - Mount API: `files` dict, `mounts` list (read-only default), runtime `mount`/`unmount` (see `knowledge/vfs.md` § Binding API Parity) - Tool metadata: `name`, `description`, `help`, `system_prompt`, `input_schema`, `output_schema`, `version` - Module functions: `getVersion`/`get_version` - Framework integrations: LangChain available in both bindings @@ -226,6 +231,6 @@ Use `/maintain` skill to execute this checklist interactively. ## References -- `specs/release-process.md` — release workflow -- `specs/limitations.md` — negative spec (intentional gaps, partial features) -- `specs/threat-model.md` — threat model +- `knowledge/release-process.md` — release workflow +- `knowledge/limitations.md` — negative spec (intentional gaps, partial features) +- `knowledge/threat-model.md` — threat model diff --git a/specs/parallel-execution.md b/knowledge/parallel-execution.md similarity index 92% rename from specs/parallel-execution.md rename to knowledge/parallel-execution.md index a0d2530d3..6338f79e5 100644 --- a/specs/parallel-execution.md +++ b/knowledge/parallel-execution.md @@ -1,3 +1,8 @@ +--- +title: Parallel Execution +summary: Threading model, shared ownership, and concurrency safety requirements. +--- + # Parallel Execution ## Status diff --git a/specs/parser.md b/knowledge/parser.md similarity index 93% rename from specs/parser.md rename to knowledge/parser.md index 3d31dfc25..d2880707a 100644 --- a/specs/parser.md +++ b/knowledge/parser.md @@ -1,3 +1,8 @@ +--- +title: Parser +summary: Bash syntax parser and lexer architecture and compatibility decisions. +--- + # Parser Design ## Status diff --git a/specs/performance-results.md b/knowledge/performance-results.md similarity index 92% rename from specs/performance-results.md rename to knowledge/performance-results.md index a991fad32..87044d380 100644 --- a/specs/performance-results.md +++ b/knowledge/performance-results.md @@ -1,3 +1,8 @@ +--- +title: Performance Results +summary: Benchmark harnesses, result locations, naming, and publication contract. +--- + # Performance Results and Site Aggregation ## Status @@ -22,7 +27,7 @@ Markdown files are the user-facing reports linked from `/benches`; JSON files are the aggregation input for benchmark and eval summaries. > `bashkit-eval` was reimplemented as a [mira](https://github.com/everruns/mira) -> study (see `specs/eval.md`); mira now owns eval run output (written under +> study (see `knowledge/eval.md`); mira now owns eval run output (written under > `./results//` in mira's own format). The `crates/bashkit-eval/results/` > directory is retained as an **archive** of pre-mira runs and remains the > `/benches` eval input until the site is re-wired to mira's output format diff --git a/specs/python-builtin.md b/knowledge/python-builtin.md similarity index 97% rename from specs/python-builtin.md rename to knowledge/python-builtin.md index f57e0d513..25cb75dc9 100644 --- a/specs/python-builtin.md +++ b/knowledge/python-builtin.md @@ -1,3 +1,8 @@ +--- +title: Python Builtin +summary: Embedded Python execution through Monty with security and resource controls. +--- + # Python Builtin (Monty) > **Experimental.** Monty is an early-stage Python interpreter that may have @@ -125,7 +130,7 @@ let bash = Bash::builder() ### Security -See `specs/threat-model.md` § "Python / Monty Security (TM-PY)" for the full +See `knowledge/threat-model.md` § "Python / Monty Security (TM-PY)" for the full analysis. Summary: - **Code injection via bash expansion**: variables expand before reaching the builtin (by-design, consistent with all builtins); use single quotes to prevent. diff --git a/specs/python-package.md b/knowledge/python-package.md similarity index 98% rename from specs/python-package.md rename to knowledge/python-package.md index 694ce88b5..520b8486c 100644 --- a/specs/python-package.md +++ b/knowledge/python-package.md @@ -1,3 +1,8 @@ +--- +title: Python Package +summary: Python bindings, PyPI wheels, ABI strategy, and platform build matrix. +--- + # Python Package ## Status @@ -42,7 +47,7 @@ Thanks to abi3 (below) this is **7 native wheels per release** (one In addition, a **reduced-feature Pyodide/Emscripten wheel** (`wasm32-unknown-emscripten`) ships for browser / JupyterLite use — built and published separately (different toolchain, single Python version, no -async/network/sqlite/realfs). See `specs/emscripten-wheels.md`. +async/network/sqlite/realfs). See `knowledge/emscripten-wheels.md`. ## PyPI Publishing @@ -255,7 +260,7 @@ Limited-API constraints observed in `crates/bashkit-python/src/lib.rs`: below 3.10). Lazy file providers use `to_cow()`, which is in the stable ABI. The emscripten/Pyodide wheel is unaffected — it already ships a single Python -version on a separate toolchain (see `specs/emscripten-wheels.md`). +version on a separate toolchain (see `knowledge/emscripten-wheels.md`). ## Design Decisions diff --git a/specs/release-process.md b/knowledge/release-process.md similarity index 96% rename from specs/release-process.md rename to knowledge/release-process.md index 2c6421d3a..10cf7ad1d 100644 --- a/specs/release-process.md +++ b/knowledge/release-process.md @@ -1,3 +1,8 @@ +--- +title: Release Process +summary: Versioning, validation, tagging, and publication to crates.io, PyPI, and npm. +--- + # Release Process ## Status @@ -45,7 +50,7 @@ silently failed. - Refresh the self-hosted API references: `just apidocs` and commit any changes. The `apidocs-drift` workflow only checks TypeScript weekly (its regen needs a Rust build), so a release is the reliable point to catch TS - drift. See `specs/documentation.md` ("API reference hosting"). + drift. See `knowledge/documentation.md` ("API reference hosting"). 4. **Run local verification** — `cargo fmt --check`, `cargo clippy --all-targets --all-features -- -D warnings`, `cargo test`. 5. **Verify publish-readiness** (catches what local tests don't — the @@ -132,7 +137,7 @@ Use the latest entries in `CHANGELOG.md` as the template. Rules: Crates publish in dependency order: `bashkit` (no internal deps) then `bashkit-cli` (depends on bashkit). Python wheels (native matrix + the -reduced-feature Pyodide/Emscripten wheel — see `specs/emscripten-wheels.md`) +reduced-feature Pyodide/Emscripten wheel — see `knowledge/emscripten-wheels.md`) and both npm packages publish independently (no crates.io dependency). CI workflows handle ordering automatically on GitHub Release. @@ -164,7 +169,7 @@ verifies published versions. Secret: `CARGO_REGISTRY_TOKEN`. ### publish-python.yml Trigger: Release published (parallel with publish.yml). Builds wheels for -all platforms (matrix in `specs/python-package.md`), smoke-tests, publishes +all platforms (matrix in `knowledge/python-package.md`), smoke-tests, publishes to PyPI via trusted publishing (OIDC, no secrets; environment `release-python` must exist in repo settings). Python version is read dynamically from `Cargo.toml` via maturin (`dynamic = ["version"]`). diff --git a/specs/request-signing.md b/knowledge/request-signing.md similarity index 96% rename from specs/request-signing.md rename to knowledge/request-signing.md index 550079bba..c77c0f67c 100644 --- a/specs/request-signing.md +++ b/knowledge/request-signing.md @@ -1,3 +1,8 @@ +--- +title: Request Signing +summary: Transparent Ed25519 HTTP message signing according to RFC 9421. +--- + # Transparent Request Signing (bot-auth) > Ed25519 request signing for all outbound HTTP requests per RFC 9421 / web-bot-auth profile. @@ -28,7 +33,7 @@ Signing happens in `HttpClient` at the same layer as the allowlist check. **All* |------|--------|-----| | `HttpClient::request_with_headers` (default reqwest) | Yes | `bot_auth_headers()` injected before `request.send()` | | `HttpClient::request_with_timeouts` (per-request timeout) | Yes | Same `bot_auth_headers()` injection | -| Custom `HttpTransport` | Yes | Signing headers merged into `HttpTransportRequest.headers` before dispatch (see `specs/http-transport.md`) | +| Custom `HttpTransport` | Yes | Signing headers merged into `HttpTransportRequest.headers` before dispatch (see `knowledge/http-transport.md`) | | Redirects (manual follow in curl/wget) | Yes | Each redirect is a new `HttpClient` request, re-signed with the new authority | Every HTTP builtin — `curl`, `wget`, `http` — goes through `HttpClient`, so no builtin can bypass signing. diff --git a/specs/scripted-tool-orchestration.md b/knowledge/scripted-tool-orchestration.md similarity index 99% rename from specs/scripted-tool-orchestration.md rename to knowledge/scripted-tool-orchestration.md index f46dfa1f2..9c53096ed 100644 --- a/specs/scripted-tool-orchestration.md +++ b/knowledge/scripted-tool-orchestration.md @@ -1,3 +1,8 @@ +--- +title: Scripted Tool Orchestration +summary: Composition of tool definitions and callbacks into Bash-scripted orchestrators. +--- + # Scripted Tool Orchestration ## Status diff --git a/specs/security-testing.md b/knowledge/security-testing.md similarity index 96% rename from specs/security-testing.md rename to knowledge/security-testing.md index f52b3c12d..6617cf27a 100644 --- a/specs/security-testing.md +++ b/knowledge/security-testing.md @@ -1,3 +1,8 @@ +--- +title: Security Testing +summary: Fail-point injection and layered security regression testing strategy. +--- + # Security Testing with Fail Points ## Status @@ -96,4 +101,4 @@ pnpm test`). White-box and black-box scenarios across 18 categories: - `crates/bashkit/src/fs/memory.rs` - Filesystem fail points - `crates/bashkit/src/interpreter/mod.rs` - Interpreter fail points, panic catching - `crates/bashkit/src/builtins/system.rs` - Hardcoded system builtins -- `specs/threat-model.md` - Threat model specification +- `knowledge/threat-model.md` - Threat model specification diff --git a/specs/sqlite-builtin.md b/knowledge/sqlite-builtin.md similarity index 99% rename from specs/sqlite-builtin.md rename to knowledge/sqlite-builtin.md index 4074e0c97..d11803ae1 100644 --- a/specs/sqlite-builtin.md +++ b/knowledge/sqlite-builtin.md @@ -1,3 +1,8 @@ +--- +title: SQLite Builtin +summary: Embedded SQLite through Turso with memory and virtual filesystem backends. +--- + # `sqlite` Builtin > **Experimental.** Backed by [Turso](https://github.com/tursodatabase/turso) diff --git a/specs/ssh-support.md b/knowledge/ssh-support.md similarity index 96% rename from specs/ssh-support.md rename to knowledge/ssh-support.md index d1a528165..35f45be36 100644 --- a/specs/ssh-support.md +++ b/knowledge/ssh-support.md @@ -1,3 +1,8 @@ +--- +title: SSH Support +summary: Sandboxed SSH, SCP, and SFTP operations and security boundaries. +--- + # SSH Support ## Status diff --git a/specs/status/builtins.json b/knowledge/status/builtins.json similarity index 100% rename from specs/status/builtins.json rename to knowledge/status/builtins.json diff --git a/knowledge/status/index.md b/knowledge/status/index.md new file mode 100644 index 000000000..1a61f0d44 --- /dev/null +++ b/knowledge/status/index.md @@ -0,0 +1,14 @@ +--- +title: Generated Status +summary: Machine-generated inventories that capture the current Bashkit implementation state. +tags: + - bashkit + - generated + - status +--- + +# Generated Status + +Files in this collection are generated views of implementation state. Do not edit generated artifacts by hand; use the repository generator and commit updates with the behavior that caused them. + +- [`builtins.json`](builtins.json) — builtin command inventory; regenerate with `just regen-builtins`. diff --git a/specs/testing.md b/knowledge/testing.md similarity index 96% rename from specs/testing.md rename to knowledge/testing.md index 3bb9a7dab..4a27af7c3 100644 --- a/specs/testing.md +++ b/knowledge/testing.md @@ -1,3 +1,8 @@ +--- +title: Testing Strategy +summary: Test organization, patterns, fixtures, differential testing, and CI expectations. +--- + # Testing Strategy ## Status @@ -89,7 +94,7 @@ tests via `cargo llvm-cov`. 2. Run `just check-bash-compat` to verify expected output matches real bash 3. Unimplemented feature → `### skip: reason`; intentional difference → `### bash_diff: reason` -4. Record the limitation in `specs/limitations.md` (skip reason = evidence) +4. Record the limitation in `knowledge/limitations.md` (skip reason = evidence) ## Comparison Testing diff --git a/specs/threat-model.md b/knowledge/threat-model.md similarity index 99% rename from specs/threat-model.md rename to knowledge/threat-model.md index 613078101..6d93eae35 100644 --- a/specs/threat-model.md +++ b/knowledge/threat-model.md @@ -1,3 +1,8 @@ +--- +title: Threat Model +summary: Bashkit assets, trust boundaries, threats, mitigations, and stable threat identifiers. +--- + # Bashkit Threat Model ## Status @@ -615,18 +620,18 @@ matches literal host strings exactly, never resolved IPs; no DNS lookup. | TM-NET-018 | JSON body injection | `http POST url name='x","admin":true'` via unescaped string formatting | Use `serde_json` for JSON construction | **MITIGATED** | | TM-NET-019 | Query param injection | `http GET url q=='foo&admin=true'` injects extra params | URL-encode via local x-www-form-urlencoded encoder | **MITIGATED** | | TM-NET-020 | Form body injection | `http --form POST url user='x&role=admin'` injects extra fields | URL-encode via local x-www-form-urlencoded encoder | **MITIGATED** | -| TM-NET-021 | Bot identity spoofing | Forge requests as a trusted bot | Ed25519 request signing (bot-auth feature, `specs/request-signing.md`) | **MITIGATED** (opt-in) | +| TM-NET-021 | Bot identity spoofing | Forge requests as a trusted bot | Ed25519 request signing (bot-auth feature, `knowledge/request-signing.md`) | **MITIGATED** (opt-in) | | TM-NET-022 | IPv4-mapped IPv6 SSRF bypass | AAAA record returns `::ffff:127.0.0.1`, `::ffff:10.0.0.1`, `::ffff:169.254.169.254`, etc. — embedded v4 address would re-enter the v4 address space at the kernel/socket layer, but the v6 branch of `is_private_ip` only inspected `is_loopback`/`is_unspecified`/`fd00::/8`/`fe80::/10`, treating everything else as public | `is_private_ip` normalizes IPv4-mapped (`::ffff:0:0/96`) and IPv4-compatible (`::a.b.c.d`) v6 forms back to v4 via `Ipv6Addr::to_ipv4_mapped()` and applies the v4 classifier (`is_private_ipv4`). Tested via `test_is_private_ip_v4_mapped_v6_*` cases for loopback, RFC1918, AWS metadata (169.254.169.254), CGNAT, unspecified, public, and IPv4-compatible. Mitigation reaches both the v6 connect-time `PrivateIpFilteringResolver` and the URL/precheck path. | **FIXED** (#1569) | -| TM-NET-023 | HTTP-handler SSRF via fail-open precheck and rebind window | `HttpClient::check_private_ip` returned `Ok(())` on URL-parse failures and on URLs with no host, letting malformed targets reach the connect path with no IP filter. Custom `HttpHandler` implementations are doubly exposed because they don't get reqwest's connect-time `PrivateIpFilteringResolver` — even a successful precheck leaves a rebind window between validation and the moment the handler opens its own socket. | (1) `check_private_ip` now fails closed on malformed URLs and on URLs with no host. The direct-IP branch and the successful-DNS branch remain fail-closed against private addresses (including the v4-mapped IPv6 forms covered by TM-NET-022). Tested via `test_check_private_ip_fails_closed_on_invalid_url`, `test_check_private_ip_fails_closed_on_no_host`, `test_check_private_ip_blocks_literal_private_ip`, `test_check_private_ip_blocks_metadata_via_v4_mapped_v6`. (2) The `HttpTransport` trait doc explicitly assigns SSRF responsibility to network-dialing custom transports and points them at `bashkit::network::is_private_ip` for the same classifier the default reqwest path uses; `HttpTransportRequest.pinned_addrs` additionally forwards the precheck's resolve-then-check result so transports (and host egress boundaries behind them) can pin the validated addresses and close the rebind window (see `specs/http-transport.md`). DNS-lookup errors at the precheck still pass through (fail-open by design — the rebind / connect-time threat is the handler's responsibility, and failing closed there breaks legitimate `before_http` hook flows that intentionally target unresolved hostnames). | **MITIGATED** (#1570) | +| TM-NET-023 | HTTP-handler SSRF via fail-open precheck and rebind window | `HttpClient::check_private_ip` returned `Ok(())` on URL-parse failures and on URLs with no host, letting malformed targets reach the connect path with no IP filter. Custom `HttpHandler` implementations are doubly exposed because they don't get reqwest's connect-time `PrivateIpFilteringResolver` — even a successful precheck leaves a rebind window between validation and the moment the handler opens its own socket. | (1) `check_private_ip` now fails closed on malformed URLs and on URLs with no host. The direct-IP branch and the successful-DNS branch remain fail-closed against private addresses (including the v4-mapped IPv6 forms covered by TM-NET-022). Tested via `test_check_private_ip_fails_closed_on_invalid_url`, `test_check_private_ip_fails_closed_on_no_host`, `test_check_private_ip_blocks_literal_private_ip`, `test_check_private_ip_blocks_metadata_via_v4_mapped_v6`. (2) The `HttpTransport` trait doc explicitly assigns SSRF responsibility to network-dialing custom transports and points them at `bashkit::network::is_private_ip` for the same classifier the default reqwest path uses; `HttpTransportRequest.pinned_addrs` additionally forwards the precheck's resolve-then-check result so transports (and host egress boundaries behind them) can pin the validated addresses and close the rebind window (see `knowledge/http-transport.md`). DNS-lookup errors at the precheck still pass through (fail-open by design — the rebind / connect-time threat is the handler's responsibility, and failing closed there breaks legitimate `before_http` hook flows that intentionally target unresolved hostnames). | **MITIGATED** (#1570) | **Current Risk**: LOW - Multiple mitigations in place -**Bot-auth signing** (feature `bot-auth`): When configured, all outbound HTTP requests from curl/wget/http builtins are transparently signed with Ed25519 per RFC 9421. Signing is non-blocking — failures send requests unsigned. See `specs/request-signing.md`. +**Bot-auth signing** (feature `bot-auth`): When configured, all outbound HTTP requests from curl/wget/http builtins are transparently signed with Ed25519 per RFC 9421. Signing is non-blocking — failures send requests unsigned. See `knowledge/request-signing.md`. #### 5.4 Credential Injection Per-host HTTP credentials injected by the embedding host without exposing the -secret to the script. See `specs/credential-injection.md`. +secret to the script. See `knowledge/credential-injection.md`. | ID | Threat | Attack Vector | Mitigation | Status | |----|--------|--------------|------------|--------| @@ -648,7 +653,7 @@ redacted everywhere they could surface. | ID | Threat | Attack Vector | Mitigation | Status | |----|--------|--------------|------------|--------| -| TM-AVAIL-001 | Optional auth failure blocks legitimate requests | A transient signing or credential-injection failure (missing placeholder, callback error, key load failure) hard-fails an otherwise valid request | **Non-blocking by design**: bot-auth signing and credential injection fail open — on failure the request is sent unsigned / without the credential rather than aborted. The security enforcement (allowlist, SSRF precheck) still runs; only the *optional* auth augmentation is skipped. Accepted trade-off: availability over strict auth attachment, since the destination enforces its own authn. See `specs/request-signing.md`, `specs/credential-injection.md` | **ACCEPTED** | +| TM-AVAIL-001 | Optional auth failure blocks legitimate requests | A transient signing or credential-injection failure (missing placeholder, callback error, key load failure) hard-fails an otherwise valid request | **Non-blocking by design**: bot-auth signing and credential injection fail open — on failure the request is sent unsigned / without the credential rather than aborted. The security enforcement (allowlist, SSRF precheck) still runs; only the *optional* auth augmentation is skipped. Accepted trade-off: availability over strict auth attachment, since the destination enforces its own authn. See `knowledge/request-signing.md`, `knowledge/credential-injection.md` | **ACCEPTED** | **Implementation**: `network/client.rs` — `DEFAULT_MAX_RESPONSE_BYTES` 10MB, timeouts default 30s / connect 10s, clamped to [1s, 10min] (TM-NET-008/009/010); `redirect(Policy::none())` @@ -1918,10 +1923,10 @@ delimiters); scripted_tool (no byte/char patterns). ## References -- `specs/architecture.md` - System design -- `specs/vfs.md` - Virtual filesystem design -- `specs/security-testing.md` - Fail-point testing -- `specs/python-builtin.md` - Python builtin specification +- `knowledge/architecture.md` - System design +- `knowledge/vfs.md` - Virtual filesystem design +- `knowledge/security-testing.md` - Fail-point testing +- `knowledge/python-builtin.md` - Python builtin specification - `src/builtins/system.rs` - Hardcoded system builtins - `tests/threat_model_tests.rs` - Threat model test suite - `tests/security_failpoint_tests.rs` - Fail-point security tests diff --git a/specs/tool-contract.md b/knowledge/tool-contract.md similarity index 97% rename from specs/tool-contract.md rename to knowledge/tool-contract.md index ff5d661c8..d6d13a1c9 100644 --- a/specs/tool-contract.md +++ b/knowledge/tool-contract.md @@ -1,3 +1,8 @@ +--- +title: Tool Contract +summary: Public LLM tool trait behavior, schemas, callbacks, and error semantics. +--- + # Tool Contract ## Status diff --git a/specs/vfs.md b/knowledge/vfs.md similarity index 98% rename from specs/vfs.md rename to knowledge/vfs.md index 9a143cafe..e626100d4 100644 --- a/specs/vfs.md +++ b/knowledge/vfs.md @@ -1,3 +1,8 @@ +--- +title: Virtual Filesystem +summary: Filesystem abstraction, path safety, implementations, and sandbox invariants. +--- + # Virtual Filesystem Design ## Status diff --git a/specs/zapcode-runtime.md b/knowledge/zapcode-runtime.md similarity index 96% rename from specs/zapcode-runtime.md rename to knowledge/zapcode-runtime.md index 6e97fed78..4a05be262 100644 --- a/specs/zapcode-runtime.md +++ b/knowledge/zapcode-runtime.md @@ -1,3 +1,8 @@ +--- +title: ZapCode Runtime +summary: Embedded TypeScript runtime, external functions, VFS bridging, and resource limits. +--- + # ZapCode TypeScript Runtime > **Experimental.** ZapCode is an early-stage TypeScript interpreter. Resource @@ -94,7 +99,7 @@ where `handler: TypeScriptExternalFnHandler` is an ### Security -See `specs/threat-model.md` section "TypeScript / ZapCode Security (TM-TS)" +See `knowledge/threat-model.md` section "TypeScript / ZapCode Security (TM-TS)" for the full threat analysis. - **Code injection via bash variable expansion**: variables expand before diff --git a/mira.toml b/mira.toml index d52abc0b1..08b6a7051 100644 --- a/mira.toml +++ b/mira.toml @@ -1,6 +1,6 @@ # mira host config for the bashkit-eval study. # Saved run folders (/ with per-case results) land here so they live -# with the repo and can be resumed / re-reported. See specs/eval.md. +# with the repo and can be resumed / re-reported. See knowledge/eval.md. [results] dir = "crates/bashkit-eval/results/mira" diff --git a/scripts/gen_python_apidocs.py b/scripts/gen_python_apidocs.py index 279ea2906..e8ebda3f8 100644 --- a/scripts/gen_python_apidocs.py +++ b/scripts/gen_python_apidocs.py @@ -11,7 +11,7 @@ statically parse them (no compiled extension or third-party deps required, `allow_inspection=False`), then render markdown. Latest-only: regenerated on release, output committed to the repo so the node-only site build just renders -it. See specs/documentation.md ("API reference hosting"). +it. See knowledge/documentation.md ("API reference hosting"). Usage: python3 scripts/gen_python_apidocs.py """ diff --git a/site/README.md b/site/README.md index d8f378c19..948345fa3 100644 --- a/site/README.md +++ b/site/README.md @@ -20,7 +20,7 @@ pnpm run preview # serve dist/ via wrangler `pnpm run build` regenerates `src/data/performance-timeline.json` from saved benchmark and eval artifacts before Astro builds. The `/benches` page contract is -specified in `../specs/performance-results.md`. +specified in `../knowledge/performance-results.md`. ## Deploy diff --git a/site/astro.config.mjs b/site/astro.config.mjs index b09608cee..56a737700 100644 --- a/site/astro.config.mjs +++ b/site/astro.config.mjs @@ -95,9 +95,9 @@ function repoUrl(url) { return `https://github.com/everruns/bashkit/blob/main/${cleanUrl}`; } - const specsIndex = cleanUrl.indexOf("specs/"); - if (specsIndex >= 0) { - return `https://github.com/everruns/bashkit/blob/main/${cleanUrl.slice(specsIndex)}`; + const knowledgeIndex = cleanUrl.indexOf("knowledge/"); + if (knowledgeIndex >= 0) { + return `https://github.com/everruns/bashkit/blob/main/${cleanUrl.slice(knowledgeIndex)}`; } const examplesIndex = cleanUrl.indexOf("examples/"); @@ -119,9 +119,9 @@ function renderedDocsRepoUrl(url) { return `https://github.com/everruns/bashkit/blob/main/${docsPath}`; } - const specsIndex = docsPath.indexOf("specs/"); - if (specsIndex >= 0) { - return `https://github.com/everruns/bashkit/blob/main/${docsPath.slice(specsIndex)}`; + const knowledgeIndex = docsPath.indexOf("knowledge/"); + if (knowledgeIndex >= 0) { + return `https://github.com/everruns/bashkit/blob/main/${docsPath.slice(knowledgeIndex)}`; } const cratesDocsIndex = docsPath.indexOf("crates/bashkit/docs/"); diff --git a/site/src/content.config.ts b/site/src/content.config.ts index 0b426dbb9..e122f2aba 100644 --- a/site/src/content.config.ts +++ b/site/src/content.config.ts @@ -14,7 +14,7 @@ const rustdocs = defineCollection({ // API references for the PyPI/npm packages — the self-hosted analog to docs.rs // for Rust. Generated markdown (committed, regenerated on release) so the site -// build stays node-only. See specs/documentation.md ("API reference hosting"). +// build stays node-only. See knowledge/documentation.md ("API reference hosting"). const apidocs = defineCollection({ loader: glob({ pattern: "*.md", base: "./src/content/apidocs" }), }); diff --git a/site/src/content/home.ts b/site/src/content/home.ts index e552d93b2..19c780eff 100644 --- a/site/src/content/home.ts +++ b/site/src/content/home.ts @@ -1,12 +1,12 @@ // Decision: homepage HTML and Markdown are generated from the same content // tables so agent-facing navigation and product claims stay in sync. // Decision: the builtin count comes from the generated inventory -// (specs/status/builtins.json) so marketing copy can't drift from the code. +// (knowledge/status/builtins.json) so marketing copy can't drift from the code. import { readFileSync } from "node:fs"; import { resolve } from "node:path"; const inventory = JSON.parse( - readFileSync(resolve(process.cwd(), "../specs/status/builtins.json"), "utf8"), + readFileSync(resolve(process.cwd(), "../knowledge/status/builtins.json"), "utf8"), ) as { builtins: { name: string }[] }; export const builtinCount = inventory.builtins.length; @@ -70,7 +70,7 @@ export const heroStats = [ { label: "Threats mitigated", value: "250+", - href: "https://github.com/everruns/bashkit/blob/main/specs/threat-model.md", + href: "https://github.com/everruns/bashkit/blob/main/knowledge/threat-model.md", external: true, }, { @@ -305,7 +305,7 @@ export const resources = [ { title: "Threat model", detail: "268 documented threat cases across parser, VFS, network, and runtimes.", - href: "https://github.com/everruns/bashkit/blob/main/specs/threat-model.md", + href: "https://github.com/everruns/bashkit/blob/main/knowledge/threat-model.md", cta: "Security spec", }, { diff --git a/site/src/pages/api/_meta.ts b/site/src/pages/api/_meta.ts index 087a43148..6f338924b 100644 --- a/site/src/pages/api/_meta.ts +++ b/site/src/pages/api/_meta.ts @@ -1,7 +1,7 @@ // Registry for the self-hosted package API references — the docs.rs analog for // the PyPI and npm packages. Rust keeps using docs.rs (external); Python and // TypeScript render generated markdown from the `apidocs` content collection -// through the same branded DocsLayout. See specs/documentation.md. +// through the same branded DocsLayout. See knowledge/documentation.md. export type ApiRef = { // Matches the `apidocs` collection entry id and the /api/ route. diff --git a/site/src/pages/builtins.astro b/site/src/pages/builtins.astro index fa2902c44..bf0bbaa36 100644 --- a/site/src/pages/builtins.astro +++ b/site/src/pages/builtins.astro @@ -4,14 +4,14 @@ import { resolve } from "node:path"; import BaseLayout from "../layouts/BaseLayout.astro"; // Decision: build the public builtins index from the generated inventory -// specs/status/builtins.json (`just regen-builtins`), so the page reflects +// knowledge/status/builtins.json (`just regen-builtins`), so the page reflects // what the code actually registers. The builtins-drift workflow keeps the // committed JSON in sync with the source. type BuiltinEntry = { name: string; feature: string | null }; const inventory = JSON.parse( - readFileSync(resolve(process.cwd(), "../specs/status/builtins.json"), "utf8"), + readFileSync(resolve(process.cwd(), "../knowledge/status/builtins.json"), "utf8"), ) as { builtins: BuiltinEntry[] }; const builtins = [...new Set(inventory.builtins.map((entry) => entry.name))].sort( @@ -59,9 +59,9 @@ const groupedBuiltins = Object.entries( ).sort(([left], [right]) => left.localeCompare(right)); const builtinsSpecHref = - "https://github.com/everruns/bashkit/blob/main/specs/builtins.md"; + "https://github.com/everruns/bashkit/blob/main/knowledge/builtins.md"; const builtinsJsonHref = - "https://github.com/everruns/bashkit/blob/main/specs/status/builtins.json"; + "https://github.com/everruns/bashkit/blob/main/knowledge/status/builtins.json"; ---

The count and command names come from - specs/status/builtins.json, + knowledge/status/builtins.json, regenerated from the builtin registry via just regen-builtins.

diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro index eb44b5970..6fc5560ae 100644 --- a/site/src/pages/index.astro +++ b/site/src/pages/index.astro @@ -270,7 +270,7 @@ import { Defense in depth across every layer — process, filesystem, network, parser, and runtime. See the full threat model for 250+ mitigations. diff --git a/skills/bashkit/references/builtins.md b/skills/bashkit/references/builtins.md index e3c3fbe39..eeb285031 100644 --- a/skills/bashkit/references/builtins.md +++ b/skills/bashkit/references/builtins.md @@ -26,7 +26,7 @@ If the user needs exact Bash parity, check the compatibility docs before answeri ## Builtin Categories -The project tracks 164 built-in commands (generated specs/status/builtins.json). Important groups: +The project tracks 164 built-in commands (generated knowledge/status/builtins.json). Important groups: - Core: `echo`, `printf`, `cat`, `nl`, `read`, `mapfile`, `readarray` - Navigation: `cd`, `pwd`, `ls`, `tree`, `find`, `pushd`, `popd`, `dirs`