Skip to content

test: add fuzz and property-based testing across all layers#421

Merged
Aureliolo merged 7 commits intomainfrom
test/fuzz-property-testing
Mar 14, 2026
Merged

test: add fuzz and property-based testing across all layers#421
Aureliolo merged 7 commits intomainfrom
test/fuzz-property-testing

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Go CLI: 10 native fuzz functions across 5 files (compose, selfupdate, config, docker) — targets security-critical input parsing (YAML injection, archive extraction, path traversal, version comparison, checksum verification)
  • Python: 69 Hypothesis property tests across 9 files — model validation roundtrips, algebraic properties (transitivity, antisymmetry, totality), boundary validation, crash-safety for parsers
  • Vue dashboard: 55 fast-check property tests across 5 files — utility function robustness (sanitizeForLog, formatters, error handling, API client unwrap, transition constants)
  • CI: new cli-fuzz job in cli.yml (main-only, 30s/target, continue-on-error, matrix over 4 packages)
  • Infrastructure: hypothesis + fast-check deps, Hypothesis CI/dev profiles, .gitignore, CLAUDE.md updates
  • Landing page: remove duplicate terminal block from final CTA, tighten section spacing

Pre-reviewed by 10 agents, 26 findings addressed before first push.

Closes #414

Test plan

  • Python: uv run python -m pytest tests/ -n auto --cov=ai_company --cov-fail-under=80 — 7989 passed, 94.49% coverage
  • Web: npm --prefix web run test — 520 passed
  • Web: npm --prefix web run type-check — clean
  • Go: cd cli && go test ./... — all packages pass
  • Go: cd cli && go vet ./... — clean
  • Lint: ruff, mypy, ESLint, golangci-lint — all clean
  • Pre-push hooks: all passed

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
Copilot AI review requested due to automatic review settings March 14, 2026 21:58
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 14, 2026

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 1 package(s) with unknown licenses.
See the Details below.

License Issues

uv.lock

PackageVersionLicenseIssue Type
hypothesis6.151.5NullUnknown License
Allowed Licenses: MIT, MIT-0, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, MPL-2.0, PSF-2.0, Unlicense, 0BSD, CC0-1.0, Python-2.0, Python-2.0.1, LicenseRef-scancode-free-unknown, LicenseRef-scancode-protobuf, LicenseRef-scancode-google-patent-license-golang, ZPL-2.1, LGPL-2.0-only, LGPL-2.1-only, LGPL-3.0-only, LGPL-3.0-or-later, BlueOak-1.0.0
Excluded from license check: pkg:pypi/mem0ai@1.0.5, pkg:pypi/numpy@2.4.3, pkg:pypi/qdrant-client@1.17.0, pkg:pypi/posthog@7.9.12, pkg:npm/@img/sharp-wasm32@0.33.5, pkg:npm/@img/sharp-win32-ia32@0.33.5, pkg:npm/@img/sharp-win32-x64@0.33.5

OpenSSF Scorecard

PackageVersionScoreDetails
pip/hypothesis 6.151.5 UnknownUnknown
npm/fast-check 4.6.0 🟢 8.1
Details
CheckScoreReason
Code-Review⚠️ 0Found 0/11 approved changesets -- score normalized to 0
Maintained🟢 1030 commit(s) and 18 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Security-Policy🟢 10security policy file detected
Dependency-Update-Tool🟢 10update tool detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Pinned-Dependencies🟢 9dependency not pinned by hash detected -- score normalized to 9
License🟢 10license file detected
CII-Best-Practices🟢 5badge detected: Passing
Signed-Releases⚠️ -1no releases found
Packaging🟢 10packaging workflow detected
Fuzzing🟢 10project is fuzzed
Branch-Protection🟢 3branch protection is not maximal on development and all release branches
SAST🟢 10SAST tool is run on all commits
Vulnerabilities🟢 46 existing vulnerabilities detected
CI-Tests🟢 1030 out of 30 merged PRs checked by a CI test -- score normalized to 10
Contributors🟢 10project has 4 contributing companies or organizations
npm/pure-rand 8.0.0 🟢 6
Details
CheckScoreReason
Code-Review⚠️ 0Found 0/22 approved changesets -- score normalized to 0
Maintained🟢 1030 commit(s) and 4 issue activity found in the last 90 days -- score normalized to 10
Binary-Artifacts🟢 10no binaries found in the repo
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 9dependency not pinned by hash detected -- score normalized to 9
Security-Policy⚠️ 0security policy file not detected
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Packaging🟢 10packaging workflow detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0

Scanned Files

  • uv.lock
  • web/package-lock.json

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 14, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2d5f2fa8-f520-451c-8a14-5a8ea9dcd526

📥 Commits

Reviewing files that changed from the base of the PR and between f4b2f47 and 889a2f3.

📒 Files selected for processing (3)
  • .github/workflows/cli.yml
  • cli/internal/compose/generate_fuzz_test.go
  • cli/internal/selfupdate/updater_fuzz_test.go

📝 Walkthrough

Summary by CodeRabbit

  • Tests
    • Added extensive property-based tests and new fuzz suites; CI now runs CLI fuzzing and surfaces fuzz outcomes as non-fatal warnings.
  • Chores
    • Added test dependencies (Hypothesis, fast-check) and updated test workflows to include fuzz coverage.
  • Style
    • Reduced vertical spacing site-wide and removed an interactive terminal example.
  • Documentation
    • Expanded testing guidance with property-based and fuzzing examples and CLI notes.
  • Chores
    • Updated web message type set to include additional message kinds.

Walkthrough

Adds 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

Cohort / File(s) Summary
Go CLI fuzz tests
cli/internal/compose/generate_fuzz_test.go, cli/internal/config/paths_fuzz_test.go, cli/internal/config/state_fuzz_test.go, cli/internal/docker/client_fuzz_test.go, cli/internal/selfupdate/updater_fuzz_test.go
Adds multiple Fuzz* tests covering YAML generation, params validation, secure paths, state loading, version comparison, checksum verification, and archive extraction; asserts invariants, non-panics, and behavior on malformed inputs.
Python property tests & Hypothesis config
tests/unit/api/test_dto_properties.py, tests/unit/budget/test_config_properties.py, tests/unit/communication/test_message_properties.py, tests/unit/config/test_loader_properties.py, tests/unit/config/test_utils_properties.py, tests/unit/core/test_enums_properties.py, tests/unit/core/test_task_properties.py, tests/unit/core/test_transitions_properties.py, tests/unit/core/test_types_properties.py, tests/conftest.py, pyproject.toml, .gitignore
Adds ~9 Hypothesis-based test modules for models, utils, enums, transitions, and configs; registers CI/dev Hypothesis profiles in tests/conftest.py; adds hypothesis to test deps and ignores .hypothesis/.
Vue frontend property tests & runtime guards
web/src/__tests__/api/client.property.test.ts, web/src/__tests__/utils/constants.property.test.ts, web/src/__tests__/utils/errors.property.test.ts, web/src/__tests__/utils/format.property.test.ts, web/src/__tests__/utils/sanitizeForLog.property.test.ts, web/src/api/client.ts, web/src/api/types.ts, web/package.json
Adds fast-check property tests for API clients, constants, error handling, formatting, and sanitization; tightens runtime guards in unwrap/unwrapPaginated; extends MessageType union; adds fast-check devDependency.
CI workflow and docs/website
.github/workflows/cli.yml, CLAUDE.md, site/src/pages/index.astro
Introduces cli-fuzz GitHub Actions job (matrix over CLI packages, 30s per fuzz target, continue-on-error) and wires result into cli-pass as informational warnings; updates docs for Hypothesis/fast-check and python -m pytest; reduces site vertical padding and removes a terminal example.
Misc
.gitignore
Adds .hypothesis/ to ignore Hypothesis cache files.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title 'test: add fuzz and property-based testing across all layers' directly and concisely describes the main change: comprehensive addition of fuzz testing and property-based testing infrastructure.
Description check ✅ Passed Description provides detailed summary of changes across Go, Python, Vue, CI, and infrastructure, covering all major components of the changeset with context and test results.
Linked Issues check ✅ Passed All objectives from issue #414 are met: Go fuzz functions added (10 across 5 files), Hypothesis tests added (69 across 9 files), fast-check tests added (55 across 5 files), CI integration with cli-fuzz job, and infrastructure updates completed.
Out of Scope Changes check ✅ Passed Changes are well-scoped to testing infrastructure and documentation. Landing page spacing/terminal block removal is minor UI polish related to content density and does not constitute material out-of-scope work.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test/fuzz-property-testing
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch test/fuzz-property-testing
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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

  • Go CLI Fuzzing: Introduced 10 native fuzz functions across compose, selfupdate, config, and docker packages, targeting security-critical input parsing (e.g., YAML injection, archive extraction, path traversal, version comparison, checksum verification).
  • Python Property Testing: Added 69 Hypothesis property tests across 9 files to validate model roundtrips, algebraic properties, boundary conditions, and crash-safety for parsers.
  • Vue Dashboard Property Testing: Implemented 55 fast-check property tests across 5 files to ensure robustness of utility functions (e.g., sanitizeForLog, formatters, error handling, API client unwrap) and transition constants.
  • CI Integration: A new cli-fuzz job was added to cli.yml for continuous fuzz testing of the Go CLI, configured to run on main branch only with a 30-second timeout per target and continue-on-error.
  • Infrastructure Updates: Dependencies for Hypothesis and fast-check were added, Hypothesis CI/dev profiles configured, .gitignore updated to ignore Hypothesis-generated files, and CLAUDE.md documentation expanded to reflect new testing methodologies.
  • Landing Page Refinement: Removed a duplicate terminal block from the final Call-to-Action section and adjusted section spacing for a cleaner, more concise layout.
Changelog
  • .gitignore
    • Added .hypothesis/ to the list of ignored files.
  • CLAUDE.md
    • Updated Python pytest commands to explicitly use python -m pytest.
    • Added a new command for running Hypothesis property tests with a 'dev' profile.
    • Updated the Go testing command to clarify its role for fuzzing seed corpus.
    • Added an example command for running a specific Go fuzz test.
    • Expanded the "Development" section with a new point on property-based testing methodologies used across Python, Vue, and Go.
    • Updated the description of the CLI CI workflow to include fuzz testing.
    • Updated the "Dependencies" section to reflect the addition of hypothesis and fast-check.
  • cli/internal/compose/generate_fuzz_test.go
    • Added fuzz tests for yamlStr, validateParams, and Generate functions, covering YAML string handling, parameter validation, and compose file generation.
  • cli/internal/config/paths_fuzz_test.go
    • Added a fuzz test for SecurePath to validate path sanitization and prevent path traversal vulnerabilities.
  • cli/internal/config/state_fuzz_test.go
    • Added a fuzz test for LoadState to ensure robust handling of various JSON inputs for configuration state.
  • cli/internal/docker/client_fuzz_test.go
    • Added a fuzz test for versionAtLeast to verify semantic version comparison logic.
  • cli/internal/selfupdate/updater_fuzz_test.go
    • Added fuzz tests for compareSemver, verifyChecksum, extractFromTarGz, and extractFromZip to enhance the security and reliability of the self-update mechanism.
  • pyproject.toml
    • Added hypothesis to the test dependency group.
  • site/src/pages/index.astro
    • Adjusted vertical padding for several sections from py-24 to py-16.
    • Removed a duplicate terminal block from the final Call-to-Action section.
  • tests/conftest.py
    • Configured Hypothesis profiles (ci and dev) for test execution, allowing environment variable control.
  • tests/unit/api/test_dto_properties.py
    • Added property-based tests for CoordinateTaskRequest and CreateApprovalRequest DTOs, validating agent name uniqueness, metadata constraints, and roundtrip serialization.
  • tests/unit/budget/test_config_properties.py
    • Added property-based tests for BudgetAlertConfig, AutoDowngradeConfig, and BudgetConfig, verifying threshold ordering, downgrade map logic, and budget limits.
  • tests/unit/communication/test_message_properties.py
    • Added property-based tests for Message, Attachment, and MessageMetadata models, ensuring correct serialization, deserialization, and alias handling.
  • tests/unit/config/test_loader_properties.py
    • Added property-based tests for _substitute_env_vars and _parse_yaml_string, focusing on crash-safety and correct handling of various inputs.
  • tests/unit/config/test_utils_properties.py
    • Added property-based tests for deep_merge and to_float utility functions, verifying merge logic, immutability, and numeric conversion robustness.
  • tests/unit/core/test_enums_properties.py
    • Added property-based tests for compare_seniority and compare_autonomy functions, validating their algebraic properties (reflexivity, anti-symmetry, transitivity, totality).
  • tests/unit/core/test_task_properties.py
    • Added property-based tests for the Task model, including roundtrip serialization, self-dependency rejection, and valid/invalid status transitions.
  • tests/unit/core/test_transitions_properties.py
    • Added property-based tests for validate_transition and VALID_TRANSITIONS map, ensuring consistency and correctness of task status transitions.
  • tests/unit/core/test_types_properties.py
    • Added property-based tests for the NotBlankStr Pydantic type, validating its behavior with various string inputs including whitespace.
  • uv.lock
    • Updated Python dependency lock file to include hypothesis and related changes.
  • web/package-lock.json
    • Updated Node.js dependency lock file to include fast-check and pure-rand.
  • web/package.json
    • Added fast-check as a dev dependency.
  • web/src/tests/api/client.property.test.ts
    • Added property-based tests for unwrap and unwrapPaginated API client utility functions, verifying their robustness against various API response structures.
  • web/src/tests/utils/constants.property.test.ts
    • Added property-based tests to verify invariants of task status constants (TASK_STATUS_ORDER, VALID_TRANSITIONS, TERMINAL_STATUSES).
  • web/src/tests/utils/errors.property.test.ts
    • Added property-based tests for getErrorMessage, ensuring it handles various error inputs gracefully and returns meaningful messages.
  • web/src/tests/utils/format.property.test.ts
    • Added property-based tests for formatting utility functions (formatDate, formatUptime, formatCurrency, formatLabel, formatNumber), verifying their output consistency and error handling.
  • web/src/tests/utils/sanitizeForLog.property.test.ts
    • Added property-based tests for sanitizeForLog, ensuring it correctly removes control characters and limits output length for logging purposes.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/cli.yml
Activity
  • The pull request was pre-reviewed by 10 agents, and 26 findings were addressed before the initial push, indicating a thorough internal review process.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 14, 2026 21:58 — with GitHub Actions Inactive
@socket-security
Copy link
Copy Markdown

socket-security bot commented Mar 14, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​fast-check@​4.6.010010010085100

View full report

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 14, 2026

Greptile Summary

This 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:

  • All previously flagged issues from the thread (absolute-path check in FuzzLoadState, HealthCheck.too_slow in dev profile, hardcoded _TERMINAL_STATES) have been resolved in this revision.
  • Algebraic properties (reflexivity, antisymmetry, total-order) in the Go fuzz tests are correctly formulated, including the intentional asymmetry documentation for versionAtLeast.
  • The CI fuzz job correctly uses step-level continue-on-error: true so fuzz findings surface as warnings without blocking the release gate; cli-pass handles skipped fuzz runs on PRs cleanly via if: always().
  • Two style-level concerns in updater_fuzz_test.go: (1) The 1-MB compressed-size cap in FuzzExtractFromTarGz / FuzzExtractFromZip does not bound the decompressed output size, creating a potential OOM risk during extended local fuzzing. (2) The FuzzVerifyChecksum post-success invariant check may emit a false positive if the production verifyChecksum accepts binary-mode checksum lines (*-prefixed filenames) — the invariant should mirror the production code's exact filename-matching logic.

Confidence Score: 4/5

  • Safe to merge; two style-level concerns in the Go fuzz harness do not affect production correctness.
  • The changes are purely additive test infrastructure. No production logic is altered except the addition of unwrapPaginated in web/src/api/client.ts, which is straightforward and well-tested. The two flagged concerns (decompression size cap and verifyChecksum invariant) are fuzz-harness quality issues, not bugs in production code. All previously-raised review thread items have been addressed.
  • cli/internal/selfupdate/updater_fuzz_test.go — decompressed-size cap and verifyChecksum invariant correctness.

Important Files Changed

Filename Overview
cli/internal/selfupdate/updater_fuzz_test.go Adds fuzz tests for compareSemver, verifyChecksum, extractFromTarGz, and extractFromZip. Algebraic properties (reflexivity, antisymmetry, total-order) are well-constructed. Two concerns: no decompressed-size cap creates a potential OOM during extended local fuzzing, and the verifyChecksum invariant check may false-positive if the production code supports binary-mode (*-prefixed) checksum filenames.
cli/internal/compose/generate_fuzz_test.go Fuzz tests for yamlStr, validateParams, and Generate. Invariants are correct: double-quote escaping logic, port-range/sandbox validation post-conditions, and Generate nil-on-error contract. Well-seeded with security-relevant edge cases (YAML injection characters, boundary ports).
cli/internal/config/paths_fuzz_test.go FuzzSecurePath correctly checks that relative paths are rejected and that successful results are absolute and clean. Good seed corpus covering traversal attempts, Windows paths, null bytes, and whitespace.
cli/internal/config/state_fuzz_test.go FuzzLoadState now checks both non-empty and filepath.IsAbs for DataDir (the previously-flagged comment/assertion mismatch is resolved). Correctly caps input at 64 KB and covers a range of degenerate JSON inputs.
cli/internal/docker/client_fuzz_test.go FuzzVersionAtLeast checks reflexivity and total-order completeness. The asymmetric suffix-stripping behavior of versionAtLeast (applies to got but not min) is correctly documented, and the check is scoped to the total-order property rather than full antisymmetry.
.github/workflows/cli.yml New cli-fuzz job runs on main-only pushes with continue-on-error at the step level, emitting warnings rather than hard failures. Correctly added to cli-pass needs; since cli-pass uses if: always() and the gate only rejects failure
tests/conftest.py Hypothesis CI profile (200 examples, suppress HealthCheck.too_slow) and dev profile (1000 examples, no suppression) are correctly registered and loaded. HealthCheck.too_slow is intentionally absent from the dev profile, preserving it as a local signal.
tests/unit/core/test_transitions_properties.py _TERMINAL_STATES is now derived dynamically from VALID_TRANSITIONS (resolving the previously flagged hardcoding concern). All five property tests cover the full transition matrix correctly.
web/src/tests/api/client.property.test.ts Property tests for unwrap and unwrapPaginated cover success/error discrimination, malformed envelopes, and type safety (Error vs TypeError). The arbitrary-body test correctly validates that the function never propagates a TypeError.
web/src/api/client.ts Adds unwrapPaginated alongside the existing unwrap helper. Both follow the same guard pattern (!body

Comments Outside Diff (1)

  1. cli/internal/selfupdate/updater_fuzz_test.go, line 130-145 (link)

    No decompressed-size cap — zip/tar bomb risk during fuzzing

    The 1-MB guard at the top of FuzzExtractFromTarGz (line 130) and FuzzExtractFromZip (line 167) bounds the compressed bytes, but not the decompressed output. Compressed data is highly space-efficient for repetitive byte sequences; a valid gzip/zip archive that fits inside 1 MB can easily expand to hundreds of MB (or more) when inflated, which can OOM the fuzzer process — most notably for a developer running the target locally without the CI 30-second wall-clock limit.

    Consider wrapping the decompression reader with io.LimitReader inside the production extractFromTarGz/extractFromZip helpers, or adding a quick pre-check in the fuzz harness itself:

    // After the compressed-size guard, also cap decompressed data consumed.
    // This protects both the fuzz harness and (more importantly) the production code.
    if len(data) > 1024*1024 {
        return
    }
    // In the production helper, wrap the gzip reader:
    // gr, _ := gzip.NewReader(r)
    // limited := io.LimitReader(gr, 32*1024*1024) // e.g. 32 MB

    The same concern applies to FuzzExtractFromZip (lines 165–184), where zip.NewReader can read all entry data into memory.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: cli/internal/selfupdate/updater_fuzz_test.go
Line: 130-145

Comment:
**No decompressed-size cap — zip/tar bomb risk during fuzzing**

The 1-MB guard at the top of `FuzzExtractFromTarGz` (line 130) and `FuzzExtractFromZip` (line 167) bounds the *compressed* bytes, but not the *decompressed* output. Compressed data is highly space-efficient for repetitive byte sequences; a valid gzip/zip archive that fits inside 1 MB can easily expand to hundreds of MB (or more) when inflated, which can OOM the fuzzer process — most notably for a developer running the target locally without the CI 30-second wall-clock limit.

Consider wrapping the decompression reader with `io.LimitReader` inside the production `extractFromTarGz`/`extractFromZip` helpers, or adding a quick pre-check in the fuzz harness itself:

```go
// After the compressed-size guard, also cap decompressed data consumed.
// This protects both the fuzz harness and (more importantly) the production code.
if len(data) > 1024*1024 {
    return
}
// In the production helper, wrap the gzip reader:
// gr, _ := gzip.NewReader(r)
// limited := io.LimitReader(gr, 32*1024*1024) // e.g. 32 MB
```

The same concern applies to `FuzzExtractFromZip` (lines 165–184), where `zip.NewReader` can read all entry data into memory.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: cli/internal/selfupdate/updater_fuzz_test.go
Line: 586-596

Comment:
**Invariant check may false-positive if `verifyChecksum` supports binary-mode filenames**

The invariant after a successful `verifyChecksum` call searches for a line with exactly `len(parts) == 2 && parts[0] == expectedHash && parts[1] == assetName`. Many checksum tools (including GNU `sha256sum`) also emit lines in binary mode: `"<hash>  *<filename>"` — where the leading `*` denotes binary mode. If `verifyChecksum` strips the `*` prefix when matching filenames (a common implementation choice), the fuzzer could craft a checksumData like `"<expectedHash>  *test_asset.tar.gz"` that passes production validation, but the test's invariant check would see `parts[1] == "*test_asset.tar.gz"` (≠ `"test_asset.tar.gz"`) and fire `t.Fatalf` — a false positive.

The invariant should mirror whatever filename-parsing logic `verifyChecksum` uses (e.g., trimming a leading `*` from `parts[1]` before comparing). If the production code only ever emits/accepts the plain two-space format this is a non-issue, but it's worth confirming and, if so, adding a brief comment to that effect.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 889a2f3

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-pass will never detect fuzz test failures due to job-level continue-on-error: true.

With continue-on-error: true at the job level, needs.cli-fuzz.result always evaluates to 'success' even when steps fail. The condition checking for "failure" in FUZZ_RESULT will never trigger, so fuzz failures will silently pass the gate.

Move continue-on-error: true to 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a47e4a and a732ca2.

⛔ Files ignored due to path filters (2)
  • uv.lock is excluded by !**/*.lock
  • web/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (26)
  • .github/workflows/cli.yml
  • .gitignore
  • CLAUDE.md
  • cli/internal/compose/generate_fuzz_test.go
  • cli/internal/config/paths_fuzz_test.go
  • cli/internal/config/state_fuzz_test.go
  • cli/internal/docker/client_fuzz_test.go
  • cli/internal/selfupdate/updater_fuzz_test.go
  • pyproject.toml
  • site/src/pages/index.astro
  • tests/conftest.py
  • tests/unit/api/test_dto_properties.py
  • tests/unit/budget/test_config_properties.py
  • tests/unit/communication/test_message_properties.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/config/test_utils_properties.py
  • tests/unit/core/test_enums_properties.py
  • tests/unit/core/test_task_properties.py
  • tests/unit/core/test_transitions_properties.py
  • tests/unit/core/test_types_properties.py
  • web/package.json
  • web/src/__tests__/api/client.property.test.ts
  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/src/__tests__/utils/format.property.test.ts
  • web/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 pass golangci-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.go
  • cli/internal/config/state_fuzz_test.go
  • cli/internal/compose/generate_fuzz_test.go
  • cli/internal/config/paths_fuzz_test.go
  • cli/internal/selfupdate/updater_fuzz_test.go
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ESLint for linting and vue-tsc for type checking in the Vue 3 dashboard (web/ directory)

Files:

  • web/src/__tests__/utils/format.property.test.ts
  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/__tests__/api/client.property.test.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/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.ts
  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/__tests__/api/client.property.test.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/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.ts
  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/__tests__/api/client.property.test.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/src/__tests__/utils/sanitizeForLog.property.test.ts
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Do not use from __future__ import annotations — Python 3.14 has PEP 649 native lazy annotations
Use except 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/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:

  • tests/unit/budget/test_config_properties.py
  • tests/unit/core/test_enums_properties.py
  • tests/unit/core/test_transitions_properties.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/api/test_dto_properties.py
  • tests/conftest.py
  • tests/unit/config/test_utils_properties.py
  • tests/unit/core/test_task_properties.py
  • tests/unit/core/test_types_properties.py
  • tests/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.parametrize for 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, or small/medium/large as aliases

Files:

  • tests/unit/budget/test_config_properties.py
  • tests/unit/core/test_enums_properties.py
  • tests/unit/core/test_transitions_properties.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/api/test_dto_properties.py
  • tests/conftest.py
  • tests/unit/config/test_utils_properties.py
  • tests/unit/core/test_task_properties.py
  • tests/unit/core/test_types_properties.py
  • tests/unit/communication/test_message_properties.py
pyproject.toml

📄 CodeRabbit inference engine (CLAUDE.md)

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)
Version is stored in [tool.commitizen].version and 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 shared Footer component

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 a ci-pass gate

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), run govulncheck, and use GoReleaser for releases on v* 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 existing Closes #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.json
  • web/src/__tests__/utils/format.property.test.ts
  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/__tests__/api/client.property.test.ts
  • 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 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.toml
  • 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 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.py
  • tests/conftest.py
  • 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 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.yml
  • 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/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.yml
  • 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/*.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.yml
  • 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 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.yml
  • 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:

  • .github/workflows/cli.yml
  • 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:

  • .github/workflows/cli.yml
  • 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 : 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-16 changes 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/**/*.astro should include /get/ and the shared Footer component, 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.5 is in the test group and follows the repo pinning policy.
As per coding guidelines: "All Python dependencies must be pinned with == versions in pyproject.toml; organize into groups..."

tests/conftest.py (1)

9-21: Global Hypothesis profile setup looks solid.

Centralizing profile registration/loading in conftest.py is 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 SecurePath and captures the key postconditions on successful returns.

tests/unit/core/test_types_properties.py (1)

8-60: Property coverage for NotBlankStr is 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.unit for all tests and uses vendor-agnostic naming throughout. No from __future__ import annotations is used, which is correct per coding guidelines.


55-72: LGTM: Round-trip property test is well-structured.

The test correctly validates that model_dump followed by model_validate produces 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_chain validates the happy-path progression through task states, and test_with_transition_rejects_status_override ensures 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.unit and defines reusable strategies. The _action_types regex strategy correctly generates valid category:action format 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)
  • None agent_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 use python -m pytest for consistency.

Using python -m pytest ensures 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.F fuzz functions
  • Hypothesis profiles (ci/dev) and how to run with dev profile
  • .hypothesis/ is gitignored

This 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 > b then b < a (and vice versa)
  • Symmetry for equality: if a == b then b == a

The 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 fuzzArchiveData ensures 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 buildValidTarGz and buildValidZip:

  • 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-check dependency 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

Comment on lines +88 to +101
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"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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.

Suggested change
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.

Comment on lines +55 to +67
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)
}
}),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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.ts

Repository: 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:

  1. Tighten the test to reject TypeError:
} catch (err) {
  expect(err).toBeInstanceOf(Error)
  expect(err).not.toBeInstanceOf(TypeError)
}
  1. Harden web/src/api/client.ts with 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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +64 to +65
// 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)
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
Copy link
Copy Markdown

codecov bot commented Mar 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.67%. Comparing base (6a47e4a) to head (889a2f3).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between a732ca2 and f4b2f47.

📒 Files selected for processing (22)
  • .github/workflows/cli.yml
  • CLAUDE.md
  • cli/internal/compose/generate_fuzz_test.go
  • cli/internal/config/paths_fuzz_test.go
  • cli/internal/config/state_fuzz_test.go
  • cli/internal/docker/client_fuzz_test.go
  • cli/internal/selfupdate/updater_fuzz_test.go
  • tests/conftest.py
  • tests/unit/api/test_dto_properties.py
  • tests/unit/budget/test_config_properties.py
  • tests/unit/communication/test_message_properties.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/config/test_utils_properties.py
  • tests/unit/core/test_enums_properties.py
  • tests/unit/core/test_task_properties.py
  • tests/unit/core/test_transitions_properties.py
  • tests/unit/core/test_types_properties.py
  • web/src/__tests__/api/client.property.test.ts
  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/src/api/client.ts
  • web/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 ESLint for linting and vue-tsc for type checking in the Vue 3 dashboard (web/ directory)

Files:

  • web/src/__tests__/utils/constants.property.test.ts
  • web/src/api/client.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/src/api/types.ts
  • web/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.ts
  • web/src/api/client.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/src/api/types.ts
  • web/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.ts
  • web/src/api/client.ts
  • web/src/__tests__/utils/errors.property.test.ts
  • web/src/api/types.ts
  • web/src/__tests__/api/client.property.test.ts
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Do not use from __future__ import annotations — Python 3.14 has PEP 649 native lazy annotations
Use except 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/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:

  • tests/unit/core/test_types_properties.py
  • tests/unit/config/test_utils_properties.py
  • tests/unit/core/test_task_properties.py
  • tests/unit/communication/test_message_properties.py
  • tests/conftest.py
  • tests/unit/api/test_dto_properties.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/core/test_enums_properties.py
  • tests/unit/budget/test_config_properties.py
  • tests/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.parametrize for 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, or small/medium/large as aliases

Files:

  • tests/unit/core/test_types_properties.py
  • tests/unit/config/test_utils_properties.py
  • tests/unit/core/test_task_properties.py
  • tests/unit/communication/test_message_properties.py
  • tests/conftest.py
  • tests/unit/api/test_dto_properties.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/core/test_enums_properties.py
  • tests/unit/budget/test_config_properties.py
  • tests/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 pass golangci-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.go
  • cli/internal/config/state_fuzz_test.go
  • cli/internal/config/paths_fuzz_test.go
  • cli/internal/compose/generate_fuzz_test.go
  • cli/internal/selfupdate/updater_fuzz_test.go
**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.md: Never remove existing Closes #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 a ci-pass gate

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), run govulncheck, and use GoReleaser for releases on v* 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.ts
  • CLAUDE.md
  • web/src/__tests__/utils/errors.property.test.ts
  • web/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.md
  • tests/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.yml
  • cli/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 body exists and is an object before accessing envelope properties, preventing cryptic TypeError exceptions 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 for NotBlankStr validation.

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.unit correctly 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 SecurePath contracts:

  1. Relative paths (whose filepath.Clean form is not absolute) must be rejected
  2. Successful results must be absolute (filepath.IsAbs)
  3. 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_slow health check) balances thoroughness with CI runtime constraints. The dev profile (1000 examples) enables more exhaustive local testing. Environment-based profile selection via HYPOTHESIS_PROFILE provides good flexibility.


39-58: LGTM! Improved type annotation for _patched_configure.

Changing _original from object to Callable[..., None] correctly reflects that it's callable and eliminates the need for the # type: ignore comment.

.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: true at 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-fuzz to the needs array 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 Load returns a state with non-empty, absolute DataDir

The absolute-path assertion (lines 49-51) correctly addresses the invariant that SecurePath enforces.

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 for getErrorMessage.

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 MessageType enum in src/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, and TERMINAL_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 — status is 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.unit marker 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) or versionAtLeast(b, a) must be true

The 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_transition behavior and VALID_TRANSITIONS map
  • Terminal states have no outgoing transitions
  • Every TaskStatus has a transition entry
  • All valid transitions succeed; all invalid transitions raise ValueError

The pytestmark = pytest.mark.unit at 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 >= b and b >= c then a >= c
  • Totality: returns int, equals zero iff a == b

The pytestmark = pytest.mark.unit at 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_limit and per_agent_daily_limit must not exceed total_monthly unless total is zero)

The pytestmark = pytest.mark.unit at 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 == data at 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 handling

The 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 for deep_merge and to_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 TypeError ensures 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: FuzzCompareSemver invariants are well-chosen.

Reflexivity and antisymmetry checks provide strong guardrails for compare behavior across arbitrary inputs.

Comment on lines +107 to +110
// Seed: tar.gz with path-traversal entry name.
traversalArchive := buildTarGzWithName(f, "../../synthorg")
f.Add(traversalArchive)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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
Copilot AI review requested due to automatic review settings March 14, 2026 22:40
@Aureliolo Aureliolo merged commit 115a742 into main Mar 14, 2026
43 of 45 checks passed
@Aureliolo Aureliolo deleted the test/fuzz-property-testing branch March 14, 2026 22:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +196 to +200
for target in $FUZZ_TARGETS; do
echo "::group::Fuzzing $target"
go test -fuzz="^${target}$" -fuzztime=30s ${{ matrix.package }}
echo "::endgroup::"
done
Comment on lines +143 to +146
// If extraction succeeded, the result must be non-empty.
if len(result) == 0 {
t.Fatal("extractFromTarGz returned nil/empty data without error")
}
Comment on lines +180 to +183
// If extraction succeeded, the result must be non-empty.
if len(result) == 0 {
t.Fatal("extractFromZip returned nil/empty data without error")
}
Aureliolo added a commit that referenced this pull request Mar 15, 2026
🤖 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: add fuzz and property-based testing across all layers

2 participants