-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Milestone 0 — project foundation and package skeleton (v0.1.0) #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
692062d
feat: Milestone 0 — project foundation and package skeleton (v0.1.0)
shaypal5 5173f92
fix: address Copilot review comments on Milestone 0 PR
shaypal5 9466687
chore: add AGENTS.md with rule to resolve PR review threads after com…
shaypal5 ac22ad5
fix: address Copilot review comments on PR #3 (round 2)
shaypal5 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| pull_request: | ||
|
|
||
| concurrency: | ||
| group: ci-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| lint: | ||
| name: Lint & format | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" | ||
| - run: pip install ruff | ||
| - run: ruff check . | ||
| - run: ruff format --check . | ||
|
|
||
| typecheck: | ||
| name: Type check | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" | ||
| - run: pip install -e ".[dev]" | ||
| - run: mypy leadforge/ | ||
|
|
||
| test: | ||
| name: Tests (Python ${{ matrix.python-version }}) | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| python-version: ["3.11", "3.12"] | ||
| env: | ||
| COVERAGE_FILE: .coverage.${{ matrix.python-version }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
| - run: pip install -e ".[dev]" pytest-cov | ||
| - run: pytest --cov=leadforge --cov-report=term-missing | ||
| - name: Upload coverage artifact | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: pr-agent-context-coverage-py${{ matrix.python-version }} | ||
| path: .coverage.${{ matrix.python-version }} | ||
| include-hidden-files: true | ||
| if-no-files-found: ignore |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| repos: | ||
| - repo: https://github.com/astral-sh/ruff-pre-commit | ||
| rev: v0.4.5 | ||
| hooks: | ||
| - id: ruff | ||
| args: [--fix] | ||
| - id: ruff-format | ||
| - repo: https://github.com/pre-commit/pre-commit-hooks | ||
| rev: v4.6.0 | ||
| hooks: | ||
| - id: trailing-whitespace | ||
| - id: end-of-file-fixer | ||
| - id: check-yaml | ||
| - id: check-toml | ||
| - id: check-merge-conflict |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # AGENTS.md — leadforge | ||
|
|
||
| Agent-specific conventions layered on top of CLAUDE.md. | ||
|
|
||
| --- | ||
|
|
||
| ## PR Review Comment Workflow | ||
|
|
||
| When addressing PR review comments (Copilot, human reviewers, or otherwise): | ||
|
|
||
| 1. Triage each comment — recommend one of: resolve as irrelevant, accept and implement, open a separate issue and resolve as out-of-scope, accept a different solution, or resolve as already treated. | ||
| 2. After the user confirms decisions, implement accepted changes and push **all changes in a single commit** to the PR branch. | ||
| 3. **After the commit lands, resolve the corresponding GitHub review threads** using the GraphQL API: | ||
|
|
||
| ```bash | ||
| gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "PRRT_..."}) { thread { isResolved } } }' | ||
| ``` | ||
|
|
||
| Resolve every addressed thread — whether the action was "implement", "already treated", or "irrelevant/out-of-scope". Unresolved threads indicate open work; resolved threads mean the discussion is closed. | ||
|
|
||
| Do **not** leave threads unresolved after the commit is pushed. | ||
|
|
||
| --- | ||
|
|
||
| ## Branch & PR Conventions | ||
|
|
||
| See CLAUDE.md for the full mandatory branch/PR workflow (branch → commit → update `.agent-plan.md` → open PR). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,74 @@ | ||
| # leadforge | ||
| # leadforge | ||
|
|
||
| **Opinionated framework for generating synthetic CRM and GTM datasets from simulated commercial worlds.** | ||
|
|
||
| `leadforge` generates narrative-grounded synthetic revenue datasets starting with lead scoring, designed to support teaching, portfolio projects, and research. Rather than sampling rows from a distribution, it simulates a commercial world — a specific company, selling a specific product, to a specific kind of buyer — and renders realistic CRM-style outputs from that world. | ||
|
|
||
| --- | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| pip install leadforge | ||
| ``` | ||
|
|
||
| For development: | ||
|
|
||
| ```bash | ||
| git clone https://github.com/leadforge-dev/leadforge.git | ||
| cd leadforge | ||
| pip install -e ".[dev]" | ||
| pre-commit install | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Quickstart | ||
|
|
||
| ```bash | ||
| # List available recipes | ||
| leadforge list-recipes | ||
|
|
||
| # Coming in v0.2.0: generate a dataset bundle | ||
| # leadforge generate \ | ||
| # --recipe b2b_saas_procurement_v1 \ | ||
| # --seed 42 \ | ||
| # --mode student_public \ | ||
| # --difficulty intermediate \ | ||
| # --n-leads 5000 \ | ||
| # --out ./out/demo_bundle | ||
|
|
||
| # Coming in v0.4.0: inspect a generated bundle | ||
| # leadforge inspect ./out/demo_bundle | ||
|
|
||
| # Coming in v0.5.0: validate a generated bundle | ||
| # leadforge validate ./out/demo_bundle | ||
| ``` | ||
|
|
||
| **Python API** (coming in v0.2.0): | ||
|
|
||
| ```python | ||
| from leadforge.api import Generator | ||
|
|
||
| gen = Generator.from_recipe( | ||
| "b2b_saas_procurement_v1", | ||
| seed=42, | ||
| exposure_mode="student_public", | ||
| ) | ||
| bundle = gen.generate(n_leads=5000, difficulty="intermediate") | ||
| bundle.save("./out/demo_bundle") | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Documentation | ||
|
|
||
| - [Design document](docs/leadforge_design_doc.md) | ||
| - [Architecture spec](docs/leadforge_architecture_spec.md) | ||
| - [Implementation plan](docs/leadforge_implementation_plan.md) | ||
|
|
||
| --- | ||
|
|
||
| ## License | ||
|
|
||
| MIT. See [LICENSE](LICENSE). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| """leadforge — synthetic CRM and GTM dataset generation.""" | ||
|
|
||
| from leadforge.version import __version__ | ||
|
|
||
| __all__ = ["__version__"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| """leadforge public Python API.""" | ||
|
|
||
| from leadforge.api.generator import Generator | ||
|
|
||
| __all__ = ["Generator"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| """Public Generator API — stub for Milestone 1. | ||
|
|
||
| The Generator class is the primary entry point for programmatic dataset | ||
| generation. It is fully specified in the architecture doc (§6) and will | ||
| be implemented across Milestones 1–9. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import Any | ||
|
|
||
| from leadforge.core.enums import DifficultyProfile, ExposureMode | ||
| from leadforge.core.models import GenerationConfig, WorldBundle | ||
|
|
||
|
|
||
| class Generator: | ||
| """High-level entry point for generating a synthetic CRM dataset bundle. | ||
|
|
||
| Usage (once implemented):: | ||
|
|
||
| gen = Generator.from_recipe( | ||
| "b2b_saas_procurement_v1", | ||
| seed=42, | ||
| exposure_mode="student_public", | ||
| ) | ||
| bundle = gen.generate(n_leads=5000, difficulty="intermediate") | ||
| bundle.save("./out/demo_bundle") | ||
|
|
||
| Implemented in Milestone 1 (config/recipe) through Milestone 9 (rendering). | ||
| """ | ||
|
|
||
| def __init__(self, config: GenerationConfig) -> None: | ||
| self._config = config | ||
|
|
||
| @classmethod | ||
| def from_recipe( | ||
| cls, | ||
| recipe_id: str, | ||
| *, | ||
| seed: int = 42, | ||
| exposure_mode: str | ExposureMode = ExposureMode.student_public, | ||
| **kwargs: Any, | ||
| ) -> Generator: | ||
| """Create a Generator from a recipe ID. | ||
|
|
||
| Not yet implemented — available in v0.2.0. | ||
| """ | ||
| raise NotImplementedError( | ||
| "Generator.from_recipe() is not yet implemented. Coming in v0.2.0." | ||
| ) | ||
|
|
||
| def generate( | ||
| self, | ||
| *, | ||
| n_accounts: int | None = None, | ||
| n_contacts: int | None = None, | ||
| n_leads: int | None = None, | ||
| difficulty: str | DifficultyProfile = DifficultyProfile.intermediate, | ||
| **kwargs: Any, | ||
| ) -> WorldBundle: | ||
| """Run the world simulation and return a bundle. | ||
|
|
||
| Not yet implemented — available in v0.2.0. | ||
| """ | ||
| raise NotImplementedError("Generator.generate() is not yet implemented. Coming in v0.2.0.") |
Empty file.
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| """leadforge generate command.""" | ||
|
|
||
| import typer | ||
|
|
||
|
|
||
| def generate( | ||
| recipe: str = typer.Option(..., "--recipe", "-r", help="Recipe ID to use."), | ||
| seed: int = typer.Option(..., "--seed", help="Random seed for deterministic generation."), | ||
| mode: str = typer.Option( | ||
| ..., | ||
| "--mode", | ||
| help="Exposure mode: student_public or research_instructor.", | ||
| ), | ||
| out: str = typer.Option(..., "--out", help="Output directory for the generated bundle."), | ||
| difficulty: str = typer.Option( | ||
| "intermediate", | ||
| "--difficulty", | ||
| help="Difficulty profile: intro, intermediate, or advanced.", | ||
| ), | ||
| n_accounts: int | None = typer.Option(None, "--n-accounts", help="Number of accounts."), | ||
| n_contacts: int | None = typer.Option(None, "--n-contacts", help="Number of contacts."), | ||
| n_leads: int | None = typer.Option(None, "--n-leads", help="Number of leads."), | ||
| horizon_days: int | None = typer.Option( | ||
| None, "--horizon-days", help="Simulation horizon in days." | ||
| ), | ||
| override: str | None = typer.Option( | ||
| None, "--override", help="Path to a YAML config override file." | ||
| ), | ||
| ) -> None: | ||
| """Generate a synthetic CRM dataset bundle from a recipe.""" | ||
| typer.echo( | ||
| "The 'generate' command is not yet implemented. Coming in v0.2.0.", | ||
| err=True, | ||
| ) | ||
| raise typer.Exit(1) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.