diff --git a/.github/actions/conventional-pr/action.yml b/.github/actions/conventional-pr/action.yml index 1b24ae7..fda95b3 100644 --- a/.github/actions/conventional-pr/action.yml +++ b/.github/actions/conventional-pr/action.yml @@ -1,5 +1,3 @@ -# .github/actions/validate-pr-title/action.yml -# # Usage: # - uses: actions/checkout@v4 # - uses: ./.github/actions/validate-pr-title diff --git a/.github/actions/moon-ci-matrix/action.yml b/.github/actions/moon-ci-matrix/action.yml index 576c222..e0a69af 100644 --- a/.github/actions/moon-ci-matrix/action.yml +++ b/.github/actions/moon-ci-matrix/action.yml @@ -4,11 +4,11 @@ description: "Calculates optimal runner count from affected Moon tasks" inputs: tasks-per-runner: required: false - default: "3" + default: "10" description: "Number of affected tasks to assign per runner" max-parallel: required: false - default: "6" + default: "4" description: "Maximum number of concurrent runners" outputs: @@ -17,7 +17,7 @@ outputs: value: ${{ steps.calc.outputs.matrix }} count: description: "Total number of runners" - value: ${{ steps.calc.outputs.total }} + value: ${{ steps.calc.outputs.count }} runs: using: composite @@ -31,10 +31,10 @@ runs: TASK_COUNT=$(moon query tasks --affected | jq '[.tasks[][] | select(.options.runInCI != false)] | length') WANTED=$(( (TASK_COUNT + TASKS_PER_RUNNER - 1) / TASKS_PER_RUNNER )) - TOTAL=$(( WANTED > MAX_RUNNERS ? MAX_RUNNERS : WANTED )) + COUNT=$(( WANTED > MAX_RUNNERS ? MAX_RUNNERS : WANTED )) - MATRIX_JSON=$(jq -n -c --argjson n "$TOTAL" '[range($n)]') + MATRIX_JSON=$(jq -n -c --argjson n "$COUNT" '[range($n)]') - echo "Affected CI tasks: $TASK_COUNT, Runners: $TOTAL" - echo "count=$TOTAL" >> $GITHUB_OUTPUT + echo "Affected CI tasks: $TASK_COUNT, Runners: $COUNT" + echo "count=$COUNT" >> $GITHUB_OUTPUT echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT diff --git a/.github/actions/moon-ci-matrix/notes.md b/.github/actions/moon-ci-matrix/notes.md new file mode 100644 index 0000000..e76bef3 --- /dev/null +++ b/.github/actions/moon-ci-matrix/notes.md @@ -0,0 +1,24 @@ +Smarter matrix would inlcude task to runner affinity by toolchain + +# Get affected projects with their language +moon query projects --affected --json | jq '[.projects[] | {id, language}] | group_by(.language)' + +Then your matrix becomes something like: + +json +[ + {"toolchain": "rust", "projects": ["parser", "wasm-bindings"]}, + {"toolchain": "javascript", "projects": ["web", "docs"]} +] + +Each shard runs moon ci scoped to its projects, so cargo only compiles once on the Rust runner and node_modules only installs on the JS runner. + +Moon's query commands give you a lot to work with: + + moon query projects --affected --json for affected projects with metadata + + moon query tasks --affected --json for affected tasks + + moon project-graph --json for the full dependency graph + +You could even get fancier and look at the dependency graph to keep projects that depend on each other on the same runner. But grouping by language/toolchain gets you 90% of the benefit with minimal complexity. Worth prototyping once you have more than one project type in the repo. \ No newline at end of file diff --git a/.github/actions/moon-ci/action.yml b/.github/actions/moon-ci/action.yml index b88b15b..aa7e6d6 100644 --- a/.github/actions/moon-ci/action.yml +++ b/.github/actions/moon-ci/action.yml @@ -1,5 +1,3 @@ -# .github/actions/moon-ci/action.yml -# # Usage: # - uses: ./.github/actions/moon-ci # with: diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index a0a73de..76aa957 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -1,10 +1,12 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-action.json +# # .github/actions/setup/action.yml # # Usage: # - uses: ./.github/actions/setup # with: # cache-cargo: "true" -# cache-pnpm: "flase" +# cache-pnpm: "false" # # Usage (minimal, no project caches): # - uses: ./.github/actions/setup @@ -30,21 +32,11 @@ runs: with: fetch-depth: ${{ inputs.fetch-depth }} - - uses: moonrepo/setup-toolchain@v0 - with: - auto-install: true - - - uses: actions/cache@v4 - with: - path: .moon/cache - key: moon-${{ runner.os }}-${{ hashFiles('.moon/workspace.yml', '.moon/tasks/*.yml', '.moon/toolchains.yml') }} - restore-keys: | - moon-${{ runner.os }}- - - uses: actions/cache@v4 if: inputs.cache-cargo == 'true' with: path: | + ~/.cargo/bin ~/.cargo/registry ~/.cargo/git target @@ -52,6 +44,17 @@ runs: restore-keys: | cargo-${{ runner.os }}- + - name: Install cargo-binstall + shell: bash + run: command -v cargo-binstall || curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash + + - uses: actions/cache@v4 + with: + path: .moon/cache + key: moon-${{ runner.os }}-${{ hashFiles('.moon/workspace.yml', '.moon/tasks/*.yml', '.moon/toolchains.yml') }} + restore-keys: | + moon-${{ runner.os }}- + - uses: actions/cache@v4 if: inputs.cache-pnpm == 'true' with: @@ -59,3 +62,7 @@ runs: key: pnpm-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | pnpm-${{ runner.os }}- + + - uses: moonrepo/setup-toolchain@v0 + with: + auto-install: true diff --git a/.github/run-info.sh b/.github/run-info.sh new file mode 100755 index 0000000..80c936c --- /dev/null +++ b/.github/run-info.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# Source this file: source run-debug.sh +# Then use: timing [run-id], logs [run-id], or just run directly for both + +_resolve_run_id() { + local run_id="${1:-}" + if [[ -z "$run_id" ]]; then + run_id=$(gh run list --limit 1 --json databaseId --jq '.[0].databaseId') + echo "Using latest run: $run_id" >&2 + fi + echo "$run_id" +} + +timing() { + local run_id + run_id=$(_resolve_run_id "$1") + + echo "=== Workflow Run: $run_id ===" + echo "" + + gh run view "$run_id" --json jobs --jq ' + .jobs | sort_by(.startedAt) | .[] | + "── \(.name) (\(.conclusion // "running")) ──", + " Started: \(.startedAt)", + " Duration: \( + if .completedAt then + ((.completedAt | fromdateiso8601) - (.startedAt | fromdateiso8601)) as $dur | + "\($dur / 60 | floor)m \($dur % 60)s" + else "in progress" + end + )", + "", + (.steps | map( + (if .completedAt and .startedAt then + ((.completedAt | fromdateiso8601) - (.startedAt | fromdateiso8601)) + else 0 end) as $dur | + " \(if $dur >= 60 then "!!" elif $dur >= 30 then ">>" else " " end) \( + if .completedAt and .startedAt then + "\($dur / 60 | floor)m \($dur % 60 | tostring | if length < 2 then "0" + . else . end)s" + else "--:--" + end + ) \(.conclusion // "---" | if . == "success" then "pass" elif . == "skipped" then "skip" elif . == "failure" then "FAIL" else . end) \(.name)" + ) | join("\n")), + "", + "" + ' +} + +logs() { + local run_id + run_id=$(_resolve_run_id "$1") + local outfile="run-${run_id}.log" + + echo "Downloading logs for run $run_id..." >&2 + + gh run view "$run_id" --log > "$outfile" 2>&1 + + if [[ $? -eq 0 ]]; then + echo "Saved to $outfile ($(wc -l < "$outfile") lines)" >&2 + echo "" >&2 + echo "Quick search tips:" >&2 + echo " grep -i error $outfile" >&2 + echo " grep -i warn $outfile" >&2 + echo " grep -iE 'fail|error|panic' $outfile" >&2 + else + echo "Failed to download logs" >&2 + cat "$outfile" >&2 + fi +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_id=$(_resolve_run_id "$1") + timing "$run_id" + logs "$run_id" +fi \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a9ac0a8..7171b87 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,9 @@ on: push: branches: [main] +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + concurrency: group: trunk-${{ github.sha }} cancel-in-progress: false @@ -16,9 +19,12 @@ jobs: ci-matrix: ${{ steps.ci-matrix.outputs.matrix }} runner-count: ${{ steps.ci-matrix.outputs.count }} steps: + # Shallow checkout so GH Actions can resolve local composite actions. + # The setup action re-checks out with full history for moon's affected detection. + # TODO: Remove once composite actions are published to a shared repo. - uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: 1 - uses: ./.github/actions/setup - id: ci-matrix uses: ./.github/actions/moon-ci-matrix @@ -26,7 +32,7 @@ jobs: ci: name: Moon CI needs: [config] - if: needs.config.outputs.runner-count > 0 + if: ${{ fromJson(needs.config.outputs.runner-count || '0') > 0 }} runs-on: ubuntu-latest strategy: fail-fast: true @@ -68,35 +74,9 @@ jobs: - uses: github/codeql-action/autobuild@v3 - uses: github/codeql-action/analyze@v3 - semgrep: - name: Semgrep - needs: [ci] - runs-on: ubuntu-latest - permissions: - security-events: write - container: - image: returntocorp/semgrep - steps: - - uses: actions/checkout@v4 - - name: Run Semgrep scan - run: | - semgrep ci \ - --sarif --output=semgrep.sarif \ - --config="p/default" \ - --config="p/security-audit" \ - --config="p/secrets" - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 - if: always() - with: - sarif_file: semgrep.sarif - category: semgrep - release-please: name: Release Please - needs: [ci, audit, codeql, semgrep] + needs: [ci, audit, codeql] runs-on: ubuntu-latest permissions: contents: write diff --git a/.github/workflows/pr-close.yml b/.github/workflows/pr-close.yml index 593ed17..222d80e 100644 --- a/.github/workflows/pr-close.yml +++ b/.github/workflows/pr-close.yml @@ -4,6 +4,9 @@ on: pull_request_target: types: [closed] +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + jobs: teardown: name: Review Teardown @@ -11,7 +14,12 @@ jobs: permissions: deployments: write steps: + # Shallow checkout so GH Actions can resolve local composite actions. + # The setup action re-checks out with full history for moon's affected detection. + # TODO: Remove once composite actions are published to a shared repo. - uses: actions/checkout@v4 + with: + fetch-depth: 1 - uses: ./.github/actions/setup - id: raa diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 285323c..f47cf15 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -4,6 +4,9 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + concurrency: group: pr-${{ github.event.pull_request.number }} cancel-in-progress: true @@ -16,9 +19,12 @@ jobs: ci-matrix: ${{ steps.ci-matrix.outputs.matrix }} runner-count: ${{ steps.ci-matrix.outputs.count }} steps: + # Shallow checkout so GH Actions can resolve local composite actions. + # The setup action re-checks out with full history for moon's affected detection. + # TODO: Remove once composite actions are published to a shared repo. - uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: 1 - uses: ./.github/actions/setup - id: ci-matrix uses: ./.github/actions/moon-ci-matrix @@ -26,7 +32,7 @@ jobs: ci: name: Moon CI needs: [config] - if: needs.config.outputs.runner-count > 0 + if: ${{ fromJson(needs.config.outputs.runner-count || '0') > 0 }} runs-on: ubuntu-latest strategy: fail-fast: true @@ -51,7 +57,7 @@ jobs: fetch-depth: 0 - uses: ./.github/actions/setup - name: Run Moon Audit Tasks (OSV, Cargo, Gitleaks) - run: moon run :audit + run: moon run :audit --affected codeql: name: CodeQL @@ -71,31 +77,32 @@ jobs: - uses: github/codeql-action/autobuild@v3 - uses: github/codeql-action/analyze@v3 - semgrep: - name: Semgrep - needs: [ci] - runs-on: ubuntu-latest - permissions: - security-events: write - container: - image: returntocorp/semgrep - steps: - - uses: actions/checkout@v4 - - name: Run Semgrep scan - run: | - semgrep ci \ - --sarif --output=semgrep.sarif \ - --config="p/default" \ - --config="p/security-audit" \ - --config="p/secrets" - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 - if: always() - with: - sarif_file: semgrep.sarif - category: semgrep + # will evaluate when closer to a release + # semgrep: + # name: Semgrep + # needs: [ci] + # runs-on: ubuntu-latest + # permissions: + # security-events: write + # container: + # image: returntocorp/semgrep + # steps: + # - uses: actions/checkout@v4 + # - name: Run Semgrep scan + # run: | + # semgrep ci \ + # --sarif --output=semgrep.sarif \ + # --config="p/default" \ + # --config="p/security-audit" \ + # --config="p/secrets" + # env: + # SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + # - name: Upload SARIF file + # uses: github/codeql-action/upload-sarif@v3 + # if: always() + # with: + # sarif_file: semgrep.sarif + # category: semgrep # Review App & Artifacts (RAA) review-open: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a252195..91d9629 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,10 +18,10 @@ on: type: boolean default: true +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + jobs: - # --------------------------------------------------------- - # 1. Routing Job: Determine Task & Environment - # --------------------------------------------------------- router: name: Determine Target runs-on: ubuntu-latest @@ -79,9 +79,12 @@ jobs: contents: write packages: write steps: + # Shallow checkout so GH Actions can resolve local composite actions. + # The setup action re-checks out with full history for moon's affected detection. + # TODO: Remove once composite actions are published to a shared repo. - uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: 1 - uses: ./.github/actions/setup - name: Execute Moon Task diff --git a/.moon/tasks/rust.yml b/.moon/tasks/rust.yml index 6c14a72..fc5e3b6 100644 --- a/.moon/tasks/rust.yml +++ b/.moon/tasks/rust.yml @@ -4,8 +4,6 @@ fileGroups: cargo: - "Cargo.toml" - "src/**/*" - - "/.cargo/config.toml" - - "/rust-toolchain.toml" sources: [] tests: - "benches/**/*" @@ -24,8 +22,6 @@ tasks: - "@group(sources)" env: &env CARGO_TERM_COLOR: "always" - outputs: - - "target/release/$project" build-release: <<: *build @@ -80,14 +76,7 @@ tasks: - "@group(sources)" env: *env - cargo-audit: - command: "cargo" - args: ["audit"] - inputs: - - "@group(cargo)" - env: *env - - cargo-deny: + audit: command: "cargo" args: ["deny", "check"] inputs: diff --git a/.moon/toolchains.yml b/.moon/toolchains.yml index cba71f1..a51c5a8 100644 --- a/.moon/toolchains.yml +++ b/.moon/toolchains.yml @@ -14,6 +14,8 @@ rust: - "cargo-component" - "wasm-pack" - "honggfuzz" + - "cargo-audit" + - "cargo-deny" javascript: packageManager: "pnpm" diff --git a/.moon/workspace.yml b/.moon/workspace.yml index d1fe1cb..955eb1d 100644 --- a/.moon/workspace.yml +++ b/.moon/workspace.yml @@ -1,23 +1,23 @@ $schema: "https://moonrepo.dev/schemas/workspace.json" projects: - - "wit" + # - "wit" - "parser" - - "wasm-*" - - "slash-*" - - "riff-cli" - - "website" - - "docs" + # - "wasm-*" + # - "slash-*" + # - "riff-cli" + # - "website" + # - "docs" -constraints: - enforceLayerRelationships: true - tagRelationships: - core: [] - wasm: ["core"] - sdk: ["wasm", "core"] - cli: ["sdk", "core"] - pkg: ["cli"] - docs: ["docs"] +# constraints: +# enforceLayerRelationships: true +# tagRelationships: +# core: [] +# wasm: ["core"] +# sdk: ["wasm", "core"] +# cli: ["sdk", "core"] +# pkg: ["cli"] +# docs: ["docs"] generator: templates: diff --git a/.prototools b/.prototools index feca60c..2c0bce0 100644 --- a/.prototools +++ b/.prototools @@ -1,2 +1,13 @@ +actionlint = "1.7.11" +dprint = "0.53.0" +gitleaks = "8.28.0" +shellcheck = "0.11.0" + [plugins.tools] -dprint = "https://raw.githubusercontent.com/Phault/proto-toml-plugins/main/dprint/plugin.toml" +actionlint = "https://raw.githubusercontent.com/tomdavidson/proto/refs/heads/main/plugins/actionlint/plugin.toml" +dprint = "https://raw.githubusercontent.com/tomdavidson/proto/refs/heads/main/plugins/dprint/plugin.toml" +gitleaks = "https://raw.githubusercontent.com/tomdavidson/proto/refs/heads/main/plugins/gitleaks/plugin.toml" +shellcheck = "https://raw.githubusercontent.com/tomdavidson/proto/refs/heads/main/plugins/shellcheck/plugin.toml" +shfmt = "https://raw.githubusercontent.com/tomdavidson/proto/refs/heads/main/plugins/shfmt/plugin.toml" + + diff --git a/Cargo.lock b/Cargo.lock index 9571e46..df032ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "leb128fmt" @@ -629,18 +629,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.42" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" +checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.42" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" +checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" dependencies = [ "proc-macro2", "quote", diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..786e610 --- /dev/null +++ b/deny.toml @@ -0,0 +1,6 @@ +[licenses] +allow = [ + "MIT", + "Apache-2.0", + "Unicode-3.0", +] diff --git a/moon.yml b/moon.yml index a0d8a60..b560c83 100644 --- a/moon.yml +++ b/moon.yml @@ -14,6 +14,8 @@ tasks: - "dprint.json" options: runInCI: false + runFromWorkspaceRoot: true + fmt-check: script: "rustup toolchain install nightly --component rustfmt -q && dprint check" @@ -23,3 +25,5 @@ tasks: - "**/*.yml" - "**/*.yaml" - "dprint.json" + options: + runFromWorkspaceRoot: true diff --git a/parser/direction.md b/parser/direction.md deleted file mode 100644 index 6f738bc..0000000 --- a/parser/direction.md +++ /dev/null @@ -1,122 +0,0 @@ -Your direction matches your own Rust + clean-arch guidelines and is idiomatic Rust, with a couple of -naming tweaks I’d suggest. - -## Function structure and colocated tests - -Breaking `to_plaintext` into helpers like this is exactly what you want: - -```rust -fn write_command(output: &mut String, cmd: &Command) { - match cmd.arguments.mode { - ArgumentMode::SingleLine => write_single_line(output, cmd), - ArgumentMode::Continuation => write_continuation(output, cmd), - ArgumentMode::Fence => write_fence(output, cmd), - } -} -``` - -Having `write_command`, `write_single_line`, `write_continuation`, and `write_fence` in the same -file, plus a `#[cfg(test)] mod tests` at the bottom with fast, happy-path unit tests, is perfectly -aligned with your Rust testing doc: fast tests live in `cfg(test) mod tests` in the same file; -heavier property tests and integration tests move to `tests/` and fuzz harnesses live under `fuzz/`. - -That gives you: - -- Small, focused functions per concern. -- Colocated “fast” tests with direct positive/negative assertions. -- Property-based and fuzz tests elsewhere, as you prefer. - -## Folder and layer structure - -For the `parser` crate’s internal layout, mapping your JS boundaries to Rust: - -- **domain/**: pure types and invariants: command/text-block types, argument modes, maybe - lexer/token types later. No serde, no IO. This matches your “domain.rs pure, no serde” rule. -- **application/**: parsing state machine and formatting / printing (JSON and plaintext), since they - orchestrate domain types and build DTOs. This matches your “use cases / orchestration / ports” - bucket. -- **infrastructure/**: WASM bindings, FFI shims, logging/tracing glue. That’s the adapter layer. -- **tests/**: slower integration-style tests that exercise whole flows or multiple modules together. -- **proptest-regressions/** and **fuzz/**: stay as-is, under the parser crate instead of repo root. - -In Rust terms, you might land on something like: - -```text -parser/ - src/ - domain/ - mod.rs // re-exports - types.rs // Command, TextBlock, ArgumentMode, etc. - errors.rs // ParseError, domain-level errors - application/ - mod.rs - parse.rs // parse_to_domain, state machine - format_json.rs // JSON serialization boundary - format_text.rs // to_plaintext + helpers - infrastructure/ - mod.rs - wasm_js.rs // wasm-bindgen adapter - wasm_wasi.rs // WIT adapter later - lib.rs // pub use domain::*, application::parse_to_domain, etc. - tests/ - roundtrip.rs // slower multi-file/integration-ish tests - proptest-regressions/ - fuzz/ -``` - -This lines up with the Rust patterns doc: organize by feature, then by layer (`domain.rs`, `app.rs`, -`infra.rs`), promote to multiple files once a module grows, and keep domain free of serde. - -## Naming recommendations - -You’re right that `serialize.rs` vs `to_plaintext.rs` is asymmetric. I’d suggest: - -- `format_json.rs` (or `output_json.rs`): owns DTOs + `to_json`. -- `format_text.rs` (or `output_text.rs`): owns `to_plaintext` and helpers. - -Both live under `application/` since they are output-format concerns, not infrastructure (they don’t -talk to IO, just shape data). That also distances them from your infra error-mapping and transport -adapters in other projects. - -Within `application::format_text`, functions like: - -```rust -pub fn to_plaintext(result: &SlashParseResult) -> String { … } - -fn write_command(output: &mut String, cmd: &Command) { … } - -fn write_single_line(output: &mut String, cmd: &Command) { … } - -fn write_continuation(output: &mut String, cmd: &Command) { … } - -fn write_fence(output: &mut String, cmd: &Command) { … } - -#[cfg(test)] -mod tests { … } -``` - -fit your “free functions for domain logic, not methods” pattern. - -## Clean-arch fit and “is this bad practice?” - -Given your own rules: - -- Domain imports nothing external; DTOs and serde live outside domain. -- Application orchestrates domain, defines ports, but doesn’t know about transport details. -- Infrastructure implements ports and touches IO. - -Your proposed layout is consistent with that and is not “bad Rust practice.” Rust doesn’t require -flat `src/lib.rs` with everything; feature-and-layer submodules are common in more complex crates, -and your approach is in line with your Rust patterns doc’s “organize by feature, then by layer, -promote to workspace crates when it gets big.” - -One minor tweak: I’d keep `parser/` as the crate name rather than `parser-core` so it matches -ADR-0006 and avoids “application/parser.rs” repetition. That’s purely naming and you already plan to -rename. - -## Clarifying question - -For the textual formatting layer: do you want `to_plaintext` to be strictly “round-trip faithful” to -spec semantics only, or byte-for-byte identical to original input (including all whitespace), where -that’s possible? Your testing doc leans hard into roundtrip correctness, but exact byte preservation -may constrain how we model headers vs payloads. diff --git a/parser/moon.yml b/parser/moon.yml index 93a9f0c..3030249 100644 --- a/parser/moon.yml +++ b/parser/moon.yml @@ -3,6 +3,3 @@ id: "parser" language: "rust" tags: ["core"] -workspace: - inheritedTasks: - include: [] diff --git a/slash-go/moon.yml b/slash-go/moon.yml index 4980cfe..c6f67d2 100644 --- a/slash-go/moon.yml +++ b/slash-go/moon.yml @@ -1,4 +1,8 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "go" -type: "library" + tags: ["sdk"] + +workspace: + inheritedTasks: + include: [] diff --git a/slash-javascript/moon.yml b/slash-javascript/moon.yml index 75ba71a..f45535a 100644 --- a/slash-javascript/moon.yml +++ b/slash-javascript/moon.yml @@ -1,11 +1,7 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "typescript" -type: "library" tags: ["sdk", "npm"] -tasks: - publish: - command: "pnpm" - args: ["publish", "--access", "public", "--no-git-checks"] - options: - runInCI: false +workspace: + inheritedTasks: + include: [] diff --git a/slash-python/moon.yml b/slash-python/moon.yml index c58c0fc..bb5852b 100644 --- a/slash-python/moon.yml +++ b/slash-python/moon.yml @@ -1,11 +1,8 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "python" -type: "library" + tags: ["sdk"] -tasks: - publish: - command: "python" - args: ["-m", "twine", "upload", "dist/*"] - options: - runInCI: false +workspace: + inheritedTasks: + include: [] diff --git a/slash-rust/moon.yml b/slash-rust/moon.yml index eb08538..e624f24 100644 --- a/slash-rust/moon.yml +++ b/slash-rust/moon.yml @@ -1,11 +1,7 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "rust" -type: "library" tags: ["sdk"] -tasks: - publish: - command: "cargo" - args: ["publish", "--allow-dirty"] - options: - runInCI: false +workspace: + inheritedTasks: + include: [] diff --git a/slash-web/moon.yml b/slash-web/moon.yml index 75ba71a..42dcb32 100644 --- a/slash-web/moon.yml +++ b/slash-web/moon.yml @@ -1,11 +1,10 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "typescript" -type: "library" tags: ["sdk", "npm"] -tasks: - publish: - command: "pnpm" - args: ["publish", "--access", "public", "--no-git-checks"] - options: - runInCI: false + +workspace: + inheritedTasks: + include: [] + + diff --git a/wasm-javascript/moon.yml b/wasm-javascript/moon.yml index 3263f79..703a8e8 100644 --- a/wasm-javascript/moon.yml +++ b/wasm-javascript/moon.yml @@ -1,4 +1,3 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "rust" -type: "library" tags: ["wasm"] diff --git a/wasm-wasi/moon.yml b/wasm-wasi/moon.yml index 3263f79..703a8e8 100644 --- a/wasm-wasi/moon.yml +++ b/wasm-wasi/moon.yml @@ -1,4 +1,3 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "rust" -type: "library" tags: ["wasm"] diff --git a/website/moon.yml b/website/moon.yml index d2ebd6b..4706b6b 100644 --- a/website/moon.yml +++ b/website/moon.yml @@ -1,6 +1,5 @@ $schema: "https://moonrepo.dev/schemas/project.json" language: "typescript" -type: "application" tags: ["docs"] workspace: