diff --git a/.flox/env/manifest.lock b/.flox/env/manifest.lock index 34cccd1c..ae587cde 100644 --- a/.flox/env/manifest.lock +++ b/.flox/env/manifest.lock @@ -65,6 +65,9 @@ "x86_64-darwin" ] }, + "markdownlint-cli": { + "pkg-path": "markdownlint-cli" + }, "mask": { "pkg-path": "mask" }, @@ -2294,6 +2297,8 @@ "unfree": false, "version": "109.100.2", "outputs_to_install": [ + "out", + "out", "out", "out", "out", @@ -2338,6 +2343,122 @@ "group": "toplevel", "priority": 5 }, + { + "attr_path": "markdownlint-cli", + "broken": false, + "derivation": "/nix/store/ska63kj9k8fzi9kf94g75yc0yssmg9vz-markdownlint-cli-0.46.0.drv", + "description": "Command line interface for MarkdownLint", + "install_id": "markdownlint-cli", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=f61125a668a320878494449750330ca58b78c557", + "name": "markdownlint-cli-0.46.0", + "pname": "markdownlint-cli", + "rev": "f61125a668a320878494449750330ca58b78c557", + "rev_count": 907002, + "rev_date": "2025-12-05T15:54:32Z", + "scrape_date": "2025-12-07T02:55:06.356081Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.46.0", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/8b3n1jrqvyfwgsxpshs7kd6krnlrfmay-markdownlint-cli-0.46.0" + }, + "system": "aarch64-darwin", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "markdownlint-cli", + "broken": false, + "derivation": "/nix/store/9rgnxv2s3g3ai56rj0j78fl8najk6p1p-markdownlint-cli-0.46.0.drv", + "description": "Command line interface for MarkdownLint", + "install_id": "markdownlint-cli", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=f61125a668a320878494449750330ca58b78c557", + "name": "markdownlint-cli-0.46.0", + "pname": "markdownlint-cli", + "rev": "f61125a668a320878494449750330ca58b78c557", + "rev_count": 907002, + "rev_date": "2025-12-05T15:54:32Z", + "scrape_date": "2025-12-07T03:04:56.530102Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.46.0", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/4hgvqd0ciamhhvjksg7f431x1y6w2760-markdownlint-cli-0.46.0" + }, + "system": "aarch64-linux", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "markdownlint-cli", + "broken": false, + "derivation": "/nix/store/mag3vdw3bwyazxj80hryc1g27gaagfby-markdownlint-cli-0.46.0.drv", + "description": "Command line interface for MarkdownLint", + "install_id": "markdownlint-cli", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=f61125a668a320878494449750330ca58b78c557", + "name": "markdownlint-cli-0.46.0", + "pname": "markdownlint-cli", + "rev": "f61125a668a320878494449750330ca58b78c557", + "rev_count": 907002, + "rev_date": "2025-12-05T15:54:32Z", + "scrape_date": "2025-12-07T03:15:04.594270Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.46.0", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/h6dcndmvjrj3ycjlb7bnmx0m1vys5gmx-markdownlint-cli-0.46.0" + }, + "system": "x86_64-darwin", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "markdownlint-cli", + "broken": false, + "derivation": "/nix/store/wgpr1l9ldw7rna2ak4h9libr0fhkq51w-markdownlint-cli-0.46.0.drv", + "description": "Command line interface for MarkdownLint", + "install_id": "markdownlint-cli", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=f61125a668a320878494449750330ca58b78c557", + "name": "markdownlint-cli-0.46.0", + "pname": "markdownlint-cli", + "rev": "f61125a668a320878494449750330ca58b78c557", + "rev_count": 907002, + "rev_date": "2025-12-05T15:54:32Z", + "scrape_date": "2025-12-07T03:24:33.373035Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.46.0", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/3rl4jg227zfb9k67q107z6wjxpzx1n67-markdownlint-cli-0.46.0" + }, + "system": "x86_64-linux", + "group": "toplevel", + "priority": 5 + }, { "attr_path": "mask", "broken": false, @@ -3551,4 +3672,4 @@ "priority": 5 } ] -} +} \ No newline at end of file diff --git a/.flox/env/manifest.toml b/.flox/env/manifest.toml index 42a26c33..4add0d63 100644 --- a/.flox/env/manifest.toml +++ b/.flox/env/manifest.toml @@ -41,6 +41,7 @@ openssl.pkg-path = "openssl" pkgconf.pkg-path = "pkgconf" direnv.pkg-path = "direnv" jq.pkg-path = "jq" +markdownlint-cli.pkg-path = "markdownlint-cli" [hook] on-activate = ''' diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/config.yaml rename to .github/ISSUE_TEMPLATE/config.yml diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 00000000..a0e9ea32 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,20 @@ +# Markdownlint configuration +# See https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md + +# MD013 - Line length +MD013: + line_length: 120 + code_blocks: false + tables: false +# MD024 - Multiple headings with same content +MD024: + siblings_only: true +# MD033 - Inline HTML +MD033: + allowed_elements: + - br + - details + - summary + - promise +# MD041 - First line in file should be top-level heading +MD041: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 64efc7ea..828121a9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,3 +20,12 @@ repos: - rust language: system fail_fast: true + - id: markdown + name: Check all Markdown code + entry: mask development markdown all + pass_filenames: false + types: + - file + - markdown + language: system + fail_fast: true diff --git a/CLAUDE.md b/CLAUDE.md index 08aaf184..f0dff932 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ -# claude +# claude > Agentic tooling context @@ -24,11 +24,13 @@ - Introduce new dependencies only after approval - Include type hints on all Python function parameters and return types - Rust servers primarily use [Axum](https://docs.rs/axum/latest/axum/) -- Use Polars for [Python](https://docs.pola.rs/api/python/stable/reference/index.html) and [Rust](https://docs.rs/polars/latest/polars/) dataframes +- Use Polars for [Python](https://docs.pola.rs/api/python/stable/reference/index.html) and + [Rust](https://docs.rs/polars/latest/polars/) dataframes - Use `typing` module `cast` function for `tinygrad` method outputs when necessary with union types - Write `pytest` functions for Python tests - Ensure Rust and Python automated test suites achieve at least 90% line or statement coverage per service or library -- Exclude generated code, third‑party code, tooling boilerplate, and anything explicitly excluded in this repository from test coverage calculations +- Exclude generated code, third-party code, tooling boilerplate, and anything explicitly excluded in this repository + from test coverage calculations - Check that DataFrame definitions in both Python and Rust match expected schemas defined in `pandera` resources - When adding `ValueError` exceptions, create a separate variable called `message` to hold the error string before raising - When logging after an exception, use `logger.exception()` to capture stack trace with the `structlog` package @@ -55,11 +57,12 @@ Ralph is an autonomous development loop for implementing GitHub issue specs. - `mask ralph ready ` - Mark a spec as ready for implementation - `mask ralph loop ` - Run autonomous loop on a ready spec - `mask ralph backlog` - Review open issues for duplicates, overlaps, and implementation status -- `mask ralph pr [--pr ]` - Process PR review feedback interactively +- `mask ralph pull-request [pull_request_number]` - Process pull request review feedback interactively ### Labels **Status labels:** + - `in-refinement` - Spec being built or discussed - `ready` - Spec complete, ready for implementation - `in-progress` - Work actively in progress @@ -67,6 +70,7 @@ Ralph is an autonomous development loop for implementing GitHub issue specs. - `backlog-review` - Backlog review tracking issue **Actor label:** + - `ralph` - Ralph is actively working on this (remove to hand off to human) ### Workflow @@ -74,9 +78,9 @@ Ralph is an autonomous development loop for implementing GitHub issue specs. 1. Create or refine spec: `mask ralph spec` or `mask ralph spec ` 2. When spec is complete, mark as ready: `mask ralph ready ` 3. Run autonomous loop: `mask ralph loop ` -4. Loop assigns the issue and resulting PR to the current GitHub user -5. Loop creates PR with `Closes #` on completion -6. PR merge auto-closes issue +4. Loop assigns the issue and resulting pull request to the current GitHub user +5. Loop creates pull request with `Closes #` on completion +6. Pull request merge auto-closes issue ### Context Rotation @@ -90,14 +94,17 @@ Output `COMPLETE` when all requirement checkboxes are checked ### Commit as Verification -After implementing requirements, ALWAYS attempt `git commit`. The commit triggers pre-commit hooks which run all tests/linting. This IS the verification step: +After implementing requirements, ALWAYS attempt `git commit`. The commit triggers pre-commit hooks which +run all tests/linting. This IS the verification step: + - If commit fails → fix issues and retry - If commit succeeds → requirement is verified, check it off in issue - Do not skip this step or run tests separately ### Ralph Learnings -Document failure patterns here after Ralph loops to prevent recurrence. Periodically compact this section by merging similar learnings and removing entries that have been incorporated into the workflow or specs above. +Document failure patterns here after Ralph loops to prevent recurrence. Periodically compact this section +by merging similar learnings and removing entries that have been incorporated into the workflow or specs above. #### 2026-01-26: #723 (spec: commit-as-verification not explicit) diff --git a/README.md b/README.md index d29a814e..abd5f544 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# fund +# fund > The open source capital management company + [![Python code checks](https://github.com/oscmcompany/fund/actions/workflows/run_python_code_checks.yaml/badge.svg)](https://github.com/oscmcompany/fund/actions/workflows/run_python_code_checks.yaml) [![Rust code checks](https://github.com/oscmcompany/fund/actions/workflows/run_rust_code_checks.yaml/badge.svg)](https://github.com/oscmcompany/fund/actions/workflows/run_rust_code_checks.yaml) ## About @@ -42,4 +43,5 @@ An unordered and non-exhaustive list we work towards: ### Links -Check out [our tasks](https://github.com/orgs/oscmcompany/projects/1) to see what we're working on or ping [either](https://x.com/forstmeier) of [us](https://x.com/hyperpriorai) for anything else. +Check out [our tasks](https://github.com/orgs/oscmcompany/projects/1) to see what we're working on or +ping [either](https://x.com/forstmeier) of [us](https://x.com/hyperpriorai) for anything else. diff --git a/maskfile.md b/maskfile.md index a4cd03d5..25a025d8 100644 --- a/maskfile.md +++ b/maskfile.md @@ -22,7 +22,7 @@ if [[ ${#missing_deps[@]} -gt 0 ]]; then for dep in "${missing_deps[@]}"; do case $dep in "Docker") - echo " - Docker: https://docs.docker.com/get-docker/" + echo "- Docker: https://docs.docker.com/get-docker/" ;; esac done @@ -512,6 +512,38 @@ mask development python test echo "Python development checks completed successfully" ``` +### markdown + +> Markdown development workflow commands + +#### lint + +> Run Markdown lint checks + +```bash +set -euo pipefail + +echo "Running Markdown lint checks" + +markdownlint "**/*.md" --ignore ".flox" --ignore ".venv" --ignore "target" + +echo "Markdown linting completed successfully" +``` + +#### all + +> Full Markdown development checks + +```bash +set -euo pipefail + +echo "Running Markdown development checks" + +mask development markdown lint + +echo "Markdown development checks completed successfully" +``` + ## data > Data management commands @@ -622,9 +654,9 @@ case "$preset" in echo "Unknown preset: $preset" echo "" echo "Available presets:" - echo " testing - ml.t3.xlarge (CPU, ~\$0.23/hr)" - echo " standard - ml.g5.xlarge (GPU, ~\$1.41/hr) [default]" - echo " performance - ml.p3.2xlarge (GPU, ~\$3.82/hr)" + echo "testing - ml.t3.xlarge (CPU, ~\$0.23/hr)" + echo "standard - ml.g5.xlarge (GPU, ~\$1.41/hr) [default]" + echo "performance - ml.p3.2xlarge (GPU, ~\$3.82/hr)" echo "" echo "Or specify a custom instance type: ml.g4dn.xlarge" exit 1 @@ -710,11 +742,11 @@ CW_PKG="awslabs.cloudwatch-mcp-server@latest" echo "Detecting uvx executable for ECS package: $ECS_PKG" ECS_EXE="$(detect_uvx_exe "$ECS_PKG")" -echo " -> ECS executable: $ECS_EXE" +echo "-> ECS executable: $ECS_EXE" echo "Detecting uvx executable for CloudWatch package: $CW_PKG" CW_EXE="$(detect_uvx_exe "$CW_PKG")" -echo " -> CloudWatch executable: $CW_EXE" +echo "-> CloudWatch executable: $CW_EXE" echo "Adding ECS MCP server..." claude mcp add awslabs-ecs-mcp-server -s project \ @@ -746,13 +778,13 @@ claude mcp list ```bash set -euo pipefail -source "${MASKFILE_DIR}/tools/ralph-preflight.sh" +source "${MASKFILE_DIR}/tools/ralph_preflight.sh" ralph_preflight echo "Setting up Ralph labels" labels='[ - {"name": "ralph", "color": "6f42c1", "description": "Ralph is actively working on this"}, + {"name": "ralph", "color": "5319e7", "description": "Ralph is actively working on this"}, {"name": "in-refinement", "color": "d93f0b", "description": "Spec being built or discussed"}, {"name": "ready", "color": "0e8a16", "description": "Spec complete, ready for implementation"}, {"name": "in-progress", "color": "fbca04", "description": "Work actively in progress"}, @@ -768,10 +800,10 @@ echo "$labels" | jq -c '.[]' | while read -r label; do desc=$(echo "$label" | jq -r '.description') if echo "$existing" | grep -qx "$name"; then - echo " Label '$name' already exists" + echo "Label '$name' already exists" else gh label create "$name" --color "$color" --description "$desc" - echo " Created label '$name'" + echo "Created label '$name'" fi done @@ -785,7 +817,7 @@ echo "Setup complete" ```bash set -euo pipefail -source "${MASKFILE_DIR}/tools/ralph-preflight.sh" +source "${MASKFILE_DIR}/tools/ralph_preflight.sh" ralph_preflight --claude --jq echo "Starting Ralph spec refinement" @@ -839,7 +871,7 @@ claude --system-prompt "$system_prompt" echo "" echo "Spec refinement session ended" echo "When ready, mark the spec as ready:" -echo " mask ralph ready ${issue_number}" +echo "mask ralph ready ${issue_number}" ``` ### ready (issue_number) @@ -849,7 +881,7 @@ echo " mask ralph ready ${issue_number}" ```bash set -euo pipefail -source "${MASKFILE_DIR}/tools/ralph-preflight.sh" +source "${MASKFILE_DIR}/tools/ralph_preflight.sh" ralph_preflight echo "Marking issue #${issue_number} as ready" @@ -872,7 +904,7 @@ echo "Run the loop with: mask ralph loop ${issue_number}" ```bash set -euo pipefail -source "${MASKFILE_DIR}/tools/ralph-preflight.sh" +source "${MASKFILE_DIR}/tools/ralph_preflight.sh" ralph_preflight --claude --jq max_iterations="${RALPH_MAX_ITERATIONS:-10}" @@ -886,7 +918,7 @@ if [ -n "$(git status --porcelain)" ]; then echo "Commit or stash changes before running ralph loop" exit 1 fi -echo " Working directory is clean" +echo "Working directory is clean" default_branch=$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5) current_branch=$(git rev-parse --abbrev-ref HEAD) @@ -895,15 +927,15 @@ if [ "$current_branch" != "$default_branch" ]; then echo "Run: git checkout ${default_branch}" exit 1 fi -echo " On default branch (${default_branch})" +echo "On default branch (${default_branch})" -echo " Pulling latest ${default_branch}" +echo "Pulling latest ${default_branch}" if ! git pull --ff-only origin "$default_branch"; then echo "Error: Could not pull latest ${default_branch}" echo "Resolve conflicts or check network/auth" exit 1 fi -echo " ${default_branch} is up to date" +echo "${default_branch} is up to date" if ! labels=$(gh issue view "${issue_number}" --json labels --jq '.labels[].name'); then echo "Error: Could not fetch issue #${issue_number}" @@ -915,7 +947,7 @@ if ! echo "$labels" | grep -q "^ready$"; then echo "Current labels: ${labels:-none}" exit 1 fi -echo " Issue has 'ready' label" +echo "Issue has 'ready' label" issue_title=$(gh issue view "${issue_number}" --json title --jq '.title') short_desc=$(echo "$issue_title" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-' | cut -c1-30) @@ -932,7 +964,7 @@ if git ls-remote --heads origin "${branch_name}" 2>/dev/null | grep -q .; then echo "Delete with: git push origin --delete ${branch_name}" exit 1 fi -echo " Branch '${branch_name}' does not exist" +echo "Branch '${branch_name}' does not exist" echo "Pre-flight checks passed" @@ -991,7 +1023,7 @@ WORKFLOW: COMPLETION: - When ALL requirement checkboxes are checked, output COMPLETE -- This signals the loop is done and triggers PR creation +- This signals the loop is done and triggers pull request creation CONTEXT ROTATION: - Complete logically related requirements together (same files, same concepts) @@ -1173,7 +1205,7 @@ exit 1 ```bash set -euo pipefail -source "${MASKFILE_DIR}/tools/ralph-preflight.sh" +source "${MASKFILE_DIR}/tools/ralph_preflight.sh" ralph_preflight --claude --jq echo "Starting Ralph backlog review" @@ -1274,37 +1306,30 @@ echo "Backlog review complete" echo "Report posted to: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/issues/${existing_issue}" ``` -### pull-request - -> Process PR review feedback interactively - -**OPTIONS** +### pull-request [pull_request_number] -* pr_number - * flags: --pr - * type: string - * desc: PR number (auto-detects from branch if not provided) +> Process pull request review feedback interactively ```bash set -euo pipefail -source "${MASKFILE_DIR}/tools/ralph-preflight.sh" +source "${MASKFILE_DIR}/tools/ralph_preflight.sh" ralph_preflight --claude --jq -echo "Starting Ralph PR review" +echo "Starting Ralph pull request review" -if [ -n "${pr_number:-}" ]; then - pr_num="$pr_number" - echo "Using PR #${pr_num}" +if [ -n "${pull_request_number:-}" ]; then + pr_num="$pull_request_number" + echo "Using pull request #${pr_num}" else - echo "Auto-detecting PR from current branch" + echo "Auto-detecting pull request from current branch" pr_num=$(gh pr view --json number --jq '.number' 2>/dev/null || echo "") if [ -z "$pr_num" ]; then - echo "Error: No PR found for current branch" - echo "Use --pr to specify a PR" + echo "Error: No pull request found for current branch" + echo "Use: mask ralph pull-request " exit 1 fi - echo "Found PR #${pr_num}" + echo "Found pull request #${pr_num}" fi repo_info=$(gh repo view --json nameWithOwner --jq '.nameWithOwner') @@ -1466,7 +1491,7 @@ echo "Starting execution phase" plan_json=$(cat "$plan_file") -system_prompt="You are implementing approved PR review suggestions. +system_prompt="You are implementing approved pull request review suggestions. TASK: For each suggestion in the plan, implement the requested change. @@ -1535,6 +1560,6 @@ echo "$results_json" | jq -c '.[]' | while read -r item; do done echo "" -echo "PR review complete" -echo "View PR: https://github.com/${repo_info}/pull/${pr_num}" +echo "Pull request review complete" +echo "View pull request: https://github.com/${repo_info}/pull/${pr_num}" ``` diff --git a/tools/ralph-preflight.sh b/tools/ralph_preflight.sh old mode 100644 new mode 100755 similarity index 100% rename from tools/ralph-preflight.sh rename to tools/ralph_preflight.sh