diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..2211890 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,79 @@ +name: Bug Report +description: Report a bug in JuntoAI A2A +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Please fill out the fields below so we can reproduce and fix the issue. + + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + placeholder: Tell us what happened... + validations: + required: true + + - type: textarea + id: steps-to-reproduce + attributes: + label: Steps to reproduce + description: Step-by-step instructions to reproduce the behavior. + placeholder: | + 1. Go to '...' + 2. Click on '...' + 3. Scroll down to '...' + 4. See error + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: What did you expect to happen? + placeholder: Describe what should have happened... + validations: + required: true + + - type: textarea + id: actual-behavior + attributes: + label: Actual behavior + description: What actually happened instead? + placeholder: Describe what actually happened... + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating System + description: Which OS are you running on? + options: + - macOS + - Windows + - Linux + validations: + required: true + + - type: textarea + id: docker-version + attributes: + label: Docker version + description: "Run `docker --version` and `docker compose version` and paste the output." + placeholder: "Docker version 24.0.7, Docker Compose v2.24.0" + validations: + required: true + + - type: textarea + id: llm-provider + attributes: + label: LLM provider + description: Which LLM provider are you using? (e.g., OpenAI, Anthropic, Ollama, Vertex AI) + placeholder: "e.g., OpenAI with gpt-4o" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..29b8739 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Community Chat (WhatsApp) + url: https://chat.whatsapp.com/CZblOXj7aV3LMSKCwSUxWR + about: Ask questions and coordinate with other contributors in our WhatsApp community. diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..2574f65 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,36 @@ +name: Feature Request +description: Suggest a new feature for JuntoAI A2A +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! Please fill out the fields below so we can understand your idea and evaluate it. + + - type: textarea + id: description + attributes: + label: Describe the feature + description: A clear and concise description of the feature you'd like to see. + placeholder: Tell us about the feature... + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Problem it solves + description: What problem does this feature solve? Why is it needed? + placeholder: Describe the problem or pain point this feature addresses... + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Proposed solution + description: How should this feature work? Describe your ideal implementation. + placeholder: Describe how you think this feature should work... + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..1565bd2 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,22 @@ +## Description + + + +## Related Issues + + + +## Type of Change + +- [ ] Bug fix +- [ ] Feature +- [ ] Scenario config +- [ ] Documentation +- [ ] Other (describe below) + +## Checklist + +- [ ] Tests pass locally (`cd backend && pytest --cov=app --cov-fail-under=70` and `cd frontend && npx vitest run --coverage`) +- [ ] Coverage meets the 70% threshold +- [ ] Code follows existing patterns and conventions +- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md) diff --git a/.github/workflows/pr-tests.yml b/.github/workflows/pr-tests.yml new file mode 100644 index 0000000..ef1ca8e --- /dev/null +++ b/.github/workflows/pr-tests.yml @@ -0,0 +1,43 @@ +name: PR Tests + +on: + pull_request: + branches: [main] + types: [opened, synchronize, reopened] + +jobs: + backend-tests: + name: Backend Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: pip install -r requirements.txt + working-directory: backend + + - name: Run tests with coverage + run: pytest --cov=app --cov-fail-under=70 + working-directory: backend + + frontend-tests: + name: Frontend Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: npm ci + working-directory: frontend + + - name: Run tests with coverage + run: npx vitest run --coverage + working-directory: frontend diff --git a/.kiro/specs/160_developer-community/tasks.md b/.kiro/specs/160_developer-community/tasks.md index 810cfbe..437b328 100644 --- a/.kiro/specs/160_developer-community/tasks.md +++ b/.kiro/specs/160_developer-community/tasks.md @@ -6,15 +6,15 @@ Create the static files (markdown, YAML) that transform the JuntoAI A2A repo int ## Tasks -- [ ] 1. Create CODE_OF_CONDUCT.md +- [x] 1. Create CODE_OF_CONDUCT.md - Create `CODE_OF_CONDUCT.md` at the monorepo root based on Contributor Covenant v2.1 - Include the full standard text: Pledge, Standards, Responsibilities, Scope, Enforcement, Attribution - Set enforcement contact to placeholder `conduct@juntoai.org` with a TODO comment to replace - Define scope as all community spaces: GitHub issues, PRs, discussions, and WhatsApp community channel - _Requirements: 3.1, 3.2, 3.3, 3.4_ -- [ ] 2. Create CONTRIBUTING.md - - [ ] 2.1 Create CONTRIBUTING.md with welcome, workflow, and setup sections +- [x] 2. Create CONTRIBUTING.md + - [x] 2.1 Create CONTRIBUTING.md with welcome, workflow, and setup sections - Create `CONTRIBUTING.md` at the monorepo root - Welcome section linking to Code of Conduct - Fork-and-PR workflow: fork, clone, create `feature/*` branch from `main`, push to fork, open PR to `upstream/main` @@ -22,7 +22,7 @@ Create the static files (markdown, YAML) that transform the JuntoAI A2A repo int - Exact test commands: `cd backend && pytest --cov=app --cov-fail-under=70` and `cd frontend && npx vitest run --coverage` - _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.9_ - - [ ] 2.2 Add contribution types, labels, branch protection, and community sections + - [x] 2.2 Add contribution types, labels, branch protection, and community sections - Types of contributions: scenario configs (JSON-only), bug fixes, feature proposals, documentation, agent strategies - Scenario contribution workflow: drop JSON in `backend/app/scenarios/data/`, no code changes - PR process: CI pipeline must pass, 70% coverage enforced @@ -31,7 +31,7 @@ Create the static files (markdown, YAML) that transform the JuntoAI A2A repo int - Community section: WhatsApp link (placeholder URL), Code of Conduct link - _Requirements: 2.5, 2.6, 2.7, 2.8, 2.9, 6.1, 6.2, 6.3, 8.2, 9.1, 9.2, 9.3_ -- [ ] 3. Create GitHub Actions PR CI pipeline +- [x] 3. Create GitHub Actions PR CI pipeline - Create `.github/workflows/pr-tests.yml` - Trigger on `pull_request` events (opened, synchronize, reopened) targeting `main` - Define two parallel jobs (no `needs` dependency): `backend-tests` and `frontend-tests` @@ -40,29 +40,29 @@ Create the static files (markdown, YAML) that transform the JuntoAI A2A repo int - No path filtering — all PRs trigger all jobs (Requirement 1.10) - _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10_ -- [ ] 4. Checkpoint — Verify CI pipeline and docs +- [x] 4. Checkpoint — Verify CI pipeline and docs - Ensure all files created so far are valid YAML/markdown - Verify cross-references: CONTRIBUTING.md links to CODE_OF_CONDUCT.md, CONTRIBUTING.md links to WhatsApp placeholder - Ask the user if questions arise -- [ ] 5. Create GitHub issue templates - - [ ] 5.1 Create bug report issue template +- [x] 5. Create GitHub issue templates + - [x] 5.1 Create bug report issue template - Create `.github/ISSUE_TEMPLATE/bug-report.yml` using GitHub issue forms YAML format - Required fields: description (textarea), steps to reproduce (textarea), expected behavior (textarea), actual behavior (textarea), environment info (OS dropdown + Docker version + LLM provider as textarea) - _Requirements: 4.1, 4.2_ - - [ ] 5.2 Create feature request issue template + - [x] 5.2 Create feature request issue template - Create `.github/ISSUE_TEMPLATE/feature-request.yml` using GitHub issue forms YAML format - Required fields: description (textarea), problem it solves (textarea), proposed solution (textarea) - _Requirements: 4.3, 4.4_ - - [ ] 5.3 Create issue template config + - [x] 5.3 Create issue template config - Create `.github/ISSUE_TEMPLATE/config.yml` - Set `blank_issues_enabled: false` - Add contact link to WhatsApp community channel (placeholder URL) as alternative contact option - _Requirements: 4.5, 8.3_ -- [ ] 6. Create pull request template +- [x] 6. Create pull request template - Create `.github/PULL_REQUEST_TEMPLATE.md` - Description section for changes made - Related issues section (Closes #XX / Relates to #XX) @@ -70,7 +70,7 @@ Create the static files (markdown, YAML) that transform the JuntoAI A2A repo int - Checklist: tests pass locally, coverage meets 70%, code follows existing patterns, contributor has read CONTRIBUTING.md - _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5_ -- [ ] 7. Update README.md community section +- [x] 7. Update README.md community section - Replace the existing `## 🤝 Contributing` section in `README.md` - Link to `CONTRIBUTING.md` as primary call to action - Link to `CODE_OF_CONDUCT.md` @@ -80,7 +80,7 @@ Create the static files (markdown, YAML) that transform the JuntoAI A2A repo int - Retain existing contribution types: scenario configs, bug reports, feature proposals, documentation, agent strategies - _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 6.4, 8.1, 8.4_ -- [ ] 8. Final checkpoint — Cross-reference validation +- [x] 8. Final checkpoint — Cross-reference validation - Verify all cross-references between documents are correct and use relative links - Verify WhatsApp placeholder URL appears in: README.md, CONTRIBUTING.md, `.github/ISSUE_TEMPLATE/config.yml` - Ensure all files created so far are valid diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..27f2ecd --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,140 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, including but not +limited to: + +* GitHub issues, pull requests, and discussions +* The JuntoAI WhatsApp community channel +* Any other spaces where community members represent or participate in the + project + +It also applies when an individual is officially representing the community in +public spaces. Examples of representing our community include using an official +e-mail address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +**support@juntoai.org**. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d2d7dba --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,131 @@ +# Contributing to JuntoAI A2A + +Welcome, and thanks for your interest in contributing to JuntoAI A2A! Whether you're fixing a bug, proposing a feature, adding a new negotiation scenario, or improving docs — we're glad you're here. + +All contributors are expected to follow our [Code of Conduct](./CODE_OF_CONDUCT.md). Please read it before participating. + +## Getting Started — Fork & PR Workflow + +We use a standard fork-and-PR workflow: + +1. **Fork** this repository on GitHub. +2. **Clone** your fork locally: + ```bash + git clone https://github.com//a2a.git + cd a2a + ``` +3. **Add the upstream remote**: + ```bash + git remote add upstream https://github.com/JuntoAI/a2a.git + ``` +4. **Create a feature branch** from `main`: + ```bash + git checkout -b feature/your-feature-name main + ``` +5. **Make your changes**, commit with clear messages. +6. **Push** to your fork: + ```bash + git push origin feature/your-feature-name + ``` +7. **Open a Pull Request** from your fork's branch to `upstream/main`. + +## Local Development Setup + +### Prerequisites + +| Tool | Version | +| ----------------- | ------------- | +| Docker | Latest stable | +| Docker Compose | v2.24+ | +| Python | 3.11 | +| Node.js | 20 | + +### Running the Full Stack + +Start all services with Docker Compose: + +```bash +docker compose up +``` + +This spins up the backend, frontend, and any supporting services. See the project README for environment variable configuration. + +### Running Tests Independently + +Backend and frontend test suites can be run independently outside of Docker. + +## Running Tests + +All pull requests must pass the GitHub Actions CI pipeline before merge. The pipeline enforces a minimum 70% code coverage threshold on both backend and frontend. + +### Backend Tests + +```bash +cd backend && pytest --cov=app --cov-fail-under=70 +``` + +This runs the full pytest suite with coverage reporting. The `--cov-fail-under=70` flag ensures the build fails if coverage drops below 70%. + +### Frontend Tests + +```bash +cd frontend && npx vitest run --coverage +``` + +This runs the Vitest suite with coverage. The 70% coverage threshold is enforced in the CI pipeline. + +> **Note:** Make sure both test suites pass locally before opening a PR. The CI pipeline runs these exact commands and will block merge on failure. + +## Types of Contributions + +We welcome several types of contributions: + +- **Scenario Configs** — JSON-only negotiation scenarios (no code changes required) +- **Bug Fixes** — Fixing issues in the backend, frontend, or infrastructure +- **Feature Proposals** — New capabilities or improvements (open an issue first to discuss) +- **Documentation** — README updates, guide improvements, inline code docs +- **Agent Strategies** — New agent behaviors and negotiation tactics + +## Scenario Contributions + +Adding a new negotiation scenario is the easiest way to contribute — no code changes needed. + +1. Create a new JSON file following the existing scenario format in `backend/app/scenarios/data/`. +2. Drop your file into `backend/app/scenarios/data/`. +3. The scenario engine picks it up automatically at runtime. + +That's it. Look at the existing `.scenario.json` files in that directory for the expected structure. + +## Pull Request Process + +1. Ensure your branch is up to date with `main`. +2. Run both test suites locally and confirm they pass (see [Running Tests](#running-tests)). +3. Open a PR targeting `upstream/main`. +4. The GitHub Actions CI pipeline runs automatically on every PR. Both backend and frontend test jobs must pass. +5. A minimum **70% code coverage** threshold is enforced by the CI pipeline. PRs that drop coverage below this threshold will not be merged. +6. A maintainer will review your PR once CI passes. + +## Branch Protection + +The `main` branch is protected: + +- All changes must go through a pull request — **no direct pushes to `main`**. +- The GitHub Actions CI pipeline must pass before a PR can be merged. +- Keep your feature branches short-lived and focused. + +## Labels + +We use GitHub labels to organize issues and help contributors find work: + +| Label | Description | +| ----- | ----------- | +| `good first issue` | Curated for new contributors — clear scope, minimal context required. | +| `scenario-contribution` | Adding a new negotiation scenario JSON config to `backend/app/scenarios/data/`. | +| `help wanted` | Maintainers are actively seeking community contributions on these issues. | + +If you're new here, filter issues by [`good first issue`](../../issues?q=label%3A%22good+first+issue%22) to get started. + +## Community + +- **Chat**: Join our [WhatsApp community](https://chat.whatsapp.com/CZblOXj7aV3LMSKCwSUxWR) to ask questions, share ideas, and coordinate with other contributors. +- **Code of Conduct**: All participants must follow our [Code of Conduct](./CODE_OF_CONDUCT.md). Be respectful, be constructive, be kind. diff --git a/README.md b/README.md index 0a4daed..9f046b8 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ - [🛠️ Developing with Kiro](#-developing-with-kiro) - [🤝 Contributing](#-contributing) - [📄 License](#-license) -- [📋 Changelog](CHANGELOG.md) +- [📋 Changelog](#-changelog) --- @@ -426,7 +426,9 @@ Kiro is recommended but not required. Contributors can use any IDE — Kiro just ## 🤝 Contributing -Contributions are welcome! Check out the [open issues](https://github.com/Juntoai/a2a/issues) or propose something new. +We love contributions! Read the **[Contributing Guide](./CONTRIBUTING.md)** to get started — it covers the fork-and-PR workflow, local setup, test commands, and everything you need to open your first PR. + +All pull requests are automatically tested by GitHub Actions CI. Both backend (pytest) and frontend (Vitest) suites must pass with 70% coverage before merge. **Ways to contribute:** @@ -436,11 +438,11 @@ Contributions are welcome! Check out the [open issues](https://github.com/Juntoa - **Documentation** — Improve the README, add examples, fix typos. - **Agent strategies** — Share creative persona prompts and negotiation tactics. -**Branch strategy:** +**Get involved:** -1. Fork the repo -2. Create a `feature/*` branch from `main` -3. Submit a pull request to `main` +- 🆕 **First contribution?** Browse [`good first issue`](https://github.com/Juntoai/a2a/issues?q=label%3A%22good+first+issue%22) for curated starter tasks. +- 💬 **Join the community** — Ask questions and coordinate with other contributors on [WhatsApp](https://chat.whatsapp.com/CZblOXj7aV3LMSKCwSUxWR). +- 📜 **Code of Conduct** — Please read our [Code of Conduct](./CODE_OF_CONDUCT.md). We're committed to a welcoming, inclusive community. > Scenario contributions are JSON-only — drop a file in `backend/app/scenarios/data/` and open a PR. No code changes required. diff --git a/frontend/__tests__/context/SessionContext.test.ts b/frontend/__tests__/context/SessionContext.test.ts index 196260f..2637866 100644 --- a/frontend/__tests__/context/SessionContext.test.ts +++ b/frontend/__tests__/context/SessionContext.test.ts @@ -60,6 +60,8 @@ describe("SessionContext (cloud mode)", () => { expect(result.current.tokenBalance).toBe(0); expect(result.current.lastResetDate).toBeNull(); expect(result.current.isAuthenticated).toBe(false); + // isHydrated must stay true so the protected layout redirect fires + expect(result.current.isHydrated).toBe(true); expect(sessionStorage.getItem("junto_email")).toBeNull(); expect(sessionStorage.getItem("junto_token_balance")).toBeNull(); diff --git a/frontend/context/SessionContext.tsx b/frontend/context/SessionContext.tsx index 1ceff1b..60ef3c9 100644 --- a/frontend/context/SessionContext.tsx +++ b/frontend/context/SessionContext.tsx @@ -110,7 +110,8 @@ export function SessionProvider({ children }: { children: ReactNode }) { // Remove cookie by setting max-age=0 document.cookie = `${SESSION_COOKIE_NAME}=; SameSite=Strict; path=/; max-age=0`; - setState(defaultState); + // Keep isHydrated true so the protected layout redirect fires + setState({ ...defaultState, isHydrated: true }); }, []); const updateTokenBalance = useCallback((newBalance: number) => {