test: add fuzz and property-based testing across all layers#421
test: add fuzz and property-based testing across all layers#421
Conversation
Add Go native fuzz tests (10 Fuzz* functions), Python Hypothesis property tests (108 tests), and Vue fast-check property tests (47 tests) to catch edge cases in input parsing, model validation, and utility functions that hand-written tests miss. Go CLI: fuzz tests for yamlStr, validateParams, Generate, compareSemver, verifyChecksum, extractFromTarGz/Zip, SecurePath, Load, versionAtLeast. Python: property tests for deep_merge, to_float, NotBlankStr, validate_transition, compare_seniority/autonomy, config loader, Task/Message model roundtrips, BudgetConfig, and API DTOs. Vue: property tests for sanitizeForLog, format functions, getErrorMessage, unwrap/unwrapPaginated, and VALID_TRANSITIONS invariants. Infrastructure: hypothesis 6.151.5 (Python), fast-check ^4 (Vue), Hypothesis profile config in conftest.py, .hypothesis/ in .gitignore, cli-fuzz CI job (main-only, continue-on-error). Also updates CLAUDE.md pytest commands to use `uv run python -m pytest` to match pre-push hook and avoid Windows path canonicalization issues.
Fix bare dict type annotations in property test files that mypy flagged as missing type parameters under strict mode.
Pre-reviewed by 10 agents, 26 findings addressed: Python tests: - Remove dead assume() calls in test_dto_properties (always true) - Replace bare except/pass with explicit validation in test_config_properties - Use assume() instead of return in test_loader_properties - Add crash-safety docstrings to try/except patterns - Rename strategies to _private convention in test_utils_properties - Move _is_numeric_string before use site - Add nan/inf/infinity explicit tests for to_float - Add suppress_health_check to dev Hypothesis profile - Add noqa explanation comments for DTZ001 Go fuzz tests: - Fix FuzzVerifyChecksum seed hash mismatch (used wrong data) - Add result assertions on success for extractFromTarGz/Zip - Add invariant checks on validateParams success - Replace return with t.Skip for oversized inputs - Replace JWT secret placeholder in state_fuzz_test seed corpus - Add input size guard to FuzzLoadState - Fix trichotomy comment to match actual assertion semantics - Add containment scope comment to FuzzSecurePath Vue tests: - Fix TypeScript type errors with as const and discriminated union casts CI: - Add cli-fuzz result to cli-pass gate as informational warning Docs (CLAUDE.md): - Document cli-fuzz job in CI section - Add property-based testing to Testing section - Add hypothesis to Dependencies test group - Add fast-check to web dashboard deps - Add property/fuzz test commands to Quick Commands
…ction spacing - Remove duplicate terminal/install snippet from final CTA section (instructions belong on /get/ page only, keeping just the "Get Started" button) - Reduce section vertical padding from py-24 (96px) to py-16 (64px) throughout
Dependency ReviewThe following issues were found:
License Issuesuv.lock
OpenSSF Scorecard
Scanned Files
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds Go fuzz tests, Python Hypothesis property tests, and Vue fast-check property tests; integrates Go fuzzing into GitHub Actions as an informational cli-fuzz job; updates test deps, Hypothesis profiles, .gitignore, runtime guards, docs, and site padding. Changes
Sequence DiagramsequenceDiagram
participant Dev as Developer
participant GH as GitHub Actions
participant Fuzz as cli-fuzz Job
participant Gate as cli-pass Gate
participant Report as Build Status
Dev->>GH: Push to main
GH->>Fuzz: Trigger cli-fuzz (matrix)
activate Fuzz
Fuzz->>Fuzz: Discover fuzz targets and run each (30s per target)<br/>continue-on-error: true
Fuzz-->>Gate: Emit per-target reports / fuzz outcomes
deactivate Fuzz
activate Gate
Gate->>Gate: Aggregate results (includes fuzz warnings)
alt fuzz issues present
Gate->>Report: Surface warnings, do not hard-fail infra gate
else
Gate->>Report: Normal pass
end
deactivate Gate
Report->>Dev: Workflow complete
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
✨ Simplify code
📝 Coding Plan
Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the project's robustness and security by integrating comprehensive fuzz and property-based testing across its Go CLI, Python backend, and Vue dashboard layers. These new testing methodologies aim to uncover edge cases, validate invariants, and improve the resilience of critical components against unexpected inputs and behaviors, ensuring higher software quality and reliability. Highlights
Changelog
Ignored Files
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Code Review
This pull request significantly enhances the project's testing infrastructure by introducing property-based testing across multiple components. New Go fuzz tests were added for CLI compose, config, docker, and selfupdate packages to improve robustness against unexpected inputs. Python property-based tests using Hypothesis were implemented for API DTOs, budget configurations, communication messages, config loader utilities, core enums, task models, and custom types, ensuring data model invariants and function behavior under varied conditions. Correspondingly, hypothesis was added to Python dependencies and its configuration was integrated into tests/conftest.py with CI/dev profiles. For the web frontend, TypeScript property-based tests using fast-check were introduced for API client utilities, task status constants, error handling, and formatting functions, with fast-check added to web dependencies. Documentation (CLAUDE.md) was updated to reflect these new testing methodologies, including commands for running property and fuzz tests, and CI descriptions were expanded to include fuzz testing. Additionally, the .hypothesis/ directory was added to .gitignore, and minor aesthetic adjustments were made to the site/src/pages/index.astro file by reducing section padding and removing a terminal code block.
Greptile SummaryThis PR adds comprehensive property-based and fuzz testing infrastructure across all three layers of the stack: 10 Go fuzz functions covering security-critical parsing (YAML escaping, archive extraction, path traversal, version comparison, checksum verification), 69 Hypothesis property tests for Python model/domain invariants, and 55 fast-check property tests for Vue utility functions. Supporting changes include Hypothesis profile configuration, CI fuzz job, dependency additions, and a landing page cleanup. Key highlights:
Confidence Score: 4/5
Important Files Changed
|
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/cli.yml (1)
164-225:⚠️ Potential issue | 🟠 Major
cli-passwill never detect fuzz test failures due to job-levelcontinue-on-error: true.With
continue-on-error: trueat the job level,needs.cli-fuzz.resultalways evaluates to'success'even when steps fail. The condition checking for"failure"inFUZZ_RESULTwill never trigger, so fuzz failures will silently pass the gate.Move
continue-on-error: trueto the step level and explicitly capture the step outcome in a job output for reliable failure detection:Suggested fix
cli-fuzz: name: CLI Fuzz @@ - continue-on-error: true + outputs: + fuzz_failed: ${{ steps.fuzz_status.outputs.fuzz_failed }} @@ - - name: Run fuzz tests (30s per target) + - name: Run fuzz tests (30s per target) + id: fuzz_run + continue-on-error: true working-directory: cli run: | @@ for target in $FUZZ_TARGETS; do echo "::group::Fuzzing $target" go test -fuzz="^${target}$" -fuzztime=30s ${{ matrix.package }} echo "::endgroup::" done + - name: Capture fuzz status + id: fuzz_status + if: always() + run: | + if [ "${{ steps.fuzz_run.outcome }}" = "failure" ]; then + echo "fuzz_failed=true" >> "$GITHUB_OUTPUT" + else + echo "fuzz_failed=false" >> "$GITHUB_OUTPUT" + fi @@ - FUZZ_RESULT: ${{ needs.cli-fuzz.result }} + FUZZ_FAILED: ${{ needs.cli-fuzz.outputs.fuzz_failed }} @@ - if echo "$FUZZ_RESULT" | grep -qE "failure"; then - echo "::warning::Fuzz tests reported failures (informational): $FUZZ_RESULT" + if [ "$FUZZ_FAILED" = "true" ]; then + echo "::warning::Fuzz tests reported failures (informational)" fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/cli.yml around lines 164 - 225, The job-level continue-on-error: true causes needs.cli-fuzz.result to always be "success", so update the workflow by removing continue-on-error at the job level and instead set continue-on-error: true only on the "Run fuzz tests (30s per target)" step (or equivalent) so the step can fail without failing the whole job; then emit the step outcome as a job output (use the step's outcome and set it as an output on the cli-fuzz job, e.g., capture the step result and assign it to an outputs key) so cli-pass can reliably check needs.cli-fuzz.result for "failure" and warn/handle fuzz failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cli/internal/config/state_fuzz_test.go`:
- Around line 45-48: The test currently checks that Load returns a non-empty
state.DataDir but omits verifying it's absolute; update the fuzz test to assert
the path is absolute by importing "path/filepath" and adding a check like if
!filepath.IsAbs(state.DataDir) { t.Errorf("Load returned non-absolute DataDir:
%q", state.DataDir) }; locate the check around the existing DataDir empty
assertion that follows the Load call and use filepath.IsAbs to enforce the
invariant.
In `@tests/unit/config/test_loader_properties.py`:
- Around line 47-55: The test test_no_env_vars_passes_through should assert
value equality in addition to identity and type checks: after calling
_substitute_env_vars(data) keep the existing asserts (isinstance(result, dict)
and result is not data) and add an equality assertion (e.g., assert result ==
data) to verify the contents are unchanged; locate this in the test function
test_no_env_vars_passes_through that calls _substitute_env_vars and add the
equality check there.
In `@tests/unit/config/test_utils_properties.py`:
- Around line 55-60: The test test_identity_merge_with_empty should always
assert that deep_merge returns a distinct object even when `a` is empty; update
the test to remove the conditional "if a:" and unconditionally assert "result is
not a" so the identity separation is validated for {} as well, referencing the
test function name test_identity_merge_with_empty and the deep_merge call.
In `@tests/unit/core/test_task_properties.py`:
- Around line 88-101: The test contains a redundant conditional because
VALID_TRANSITIONS for TaskStatus.CREATED only allows TaskStatus.ASSIGNED;
simplify TestWithTransitionProperties.test_valid_transition_from_created by
removing the if-check and directly exercising
task.with_transition(TaskStatus.ASSIGNED, assigned_to="agent-a") and asserting
new_task.status and new_task.assigned_to; keep references to TaskStatus.CREATED,
TaskStatus.ASSIGNED, VALID_TRANSITIONS and the Task.with_transition call so the
change is localized and clear.
In `@web/src/__tests__/api/client.property.test.ts`:
- Around line 55-67: The property tests are allowing TypeError to pass when
non-object response bodies are dereferenced; update the two property tests that
call unwrap/mockResponse so their catch blocks assert not only
expect(err).toBeInstanceOf(Error) but also
expect(err).not.toBeInstanceOf(TypeError), and harden the unwrap function in
client.ts by adding a guard at the top (if (!body || typeof body !== 'object')
throw new Error('Unknown API error')) before accessing
body.success/body.pagination so malformed response shapes produce a controlled
Error rather than a TypeError.
In `@web/src/__tests__/utils/errors.property.test.ts`:
- Around line 5-12: The axios mock is checking for a non-existent
`_isAxiosError` property; update both mocked implementations (the
default.isAxiosError function and the top-level isAxiosError export) to detect
Axios v1.x errors by checking that the error object has isAxiosError === true
(e.g., ensure the predicate returns true only when typeof err === 'object' &&
err !== null && (err as any).isAxiosError === true), so the test error-detection
paths align with Axios v1.x behavior.
---
Outside diff comments:
In @.github/workflows/cli.yml:
- Around line 164-225: The job-level continue-on-error: true causes
needs.cli-fuzz.result to always be "success", so update the workflow by removing
continue-on-error at the job level and instead set continue-on-error: true only
on the "Run fuzz tests (30s per target)" step (or equivalent) so the step can
fail without failing the whole job; then emit the step outcome as a job output
(use the step's outcome and set it as an output on the cli-fuzz job, e.g.,
capture the step result and assign it to an outputs key) so cli-pass can
reliably check needs.cli-fuzz.result for "failure" and warn/handle fuzz
failures.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9430d244-9581-49e1-bf40-7c2076d6fd94
⛔ Files ignored due to path filters (2)
uv.lockis excluded by!**/*.lockweb/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (26)
.github/workflows/cli.yml.gitignoreCLAUDE.mdcli/internal/compose/generate_fuzz_test.gocli/internal/config/paths_fuzz_test.gocli/internal/config/state_fuzz_test.gocli/internal/docker/client_fuzz_test.gocli/internal/selfupdate/updater_fuzz_test.gopyproject.tomlsite/src/pages/index.astrotests/conftest.pytests/unit/api/test_dto_properties.pytests/unit/budget/test_config_properties.pytests/unit/communication/test_message_properties.pytests/unit/config/test_loader_properties.pytests/unit/config/test_utils_properties.pytests/unit/core/test_enums_properties.pytests/unit/core/test_task_properties.pytests/unit/core/test_transitions_properties.pytests/unit/core/test_types_properties.pyweb/package.jsonweb/src/__tests__/api/client.property.test.tsweb/src/__tests__/utils/constants.property.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/__tests__/utils/format.property.test.tsweb/src/__tests__/utils/sanitizeForLog.property.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Agent
- GitHub Check: CLI Test (windows-latest)
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Backend
- GitHub Check: Greptile Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (11)
cli/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
cli/**/*.go: CLI (Go binary) must support cross-platform builds (linux/darwin/windows × amd64/arm64) via GoReleaser, use Cobra for CLI commands, and passgolangci-lint+go vet+govulncheck
CLI must manage Docker/Compose lifecycle detection and execution, config via XDG/macOS/Windows data directories, and support self-update from GitHub Releases
Files:
cli/internal/docker/client_fuzz_test.gocli/internal/config/state_fuzz_test.gocli/internal/compose/generate_fuzz_test.gocli/internal/config/paths_fuzz_test.gocli/internal/selfupdate/updater_fuzz_test.go
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
ESLintfor linting andvue-tscfor type checking in the Vue 3 dashboard (web/directory)
Files:
web/src/__tests__/utils/format.property.test.tsweb/src/__tests__/utils/constants.property.test.tsweb/src/__tests__/api/client.property.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/__tests__/utils/sanitizeForLog.property.test.ts
web/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Vue 3 dashboard must use PrimeVue + Tailwind CSS for components and styling, Pinia for state management, VueFlow for org chart visualization, and Axios for API client
Files:
web/src/__tests__/utils/format.property.test.tsweb/src/__tests__/utils/constants.property.test.tsweb/src/__tests__/api/client.property.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/__tests__/utils/sanitizeForLog.property.test.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
API endpoint modules and TypeScript types in
web/src/api/must mirror Pydantic models from the backend
Files:
web/src/__tests__/utils/format.property.test.tsweb/src/__tests__/utils/constants.property.test.tsweb/src/__tests__/api/client.property.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/__tests__/utils/sanitizeForLog.property.test.ts
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Do not usefrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations
Useexcept A, B:(no parentheses) for exception handling — PEP 758 syntax enforced by ruff on Python 3.14
Line length is 88 characters (ruff enforced)
Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names:example-provider,example-large-001,example-medium-001,example-small-001,large/medium/smallas aliases; vendor names only allowed in: (1) Operations design page provider list, (2).claude/skill/agent files, (3) third-party import paths/module names
Files:
tests/unit/budget/test_config_properties.pytests/unit/core/test_enums_properties.pytests/unit/core/test_transitions_properties.pytests/unit/config/test_loader_properties.pytests/unit/api/test_dto_properties.pytests/conftest.pytests/unit/config/test_utils_properties.pytests/unit/core/test_task_properties.pytests/unit/core/test_types_properties.pytests/unit/communication/test_message_properties.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Mark all tests with@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e, or@pytest.mark.slow; maintain 80% code coverage minimum (enforced in CI)
Use@pytest.mark.parametrizefor testing similar cases; do not manually implement retry loops or polling in tests
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in tests; use generic names:test-provider,test-small-001,test-medium-001,test-large-001, orsmall/medium/largeas aliases
Files:
tests/unit/budget/test_config_properties.pytests/unit/core/test_enums_properties.pytests/unit/core/test_transitions_properties.pytests/unit/config/test_loader_properties.pytests/unit/api/test_dto_properties.pytests/conftest.pytests/unit/config/test_utils_properties.pytests/unit/core/test_task_properties.pytests/unit/core/test_types_properties.pytests/unit/communication/test_message_properties.py
pyproject.toml
📄 CodeRabbit inference engine (CLAUDE.md)
pyproject.toml: All Python dependencies must be pinned with==versions inpyproject.toml; organize into groups:test(pytest + plugins),dev(includes test + ruff, mypy, pre-commit, commitizen, pip-audit),docs(zensical, mkdocstrings[python], griffe-pydantic);mem0aiis required (Mem0 memory backend — currently the only backend)
Version is stored in[tool.commitizen].versionand must be bumped by Release Please; version is used to tag Docker images and CLI builds
Files:
pyproject.toml
site/**/*.astro
📄 CodeRabbit inference engine (CLAUDE.md)
Landing page is built with Astro (Concept C hybrid design) in
site/and deployed to GitHub Pages alongside Zensical docs; includes/get/CLI installation page and sharedFootercomponent
Files:
site/src/pages/index.astro
.github/workflows/*.yml
📄 CodeRabbit inference engine (CLAUDE.md)
Workflows must use path filtering (
dorny/paths-filter) to run jobs only when their domain is affected (Python/dashboard/docker changes); CI includes lint, type-check, test, audit, and dockerfile-lint jobs running in parallel with aci-passgate
Files:
.github/workflows/cli.yml
.github/workflows/cli.yml
📄 CodeRabbit inference engine (CLAUDE.md)
CLI workflow must lint (
golangci-lint+go vet), test (-race -coverprofile), build cross-compile matrix (linux/darwin/windows × amd64/arm64), rungovulncheck, and use GoReleaser for releases onv*tags; post-release updates checksums in install scripts and appends to release notes
Files:
.github/workflows/cli.yml
**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.md: Never remove existingCloses#NNN`` PR references in commit messages or documentation — preserve these unless explicitly asked
Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names:example-provider, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases; vendor names only allowed in: (1) Operations design page provider list, (2) `.claude/` skill/agent files, (3) third-party import paths/module names
Files:
CLAUDE.md
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: When review agents find valid issues (including pre-existing issues in surrounding code, suggestions, and findings adjacent to the PR's changes), fix them all — no deferring, no 'out of scope' skipping
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Mark all tests with `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, or `pytest.mark.slow`; maintain 80% code coverage minimum (enforced in CI)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to web/__tests__/**/*.{ts,tsx} : Use Vitest for unit testing the Vue 3 dashboard; organize tests by feature
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow must lint (`golangci-lint` + `go vet`), test (`-race -coverprofile`), build cross-compile matrix (linux/darwin/windows × amd64/arm64), run `govulncheck`, and use GoReleaser for releases on `v*` tags; post-release updates checksums in install scripts and appends to release notes
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .pre-commit-config.yaml : Pre-commit hooks must include: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint; pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on `cli/**/*.go`); autoupdate must be disabled (`autoupdate_schedule: never`) so Dependabot owns hook version bumps
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI must manage Docker/Compose lifecycle detection and execution, config via XDG/macOS/Windows data directories, and support self-update from GitHub Releases
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to **/*.{ts,tsx,js} : Use `ESLint` for linting and `vue-tsc` for type checking in the Vue 3 dashboard (`web/` directory)
Applied to files:
web/package.json
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to web/__tests__/**/*.{ts,tsx} : Use Vitest for unit testing the Vue 3 dashboard; organize tests by feature
Applied to files:
web/package.jsonweb/src/__tests__/utils/format.property.test.tsweb/src/__tests__/utils/constants.property.test.tsweb/src/__tests__/api/client.property.test.tsCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to web/**/*.{ts,tsx,vue} : Vue 3 dashboard must use PrimeVue + Tailwind CSS for components and styling, Pinia for state management, VueFlow for org chart visualization, and Axios for API client
Applied to files:
web/package.json
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to pyproject.toml : All Python dependencies must be pinned with `==` versions in `pyproject.toml`; organize into groups: `test` (pytest + plugins), `dev` (includes test + ruff, mypy, pre-commit, commitizen, pip-audit), `docs` (zensical, mkdocstrings[python], griffe-pydantic); `mem0ai` is required (Mem0 memory backend — currently the only backend)
Applied to files:
pyproject.tomlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to site/**/*.astro : Landing page is built with Astro (Concept C hybrid design) in `site/` and deployed to GitHub Pages alongside Zensical docs; includes `/get/` CLI installation page and shared `Footer` component
Applied to files:
site/src/pages/index.astro
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Mark all tests with `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, or `pytest.mark.slow`; maintain 80% code coverage minimum (enforced in CI)
Applied to files:
tests/unit/core/test_transitions_properties.pytests/conftest.pyCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI must manage Docker/Compose lifecycle detection and execution, config via XDG/macOS/Windows data directories, and support self-update from GitHub Releases
Applied to files:
cli/internal/compose/generate_fuzz_test.go.github/workflows/cli.ymlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow must lint (`golangci-lint` + `go vet`), test (`-race -coverprofile`), build cross-compile matrix (linux/darwin/windows × amd64/arm64), run `govulncheck`, and use GoReleaser for releases on `v*` tags; post-release updates checksums in install scripts and appends to release notes
Applied to files:
.github/workflows/cli.ymlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/*.yml : Workflows must use path filtering (`dorny/paths-filter`) to run jobs only when their domain is affected (Python/dashboard/docker changes); CI includes lint, type-check, test, audit, and dockerfile-lint jobs running in parallel with a `ci-pass` gate
Applied to files:
.github/workflows/cli.ymlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI (Go binary) must support cross-platform builds (linux/darwin/windows × amd64/arm64) via GoReleaser, use Cobra for CLI commands, and pass `golangci-lint` + `go vet` + `govulncheck`
Applied to files:
.github/workflows/cli.ymlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .pre-commit-config.yaml : Pre-commit hooks must include: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint; pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on `cli/**/*.go`); autoupdate must be disabled (`autoupdate_schedule: never`) so Dependabot owns hook version bumps
Applied to files:
.github/workflows/cli.ymlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow must build backend + web images, scan with Trivy (CRITICAL = hard fail, HIGH = warn-only) + Grype (critical cutoff), sign with cosign, and push to GHCR only after scans pass; use `.github/.trivyignore.yaml` and `.github/.grype.yaml` for CVE triage; trigger on push to main and version tags
Applied to files:
.github/workflows/cli.ymlCLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in tests; use generic names: `test-provider`, `test-small-001`, `test-medium-001`, `test-large-001`, or `small`/`medium`/`large` as aliases
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to **/*.py : Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names: `example-provider`, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases; vendor names only allowed in: (1) Operations design page provider list, (2) `.claude/` skill/agent files, (3) third-party import paths/module names
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to **/*.md : Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names: `example-provider`, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases; vendor names only allowed in: (1) Operations design page provider list, (2) `.claude/` skill/agent files, (3) third-party import paths/module names
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Use `pytest.mark.parametrize` for testing similar cases; do not manually implement retry loops or polling in tests
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/pages.yml : Pages workflow must export OpenAPI schema via `scripts/export_openapi.py`, build Astro landing + Zensical docs, merge, and deploy to GitHub Pages on push to main; triggers on docs, site, mkdocs.yml, pyproject.toml, uv.lock, src/ai_company/**, scripts/**, CLI install scripts, and workflow changes
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/release-please-config.json : Release Please must auto-create release PRs on push to main; merging creates git tag (`vX.Y.Z`) + GitHub Release; tag push triggers Docker workflow; after PR creation, auto-update BSL Change Date in LICENSE to 3 years ahead; use `RELEASE_PLEASE_TOKEN` secret so tag creation triggers downstream workflows
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/pages-preview.yml : PR preview workflow must build on PRs, inject a 'Development Preview' banner, deploy to Cloudflare Pages (`synthorg-pr-preview`), and clean up on PR close; use Cloudflare wrangler from lockfile-pinned `.github/package.json` and check out PR head SHA not merge commit
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to docker/Dockerfile* : Backend Dockerfile must use 3-stage build (builder → setup → distroless runtime), Chainguard Python base, run as non-root (UID 65532), and follow CIS hardening guidelines
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to src/ai_company/**/*.py : Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators
Applied to files:
tests/unit/core/test_types_properties.py
🧬 Code graph analysis (15)
web/src/__tests__/utils/format.property.test.ts (1)
web/src/utils/format.ts (5)
formatDate(6-17)formatUptime(60-70)formatCurrency(41-48)formatLabel(75-80)formatNumber(53-55)
cli/internal/config/state_fuzz_test.go (2)
cli/internal/config/state.go (1)
Load(43-75)cli/internal/config/paths.go (1)
DataDir(18-31)
web/src/__tests__/utils/constants.property.test.ts (1)
web/src/utils/constants.ts (3)
TASK_STATUS_ORDER(23-33)VALID_TRANSITIONS(39-49)TERMINAL_STATUSES(36-36)
web/src/__tests__/api/client.property.test.ts (1)
web/src/api/client.ts (2)
unwrap(56-62)unwrapPaginated(68-84)
web/src/__tests__/utils/errors.property.test.ts (1)
web/src/utils/errors.ts (1)
getErrorMessage(16-66)
tests/unit/core/test_enums_properties.py (1)
src/ai_company/core/enums.py (2)
compare_autonomy(481-494)compare_seniority(51-64)
tests/unit/core/test_transitions_properties.py (2)
web/src/utils/constants.ts (1)
VALID_TRANSITIONS(39-49)src/ai_company/core/task_transitions.py (1)
validate_transition(69-103)
cli/internal/compose/generate_fuzz_test.go (1)
cli/internal/compose/generate.go (2)
Params(31-40)Generate(58-76)
tests/unit/config/test_loader_properties.py (2)
src/ai_company/config/errors.py (2)
ConfigParseError(66-67)ConfigValidationError(70-106)src/ai_company/config/loader.py (2)
_parse_yaml_string(96-147)_substitute_env_vars(330-354)
tests/unit/api/test_dto_properties.py (1)
src/ai_company/api/dto.py (1)
CoordinateTaskRequest(274-313)
tests/unit/config/test_utils_properties.py (1)
src/ai_company/config/utils.py (2)
deep_merge(37-61)to_float(12-34)
cli/internal/config/paths_fuzz_test.go (1)
cli/internal/config/paths.go (1)
SecurePath(58-64)
web/src/__tests__/utils/sanitizeForLog.property.test.ts (1)
web/src/utils/logging.ts (1)
sanitizeForLog(2-11)
tests/unit/core/test_task_properties.py (1)
web/src/utils/constants.ts (1)
VALID_TRANSITIONS(39-49)
tests/unit/communication/test_message_properties.py (1)
tests/unit/core/test_task_properties.py (1)
test_model_dump_validate_roundtrip(58-72)
🪛 GitHub Check: Dashboard Lint
web/src/__tests__/utils/format.property.test.ts
[warning] 138-138:
Generic Object Injection Sink
[warning] 137-137:
Generic Object Injection Sink
[warning] 129-129:
Unsafe Regular Expression
[warning] 82-82:
Unsafe Regular Expression
web/src/__tests__/utils/constants.property.test.ts
[warning] 51-51:
Variable Assigned to Object Injection Sink
[warning] 23-23:
Variable Assigned to Object Injection Sink
🔇 Additional comments (36)
site/src/pages/index.astro (1)
76-76: Spacing compaction and section updates look consistent and safe.The
py-16changes are coherent across sections, and the page still preserves the key landing-page integration points (/get/CTAs and shared footer).As per coding guidelines,
site/**/*.astroshould include/get/and the sharedFootercomponent, and both are present.Also applies to: 141-141, 188-188, 222-222, 282-282, 310-310, 384-384
.gitignore (1)
22-22: Good ignore addition for Hypothesis artifacts.This keeps local Hypothesis cache/examples out of version control.
pyproject.toml (1)
51-51: Dependency addition is correctly pinned and grouped.
hypothesis==6.151.5is in thetestgroup and follows the repo pinning policy.
As per coding guidelines: "All Python dependencies must be pinned with==versions inpyproject.toml; organize into groups..."tests/conftest.py (1)
9-21: Global Hypothesis profile setup looks solid.Centralizing profile registration/loading in
conftest.pyis a good pattern for consistent property-test behavior across the suite.cli/internal/config/paths_fuzz_test.go (1)
8-50: Strong fuzz seed corpus and success invariants.This is a useful fuzz harness for
SecurePathand captures the key postconditions on successful returns.tests/unit/core/test_types_properties.py (1)
8-60: Property coverage forNotBlankStris well-structured.The suite exercises both acceptance and rejection boundaries and is correctly marked as unit tests.
tests/unit/budget/test_config_properties.py (1)
12-204: Excellent property-based coverage for budget config invariants.The scenarios cover critical constraints (ordering, self/duplicate downgrade guards, cross-field budget limits) and include round-trip consistency checks.
web/src/__tests__/utils/constants.property.test.ts (1)
8-62: Solid invariant coverage for status constants.This suite cleanly enforces bidirectional map consistency, terminal-state behavior, and transition integrity.
tests/unit/core/test_enums_properties.py (1)
18-99: Comparator algebra properties are well tested.The property set is comprehensive and matches the expected ordering semantics.
cli/internal/docker/client_fuzz_test.go (1)
7-43: Good fuzz entry-point coverage for version comparison.Seed corpus and invariants provide strong crash-safety and ordering checks.
tests/unit/config/test_utils_properties.py (1)
62-164: Strong property coverage for merge and numeric coercion behavior.The tests exercise both semantic invariants and error boundaries effectively.
tests/unit/config/test_loader_properties.py (1)
56-130: Nice crash-safety and behavior partitioning for loader helpers.The success/error-path assertions are clear and robust.
tests/unit/communication/test_message_properties.py (1)
65-153: Great coverage of aliasing and model roundtrip invariants.These properties effectively protect the serialization/deserialization contract.
cli/internal/compose/generate_fuzz_test.go (1)
8-126: Fuzz coverage here is practical and well-targeted.Good invariant checks across YAML escaping, parameter validation, and compose generation.
tests/unit/core/test_transitions_properties.py (1)
16-85: Transition validator properties are well covered.This suite gives strong confidence that map invariants and runtime validation stay in sync.
tests/unit/core/test_task_properties.py (3)
1-17: LGTM: Imports and module setup are correct.The file properly sets
pytestmark = pytest.mark.unitfor all tests and uses vendor-agnostic naming throughout. Nofrom __future__ import annotationsis used, which is correct per coding guidelines.
55-72: LGTM: Round-trip property test is well-structured.The test correctly validates that
model_dumpfollowed bymodel_validateproduces an equivalent Task object. The strategy generates diverse but bounded inputs.
117-141: LGTM: Transition chain and override protection tests are correct.
test_valid_transition_chainvalidates the happy-path progression through task states, andtest_with_transition_rejects_status_overrideensures the guard against status manipulation works correctly.tests/unit/api/test_dto_properties.py (3)
1-21: LGTM: Imports, setup, and strategy definitions are correct.The file properly sets
pytestmark = pytest.mark.unitand defines reusable strategies. The_action_typesregex strategy correctly generates validcategory:actionformat strings.
23-98: LGTM: CoordinateTaskRequest property tests are comprehensive.Good coverage of:
- Case-insensitive uniqueness validation with dynamic duplicate detection
- Single agent always valid (edge case)
Noneagent_names valid (default behavior)- Same-case and different-case duplicate rejection
- Roundtrip serialization integrity
101-216: LGTM: CreateApprovalRequest property tests thoroughly validate constraints.The tests cover:
- Valid request roundtrip
- Metadata key count limits
- Metadata key/value length limits
- Invalid action_type format rejection
- Valid metadata acceptance
The use of imported constants (
_MAX_METADATA_KEYS,_MAX_METADATA_STR_LEN) ensures tests stay in sync with implementation.CLAUDE.md (5)
36-40: LGTM: Updated pytest commands usepython -m pytestfor consistency.Using
python -m pytestensures the test module resolution works correctly regardless of environment setup.
64-67: LGTM: CLI fuzz test command example is clear and useful.The example shows a 30-second fuzz run targeting a specific package, which aligns with the CI configuration mentioned in the PR objectives.
216-216: LGTM: Property-based testing documentation is comprehensive.The documentation clearly describes:
- Python: Hypothesis with
@given+@settings- Vue: fast-check with
fc.assert+fc.property- Go: native
testing.Ffuzz functions- Hypothesis profiles (
ci/dev) and how to run with dev profile.hypothesis/is gitignoredThis provides clear guidance for contributors.
262-262: LGTM: CLI workflow documentation accurately reflects the new fuzz job.The documentation correctly describes the fuzz testing as main-only, 30s/target,
continue-on-error, and informational (not a hard gate).
280-283: LGTM: Dependency documentation updated to include hypothesis and fast-check.cli/internal/selfupdate/updater_fuzz_test.go (5)
14-56: LGTM: FuzzCompareSemver correctly validates comparison function properties.The test verifies:
- Reflexivity:
compareSemver(x, x) == 0- Antisymmetry: if
a > bthenb < a(and vice versa)- Symmetry for equality: if
a == bthenb == aThe seed corpus includes good edge cases: empty strings, partial versions, pre-release suffixes, and large version numbers.
58-79: LGTM: FuzzVerifyChecksum is well-designed.Using a package-level
fuzzArchiveDataensures deterministic hashing for the valid seed. The seeds cover valid checksums, empty data, invalid format, and edge cases.
81-116: LGTM: FuzzExtractFromTarGz has proper OOM protection and good seed coverage.The 1MB input cap prevents OOM during fuzzing. Seeds include:
- Valid tar.gz archive
- Empty input
- Non-gzip garbage
- Valid gzip but invalid tar content
The invariant check (non-empty result on success) is appropriate.
118-145: LGTM: FuzzExtractFromZip mirrors tar.gz fuzz with appropriate adaptations.The minimal PK header seed (
"PK\x03\x04garbage") is a good edge case for testing zip parsing robustness.
147-191: LGTM: Helper functions are well-structured.Both
buildValidTarGzandbuildValidZip:
- Use
f.Helper()for proper test output attribution- Handle all errors with
f.Fatalf()- Create valid archives with the expected binary names (
synthorg/synthorg.exe)web/package.json (1)
47-47:fast-checkdependency addition is correct.This cleanly enables the new property-based Vitest suites without affecting runtime dependencies.
web/src/__tests__/utils/format.property.test.ts (1)
11-209: Strong property coverage for formatting utilities.The suite is well-structured and exercises both invariants and edge inputs across all formatter helpers.
web/src/__tests__/utils/sanitizeForLog.property.test.ts (1)
22-114: Sanitizer properties are thorough and aligned with implementation invariants.Nice coverage of safety guarantees (control chars, DEL, truncation) and behavior-preservation cases.
web/src/__tests__/utils/errors.property.test.ts (1)
16-102: Overall property suite quality is good.The non-throw and message-shape properties provide strong broad-input validation for
getErrorMessage.web/src/__tests__/api/client.property.test.ts (1)
17-53: Great coverage of explicit malformed-envelope branches.The targeted null/undefined/pagination-shape tests are valuable and complement the broad arbitrary-input checks.
Also applies to: 72-153
| class TestWithTransitionProperties: | ||
| @given( | ||
| target=st.sampled_from( | ||
| list(VALID_TRANSITIONS[TaskStatus.CREATED]), | ||
| ), | ||
| ) | ||
| @settings(max_examples=20) | ||
| def test_valid_transition_from_created(self, target: TaskStatus) -> None: | ||
| task = Task(**_make_task_kwargs()) | ||
| # CREATED can only go to ASSIGNED, which requires assigned_to | ||
| if target == TaskStatus.ASSIGNED: | ||
| new_task = task.with_transition(target, assigned_to="agent-a") | ||
| assert new_task.status == target | ||
| assert new_task.assigned_to == "agent-a" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Simplify: the conditional is redundant since CREATED only transitions to ASSIGNED.
Based on the VALID_TRANSITIONS definition (where created: ['assigned']), TaskStatus.CREATED can only transition to ASSIGNED. The if target == TaskStatus.ASSIGNED check will always be true, making this branch unconditional.
Consider simplifying to remove the dead conditional or converting to a non-property test if only one transition is valid.
♻️ Suggested simplification
`@given`(
target=st.sampled_from(
list(VALID_TRANSITIONS[TaskStatus.CREATED]),
),
)
`@settings`(max_examples=20)
def test_valid_transition_from_created(self, target: TaskStatus) -> None:
task = Task(**_make_task_kwargs())
- # CREATED can only go to ASSIGNED, which requires assigned_to
- if target == TaskStatus.ASSIGNED:
- new_task = task.with_transition(target, assigned_to="agent-a")
- assert new_task.status == target
- assert new_task.assigned_to == "agent-a"
+ # CREATED can only go to ASSIGNED, which requires assigned_to
+ new_task = task.with_transition(target, assigned_to="agent-a")
+ assert new_task.status == target
+ assert new_task.assigned_to == "agent-a"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| class TestWithTransitionProperties: | |
| @given( | |
| target=st.sampled_from( | |
| list(VALID_TRANSITIONS[TaskStatus.CREATED]), | |
| ), | |
| ) | |
| @settings(max_examples=20) | |
| def test_valid_transition_from_created(self, target: TaskStatus) -> None: | |
| task = Task(**_make_task_kwargs()) | |
| # CREATED can only go to ASSIGNED, which requires assigned_to | |
| if target == TaskStatus.ASSIGNED: | |
| new_task = task.with_transition(target, assigned_to="agent-a") | |
| assert new_task.status == target | |
| assert new_task.assigned_to == "agent-a" | |
| class TestWithTransitionProperties: | |
| `@given`( | |
| target=st.sampled_from( | |
| list(VALID_TRANSITIONS[TaskStatus.CREATED]), | |
| ), | |
| ) | |
| `@settings`(max_examples=20) | |
| def test_valid_transition_from_created(self, target: TaskStatus) -> None: | |
| task = Task(**_make_task_kwargs()) | |
| # CREATED can only go to ASSIGNED, which requires assigned_to | |
| new_task = task.with_transition(target, assigned_to="agent-a") | |
| assert new_task.status == target | |
| assert new_task.assigned_to == "agent-a" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/unit/core/test_task_properties.py` around lines 88 - 101, The test
contains a redundant conditional because VALID_TRANSITIONS for
TaskStatus.CREATED only allows TaskStatus.ASSIGNED; simplify
TestWithTransitionProperties.test_valid_transition_from_created by removing the
if-check and directly exercising task.with_transition(TaskStatus.ASSIGNED,
assigned_to="agent-a") and asserting new_task.status and new_task.assigned_to;
keep references to TaskStatus.CREATED, TaskStatus.ASSIGNED, VALID_TRANSITIONS
and the Task.with_transition call so the change is localized and clear.
| it('either returns data or throws Error on arbitrary envelope shapes', () => { | ||
| fc.assert( | ||
| fc.property(fc.anything(), (body) => { | ||
| const response = mockResponse(body) | ||
| try { | ||
| const result = unwrap(response as unknown as AxiosResponse<ApiResponse<unknown>>) | ||
| // If it didn't throw, we got a value back — that's fine | ||
| expect(result).toBeDefined() | ||
| } catch (err) { | ||
| // Must throw an Error, not crash with a TypeError | ||
| expect(err).toBeInstanceOf(Error) | ||
| } | ||
| }), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Inspect dereference guards in API unwrap helpers:"
rg -n -C2 "const body = response.data|!body.success|!body.pagination|Array.isArray\\(body.data\\)" web/src/api/client.ts
echo
echo "Inspect permissive catch assertions in property tests:"
rg -n -C2 "toBeInstanceOf\\(Error\\)|TypeError|either returns" web/src/__tests__/api/client.property.test.tsRepository: Aureliolo/synthorg
Length of output: 1502
Property tests are too permissive—they allow TypeError to pass as a valid error response.
The catch blocks check expect(err).toBeInstanceOf(Error), which passes for TypeError. If response.data is null, undefined, or a non-object, accessing body.success (line 58) or body.pagination (line 75) throws TypeError, masking a crash-class bug while the test still passes.
Fix in two ways:
- Tighten the test to reject
TypeError:
} catch (err) {
expect(err).toBeInstanceOf(Error)
expect(err).not.toBeInstanceOf(TypeError)
}- Harden
web/src/api/client.tswith a body-shape guard before dereferencing (line 57):
if (!body || typeof body !== 'object') {
throw new Error('Unknown API error')
}Applies to both test cases at lines 55–66 and 155–169.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/__tests__/api/client.property.test.ts` around lines 55 - 67, The
property tests are allowing TypeError to pass when non-object response bodies
are dereferenced; update the two property tests that call unwrap/mockResponse so
their catch blocks assert not only expect(err).toBeInstanceOf(Error) but also
expect(err).not.toBeInstanceOf(TypeError), and harden the unwrap function in
client.ts by adding a guard at the top (if (!body || typeof body !== 'object')
throw new Error('Unknown API error')) before accessing
body.success/body.pagination so malformed response shapes produce a controlled
Error rather than a TypeError.
There was a problem hiding this comment.
Pull request overview
Adds fuzz/property-based testing across the Go CLI, Python backend, and Vue dashboard to improve robustness of parsing/validation utilities and raise OSSF Scorecard fuzzing coverage, plus small CI/docs/site updates to support and document the new testing approach.
Changes:
- Introduces Go native fuzz targets for security-sensitive CLI parsing and archive handling, and adds a main-branch CI fuzz job.
- Adds Hypothesis (Python) and fast-check (Web) property tests covering model validation roundtrips and utility invariants.
- Updates dependencies/tooling docs and small landing-page layout cleanup.
Reviewed changes
Copilot reviewed 25 out of 28 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/tests/utils/sanitizeForLog.property.test.ts | fast-check properties for sanitizeForLog output sanitization and truncation. |
| web/src/tests/utils/format.property.test.ts | fast-check properties for formatting utilities (formatDate, formatUptime, etc.). |
| web/src/tests/utils/errors.property.test.ts | fast-check properties for getErrorMessage with axios mocking. |
| web/src/tests/utils/constants.property.test.ts | Invariant tests for task status ordering and transition maps. |
| web/src/tests/api/client.property.test.ts | Property tests for API envelope unwrapping (unwrap, unwrapPaginated). |
| web/package.json | Adds fast-check dev dependency. |
| web/package-lock.json | Locks fast-check and pure-rand dependency tree. |
| pyproject.toml | Adds hypothesis to Python test dependencies. |
| uv.lock | Locks Hypothesis and related Python dependency resolution. |
| tests/conftest.py | Registers/loads Hypothesis profiles (ci/dev) for the test suite. |
| tests/unit/core/test_types_properties.py | Hypothesis properties for NotBlankStr validation boundaries. |
| tests/unit/core/test_transitions_properties.py | Hypothesis properties ensuring validate_transition matches VALID_TRANSITIONS. |
| tests/unit/core/test_task_properties.py | Hypothesis properties for Task roundtrips and transition constraints. |
| tests/unit/core/test_enums_properties.py | Hypothesis properties for enum comparison functions (order axioms). |
| tests/unit/config/test_utils_properties.py | Hypothesis properties for deep_merge and to_float. |
| tests/unit/config/test_loader_properties.py | Hypothesis crash-safety properties for YAML/env-var parsing helpers. |
| tests/unit/communication/test_message_properties.py | Hypothesis roundtrip/alias properties for Message and related models. |
| tests/unit/budget/test_config_properties.py | Hypothesis properties for budget config validation invariants. |
| tests/unit/api/test_dto_properties.py | Hypothesis properties for DTO validation (uniqueness, metadata bounds). |
| cli/internal/compose/generate_fuzz_test.go | Go fuzz tests for YAML string escaping, param validation, and compose generation. |
| cli/internal/selfupdate/updater_fuzz_test.go | Go fuzz tests for semver compare, checksum verification, and archive extraction. |
| cli/internal/config/paths_fuzz_test.go | Go fuzz tests for SecurePath path sanitation invariants. |
| cli/internal/config/state_fuzz_test.go | Go fuzz tests for state JSON parsing crash-safety/invariants. |
| cli/internal/docker/client_fuzz_test.go | Go fuzz tests for Docker/Compose version comparison helper. |
| .github/workflows/cli.yml | Adds cli-fuzz job (main-only) and wires it into CLI gating. |
| .gitignore | Ignores .hypothesis/ cache directory. |
| CLAUDE.md | Documents new property/fuzz testing tooling and updated pytest commands. |
| site/src/pages/index.astro | Reduces section spacing and removes duplicate terminal block from final CTA. |
Files not reviewed (1)
- web/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Must throw an Error, not crash with a TypeError | ||
| expect(err).toBeInstanceOf(Error) |
| expect(typeof result.offset).toBe('number') | ||
| expect(typeof result.limit).toBe('number') | ||
| } catch (err) { | ||
| expect(err).toBeInstanceOf(Error) |
.github/workflows/cli.yml
Outdated
| needs: cli-changes | ||
| if: needs.cli-changes.outputs.changed == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
| runs-on: ubuntu-latest | ||
| continue-on-error: true |
CLAUDE.md
Outdated
| ```bash | ||
| cd cli && go build -o synthorg ./main.go # build CLI | ||
| cd cli && go test ./... # run tests | ||
| cd cli && go test ./... # run tests (seed corpus only for fuzz) |
29 items addressed across Go fuzz tests, Python property tests, Vue tests, CI workflow, and documentation: - Go: add filepath.IsAbs assertion, path-traversal seeds, error-path nil checks, sandbox/imageTag invariants, verifyChecksum return value check, negative SecurePath assertion, unescaped-quote assertion, t.Skip→return - Python: fix conditional assertion gap, add crash-safety event tracking, assert pass-through equality, derive _TERMINAL_STATES, fix Callable type, remove HealthCheck.too_slow from dev profile, add module docstrings, remove redundant list() wraps, broaden _action_types strategy - Vue: fix axios mock property name, reject TypeError in unwrap tests, harden unwrap/unwrapPaginated with body-shape guard, sync MessageType enum with backend, clarify constants test naming - CI: move continue-on-error to step level with per-matrix fuzz reporting - Docs: fix CLAUDE.md dev profile command and go test fuzz comment
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #421 +/- ##
==========================================
+ Coverage 93.65% 93.67% +0.02%
==========================================
Files 469 469
Lines 22214 22214
Branches 2142 2142
==========================================
+ Hits 20804 20809 +5
+ Misses 1097 1094 -3
+ Partials 313 311 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cli/internal/selfupdate/updater_fuzz_test.go`:
- Around line 107-110: The traversal-seed archives created via
buildTarGzWithName and added as traversalArchive (f.Add) are not asserted to be
rejected — the fuzz oracle only checks for len(result) > 0 on success; update
the fuzz test so when a seed contains a path-traversal entry (the
traversalArchive built by buildTarGzWithName) the test asserts that processing
returns no successful extraction (e.g., result is empty or an explicit error)
rather than just allowing any non-empty success; specifically add assertions
around the handling of traversalArchive (and similar traversal seeds) to ensure
they produce a failure/empty result from the function under test instead of
being treated as valid.
- Around line 75-84: The fuzz test (FuzzVerifyChecksum) currently stops after
verifyChecksum returns nil without asserting the checksum content, allowing
false positives; after err == nil compute the SHA-256 of fuzzArchiveData, encode
it as a hex string, and assert that checksumData contains a line pairing that
hex digest with the provided assetName (e.g. a line matching "<hex> <whitespace>
<assetName>" or with two spaces depending on your checksum format). Use the same
assertion helpers used elsewhere in tests (t.Helper()/t.Fatalf or
testify/require) so the fuzz case fails when the expected digest/asset pairing
is not present; reference the existing verifyChecksum call and the fuzz closure
in FuzzVerifyChecksum to locate where to add this check.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ddb65535-849a-42ce-9acb-01d370a84f0a
📒 Files selected for processing (22)
.github/workflows/cli.ymlCLAUDE.mdcli/internal/compose/generate_fuzz_test.gocli/internal/config/paths_fuzz_test.gocli/internal/config/state_fuzz_test.gocli/internal/docker/client_fuzz_test.gocli/internal/selfupdate/updater_fuzz_test.gotests/conftest.pytests/unit/api/test_dto_properties.pytests/unit/budget/test_config_properties.pytests/unit/communication/test_message_properties.pytests/unit/config/test_loader_properties.pytests/unit/config/test_utils_properties.pytests/unit/core/test_enums_properties.pytests/unit/core/test_task_properties.pytests/unit/core/test_transitions_properties.pytests/unit/core/test_types_properties.pyweb/src/__tests__/api/client.property.test.tsweb/src/__tests__/utils/constants.property.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/api/client.tsweb/src/api/types.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Backend
- GitHub Check: Test (Python 3.14)
- GitHub Check: CLI Test (windows-latest)
- GitHub Check: Greptile Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
ESLintfor linting andvue-tscfor type checking in the Vue 3 dashboard (web/directory)
Files:
web/src/__tests__/utils/constants.property.test.tsweb/src/api/client.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/api/types.tsweb/src/__tests__/api/client.property.test.ts
web/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Vue 3 dashboard must use PrimeVue + Tailwind CSS for components and styling, Pinia for state management, VueFlow for org chart visualization, and Axios for API client
Files:
web/src/__tests__/utils/constants.property.test.tsweb/src/api/client.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/api/types.tsweb/src/__tests__/api/client.property.test.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
API endpoint modules and TypeScript types in
web/src/api/must mirror Pydantic models from the backend
Files:
web/src/__tests__/utils/constants.property.test.tsweb/src/api/client.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/api/types.tsweb/src/__tests__/api/client.property.test.ts
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Do not usefrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations
Useexcept A, B:(no parentheses) for exception handling — PEP 758 syntax enforced by ruff on Python 3.14
Line length is 88 characters (ruff enforced)
Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names:example-provider,example-large-001,example-medium-001,example-small-001,large/medium/smallas aliases; vendor names only allowed in: (1) Operations design page provider list, (2).claude/skill/agent files, (3) third-party import paths/module names
Files:
tests/unit/core/test_types_properties.pytests/unit/config/test_utils_properties.pytests/unit/core/test_task_properties.pytests/unit/communication/test_message_properties.pytests/conftest.pytests/unit/api/test_dto_properties.pytests/unit/config/test_loader_properties.pytests/unit/core/test_enums_properties.pytests/unit/budget/test_config_properties.pytests/unit/core/test_transitions_properties.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Mark all tests with@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e, or@pytest.mark.slow; maintain 80% code coverage minimum (enforced in CI)
Use@pytest.mark.parametrizefor testing similar cases; do not manually implement retry loops or polling in tests
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in tests; use generic names:test-provider,test-small-001,test-medium-001,test-large-001, orsmall/medium/largeas aliases
Files:
tests/unit/core/test_types_properties.pytests/unit/config/test_utils_properties.pytests/unit/core/test_task_properties.pytests/unit/communication/test_message_properties.pytests/conftest.pytests/unit/api/test_dto_properties.pytests/unit/config/test_loader_properties.pytests/unit/core/test_enums_properties.pytests/unit/budget/test_config_properties.pytests/unit/core/test_transitions_properties.py
cli/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
cli/**/*.go: CLI (Go binary) must support cross-platform builds (linux/darwin/windows × amd64/arm64) via GoReleaser, use Cobra for CLI commands, and passgolangci-lint+go vet+govulncheck
CLI must manage Docker/Compose lifecycle detection and execution, config via XDG/macOS/Windows data directories, and support self-update from GitHub Releases
Files:
cli/internal/docker/client_fuzz_test.gocli/internal/config/state_fuzz_test.gocli/internal/config/paths_fuzz_test.gocli/internal/compose/generate_fuzz_test.gocli/internal/selfupdate/updater_fuzz_test.go
**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.md: Never remove existingCloses#NNN`` PR references in commit messages or documentation — preserve these unless explicitly asked
Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names:example-provider, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases; vendor names only allowed in: (1) Operations design page provider list, (2) `.claude/` skill/agent files, (3) third-party import paths/module names
Files:
CLAUDE.md
.github/workflows/*.yml
📄 CodeRabbit inference engine (CLAUDE.md)
Workflows must use path filtering (
dorny/paths-filter) to run jobs only when their domain is affected (Python/dashboard/docker changes); CI includes lint, type-check, test, audit, and dockerfile-lint jobs running in parallel with aci-passgate
Files:
.github/workflows/cli.yml
.github/workflows/cli.yml
📄 CodeRabbit inference engine (CLAUDE.md)
CLI workflow must lint (
golangci-lint+go vet), test (-race -coverprofile), build cross-compile matrix (linux/darwin/windows × amd64/arm64), rungovulncheck, and use GoReleaser for releases onv*tags; post-release updates checksums in install scripts and appends to release notes
Files:
.github/workflows/cli.yml
🧠 Learnings (20)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow must lint (`golangci-lint` + `go vet`), test (`-race -coverprofile`), build cross-compile matrix (linux/darwin/windows × amd64/arm64), run `govulncheck`, and use GoReleaser for releases on `v*` tags; post-release updates checksums in install scripts and appends to release notes
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Mark all tests with `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, or `pytest.mark.slow`; maintain 80% code coverage minimum (enforced in CI)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI (Go binary) must support cross-platform builds (linux/darwin/windows × amd64/arm64) via GoReleaser, use Cobra for CLI commands, and pass `golangci-lint` + `go vet` + `govulncheck`
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI must manage Docker/Compose lifecycle detection and execution, config via XDG/macOS/Windows data directories, and support self-update from GitHub Releases
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .pre-commit-config.yaml : Pre-commit hooks must include: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint; pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on `cli/**/*.go`); autoupdate must be disabled (`autoupdate_schedule: never`) so Dependabot owns hook version bumps
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to web/__tests__/**/*.{ts,tsx} : Use Vitest for unit testing the Vue 3 dashboard; organize tests by feature
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to web/__tests__/**/*.{ts,tsx} : Use Vitest for unit testing the Vue 3 dashboard; organize tests by feature
Applied to files:
web/src/__tests__/utils/constants.property.test.tsCLAUDE.mdweb/src/__tests__/utils/errors.property.test.tsweb/src/__tests__/api/client.property.test.ts
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to src/ai_company/**/*.py : Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators
Applied to files:
tests/unit/core/test_types_properties.py
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Mark all tests with `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, or `pytest.mark.slow`; maintain 80% code coverage minimum (enforced in CI)
Applied to files:
CLAUDE.mdtests/conftest.py
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI must manage Docker/Compose lifecycle detection and execution, config via XDG/macOS/Windows data directories, and support self-update from GitHub Releases
Applied to files:
CLAUDE.md.github/workflows/cli.ymlcli/internal/compose/generate_fuzz_test.go
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow must lint (`golangci-lint` + `go vet`), test (`-race -coverprofile`), build cross-compile matrix (linux/darwin/windows × amd64/arm64), run `govulncheck`, and use GoReleaser for releases on `v*` tags; post-release updates checksums in install scripts and appends to release notes
Applied to files:
CLAUDE.md.github/workflows/cli.yml
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to cli/**/*.go : CLI (Go binary) must support cross-platform builds (linux/darwin/windows × amd64/arm64) via GoReleaser, use Cobra for CLI commands, and pass `golangci-lint` + `go vet` + `govulncheck`
Applied to files:
CLAUDE.md.github/workflows/cli.yml
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in tests; use generic names: `test-provider`, `test-small-001`, `test-medium-001`, `test-large-001`, or `small`/`medium`/`large` as aliases
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to **/*.py : Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names: `example-provider`, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases; vendor names only allowed in: (1) Operations design page provider list, (2) `.claude/` skill/agent files, (3) third-party import paths/module names
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to **/*.md : Vendor-agnostic naming required everywhere: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or config examples; use generic names: `example-provider`, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases; vendor names only allowed in: (1) Operations design page provider list, (2) `.claude/` skill/agent files, (3) third-party import paths/module names
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .pre-commit-config.yaml : Pre-commit hooks must include: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint; pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on `cli/**/*.go`); autoupdate must be disabled (`autoupdate_schedule: never`) so Dependabot owns hook version bumps
Applied to files:
CLAUDE.md.github/workflows/cli.yml
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to tests/**/*.py : Use `pytest.mark.parametrize` for testing similar cases; do not manually implement retry loops or polling in tests
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to pyproject.toml : All Python dependencies must be pinned with `==` versions in `pyproject.toml`; organize into groups: `test` (pytest + plugins), `dev` (includes test + ruff, mypy, pre-commit, commitizen, pip-audit), `docs` (zensical, mkdocstrings[python], griffe-pydantic); `mem0ai` is required (Mem0 memory backend — currently the only backend)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to src/ai_company/**/*.py : Use immutability patterns: create new objects instead of mutating; for non-Pydantic internal collections use `copy.deepcopy()` at construction + `MappingProxyType` wrapping; for `dict`/`list` fields in frozen Pydantic models use `copy.deepcopy()` at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow must build backend + web images, scan with Trivy (CRITICAL = hard fail, HIGH = warn-only) + Grype (critical cutoff), sign with cosign, and push to GHCR only after scans pass; use `.github/.trivyignore.yaml` and `.github/.grype.yaml` for CVE triage; trigger on push to main and version tags
Applied to files:
CLAUDE.md.github/workflows/cli.yml
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/*.yml : Workflows must use path filtering (`dorny/paths-filter`) to run jobs only when their domain is affected (Python/dashboard/docker changes); CI includes lint, type-check, test, audit, and dockerfile-lint jobs running in parallel with a `ci-pass` gate
Applied to files:
CLAUDE.md.github/workflows/cli.yml
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/pages.yml : Pages workflow must export OpenAPI schema via `scripts/export_openapi.py`, build Astro landing + Zensical docs, merge, and deploy to GitHub Pages on push to main; triggers on docs, site, mkdocs.yml, pyproject.toml, uv.lock, src/ai_company/**, scripts/**, CLI install scripts, and workflow changes
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/release-please-config.json : Release Please must auto-create release PRs on push to main; merging creates git tag (`vX.Y.Z`) + GitHub Release; tag push triggers Docker workflow; after PR creation, auto-update BSL Change Date in LICENSE to 3 years ahead; use `RELEASE_PLEASE_TOKEN` secret so tag creation triggers downstream workflows
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.128Z
Learning: Applies to .github/workflows/pages-preview.yml : PR preview workflow must build on PRs, inject a 'Development Preview' banner, deploy to Cloudflare Pages (`synthorg-pr-preview`), and clean up on PR close; use Cloudflare wrangler from lockfile-pinned `.github/package.json` and check out PR head SHA not merge commit
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T21:51:15.127Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T21:51:15.127Z
Learning: Applies to docker/Dockerfile* : Backend Dockerfile must use 3-stage build (builder → setup → distroless runtime), Chainguard Python base, run as non-root (UID 65532), and follow CIS hardening guidelines
Applied to files:
CLAUDE.md
🧬 Code graph analysis (13)
web/src/__tests__/utils/constants.property.test.ts (1)
web/src/utils/constants.ts (3)
TASK_STATUS_ORDER(23-33)VALID_TRANSITIONS(39-49)TERMINAL_STATUSES(36-36)
tests/unit/config/test_utils_properties.py (1)
src/ai_company/config/utils.py (2)
deep_merge(37-61)to_float(12-34)
web/src/__tests__/utils/errors.property.test.ts (1)
web/src/utils/errors.ts (1)
getErrorMessage(16-66)
tests/unit/core/test_task_properties.py (3)
web/src/api/types.ts (5)
Complexity(26-26)Priority(24-24)TaskStatus(5-14)TaskType(16-22)Task(152-178)web/src/utils/constants.ts (1)
VALID_TRANSITIONS(39-49)tests/unit/communication/test_message_properties.py (1)
test_model_dump_validate_roundtrip(70-74)
tests/unit/communication/test_message_properties.py (1)
web/src/api/types.ts (6)
AttachmentType(436-436)MessagePriority(434-434)MessageType(422-432)Attachment(438-441)Message(451-462)MessageMetadata(443-449)
cli/internal/config/state_fuzz_test.go (2)
cli/internal/config/state.go (1)
Load(43-75)cli/internal/config/paths.go (1)
DataDir(18-31)
cli/internal/config/paths_fuzz_test.go (1)
cli/internal/config/paths.go (1)
SecurePath(58-64)
cli/internal/compose/generate_fuzz_test.go (1)
cli/internal/compose/generate.go (2)
Params(31-40)Generate(58-76)
tests/unit/api/test_dto_properties.py (1)
src/ai_company/api/dto.py (1)
CoordinateTaskRequest(274-313)
tests/unit/core/test_enums_properties.py (2)
web/src/api/types.ts (2)
AutonomyLevel(44-44)SeniorityLevel(32-40)src/ai_company/core/enums.py (2)
compare_autonomy(481-494)compare_seniority(51-64)
web/src/__tests__/api/client.property.test.ts (2)
web/src/api/client.ts (2)
unwrap(56-65)unwrapPaginated(71-90)web/src/api/types.ts (2)
ApiResponse(94-96)PaginatedResponse(105-107)
tests/unit/budget/test_config_properties.py (1)
web/src/api/types.ts (3)
AutoDowngradeConfig(349-354)BudgetAlertConfig(343-347)BudgetConfig(356-363)
tests/unit/core/test_transitions_properties.py (3)
web/src/api/types.ts (1)
TaskStatus(5-14)web/src/utils/constants.ts (1)
VALID_TRANSITIONS(39-49)src/ai_company/core/task_transitions.py (1)
validate_transition(69-103)
🪛 GitHub Actions: Workflow Security
.github/workflows/cli.yml
[informational] 205-205: Template injection risk detected in workflow expansion in cli.yml at line 205. Audit notes potential attacker-controlled code expansion.
🪛 GitHub Check: Dashboard Lint
web/src/__tests__/utils/constants.property.test.ts
[warning] 54-54:
Variable Assigned to Object Injection Sink
[warning] 26-26:
Variable Assigned to Object Injection Sink
🔇 Additional comments (26)
web/src/api/client.ts (1)
58-60: LGTM! Defensive guards for malformed API responses.The added validation ensures that
bodyexists and is an object before accessing envelope properties, preventing crypticTypeErrorexceptions when the API returns unexpected responses (e.g.,null, primitives, or network errors with empty bodies).Also applies to: 75-77
tests/unit/core/test_types_properties.py (1)
1-62: LGTM! Well-structured property tests forNotBlankStrvalidation.The test suite properly covers:
- Valid non-blank strings preserved exactly
- Whitespace-only strings rejected
- Empty strings rejected
- Strings with non-whitespace core surrounded by whitespace accepted
The
pytestmark = pytest.mark.unitcorrectly marks all tests per coding guidelines.cli/internal/config/paths_fuzz_test.go (1)
8-55: LGTM! Solid fuzz test with well-defined invariants.The test properly validates
SecurePathcontracts:
- Relative paths (whose
filepath.Cleanform is not absolute) must be rejected- Successful results must be absolute (
filepath.IsAbs)- Successful results must be already cleaned (
filepath.Clean(result) == result)The seed corpus covers a good range of edge cases including path traversal attempts, Windows-style paths, and special characters.
tests/conftest.py (2)
10-21: LGTM! Well-configured Hypothesis profiles.The CI profile (200 examples, suppressed
too_slowhealth check) balances thoroughness with CI runtime constraints. The dev profile (1000 examples) enables more exhaustive local testing. Environment-based profile selection viaHYPOTHESIS_PROFILEprovides good flexibility.
39-58: LGTM! Improved type annotation for_patched_configure.Changing
_originalfromobjecttoCallable[..., None]correctly reflects that it's callable and eliminates the need for the# type: ignorecomment..github/workflows/cli.yml (2)
158-207: LGTM! Well-structured CLI fuzz job.The job correctly:
- Runs only on main pushes to avoid slowing PR CI
- Uses
continue-on-error: trueat step level for per-target failure isolation- Discovers fuzz targets dynamically with
go test -list- Reports failures as warnings without blocking the gate
Regarding the pipeline security warning at line 205:
${{ steps.fuzz_run.outcome }}is safe—step outcomes are a fixed set of values (success,failure,cancelled,skipped) controlled by GitHub Actions, not user input.
213-213: LGTM! Gate correctly handles fuzz results as non-blocking.Adding
cli-fuzzto theneedsarray ensures it completes before the gate, while the comment clarifies that fuzz warnings are emitted at the step level rather than causing hard failures. This aligns with the PR objective of running fuzz tests as informational.Also applies to: 230-232
cli/internal/config/state_fuzz_test.go (1)
9-52: LGTM! Comprehensive fuzz test for config state loading.The test properly:
- Seeds a variety of inputs including valid JSON, malformed JSON, and binary data
- Caps input size at 64KB to prevent excessive I/O
- Validates that successful
Loadreturns a state with non-empty, absoluteDataDirThe absolute-path assertion (lines 49-51) correctly addresses the invariant that
SecurePathenforces.web/src/__tests__/utils/errors.property.test.ts (2)
5-18: LGTM! Axios mock now uses correct property check.The mock correctly checks for
isAxiosError === true(not_isAxiosError), matching Axios v1.x behavior. Both the default export and named export are properly mocked to handle different import styles.
22-107: LGTM! Comprehensive property tests forgetErrorMessage.The test suite validates key invariants:
- Always returns a non-empty string (lines 23-31)
- Never throws (lines 33-39)
- Filters long messages (≥200 chars) to generic message (lines 52-63)
- Filters JSON-like messages starting with
{(lines 65-76)- Preserves short, non-JSON-like error messages (lines 78-89)
Good coverage of edge cases including empty messages and non-Error inputs.
web/src/api/types.ts (1)
426-432: MessageType union correctly mirrors backend Pydantic enum.All TypeScript message types (task_update, question, announcement, review_request, approval, delegation, status_report, escalation, meeting_contribution, hr_notification) match the backend
MessageTypeenum insrc/ai_company/communication/enums.py. No discrepancies found.web/src/__tests__/utils/constants.property.test.ts (1)
1-65: LGTM! Well-structured structural invariant tests.The test suite comprehensively validates the relationships between
TASK_STATUS_ORDER,VALID_TRANSITIONS, andTERMINAL_STATUSES. The comment at lines 8-10 appropriately explains why fast-check isn't needed for this finite, enumerable input space.The static analysis warnings about "object injection sink" at lines 26 and 54 are false positives —
statusis sourced from known constants (TERMINAL_STATUSES,TASK_STATUS_ORDER), not user input.tests/unit/communication/test_message_properties.py (1)
1-155: LGTM! Comprehensive property tests for Message models.The test suite properly validates:
- Roundtrip serialization for Message, Attachment, and MessageMetadata
- Alias handling (from/sender field population)
- UTC-aware datetime handling with appropriate noqa justifications
The
pytestmark = pytest.mark.unitmarker at line 17 satisfies the coding guidelines requirement for test markers.CLAUDE.md (1)
36-40: LGTM! Documentation accurately reflects new testing infrastructure.The updates comprehensively document:
- Updated pytest invocation pattern (
python -m pytest)- Hypothesis profiles (ci/dev) with example commands
- Go fuzz test behavior and example
- Property-based testing across all three languages
- CI workflow changes for fuzz testing
Also applies to: 64-67, 216-216, 262-262, 280-280, 283-283
cli/internal/docker/client_fuzz_test.go (1)
7-49: LGTM! Well-designed fuzz test for version comparison.The test properly validates:
- Reflexivity:
versionAtLeast(x, x)is always true- Total-order completeness: at least one of
versionAtLeast(a, b)orversionAtLeast(b, a)must be trueThe seed corpus at lines 9-22 provides excellent coverage of edge cases including empty strings, single-component versions, pre-release suffixes, and v-prefixed versions. The antisymmetry note at lines 43-48 appropriately explains the normalization behavior.
tests/unit/core/test_transitions_properties.py (1)
1-87: LGTM! Comprehensive property tests for task transition validation.The test suite validates all key invariants:
- Consistency between
validate_transitionbehavior andVALID_TRANSITIONSmap- Terminal states have no outgoing transitions
- Every
TaskStatushas a transition entry- All valid transitions succeed; all invalid transitions raise
ValueErrorThe
pytestmark = pytest.mark.unitat line 10 satisfies the marker requirement.tests/unit/core/test_enums_properties.py (1)
1-101: LGTM! Thorough algebraic property tests for enum comparators.The tests validate all expected comparator properties:
- Reflexivity:
compare_X(a, a) == 0- Anti-symmetry:
compare_X(a, b) == -compare_X(b, a)- Transitivity: if
a >= bandb >= cthena >= c- Totality: returns int, equals zero iff
a == bThe
pytestmark = pytest.mark.unitat line 14 satisfies the marker requirement.tests/unit/budget/test_config_properties.py (1)
1-206: LGTM! Comprehensive property tests for budget configuration validation.The test suite validates:
- BudgetAlertConfig: threshold ordering invariant (
warn < critical < hard_stop) and roundtrip serialization- AutoDowngradeConfig: self-downgrade rejection, duplicate source rejection, and valid map constraints
- BudgetConfig: cross-field constraints (
per_task_limitandper_agent_daily_limitmust not exceedtotal_monthlyunless total is zero)The
pytestmark = pytest.mark.unitat line 14 satisfies the marker requirement.tests/unit/config/test_loader_properties.py (2)
49-57: Past review comment addressed.The equality assertion (
assert result == dataat line 56) has been added as requested in the previous review, properly verifying pass-through semantics alongside the identity check.
1-136: LGTM! Comprehensive crash-safety property tests for config loader.The test suite validates:
_substitute_env_vars: pass-through for non-pattern data, crash-safety for arbitrary patterns, non-string value preservation, and default resolution_parse_yaml_string: crash-safety for arbitrary text, empty/null handling, valid YAML parsing, non-mapping rejection, and garbled input handlingThe use of
event()for Hypothesis statistics (lines 66-67, 99-102, 132-135) provides useful debugging information during property test runs.tests/unit/config/test_utils_properties.py (1)
54-165: Strong property coverage fordeep_mergeandto_float.The suite checks immutability, recursive merge semantics, override behavior, and malformed/special float inputs with clear invariants.
cli/internal/compose/generate_fuzz_test.go (1)
8-141: Fuzz contracts are well-scoped and useful.Good no-panic posture plus postcondition checks on successful validation/generation paths.
tests/unit/core/test_task_properties.py (1)
57-144: Task property suite is robust and focused.Roundtrip, validation, valid/invalid transitions, and status override protection are covered cleanly.
web/src/__tests__/api/client.property.test.ts (1)
55-68: Great hardening for arbitrary-envelope crash safety.Catching and explicitly rejecting
TypeErrorensures malformed bodies are treated as controlled API errors.Also applies to: 156-170
tests/unit/api/test_dto_properties.py (1)
25-218: DTO property tests meaningfully strengthen validation coverage.Nice balance of invariants, boundary/error checks, and model roundtrip assertions.
cli/internal/selfupdate/updater_fuzz_test.go (1)
14-56:FuzzCompareSemverinvariants are well-chosen.Reflexivity and antisymmetry checks provide strong guardrails for compare behavior across arbitrary inputs.
| // Seed: tar.gz with path-traversal entry name. | ||
| traversalArchive := buildTarGzWithName(f, "../../synthorg") | ||
| f.Add(traversalArchive) | ||
|
|
There was a problem hiding this comment.
Traversal seeds are added but never required to fail.
Lines 108-109 and 144-145 seed ../../... archive entries, but the fuzz oracle only checks len(result) > 0 on success. If traversal entries are incorrectly accepted, this test still passes.
🔒 Proposed fix
// Seed: tar.gz with path-traversal entry name.
traversalArchive := buildTarGzWithName(f, "../../synthorg")
f.Add(traversalArchive)
+ if out, err := extractFromTarGz(traversalArchive); err == nil {
+ f.Fatalf("extractFromTarGz accepted traversal entry (out_len=%d)", len(out))
+ }
@@
// Seed: zip with path-traversal entry name.
traversalZip := buildZipWithName(f, "../../synthorg.exe")
f.Add(traversalZip)
+ if out, err := extractFromZip(traversalZip); err == nil {
+ f.Fatalf("extractFromZip accepted traversal entry (out_len=%d)", len(out))
+ }Also applies to: 117-128, 143-145, 153-164
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@cli/internal/selfupdate/updater_fuzz_test.go` around lines 107 - 110, The
traversal-seed archives created via buildTarGzWithName and added as
traversalArchive (f.Add) are not asserted to be rejected — the fuzz oracle only
checks for len(result) > 0 on success; update the fuzz test so when a seed
contains a path-traversal entry (the traversalArchive built by
buildTarGzWithName) the test asserts that processing returns no successful
extraction (e.g., result is empty or an explicit error) rather than just
allowing any non-empty success; specifically add assertions around the handling
of traversalArchive (and similar traversal seeds) to ensure they produce a
failure/empty result from the function under test instead of being treated as
valid.
…ed intent - FuzzVerifyChecksum: assert that on success, checksumData actually contains the expected SHA-256 hash paired with the asset name - Traversal seeds: add comments explaining why extractFromTarGz/Zip intentionally extracts traversal-named entries (filepath.Base matching) - CI: pass steps.fuzz_run.outcome through env var to avoid zizmor template-injection finding
…heck - cli-pass: add needs.cli-fuzz.result to RESULTS so infra failures (checkout, setup-go) are caught; fuzz findings remain informational via step-level continue-on-error - FuzzYamlStr: replace single-char lookback with backslash parity count to correctly detect unescaped quotes after \ sequences
There was a problem hiding this comment.
Pull request overview
Adds fuzz/property-based testing across the Go CLI, Python backend, and Vue dashboard to improve robustness of parsers/validators and to satisfy OSSF Scorecard “Fuzzing”, plus wires Go fuzzing into CI (main-only) and makes a small landing-page layout cleanup.
Changes:
- Add Go native fuzz targets for security-sensitive CLI parsing/extraction paths and a main-branch CI job to run them.
- Add Hypothesis (Python) + fast-check (Vue) property tests across core validation/model/utility layers, plus shared Hypothesis configuration.
- Update a few supporting types/docs/infra files (API message types, dependencies/locks,
.gitignore, landing page spacing/CTA cleanup).
Reviewed changes
Copilot reviewed 27 out of 30 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/api/types.ts | Extends frontend MessageType union to match backend message type set. |
| web/src/api/client.ts | Hardens unwrap / unwrapPaginated against non-object envelopes to avoid TypeErrors. |
| web/src/tests/utils/sanitizeForLog.property.test.ts | fast-check properties for sanitizeForLog invariants (control chars, truncation, no-throw). |
| web/src/tests/utils/format.property.test.ts | fast-check properties for formatters (never throw, basic invariants). |
| web/src/tests/utils/errors.property.test.ts | fast-check properties for getErrorMessage plus axios mocking. |
| web/src/tests/utils/constants.property.test.ts | Structural invariant tests for transition constants (no randomness). |
| web/src/tests/api/client.property.test.ts | Property tests for API envelope unwrapping behavior on arbitrary inputs. |
| web/package.json | Adds fast-check dev dependency. |
| web/package-lock.json | Locks fast-check (and pure-rand) versions. |
| uv.lock | Adds hypothesis==6.151.5 and related lock updates. |
| pyproject.toml | Adds hypothesis==6.151.5 to the test dependency group. |
| tests/conftest.py | Registers/loads global Hypothesis profiles (ci/dev) and tightens structlog wrapper typing. |
| tests/unit/core/test_types_properties.py | Hypothesis properties for NotBlankStr acceptance/rejection boundaries. |
| tests/unit/core/test_transitions_properties.py | Hypothesis properties asserting validate_transition matches VALID_TRANSITIONS. |
| tests/unit/core/test_task_properties.py | Hypothesis + example tests for Task roundtrip, self-dependency, transitions. |
| tests/unit/core/test_enums_properties.py | Hypothesis algebraic properties for enum comparators (reflexive/antisymmetry/transitivity/totality). |
| tests/unit/config/test_utils_properties.py | Hypothesis properties for deep_merge and to_float. |
| tests/unit/config/test_loader_properties.py | Hypothesis crash-safety properties for YAML parsing/env substitution helpers. |
| tests/unit/communication/test_message_properties.py | Hypothesis roundtrip/alias properties for Message and related models. |
| tests/unit/budget/test_config_properties.py | Hypothesis properties for budget config cross-field constraints and roundtrips. |
| tests/unit/api/test_dto_properties.py | Hypothesis properties for DTO validation (uniqueness, metadata bounds, action_type format). |
| cli/internal/compose/generate_fuzz_test.go | Adds fuzz targets for YAML quoting, param validation, and compose generation. |
| cli/internal/selfupdate/updater_fuzz_test.go | Adds fuzz targets for semver compare, checksum verification, tar.gz/zip extraction. |
| cli/internal/config/paths_fuzz_test.go | Adds fuzz target for SecurePath invariants (absolute/clean). |
| cli/internal/config/state_fuzz_test.go | Adds fuzz target for crash-safety of state JSON load. |
| cli/internal/docker/client_fuzz_test.go | Adds fuzz target for versionAtLeast comparator invariants. |
| .github/workflows/cli.yml | Adds cli-fuzz job (main-only) and includes it in cli-pass gate as informational. |
| .gitignore | Ignores .hypothesis/ cache directory. |
| CLAUDE.md | Documents new test commands and property/fuzz testing conventions. |
| site/src/pages/index.astro | Adjusts section spacing and removes duplicate terminal block from final CTA. |
Files not reviewed (1)
- web/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for target in $FUZZ_TARGETS; do | ||
| echo "::group::Fuzzing $target" | ||
| go test -fuzz="^${target}$" -fuzztime=30s ${{ matrix.package }} | ||
| echo "::endgroup::" | ||
| done |
| // If extraction succeeded, the result must be non-empty. | ||
| if len(result) == 0 { | ||
| t.Fatal("extractFromTarGz returned nil/empty data without error") | ||
| } |
| // If extraction succeeded, the result must be non-empty. | ||
| if len(result) == 0 { | ||
| t.Fatal("extractFromZip returned nil/empty data without error") | ||
| } |
🤖 I have created a release *beep* *boop* --- ## [0.2.0](v0.1.4...v0.2.0) (2026-03-15) ##First probably usable release? Most likely not no and everything will break ### Features * add /get/ installation page for CLI installer ([#413](#413)) ([6a47e4a](6a47e4a)) * add cross-platform Go CLI for container lifecycle management ([#401](#401)) ([0353d9e](0353d9e)), closes [#392](#392) * add explicit ScanOutcome signal to OutputScanResult ([#394](#394)) ([be33414](be33414)), closes [#284](#284) * add meeting scheduler, event-triggered meetings, and Go CLI lint fixes ([#407](#407)) ([5550fa1](5550fa1)) * wire MultiAgentCoordinator into runtime ([#396](#396)) ([7a9e516](7a9e516)) ### Bug Fixes * CLA signatures branch + declutter repo root ([#409](#409)) ([cabe953](cabe953)) * correct Release Please branch name in release workflow ([#410](#410)) ([515d816](515d816)) * replace slsa-github-generator with attest-build-provenance, fix DAST ([#424](#424)) ([eeaadff](eeaadff)) * resolve CodeQL path-injection alerts in Go CLI ([#412](#412)) ([f41bf16](f41bf16)) ### Refactoring * rename package from ai_company to synthorg ([#422](#422)) ([df27c6e](df27c6e)), closes [#398](#398) ### Tests * add fuzz and property-based testing across all layers ([#421](#421)) ([115a742](115a742)) ### CI/CD * add SLSA L3 provenance for CLI binaries and container images ([#423](#423)) ([d3dc75d](d3dc75d)) * bump the major group with 4 updates ([#405](#405)) ([20c7a04](20c7a04)) ### Maintenance * bump github.com/spf13/cobra from 1.9.1 to 1.10.2 in /cli in the minor-and-patch group ([#402](#402)) ([e31edbb](e31edbb)) * narrow BSL Additional Use Grant and add CLA ([#408](#408)) ([5ab15bd](5ab15bd)), closes [#406](#406) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
cli-fuzzjob incli.yml(main-only, 30s/target, continue-on-error, matrix over 4 packages).gitignore, CLAUDE.md updatesPre-reviewed by 10 agents, 26 findings addressed before first push.
Closes #414
Test plan
uv run python -m pytest tests/ -n auto --cov=ai_company --cov-fail-under=80— 7989 passed, 94.49% coveragenpm --prefix web run test— 520 passednpm --prefix web run type-check— cleancd cli && go test ./...— all packages passcd cli && go vet ./...— clean