Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 76 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,89 @@ on:
branches: [main]

jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13.5"

- name: Install dependencies
run: uv sync --frozen --extra dev

- name: Check formatting
run: uv run scripts/format.py

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
run: uv python install 3.13.5
uses: actions/setup-python@v5
with:
python-version: "3.13.5"

- name: Install dependencies
run: uv sync --extra dev
run: uv sync --frozen --extra dev

- name: Lint with ruff
run: uv run ruff check src/
run: uv run scripts/lint.py

cpd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13.5"

- name: Install dependencies
run: uv sync --frozen --extra dev

- name: Check for duplicated code
run: uv run scripts/cpd.py --check

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13.5"

- name: Install dependencies
run: uv sync --frozen --extra dev

- name: Run ty
run: uv run scripts/typecheck.py

test:
runs-on: ubuntu-latest
Expand All @@ -31,12 +98,16 @@ jobs:

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
run: uv python install 3.13.5
uses: actions/setup-python@v5
with:
python-version: "3.13.5"

- name: Install dependencies
run: uv sync --extra dev
run: uv sync --frozen --extra dev

- name: Run tests
run: uv run pytest -v
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ Thumbs.db
*.tmp
*.temp
*.txt
.smoke-test/
.fast-agent/
.fast-agent-old/
skills/
61 changes: 61 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Agent guidance

## Code quality baseline

- Target Python `3.13`.
- Keep changes compatible with the repo's `pyproject.toml` settings.
- Prefer small, typed, composable functions over large command-style blocks.
- Avoid introducing new complexity suppressions unless there is a strong reason.

## Required local checks

Before finishing a change, run:

```bash
uv sync --extra dev
uv run scripts/format.py
uv run scripts/lint.py
uv run scripts/typecheck.py
uv run --extra dev pytest -v
```

CI enforces the same flow in `.github/workflows/ci.yml`.

## Ruff rules

Formatting and linting are enforced with Ruff.

- Line length: `100`
- Target version: `py313`
- Enabled lint families:
- `B` - bugbear
- `C90` - cyclomatic complexity
- `E` - pycodestyle errors
- `F` - pyflakes
- `I` - import sorting
- `RUF` - Ruff-specific rules
- `SIM` - simplifications
- `TCH` - type-checking import hygiene
- `UP` - pyupgrade
- `E501` is ignored; let `ruff format` own line wrapping.
- Cyclomatic complexity limit: `15`

## Type checking

- `ty` is required for `src`, `tests`, and `scripts`.
- Add or improve annotations when touching code that is ambiguous to the type checker.
- Prefer explicit protocols / typed helper structures over `object` when wiring dynamic APIs.
- Keep type-only imports behind `TYPE_CHECKING` when appropriate.

## Tests

- Add or update tests for behavior changes.
- Keep the test suite passing with `pytest`.
- Use focused unit-style tests for logic changes when possible.

## Practical authoring guidance

- Prefer refactoring over adding broad ignores.
- If a function is nearing the complexity limit, split it before adding more branches.
- Keep CLI orchestration, model resolution, and persistence logic separated when possible.
- When adding developer tooling, update the README and CI together.
91 changes: 91 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
SHELL := /usr/bin/env bash

# Common
ARTIFACT_REPO ?=
FLAVOR ?= cpu-basic
TIMEOUT ?= 45m
SECRETS ?= HF_TOKEN,OPENAI_API_KEY

# Fast-agent mode (lean)
SKILLS_DIR ?=
CARD_DIR ?=
FAST_AGENT ?=
FAST_MODEL ?= haiku
MESSAGE ?= Write a concise conventional commit message for: add password reset endpoint with tests.
PROMPT_FILE ?=
PROMPTS_JSONL ?=

.PHONY: \
format format-write lint typecheck test check \
hf-go-check hf-go-smoke hf-go-prompt hf-go-batch

format:
uv run --extra dev scripts/format.py

format-write:
uv run --extra dev scripts/format.py --write

lint:
uv run --extra dev scripts/lint.py

typecheck:
uv run --extra dev scripts/typecheck.py

test:
uv run --extra dev pytest -v

check: format lint typecheck test

hf-go-check:
@test -n "$(ARTIFACT_REPO)" || (echo "ARTIFACT_REPO is required" && exit 1)
@test -n "$(SKILLS_DIR)" || (echo "SKILLS_DIR is required" && exit 1)
@test -d "$(SKILLS_DIR)" || (echo "SKILLS_DIR not found: $(SKILLS_DIR)" && exit 1)
@test -x scripts/hf/submit_hf_job.sh || (echo "scripts/hf/submit_hf_job.sh missing or not executable" && exit 1)
@test -x scripts/hf/job_entrypoint_fast_agent.sh || (echo "scripts/hf/job_entrypoint_fast_agent.sh missing or not executable" && exit 1)
@hf auth whoami >/dev/null || (echo "hf auth required: run 'hf auth login'" && exit 1)

hf-go-smoke: hf-go-check
@cmd=(scripts/hf/submit_hf_job.sh \
--artifact-repo "$(ARTIFACT_REPO)" \
--skills-dir "$(SKILLS_DIR)" \
--model "$(FAST_MODEL)" \
--message "$(MESSAGE)" \
--flavor "$(FLAVOR)" \
--timeout "$(TIMEOUT)" \
--secrets "$(SECRETS)"); \
if [[ -n "$(CARD_DIR)" ]]; then cmd+=(--card-dir "$(CARD_DIR)"); fi; \
if [[ -n "$(FAST_AGENT)" ]]; then cmd+=(--agent "$(FAST_AGENT)"); fi; \
echo "Running: $${cmd[*]}"; \
"$${cmd[@]}"

hf-go-prompt: hf-go-check
@test -n "$(PROMPT_FILE)" || (echo "PROMPT_FILE is required" && exit 1)
@test -f "$(PROMPT_FILE)" || (echo "PROMPT_FILE not found: $(PROMPT_FILE)" && exit 1)
@cmd=(scripts/hf/submit_hf_job.sh \
--artifact-repo "$(ARTIFACT_REPO)" \
--skills-dir "$(SKILLS_DIR)" \
--model "$(FAST_MODEL)" \
--prompt-file "$(PROMPT_FILE)" \
--flavor "$(FLAVOR)" \
--timeout "$(TIMEOUT)" \
--secrets "$(SECRETS)"); \
if [[ -n "$(CARD_DIR)" ]]; then cmd+=(--card-dir "$(CARD_DIR)"); fi; \
if [[ -n "$(FAST_AGENT)" ]]; then cmd+=(--agent "$(FAST_AGENT)"); fi; \
echo "Running: $${cmd[*]}"; \
"$${cmd[@]}"

hf-go-batch: hf-go-check
@test -n "$(PROMPTS_JSONL)" || (echo "PROMPTS_JSONL is required" && exit 1)
@test -f "$(PROMPTS_JSONL)" || (echo "PROMPTS_JSONL not found: $(PROMPTS_JSONL)" && exit 1)
@cmd=(scripts/hf/submit_hf_job.sh \
--artifact-repo "$(ARTIFACT_REPO)" \
--skills-dir "$(SKILLS_DIR)" \
--model "$(FAST_MODEL)" \
--prompts-jsonl "$(PROMPTS_JSONL)" \
--flavor "$(FLAVOR)" \
--timeout "$(TIMEOUT)" \
--secrets "$(SECRETS)"); \
if [[ -n "$(CARD_DIR)" ]]; then cmd+=(--card-dir "$(CARD_DIR)"); fi; \
if [[ -n "$(FAST_AGENT)" ]]; then cmd+=(--agent "$(FAST_AGENT)"); fi; \
echo "Running: $${cmd[*]}"; \
"$${cmd[@]}"
Loading
Loading