Skip to content

feat: brownfield codebase intake (merger/acquisition entry mode)#2042

Merged
Aureliolo merged 6 commits into
mainfrom
feat/1975-brownfield-codebase-intake
May 22, 2026
Merged

feat: brownfield codebase intake (merger/acquisition entry mode)#2042
Aureliolo merged 6 commits into
mainfrom
feat/1975-brownfield-codebase-intake

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

Adds the "merger/acquisition" entry mode (EPIC #1973): point the studio at an existing repo, and it imports, maps, analyses, and indexes the codebase, then awaits human direction and builds on the ingested base.

  • Git seed: extends the Persistent project workspace + pluggable git + agent-concurrency model #1974 GitBackend protocol with a one-shot seed(...) (clone-remote / ingest-local) across all three backends; shared fetch-HEAD + reset import helper (no named remote, so credential URLs never persist).
  • Source resolver: BrownfieldSourceResolver does SSRF validation (reuses the clone-URL validator) + forge-token injection from the connection catalog; rejects credentials embedded in the source ref.
  • Structure map: deterministic, pluggable per-ecosystem scanner (Python/Node/Go/Rust + generic fallback) → CodebaseStructureMap, persisted 1:1 per project (IdKeyedRepository, SQLite TEXT-JSON / Postgres JSONB, dual-backend conformance, one yoyo revision per backend).
  • Service + adapter: BrownfieldImportService (per-project lock; provision → seed → scan → persist → KnowledgeService.ingest(REPO)) and a thin BrownfieldEntryAdapter that drives an ANALYSIS work item through the pipeline spine so the agent analysis pass authors a CODEBASE_ANALYSIS living document.
  • Agent tool: query_structure_map (SEC-1 wrap_untrusted) for structured navigation of the imported codebase.
  • Wiring: POST /brownfield/import controller, wire_real_brownfield_entry boot hook (gated/best-effort), AppState seams, ghost-wiring manifest entries, rate-limit policy, regenerated *.gen.ts.
  • Re-import policy: same source + unchanged content hash short-circuits; a different source onto an occupied project is rejected (BrownfieldWorkspaceNotEmptyError).
  • Docs: new docs/design/brownfield-intake.md (+ DESIGN_SPEC index), DocType + persistence-protocol table updates.

Test plan

  • Unit: scanner (5 ecosystems + aggregator determinism), git seed across backends, source resolver (SSRF, token injection, embedded-cred rejection), service orchestration (fresh/idempotent/reject), query tool, adapter + factory.
  • Dual-backend conformance: tests/conformance/persistence/test_codebase_structure_map_repository.py (SQLite + Postgres).
  • e2e acceptance under the runtime harness: tests/e2e/test_brownfield_intake_e2e.py — real-git import → structure map + analysis pass → indexed → follow-up TASK_BOARD directive through the spine.
  • Full pre-push gate green (ruff, mypy, unit suite, schema-drift, dto-sync, ghost-wiring, dual-backend parity, all convention gates).

Review coverage

Pre-reviewed by 8 core agents (code-reviewer, python-reviewer, conventions-enforcer, security-reviewer, persistence-reviewer, issue-resolution-verifier, docs-consistency, comment-quality-rot). issue-resolution-verifier: all acceptance criteria RESOLVED. 6 valid findings addressed; 9 false positives documented in _audit/pre-pr-review/triage.md.

Closes #1975

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Review Change Stack

Warning

Rate limit exceeded

@Aureliolo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 48 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 58d31d22-7ee0-46e2-936c-96cf19ce06b8

📥 Commits

Reviewing files that changed from the base of the PR and between 8054aab and 56eee1b.

📒 Files selected for processing (80)
  • docs/DESIGN_SPEC.md
  • docs/design/brownfield-intake.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • scripts/_ghost_wiring_manifest.txt
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/state.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/persistence/postgres/revisions/20260522000003_codebase_structure_map.sql
  • src/synthorg/persistence/postgres/schema.sql
  • src/synthorg/persistence/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/persistence/sqlite/revisions/20260522000003_codebase_structure_map.sql
  • src/synthorg/persistence/sqlite/schema.sql
  • src/synthorg/settings/definitions/api.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/api/fakes.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/core/test_enums.py
  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/unit/observability/test_events.py
  • tests/unit/persistence/test_protocol.py
  • tests/unit/tools/structure_map/__init__.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • web/src/__tests__/utils/tasks.property.test.ts
  • web/src/api/types/enum-values.gen.ts
  • web/src/api/types/openapi.gen.ts
  • web/src/pages/agents/TaskHistoryBar.tsx
  • web/src/pages/project-docs/DocList.tsx
  • web/src/pages/tasks/TaskFilterBar.tsx
  • web/src/utils/tasks.ts

Walkthrough

Adds a complete brownfield codebase intake feature: core structure-map domain; git-backend seed workflow; ecosystem scanners and aggregator; import service with source resolver; persistence protocol and repos (Postgres/SQLite + migrations); agent tool and factory; API startup wiring, AppState, controller with rate limiting; pipeline entry adapter and boot hook; observability events; web enum/UI updates; and extensive unit, integration, and e2e tests. Documentation updates include a new design page and catalog references.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@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 implements a comprehensive 'brownfield' codebase intake system, enabling the platform to ingest, analyze, and index external repositories. By automating the mapping of project structures and integrating this data into the existing knowledge substrate, the system allows agents to effectively navigate and work within acquired codebases. The changes include secure source resolution, deterministic scanners, and new agent tools, all supported by robust persistence and pipeline integration.

Highlights

  • Brownfield Intake Entry Mode: Introduced a new merger/acquisition entry mode that allows importing existing codebases into a project workspace, complete with automated structure mapping and agent-led analysis.
  • Structure Mapping: Implemented a deterministic, pluggable scanner system for Python, Node, Go, and Rust that generates a navigable structure map (modules, entry points, dependencies) persisted per project.
  • Security and Integration: Added SSRF validation and forge-token injection for secure source resolution, along with a new agent tool 'query_structure_map' for navigating imported codebases.
  • Persistence and Wiring: Added a new persistence layer for structure maps (SQLite/Postgres) and integrated the intake service into the application startup and work pipeline.
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 the 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 counterproductive. 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.

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 May 22, 2026 15:00 — with GitHub Actions Inactive
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 22, 2026

Merging this PR will not alter performance

✅ 54 untouched benchmarks


Comparing feat/1975-brownfield-codebase-intake (56eee1b) with main (1c2660b)

Open in CodSpeed

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 implements the 'Brownfield Codebase Intake' feature, enabling the studio to import existing repositories into a persistent project workspace. The implementation includes a deterministic structure map model to track modules, entry points, and dependencies, an automated agent-driven analysis pass, and integration with the knowledge substrate for hybrid retrieval. The changes cover the API controller, engine pipeline, persistence layer (Postgres/SQLite), and new agent tools for querying the structure map. I have reviewed the feedback provided; all comments are actionable and address potential robustness issues in the scanner logic, so no comments were filtered out.

Comment on lines +86 to +92
packages = sorted(
{
path.rsplit("/__init__.py", 1)[0]
for path in rel_paths
if path.endswith("__init__.py")
}
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The rsplit logic for discovering Python packages fails when an __init__.py file exists at the repository root. In such cases, path.rsplit("/__init__.py", 1)[0] evaluates to "__init__.py" instead of the expected root directory ("."). This results in an incorrect module path in the structure map. Using removesuffix with a conditional check for the root level is more robust.

Suggested change
packages = sorted(
{
path.rsplit("/__init__.py", 1)[0]
for path in rel_paths
if path.endswith("__init__.py")
}
)
packages = sorted(
{
path.removesuffix("/__init__.py") if "/" in path else "."
for path in rel_paths
if path.endswith("__init__.py")
}
)

def _test_framework(
self, workspace_path: Path, pyproject: dict[str, Any]
) -> str | None:
if "pytest" in str(pyproject.get("tool", {})):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using str(pyproject.get("tool", {})) for framework detection is fragile and prone to false positives. It will match the string "pytest" anywhere in the tool table's values (e.g., in a plugin list for another tool like mypy). It is safer to check for the presence of the "pytest" key directly in the tool dictionary.

Suggested change
if "pytest" in str(pyproject.get("tool", {})):
if "pytest" in pyproject.get("tool", {}):

Comment on lines +105 to +111
def _test_framework(self, manifest: dict[str, Any]) -> str | None:
dev = manifest.get("devDependencies", {})
names = set(dev) if isinstance(dev, dict) else set()
for framework in _KNOWN_FRAMEWORKS:
if framework in names:
return framework
return None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The test framework detection only inspects devDependencies. While common, some projects may list test frameworks (like jest or vitest) in the main dependencies block. Checking both collections ensures better detection coverage.

    def _test_framework(self, manifest: dict[str, Any]) -> str | None:
        deps = manifest.get("dependencies", {})
        dev = manifest.get("devDependencies", {})
        names = set()
        if isinstance(deps, dict):
            names.update(deps)
        if isinstance(dev, dict):
            names.update(dev)
        for framework in _KNOWN_FRAMEWORKS:
            if framework in names:
                return framework
        return None

Copy link
Copy Markdown
Contributor

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/brownfield-intake.md`:
- Around line 16-30: Replace the unlabeled fenced pipeline block for the POST
/brownfield/import flow with a mermaid flowchart; specifically convert the plain
block describing POST /brownfield/import -> BrownfieldEntryAdapter.submit ->
BrownfieldImportService.import_codebase (and its steps 1..6 including
ProjectWorkspaceService.get_or_provision, BrownfieldSourceResolver.resolve,
GitBackend.seed, scan_codebase, KnowledgeService.ingest) and the subsequent
WorkItem -> agent CODEBASE_ANALYSIS -> 202 Accepted flow into a mermaid
flowchart (flowchart TD) so the diagram renders and removes the fenced-language
warning.

In `@src/synthorg/engine/brownfield/source_resolver.py`:
- Around line 95-104: The current check in source_resolver.py rejects any URL
with a username (urlsplit(source_ref).username), which incorrectly blocks valid
SSH refs like ssh://git@host/...; update the condition so it only raises
BrownfieldSourceUnavailableError when a username is embedded for non-SSH schemes
(e.g., check urlsplit(source_ref).username is not None AND the scheme is not an
SSH-type like "ssh" or "git+ssh"), leaving SSH usernames allowed; modify the
conditional around the raise in the block that references source_ref, urlsplit,
and BrownfieldSourceUnavailableError accordingly.

In `@src/synthorg/engine/workspace/git_backend/_git_ops.py`:
- Around line 274-293: The guard only checks tracked files via git(...,
"ls-files") so untracked files can bypass seeding; update the check to also
detect untracked content (for example by calling git(..., "ls-files",
"--others", "--exclude-standard") or git(..., "status", "--porcelain") and
inspect its output) and treat any non-empty result the same way as tracked files
(log GIT_BACKEND_SEED_FAILED with reason "workspace_not_empty" and raise
GitBackendSeedError with the existing message), keeping the same
project_id/event parameters used in the existing git and logger calls.

In `@src/synthorg/tools/structure_map/query_structure_map.py`:
- Around line 66-79: The ValueError/TypeError catch currently spans both
parse_typed(...) and self._repository.get(...), misclassifying
repository/data-layer errors as client argument errors; narrow the scope by
isolating argument parsing into its own try/except that catches
ValueError/TypeError from parse_typed("mcp.tool", arguments,
QueryStructureMapArgs) and returns the ToolExecutionResult with
safe_error_description, then call structure_map = await
self._repository.get(self._project_id) in a separate block so repository-raised
ValueError/TypeError propagate to their appropriate handlers (refer to
parse_typed, QueryStructureMapArgs, self._repository.get, ToolExecutionResult,
safe_error_description).

In `@tests/unit/core/test_enums.py`:
- Around line 65-66: The test increased TaskType membership to seven but
test_task_type_values still asserts only six values; update
test_task_type_values to include an assertion for the new TaskType member
(reference TaskType enum and the test_task_type_values function) by adding the
missing enum member’s expected string value so the test verifies all seven
members match their expected values; ensure the new expected string corresponds
to the actual enum constant name/value.

In `@tests/unit/engine/workspace/git_backend/test_external_remote_backend.py`:
- Line 379: The test fixture uses a real vendor hostname in the fetch_url value
(NotBlankStr("https://github.com/acme/legacy.git")); update the test to use a
vendor-neutral placeholder per guidelines (e.g.,
"https://example-provider/legacy.git" or "https://example-repo/legacy.git") so
tests remain policy-compliant—locate the NotBlankStr(...) assignment for
fetch_url in test_external_remote_backend.py and replace the domain portion with
the recommended placeholder.

In `@tests/unit/engine/workspace/git_backend/test_seed.py`:
- Around line 35-43: The _git helper uses asyncio.create_subprocess_exec and
needs a Windows subprocess-capable loop policy; on Windows detect platform
(e.g., sys.platform.startswith("win")) and temporarily set
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) before
calling create_subprocess_exec (and restore the previous policy afterward) so
subprocess-based unit tests run reliably under Windows; perform this change
inside the async _git function to ensure the correct policy is active for
subprocess creation.
🪄 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: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7926f0da-796b-4aae-8c07-effcc92f6fc0

📥 Commits

Reviewing files that changed from the base of the PR and between 7527078 and c574ed0.

📒 Files selected for processing (74)
  • docs/DESIGN_SPEC.md
  • docs/design/brownfield-intake.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • scripts/_ghost_wiring_manifest.txt
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/state.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/persistence/postgres/revisions/20260522000002_codebase_structure_map.sql
  • src/synthorg/persistence/postgres/schema.sql
  • src/synthorg/persistence/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/persistence/sqlite/revisions/20260522000002_codebase_structure_map.sql
  • src/synthorg/persistence/sqlite/schema.sql
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/api/fakes.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/core/test_enums.py
  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/unit/observability/test_events.py
  • tests/unit/persistence/test_protocol.py
  • tests/unit/tools/structure_map/__init__.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • web/src/api/types/enum-values.gen.ts
  • web/src/api/types/openapi.gen.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). (11)
  • GitHub Check: Deploy Preview
  • GitHub Check: Build Backend
  • GitHub Check: Dashboard Test
  • GitHub Check: Test Integration
  • GitHub Check: Test Unit
  • GitHub Check: Test E2E
  • GitHub Check: Test Conformance (SQLite)
  • GitHub Check: CodSpeed Web benchmarks
  • GitHub Check: CodSpeed Python benchmarks
  • GitHub Check: Lighthouse Site
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{py,ts,tsx,jsx,md}

📄 CodeRabbit inference engine (CLAUDE.md)

No region/currency/locale privileged; use metric units; British English per docs/reference/regional-defaults.md

Files:

  • docs/DESIGN_SPEC.md
  • tests/unit/engine/brownfield/__init__.py
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • tests/unit/core/test_enums.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • docs/design/brownfield-intake.md
  • src/synthorg/engine/brownfield/__init__.py
  • tests/unit/api/fakes.py
  • web/src/api/types/openapi.gen.ts
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • tests/unit/api/fakes_backend.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • tests/unit/observability/test_events.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • web/src/api/types/enum-values.gen.ts
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/pipeline/models.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • tests/unit/persistence/test_protocol.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/core/enums.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/engine/errors.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/persistence/sqlite/backend.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/tools/structure_map/__init__.py
  • src/synthorg/api/state.py
**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.md: Numerics in README + public docs sourced from data/runtime_stats.yaml via <!--RS:NAME--> markers per data/README.md
Use d2 for architecture / nested containers; mermaid for flowcharts / sequence / pipelines; Markdown tables for tabular data; D2 theme 200 (Dark Mauve); D2 CLI pinned to v0.7.1 in CI

Files:

  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • docs/design/brownfield-intake.md
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Timeout/slow failures = source-code regression; never edit tests/baselines/unit_timing.json or any scripts/*_baseline.{txt,json} / scripts/_*_baseline.py; both families PreToolUse-blocked; per-invocation bypass requires explicit approval (ALLOW_BASELINE_GROWTH=1 git commit)
Test markers: @pytest.mark.{unit,integration,e2e,slow}; async auto; timeout 30s global; coverage 80% min
xdist -n 8 --dist=loadfile auto-applied via pyproject addopts; Windows unit tests use WindowsSelectorEventLoopPolicy; subprocess tests override back
Test doubles: FakeClock for Clock seam, mock_of[T](**overrides) for typed-boundary substitutions, SimpleNamespace for attribute-bags; bare MagicMock at typed boundary blocked by scripts/check_mock_spec.py
Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...)); never skip/xfail flaky tests; fix fundamentally

Files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/core/test_enums.py
  • tests/unit/api/fakes.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/persistence/test_protocol.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/tools/structure_map/__init__.py

⚙️ CodeRabbit configuration file

Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare @settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which @given() honors automatically.

Files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/core/test_enums.py
  • tests/unit/api/fakes.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/persistence/test_protocol.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/tools/structure_map/__init__.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Only src/synthorg/persistence/ may import sqlite/psycopg or emit raw SQL; new repository protocols inherit from generic categories in persistence/_generics.py; bespoke methods permitted only under ADR-0001 D7
Configuration Precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1) or env > code default (Cat-2, read_only_post_init); Cat-3 bootstrap secrets pure env; YAML is ingestion format only, not precedence tier; no os.environ.get outside startup
No hardcoded numeric values; numerics live in settings/definitions/; allowlist only 0/1/-1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants (NAME: int|float|Final); enforced by scripts/check_no_magic_numbers.py
Comments document WHY only; no reviewer citations, issue back-refs, or migration framing; enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py
No from __future__ import annotations (Python 3.14 has PEP 649); use PEP 758 except: except A, B: no parens unless binding
Type hints on public functions; mypy strict; Google-style docstrings; line length 88; functions <50 lines; files <800 lines
Errors follow <Domain><Condition>Error pattern from DomainError; never inherit Exception/RuntimeError directly; enforced by check_domain_error_hierarchy.py
Pydantic v2 frozen + extra="forbid" on every frozen model project-wide; gate check_frozen_model_extra_forbid.py; @computed_field auto-exempt; per-line # lint-allow: frozen-extra-forbid -- <reason> for extra="allow"/"ignore" boundaries; use @computed_field for derived; use NotBlankStr for identifiers
Args models at every system boundary; parse_typed() for every external dict ingestion; enforced by check_boundary_typed.py
Immutability: use model_copy(update=...) or copy.deepcopy(); deepcopy at system boundaries
Async: use asyncio.TaskGroup for fan-out/fan-in; helpers catch Exception (re-raise MemoryError/`RecursionError...

Files:

  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/core/enums.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/engine/errors.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/api/state.py
src/**/*.py

⚙️ CodeRabbit configuration file

This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.

Files:

  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/core/enums.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/engine/errors.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/api/state.py
web/src/**/*.{js,jsx,ts,tsx,mts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{js,jsx,ts,tsx,mts}: Always use createLogger from @/lib/logger; never bare console.warn/console.error/console.debug in application code. Variable name must always be log. Only logger.ts itself may use bare console methods. Use log.debug() (DEV-only, stripped in production), log.warn(), log.error().
Pass dynamic/untrusted values as separate args to logger calls (not interpolated into the message string) so they go through sanitizeArg
Attacker-controlled fields inside structured objects must be wrapped in sanitizeForLog() before embedding in log calls
Error-code constants (MANDATORY): import ErrorCode and ErrorCategory from @/api/types/errors (re-exported from the generated web/src/api/types/error-codes.gen.ts). Discriminate on ErrorCode.<NAME>, never on raw integer literals.
Use @eslint-react/web-api-no-leaked-fetch to detect fetch() in effects without AbortController cleanup

Files:

  • web/src/api/types/openapi.gen.ts
  • web/src/api/types/enum-values.gen.ts
web/src/api/types/**/*.gen.ts

📄 CodeRabbit inference engine (web/CLAUDE.md)

Generated DTO types (MANDATORY): NEVER hand-edit web/src/api/types/*.gen.ts. Regenerate with uv run python scripts/generate_dto_types_ts.py. Import DTOs via the barrel (import type { AgentConfig } from '@/api/types').

Files:

  • web/src/api/types/openapi.gen.ts
  • web/src/api/types/enum-values.gen.ts
web/src/**/*.{ts,tsx,mts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{ts,tsx,mts}: Use @typescript-eslint/no-floating-promises to forbid unawaited promises so async work cannot survive the test that scheduled it and trip the active-handle gate
Use @typescript-eslint/no-misused-promises (with checksVoidReturn: { attributes: false }) to forbid passing async functions where the callsite ignores the returned promise. React 19 async event handlers stay allowed via the attributes: false exemption.

Files:

  • web/src/api/types/openapi.gen.ts
  • web/src/api/types/enum-values.gen.ts
src/synthorg/persistence/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/persistence/**/*.py: Repository CRUD: save(entity), get(id), delete(id) -> bool, list_items(...), query(...) returning tuples
Datetime in persistence: use parse_iso_utc / format_iso_utc from persistence._shared (reject naive); use normalize_utc for already-typed

Files:

  • src/synthorg/persistence/protocol.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
tests/conformance/persistence/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Dual-backend conformance: tests/conformance/persistence/ consumes backend fixture (SQLite + Postgres); enforced by check_dual_backend_test_parity.py

Files:

  • tests/conformance/persistence/test_codebase_structure_map_repository.py
🧠 Learnings (7)
📚 Learning: 2026-05-16T18:36:31.446Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/reference/conventions.md:787-789
Timestamp: 2026-05-16T18:36:31.446Z
Learning: In Aureliolo/synthorg, do not require adding `<!--RS:...-->` “Doc Numeric Claims (MANDATORY)” numeric macros for Python version numbers mentioned in documentation prose (e.g., “Python 3.14”, “Python 3.15”). The `scripts/check_doc_numeric_macros.py` gate only applies to `README.md`, `docs/index.md`, `docs/roadmap/index.md`, `docs/architecture/decisions.md`, and `docs/reference/convention-gates.md`, and it only flags digits adjacent to specific stat nouns (tests/providers/agents/stars/releases), not language version mentions like “Python 3.14”.

Applied to files:

  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo, account for the CI gate `check_doc_numeric_macros.py`: it skips fenced code blocks entirely, and it only flags digits that are adjacent to these stat nouns: `tests`, `providers`, `agents`, `stars`, `releases`. Therefore, numeric examples such as CLI flag values (e.g., `--num-workers=4` in fenced bash blocks) and prose version numbers (e.g., `3.14`/`3.15`) are not expected to trigger this check; prioritize changes only when digits appear next to one of the listed nouns (e.g., “5 tests”, “10 stars”, etc.).

Applied to files:

  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing markdown files for the "Doc Numeric Claims (MANDATORY)" RS-marker rule, only require/flag missing RS markers in the files that are actually in-scope for the rule. The scope is enforced via an identical _SCOPED_FILES allowlist in scripts/check_doc_numeric_macros.py and scripts/inject_runtime_stats.py, and currently includes: README.md; docs/index.md; docs/roadmap/index.md; docs/architecture/decisions.md; docs/reference/convention-gates.md. For any other markdown files (e.g., docs/getting_started.md, docs/guides/*), missing RS markers for numeric claims are no-ops and should NOT be flagged.

Applied to files:

  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo against the `check_doc_numeric_macros.py` gate, account for its documented behavior: it skips fenced code blocks entirely, and it only flags digits that are adjacent to specific stat nouns (`tests`, `providers`, `agents`, `stars`, `releases`). As a result, CLI-style numbers (e.g., `--num-workers=4`) inside fenced bash code blocks should never be treated as violations of this gate; only non-fenced text needs checking, and only around those specific nouns.

Applied to files:

  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-05T09:04:46.195Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1760
File: scripts/_dual_backend_parity_lib.py:215-216
Timestamp: 2026-05-05T09:04:46.195Z
Learning: This repository targets Python 3.14+ and follows PEP 758. Therefore, reviewer tooling should NOT treat unparenthesized multi-exception `except` clauses written without an `as` clause (e.g., `except MemoryError, RecursionError:`) as syntax errors. Only flag `except`-clause problems when they are genuinely invalid for Python 3.14+.

Applied to files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/core/test_enums.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/brownfield/__init__.py
  • tests/unit/api/fakes.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • tests/unit/api/fakes_backend.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • tests/unit/observability/test_events.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/pipeline/models.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • tests/unit/persistence/test_protocol.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/core/enums.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/engine/errors.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/persistence/sqlite/backend.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/tools/structure_map/__init__.py
  • src/synthorg/api/state.py
📚 Learning: 2026-05-21T22:55:20.496Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 2035
File: src/synthorg/meta/toolsmith/models.py:114-114
Timestamp: 2026-05-21T22:55:20.496Z
Learning: In this repo’s “magic number” review standard, the existing gate in `scripts/check_no_magic_numbers.py` intentionally does NOT flag numeric literals used as raw call-site arguments. So, do not flag numeric literals passed as keyword arguments to Pydantic `Field()` (e.g., `Field(ge=0, le=100)` / `Field(ge=1, le=50)`)—this is an established idiom. Only treat numeric literals as “magic numbers” when they occur in the locations the gate checks (module-level assignments and function/method parameter defaults).

Applied to files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/core/test_enums.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/brownfield/__init__.py
  • tests/unit/api/fakes.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • tests/unit/api/fakes_backend.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • tests/unit/observability/test_events.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/pipeline/models.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • tests/unit/persistence/test_protocol.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/core/enums.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/engine/errors.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/persistence/sqlite/backend.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/tools/structure_map/__init__.py
  • src/synthorg/api/state.py
📚 Learning: 2026-05-21T22:55:09.289Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 2035
File: src/synthorg/meta/toolsmith/config.py:29-30
Timestamp: 2026-05-21T22:55:09.289Z
Learning: For this repo’s Pydantic configuration idiom, do not treat numeric literals passed directly as arguments to `pydantic.Field(...)` as “magic numbers” during review. This includes call-site usages like `Field(default=0.2, ge=0.0, le=1.0)` (e.g., in config models such as `ToolAuthoringConfig`, `ToolValidationConfig`, `ToolsmithConfig`). Do not request extracting those `Field(...)` numeric arguments into named constants, since the repo’s `scripts/check_no_magic_numbers.py` intentionally excludes call-site `Field(...)` numerics and relies on `Field(...)` as the canonical way to express these constraints/defaults.

Applied to files:

  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/core/enums.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/engine/errors.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/api/state.py
🪛 markdownlint-cli2 (0.22.1)
docs/design/brownfield-intake.md

[warning] 16-16: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (71)
docs/DESIGN_SPEC.md (1)

32-32: LGTM!

tests/unit/engine/brownfield/__init__.py (1)

1-1: LGTM!

docs/design/living-documentation.md (1)

66-69: LGTM!

docs/design/persistence.md (1)

79-79: LGTM!

src/synthorg/tools/structure_map/__init__.py (1)

1-5: LGTM!

src/synthorg/engine/brownfield/scanner/_common.py (1)

1-88: LGTM!

src/synthorg/tools/structure_map/tool_factory.py (1)

22-63: LGTM!

src/synthorg/persistence/postgres/revisions/20260522000002_codebase_structure_map.sql (1)

11-28: LGTM!

src/synthorg/persistence/sqlite/revisions/20260522000002_codebase_structure_map.sql (1)

11-28: LGTM!

src/synthorg/engine/brownfield/__init__.py (1)

1-9: LGTM!

src/synthorg/persistence/sqlite/schema.sql (1)

473-491: LGTM!

tests/unit/api/fakes.py (1)

633-662: LGTM!

web/src/api/types/openapi.gen.ts (2)

7838-7844: LGTM!


12271-12271: LGTM!

src/synthorg/engine/brownfield/scanner/factory.py (1)

1-72: LGTM!

src/synthorg/persistence/protocol.py (1)

54-56: LGTM!

Also applies to: 431-434

src/synthorg/api/rate_limits/policies.py (1)

86-87: LGTM!

src/synthorg/persistence/postgres/schema.sql (1)

487-506: LGTM!

src/synthorg/observability/events/brownfield.py (1)

1-38: LGTM!

src/synthorg/engine/brownfield/scanner/__init__.py (1)

1-28: LGTM!

src/synthorg/tools/structure_map/_args.py (1)

1-34: LGTM!

src/synthorg/engine/brownfield/models.py (1)

1-66: LGTM!

src/synthorg/engine/workspace/git_backend/__init__.py (1)

26-28: LGTM!

Also applies to: 42-44

src/synthorg/api/controllers/__init__.py (1)

17-17: LGTM!

Also applies to: 188-188, 225-225

tests/unit/api/fakes_backend.py (1)

33-33: LGTM!

Also applies to: 606-606, 729-731

src/synthorg/persistence/codebase_structure_map_protocol.py (1)

1-87: LGTM!

tests/unit/observability/test_events.py (1)

354-355: LGTM!

src/synthorg/engine/workspace/git_backend/external_remote.py (1)

45-45: LGTM!

Also applies to: 55-57, 69-70, 333-372

web/src/api/types/enum-values.gen.ts (1)

278-278: LGTM!

Also applies to: 750-750

src/synthorg/engine/brownfield/scanner/protocol.py (1)

1-54: LGTM!

src/synthorg/engine/pipeline/models.py (1)

40-40: LGTM!

tests/unit/engine/pipeline/entry/test_brownfield_adapter.py (1)

1-99: LGTM!

tests/unit/engine/brownfield/test_source_resolver.py (1)

1-121: LGTM!

src/synthorg/persistence/sqlite/_backend_accessors.py (1)

49-51: LGTM!

Also applies to: 158-158, 328-333

src/synthorg/persistence/postgres/backend.py (1)

59-61: LGTM!

Also applies to: 217-219, 316-316, 384-384, 451-451, 718-723

src/synthorg/engine/brownfield/scanner/generic_scanner.py (1)

1-65: LGTM!

src/synthorg/engine/workspace/git_backend/protocol.py (1)

10-10: LGTM!

Also applies to: 14-14, 20-29, 31-56, 68-77, 123-145

tests/unit/persistence/test_protocol.py (1)

1139-1143: LGTM!

src/synthorg/observability/events/workspace.py (1)

52-54: LGTM!

src/synthorg/core/enums.py (1)

152-155: LGTM!

Also applies to: 161-161, 342-342

src/synthorg/tools/structure_map/query_structure_map.py (1)

89-99: LGTM!

Also applies to: 101-147

src/synthorg/engine/workspace/git_backend/embedded.py (1)

24-25: LGTM!

Also applies to: 32-34, 43-45, 182-240

src/synthorg/core/codebase_structure_map.py (1)

1-181: LGTM!

src/synthorg/engine/errors.py (1)

230-241: LGTM!

src/synthorg/api/controllers/brownfield.py (1)

1-152: LGTM!

src/synthorg/persistence/sqlite/backend.py (1)

58-60: LGTM!

Also applies to: 222-224, 298-298, 462-465

tests/unit/engine/brownfield/test_scanner.py (1)

1-233: LGTM!

tests/unit/engine/brownfield/test_service.py (1)

1-124: LGTM!

scripts/_ghost_wiring_manifest.txt (1)

84-91: LGTM!

src/synthorg/api/app.py (1)

1453-1477: LGTM!

src/synthorg/observability/events/persistence.py (1)

328-349: LGTM!

src/synthorg/engine/pipeline/entry/factory.py (1)

23-24: LGTM!

Also applies to: 31-31, 124-150

tests/e2e/test_brownfield_intake_e2e.py (1)

1-369: LGTM!

src/synthorg/engine/pipeline/entry/brownfield_adapter.py (1)

1-105: LGTM!

tests/unit/engine/workspace/git_backend/test_external_remote_backend.py (1)

26-29: LGTM!

Also applies to: 362-378, 380-388

src/synthorg/engine/brownfield/scanner/aggregator.py (1)

1-86: LGTM!

src/synthorg/engine/brownfield/source_resolver.py (1)

1-94: LGTM!

Also applies to: 105-162

src/synthorg/engine/brownfield/service.py (1)

1-223: LGTM!

src/synthorg/engine/workspace/git_backend/local_path.py (1)

27-28: LGTM!

Also applies to: 34-35, 43-44, 225-264

src/synthorg/engine/brownfield/scanner/node_scanner.py (1)

1-142: LGTM!

src/synthorg/persistence/sqlite/codebase_structure_map_repo.py (1)

1-234: LGTM!

tests/conformance/persistence/test_codebase_structure_map_repository.py (1)

1-158: LGTM!

src/synthorg/engine/pipeline/entry/boot.py (1)

30-33: LGTM!

Also applies to: 37-37, 304-376

src/synthorg/engine/brownfield/scanner/go_scanner.py (1)

1-114: LGTM!

src/synthorg/engine/brownfield/scanner/rust_scanner.py (1)

1-134: LGTM!

src/synthorg/engine/brownfield/errors.py (1)

1-60: LGTM!

src/synthorg/persistence/postgres/codebase_structure_map_repo.py (1)

1-212: LGTM!

src/synthorg/engine/brownfield/scanner/python_scanner.py (1)

1-179: LGTM!

tests/unit/tools/structure_map/test_query_structure_map.py (1)

1-115: LGTM!

tests/unit/tools/structure_map/__init__.py (1)

1-1: LGTM!

src/synthorg/api/state.py (1)

181-181: LGTM!

Also applies to: 227-228, 336-336, 388-388, 450-451, 531-531, 1163-1174, 1905-1983

Comment thread docs/design/brownfield-intake.md Outdated
Comment thread src/synthorg/engine/brownfield/source_resolver.py Outdated
Comment thread src/synthorg/engine/workspace/git_backend/_git_ops.py
Comment thread src/synthorg/tools/structure_map/query_structure_map.py
Comment thread tests/unit/core/test_enums.py
Comment thread tests/unit/engine/workspace/git_backend/test_external_remote_backend.py Outdated
Comment on lines +35 to +43
async def _git(cwd: Path, *args: str) -> str:
proc = await asyncio.create_subprocess_exec(
"git",
*args,
cwd=str(cwd),
env=_clean_env(),
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add an event-loop policy override for subprocess-based unit tests.

This test uses asyncio.create_subprocess_exec but does not provide the required policy override for Windows unit runs, so it can fail under the selector policy.

Suggested patch
 import asyncio
 import os
+import warnings
 from pathlib import Path
+from typing import Any
 
 import pytest
 from tests._shared import FakeClock
@@
 pytestmark = pytest.mark.unit
 
 
+@pytest.fixture(scope="session")
+def event_loop_policy() -> Any:
+    """Enable subprocess support for this subprocess-heavy test module."""
+    with warnings.catch_warnings():
+        warnings.simplefilter("ignore", DeprecationWarning)
+        return asyncio.DefaultEventLoopPolicy()  # type: ignore[attr-defined,unused-ignore]
+
+
 def _clean_env() -> dict[str, str]:
As per coding guidelines "Windows unit tests use `WindowsSelectorEventLoopPolicy`; subprocess tests override back".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/engine/workspace/git_backend/test_seed.py` around lines 35 - 43,
The _git helper uses asyncio.create_subprocess_exec and needs a Windows
subprocess-capable loop policy; on Windows detect platform (e.g.,
sys.platform.startswith("win")) and temporarily set
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) before
calling create_subprocess_exec (and restore the previous policy afterward) so
subprocess-based unit tests run reliably under Windows; perform this change
inside the async _git function to ensure the correct policy is active for
subprocess creation.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

❌ Patch coverage is 85.71429% with 132 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.05%. Comparing base (1c2660b) to head (56eee1b).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../persistence/sqlite/codebase_structure_map_repo.py 68.57% 22 Missing ⚠️
...ersistence/postgres/codebase_structure_map_repo.py 74.19% 16 Missing ⚠️
src/synthorg/api/state.py 57.14% 14 Missing and 1 partial ⚠️
...ynthorg/tools/structure_map/query_structure_map.py 75.47% 9 Missing and 4 partials ⚠️
...synthorg/engine/brownfield/scanner/node_scanner.py 72.09% 6 Missing and 6 partials ⚠️
...nthorg/engine/brownfield/scanner/python_scanner.py 75.51% 7 Missing and 5 partials ⚠️
src/synthorg/api/controllers/brownfield.py 77.77% 10 Missing ⚠️
src/synthorg/engine/brownfield/scanner/_common.py 76.66% 5 Missing and 2 partials ⚠️
...synthorg/engine/brownfield/scanner/rust_scanner.py 76.66% 4 Missing and 3 partials ⚠️
src/synthorg/engine/brownfield/source_resolver.py 90.78% 3 Missing and 4 partials ⚠️
... and 4 more
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2042    +/-   ##
========================================
  Coverage   85.04%   85.05%            
========================================
  Files        2208     2233    +25     
  Lines      128126   129048   +922     
  Branches    10613    10670    +57     
========================================
+ Hits       108962   109757   +795     
- Misses      16488    16590   +102     
- Partials     2676     2701    +25     

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

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 22, 2026 17:11 — with GitHub Actions Inactive
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 22, 2026 17:54 — with GitHub Actions Inactive
@Aureliolo Aureliolo force-pushed the feat/1975-brownfield-codebase-intake branch from 08da029 to 4b9748c Compare May 22, 2026 18:20
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 22, 2026 18:22 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@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: 12

♻️ Duplicate comments (1)
tests/unit/engine/workspace/git_backend/test_seed.py (1)

35-43: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore a subprocess-capable event-loop policy for this module.

These tests spawn real git subprocesses via asyncio.create_subprocess_exec(), but this repo’s Windows unit runs use the selector policy by default. Without a local override, the module can fail on Windows before any seed assertions execute.

Suggested patch
 import asyncio
 import os
+import sys
 from pathlib import Path
+from typing import Any
 
 import pytest
 from tests._shared import FakeClock
@@
 pytestmark = pytest.mark.unit
 
 
+@pytest.fixture(scope="module")
+def event_loop_policy() -> Any:
+    if sys.platform.startswith("win"):
+        return asyncio.WindowsProactorEventLoopPolicy()
+    return asyncio.DefaultEventLoopPolicy()
+
+
 def _clean_env() -> dict[str, str]:
#!/bin/bash
set -euo pipefail

file="tests/unit/engine/workspace/git_backend/test_seed.py"

echo "== subprocess usage in ${file} =="
rg -n "create_subprocess_exec|event_loop_policy|Windows(Proactor|Selector)EventLoopPolicy|DefaultEventLoopPolicy" "$file"

echo
echo "== existing event-loop policy overrides under tests/ =="
rg -n "def event_loop_policy|Windows(Proactor|Selector)EventLoopPolicy|DefaultEventLoopPolicy" tests

As per coding guidelines, "Windows unit tests use WindowsSelectorEventLoopPolicy; subprocess tests override back".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/engine/workspace/git_backend/test_seed.py` around lines 35 - 43,
Test module spawns real subprocesses via create_subprocess_exec in _git, but on
Windows the default selector policy breaks subprocesses; fix by setting a
subprocess-capable event loop policy at module import for Windows (e.g. call
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) when
running on Windows, with a safe fallback/no-op on other platforms) so
create_subprocess_exec in the _git coroutine works reliably; place this policy
override near the top of tests/unit/engine/workspace/git_backend/test_seed.py
before any async subprocess usage and ensure it only applies when the
WindowsProactorEventLoopPolicy attribute exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/synthorg/api/app.py`:
- Around line 1547-1562: The _wire_brownfield_intake hook currently awaits
wire_real_brownfield_entry(app_state) and will let any exception abort startup;
wrap that await in a try/except so failures are treated as best-effort: catch
Exception around the call to wire_real_brownfield_entry, log the exception
(including context and stacktrace) and do not re-raise, but only set
_brownfield_intake_installed = True on success; keep the guard using
_brownfield_intake_installed and ensure app startup continues even if
wire_real_brownfield_entry fails.

In `@src/synthorg/api/controllers/brownfield.py`:
- Around line 119-126: The import endpoint currently only applies per-minute
rate limiting but needs an inflight concurrency cap to prevent too many
simultaneous heavy imports; add a concurrency guard to the `@post`("/import")
guards list (next to require_write_access and per_op_rate_limit_from_policy)
such as per_op_concurrency_limit_from_policy("brownfield.import", key="user") or
another guard that acquires/releases a per-user semaphore before scheduling the
background work, returning 429 when the limit is reached; implement the guard
function (or reuse existing policy helpers) so it atomically
increments/decrements the in-flight count around the background task start and
integrates with the same "brownfield.import" policy key.

In `@src/synthorg/engine/brownfield/scanner/go_scanner.py`:
- Around line 29-31: The regex _REQUIRE_RE in go_scanner.py currently matches
bare words (so it picks up "retract v1.2.3") and misses some module paths;
update _REQUIRE_RE to require a module path containing at least one slash and
allow dots, hyphens and pluses in path segments (e.g. change the first capture
to require something like "<segment>/<rest>" rather than any word), e.g. make
the left capture require a '/' so lines like "require github.com/pkg/errors
v0.9.1" match and "retract v1.2.3" does not; keep the existing version capture
(v[\w.\-+]+) and apply this change to the _REQUIRE_RE definition in
go_scanner.py.

In `@src/synthorg/engine/brownfield/scanner/python_scanner.py`:
- Around line 102-103: pyproject may contain a non-table "project" key so the
chained calls like scripts = pyproject.get("project", {}).get("scripts", {}) can
raise AttributeError; update python_scanner.py to first retrieve project =
pyproject.get("project") and check isinstance(project, dict) before calling
project.get(...) (falling back to {} if not a dict), and apply the same pattern
to the other occurrence around lines 148-151 that also does chained access on
pyproject.get("project") so all accesses (scripts, dependencies, etc.) safely
degrade when "project" is not a table.

In `@src/synthorg/engine/brownfield/service.py`:
- Around line 136-137: Persisting the structure_map before calling _index causes
permanent unindexed projects when _index fails and later retries return early
due to the "unchanged" branch; change the order so that await
self._index(submission, repo_root) runs before await
self._repo.save(structure_map) (or only save after a successful index), and
ensure the unchanged-check/early-return logic around the unchanged branch still
allows re-index attempts when _index previously failed; update references to
_index, _repo.save, structure_map, submission and repo_root accordingly.
- Around line 53-63: The regex _URL_USERINFO only matches simple schemes and can
miss valid schemes like "git+ssh://" so update the pattern used by _URL_USERINFO
and the _redact_source_ref function to use the full RFC3986 scheme syntax
(scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )) when capturing the leading
scheme token, then substitute the userinfo portion as before; locate the
_URL_USERINFO definition and replace its pattern with one that matches any valid
URI scheme (so _redact_source_ref continues to call _URL_USERINFO.sub(... ) and
redact embedded "user:pass@" segments for all schemes).

In `@src/synthorg/engine/brownfield/source_resolver.py`:
- Around line 141-146: The URL netloc construction in the code that builds
authenticated HTTPS URLs (uses urlsplit -> split, hostname, token, quote,
netloc, split.port, urlunsplit) fails for IPv6 literal hosts because
split.hostname is unbracketed; detect IPv6 hosts and wrap the host in square
brackets before composing netloc. Update the logic that sets netloc to wrap
split.hostname in "[]" when the hostname contains ":" or is an IPv6 address (you
can use the ipaddress module or a simple ":" check and ensure it's not already
bracketed), then continue to append :port and the user:token@ prefix as before
so urlunsplit receives a valid netloc.

In `@src/synthorg/engine/workspace/git_backend/embedded.py`:
- Around line 209-228: In seed(), the git calls that currently raise
GitBackendPushError and emit GIT_BACKEND_PUSH_FAILED should instead use
seed-specific types/events; change the two git(...) invocations that push
REMOTE_NAME and rev-parse default_branch (they pass pid and self._cmd_timeout)
to use fail_exc=GitBackendSeedError and event=GIT_BACKEND_SEED_FAILED so
failures are typed/logged as seed failures (keep other args like project_id=pid
and cmd_timeout=self._cmd_timeout unchanged).

In
`@src/synthorg/persistence/sqlite/revisions/20260522000003_codebase_structure_map.sql`:
- Around line 16-20: The migration currently creates TEXT columns modules,
entry_points, test_suites, build_files and dependencies without validating JSON
shape; update the migration to add CHECK constraints on each column using
json_valid(column) AND json_type(column) = 'array' so only valid JSON arrays can
be written, and also mirror the exact same CHECK constraints for these columns
in the canonical schema file to keep drift checks green.

In `@tests/unit/engine/brownfield/test_source_resolver.py`:
- Around line 30-35: The test test_file_url_resolves currently only asserts
source_kind; add an assertion that the resolver also normalizes
"file://{tmp_path}" into the canonical local path by checking result.fetch_url
(from BrownfieldSourceResolver().resolve) equals the expected path string (e.g.,
str(tmp_path) or tmp_path.as_posix()) so the file:// URL is converted to the
same local-path contract used by the directory-path case.

In `@tests/unit/engine/pipeline/entry/test_brownfield_adapter.py`:
- Around line 83-86: The test currently calls adapter.submit(_submission()) and
only checks import_service.import_codebase.assert_awaited_once(), which misses
verifying the actual payload; instead assign the submission to a variable (e.g.,
submission = _submission()), call result = await adapter.submit(submission), and
replace the count-only check with
import_service.import_codebase.assert_awaited_once_with(submission) (or assert
the captured["item"] equals submission) to ensure the exact submission passed is
asserted.

---

Duplicate comments:
In `@tests/unit/engine/workspace/git_backend/test_seed.py`:
- Around line 35-43: Test module spawns real subprocesses via
create_subprocess_exec in _git, but on Windows the default selector policy
breaks subprocesses; fix by setting a subprocess-capable event loop policy at
module import for Windows (e.g. call
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) when
running on Windows, with a safe fallback/no-op on other platforms) so
create_subprocess_exec in the _git coroutine works reliably; place this policy
override near the top of tests/unit/engine/workspace/git_backend/test_seed.py
before any async subprocess usage and ensure it only applies when the
WindowsProactorEventLoopPolicy attribute exists.
🪄 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: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5257f65e-a56f-40de-91a8-0815e8c3f9ba

📥 Commits

Reviewing files that changed from the base of the PR and between 08da029 and 4b9748c.

📒 Files selected for processing (79)
  • docs/DESIGN_SPEC.md
  • docs/design/brownfield-intake.md
  • docs/design/living-documentation.md
  • docs/design/persistence.md
  • scripts/_ghost_wiring_manifest.txt
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/state.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/persistence/postgres/revisions/20260522000003_codebase_structure_map.sql
  • src/synthorg/persistence/postgres/schema.sql
  • src/synthorg/persistence/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/persistence/sqlite/revisions/20260522000003_codebase_structure_map.sql
  • src/synthorg/persistence/sqlite/schema.sql
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/api/fakes.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/core/test_enums.py
  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/brownfield/test_service.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/unit/observability/test_events.py
  • tests/unit/persistence/test_protocol.py
  • tests/unit/tools/structure_map/__init__.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • web/src/__tests__/utils/tasks.property.test.ts
  • web/src/api/types/enum-values.gen.ts
  • web/src/api/types/openapi.gen.ts
  • web/src/pages/agents/TaskHistoryBar.tsx
  • web/src/pages/project-docs/DocList.tsx
  • web/src/pages/tasks/TaskFilterBar.tsx
  • web/src/utils/tasks.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). (14)
  • GitHub Check: Deploy Preview
  • GitHub Check: Build Backend
  • GitHub Check: Build Web Assets (melange)
  • GitHub Check: CodSpeed Python benchmarks
  • GitHub Check: CodSpeed Web benchmarks
  • GitHub Check: Lighthouse Dashboard
  • GitHub Check: Lighthouse Site
  • GitHub Check: Dashboard Test
  • GitHub Check: Test E2E
  • GitHub Check: Test Unit
  • GitHub Check: Test Conformance (SQLite)
  • GitHub Check: Test Integration
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{py,ts,tsx,jsx,md}

📄 CodeRabbit inference engine (CLAUDE.md)

No region/currency/locale privileged; use metric units; British English per docs/reference/regional-defaults.md

Files:

  • tests/unit/engine/brownfield/__init__.py
  • web/src/pages/agents/TaskHistoryBar.tsx
  • tests/unit/tools/structure_map/__init__.py
  • web/src/utils/tasks.ts
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • docs/design/persistence.md
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/engine/brownfield/__init__.py
  • web/src/__tests__/utils/tasks.property.test.ts
  • web/src/pages/tasks/TaskFilterBar.tsx
  • src/synthorg/api/rate_limits/policies.py
  • web/src/pages/project-docs/DocList.tsx
  • web/src/api/types/openapi.gen.ts
  • docs/DESIGN_SPEC.md
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • docs/design/living-documentation.md
  • web/src/api/types/enum-values.gen.ts
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/api/app.py
  • src/synthorg/engine/errors.py
  • tests/unit/api/fakes_backend.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • tests/unit/api/fakes.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/tools/structure_map/_args.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • tests/unit/core/test_enums.py
  • src/synthorg/core/codebase_structure_map.py
  • docs/design/brownfield-intake.md
  • src/synthorg/persistence/postgres/backend.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/api/state.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • tests/unit/persistence/test_protocol.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • src/synthorg/api/controllers/brownfield.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/brownfield/test_service.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Timeout/slow failures = source-code regression; never edit tests/baselines/unit_timing.json or any scripts/*_baseline.{txt,json} / scripts/_*_baseline.py; both families PreToolUse-blocked; per-invocation bypass requires explicit approval (ALLOW_BASELINE_GROWTH=1 git commit)
Test markers: @pytest.mark.{unit,integration,e2e,slow}; async auto; timeout 30s global; coverage 80% min
xdist -n 8 --dist=loadfile auto-applied via pyproject addopts; Windows unit tests use WindowsSelectorEventLoopPolicy; subprocess tests override back
Test doubles: FakeClock for Clock seam, mock_of[T](**overrides) for typed-boundary substitutions, SimpleNamespace for attribute-bags; bare MagicMock at typed boundary blocked by scripts/check_mock_spec.py
Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...)); never skip/xfail flaky tests; fix fundamentally

Files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/tools/structure_map/__init__.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/api/fakes.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/core/test_enums.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/persistence/test_protocol.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/brownfield/test_service.py

⚙️ CodeRabbit configuration file

Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare @settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which @given() honors automatically.

Files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/tools/structure_map/__init__.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/api/fakes_backend.py
  • tests/unit/api/fakes.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • tests/unit/core/test_enums.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • tests/unit/persistence/test_protocol.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/brownfield/test_service.py
web/src/**/*.{js,jsx,ts,tsx,mts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{js,jsx,ts,tsx,mts}: Always use createLogger from @/lib/logger; never bare console.warn/console.error/console.debug in application code. Variable name must always be log. Only logger.ts itself may use bare console methods. Use log.debug() (DEV-only, stripped in production), log.warn(), log.error().
Pass dynamic/untrusted values as separate args to logger calls (not interpolated into the message string) so they go through sanitizeArg
Attacker-controlled fields inside structured objects must be wrapped in sanitizeForLog() before embedding in log calls
Error-code constants (MANDATORY): import ErrorCode and ErrorCategory from @/api/types/errors (re-exported from the generated web/src/api/types/error-codes.gen.ts). Discriminate on ErrorCode.<NAME>, never on raw integer literals.
Use @eslint-react/web-api-no-leaked-fetch to detect fetch() in effects without AbortController cleanup

Files:

  • web/src/pages/agents/TaskHistoryBar.tsx
  • web/src/utils/tasks.ts
  • web/src/__tests__/utils/tasks.property.test.ts
  • web/src/pages/tasks/TaskFilterBar.tsx
  • web/src/pages/project-docs/DocList.tsx
  • web/src/api/types/openapi.gen.ts
  • web/src/api/types/enum-values.gen.ts
web/src/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{jsx,tsx}: Use @eslint-react/no-leaked-conditional-rendering to catch the {count && <Foo />} bug where 0 renders verbatim. For ReactNode | undefined props use {value != null && value !== false && <jsx>}; for compound truthiness use Boolean(...).
Use @eslint-react/globals to restrict window / document / localStorage / etc. inside render. Hoist offenders into a useCallback event handler, a useEffect, or a useSyncExternalStore-backed hook.

Reuse web/src/components/ui/ design tokens in Web Dashboard Design System; detail in web/CLAUDE.md

Files:

  • web/src/pages/agents/TaskHistoryBar.tsx
  • web/src/pages/tasks/TaskFilterBar.tsx
  • web/src/pages/project-docs/DocList.tsx
web/src/**/*.{ts,tsx,mts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{ts,tsx,mts}: Use @typescript-eslint/no-floating-promises to forbid unawaited promises so async work cannot survive the test that scheduled it and trip the active-handle gate
Use @typescript-eslint/no-misused-promises (with checksVoidReturn: { attributes: false }) to forbid passing async functions where the callsite ignores the returned promise. React 19 async event handlers stay allowed via the attributes: false exemption.

Files:

  • web/src/pages/agents/TaskHistoryBar.tsx
  • web/src/utils/tasks.ts
  • web/src/__tests__/utils/tasks.property.test.ts
  • web/src/pages/tasks/TaskFilterBar.tsx
  • web/src/pages/project-docs/DocList.tsx
  • web/src/api/types/openapi.gen.ts
  • web/src/api/types/enum-values.gen.ts
web/src/{components,utils}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (web/CLAUDE.md)

NEVER write getXIcon(value): LucideIcon factories called inside JSX bodies. Export a <XIcon value={...} /> wrapper that does the lookup via createElement inside the wrapper body. Wrapper components live in their own file, not alongside utility exports.

Files:

  • web/src/utils/tasks.ts
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Only src/synthorg/persistence/ may import sqlite/psycopg or emit raw SQL; new repository protocols inherit from generic categories in persistence/_generics.py; bespoke methods permitted only under ADR-0001 D7
Configuration Precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1) or env > code default (Cat-2, read_only_post_init); Cat-3 bootstrap secrets pure env; YAML is ingestion format only, not precedence tier; no os.environ.get outside startup
No hardcoded numeric values; numerics live in settings/definitions/; allowlist only 0/1/-1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants (NAME: int|float|Final); enforced by scripts/check_no_magic_numbers.py
Comments document WHY only; no reviewer citations, issue back-refs, or migration framing; enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py
No from __future__ import annotations (Python 3.14 has PEP 649); use PEP 758 except: except A, B: no parens unless binding
Type hints on public functions; mypy strict; Google-style docstrings; line length 88; functions <50 lines; files <800 lines
Errors follow <Domain><Condition>Error pattern from DomainError; never inherit Exception/RuntimeError directly; enforced by check_domain_error_hierarchy.py
Pydantic v2 frozen + extra="forbid" on every frozen model project-wide; gate check_frozen_model_extra_forbid.py; @computed_field auto-exempt; per-line # lint-allow: frozen-extra-forbid -- <reason> for extra="allow"/"ignore" boundaries; use @computed_field for derived; use NotBlankStr for identifiers
Args models at every system boundary; parse_typed() for every external dict ingestion; enforced by check_boundary_typed.py
Immutability: use model_copy(update=...) or copy.deepcopy(); deepcopy at system boundaries
Async: use asyncio.TaskGroup for fan-out/fan-in; helpers catch Exception (re-raise MemoryError/`RecursionError...

Files:

  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/api/app.py
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/api/controllers/brownfield.py
src/**/*.py

⚙️ CodeRabbit configuration file

This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.

Files:

  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/api/app.py
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/api/controllers/brownfield.py
**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.md: Numerics in README + public docs sourced from data/runtime_stats.yaml via <!--RS:NAME--> markers per data/README.md
Use d2 for architecture / nested containers; mermaid for flowcharts / sequence / pipelines; Markdown tables for tabular data; D2 theme 200 (Dark Mauve); D2 CLI pinned to v0.7.1 in CI

Files:

  • docs/design/persistence.md
  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/brownfield-intake.md
web/src/{stores,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (web/CLAUDE.md)

Active-handle gate (MANDATORY): every unit test runs under web/test-infra/active-handle-tracker.ts, which fails any test that leaks an event-loop-holding resource. A new store that schedules timers / attaches listeners MUST expose a teardown hook and register it in the global afterEach; otherwise the gate fails the first test that triggers the schedule.

Files:

  • web/src/__tests__/utils/tasks.property.test.ts
web/src/api/types/**/*.gen.ts

📄 CodeRabbit inference engine (web/CLAUDE.md)

Generated DTO types (MANDATORY): NEVER hand-edit web/src/api/types/*.gen.ts. Regenerate with uv run python scripts/generate_dto_types_ts.py. Import DTOs via the barrel (import type { AgentConfig } from '@/api/types').

Files:

  • web/src/api/types/openapi.gen.ts
  • web/src/api/types/enum-values.gen.ts
src/synthorg/persistence/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/persistence/**/*.py: Repository CRUD: save(entity), get(id), delete(id) -> bool, list_items(...), query(...) returning tuples
Datetime in persistence: use parse_iso_utc / format_iso_utc from persistence._shared (reject naive); use normalize_utc for already-typed

Files:

  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
tests/conformance/persistence/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Dual-backend conformance: tests/conformance/persistence/ consumes backend fixture (SQLite + Postgres); enforced by check_dual_backend_test_parity.py

Files:

  • tests/conformance/persistence/test_codebase_structure_map_repository.py
🧠 Learnings (7)
📚 Learning: 2026-05-05T09:04:46.195Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1760
File: scripts/_dual_backend_parity_lib.py:215-216
Timestamp: 2026-05-05T09:04:46.195Z
Learning: This repository targets Python 3.14+ and follows PEP 758. Therefore, reviewer tooling should NOT treat unparenthesized multi-exception `except` clauses written without an `as` clause (e.g., `except MemoryError, RecursionError:`) as syntax errors. Only flag `except`-clause problems when they are genuinely invalid for Python 3.14+.

Applied to files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/tools/structure_map/__init__.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/api/app.py
  • src/synthorg/engine/errors.py
  • tests/unit/api/fakes_backend.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • tests/unit/api/fakes.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/tools/structure_map/_args.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • tests/unit/core/test_enums.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/persistence/postgres/backend.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/api/state.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • tests/unit/persistence/test_protocol.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • src/synthorg/api/controllers/brownfield.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/brownfield/test_service.py
📚 Learning: 2026-05-21T22:55:20.496Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 2035
File: src/synthorg/meta/toolsmith/models.py:114-114
Timestamp: 2026-05-21T22:55:20.496Z
Learning: In this repo’s “magic number” review standard, the existing gate in `scripts/check_no_magic_numbers.py` intentionally does NOT flag numeric literals used as raw call-site arguments. So, do not flag numeric literals passed as keyword arguments to Pydantic `Field()` (e.g., `Field(ge=0, le=100)` / `Field(ge=1, le=50)`)—this is an established idiom. Only treat numeric literals as “magic numbers” when they occur in the locations the gate checks (module-level assignments and function/method parameter defaults).

Applied to files:

  • tests/unit/engine/brownfield/__init__.py
  • tests/unit/tools/structure_map/__init__.py
  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/api/app.py
  • src/synthorg/engine/errors.py
  • tests/unit/api/fakes_backend.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • tests/unit/api/fakes.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/tools/structure_map/_args.py
  • tests/unit/tools/structure_map/test_query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • tests/unit/core/test_enums.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/persistence/postgres/backend.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/brownfield/test_scanner.py
  • tests/unit/engine/workspace/git_backend/test_seed.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/api/state.py
  • tests/e2e/test_brownfield_intake_e2e.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • tests/unit/persistence/test_protocol.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • tests/conformance/persistence/test_codebase_structure_map_repository.py
  • src/synthorg/api/controllers/brownfield.py
  • tests/unit/engine/workspace/git_backend/test_external_remote_backend.py
  • tests/unit/engine/brownfield/test_service.py
📚 Learning: 2026-05-21T22:55:09.289Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 2035
File: src/synthorg/meta/toolsmith/config.py:29-30
Timestamp: 2026-05-21T22:55:09.289Z
Learning: For this repo’s Pydantic configuration idiom, do not treat numeric literals passed directly as arguments to `pydantic.Field(...)` as “magic numbers” during review. This includes call-site usages like `Field(default=0.2, ge=0.0, le=1.0)` (e.g., in config models such as `ToolAuthoringConfig`, `ToolValidationConfig`, `ToolsmithConfig`). Do not request extracting those `Field(...)` numeric arguments into named constants, since the repo’s `scripts/check_no_magic_numbers.py` intentionally excludes call-site `Field(...)` numerics and relies on `Field(...)` as the canonical way to express these constraints/defaults.

Applied to files:

  • src/synthorg/tools/structure_map/__init__.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/engine/brownfield/models.py
  • src/synthorg/observability/events/workspace.py
  • src/synthorg/engine/brownfield/__init__.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/observability/events/brownfield.py
  • src/synthorg/engine/pipeline/models.py
  • src/synthorg/engine/brownfield/scanner/protocol.py
  • src/synthorg/persistence/sqlite/_backend_accessors.py
  • src/synthorg/engine/brownfield/scanner/__init__.py
  • src/synthorg/engine/brownfield/scanner/node_scanner.py
  • src/synthorg/api/app.py
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/aggregator.py
  • src/synthorg/engine/brownfield/scanner/generic_scanner.py
  • src/synthorg/observability/events/persistence.py
  • src/synthorg/persistence/codebase_structure_map_protocol.py
  • src/synthorg/tools/structure_map/_args.py
  • src/synthorg/engine/workspace/git_backend/protocol.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/core/enums.py
  • src/synthorg/engine/brownfield/scanner/factory.py
  • src/synthorg/tools/structure_map/tool_factory.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/brownfield/scanner/_common.py
  • src/synthorg/core/codebase_structure_map.py
  • src/synthorg/persistence/postgres/backend.py
  • src/synthorg/persistence/protocol.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/workspace/git_backend/__init__.py
  • src/synthorg/tools/structure_map/query_structure_map.py
  • src/synthorg/engine/workspace/git_backend/local_path.py
  • src/synthorg/persistence/sqlite/backend.py
  • src/synthorg/engine/workspace/git_backend/external_remote.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/brownfield/scanner/rust_scanner.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/persistence/postgres/codebase_structure_map_repo.py
  • src/synthorg/engine/pipeline/entry/brownfield_adapter.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/engine/brownfield/errors.py
  • src/synthorg/engine/workspace/git_backend/_git_ops.py
  • src/synthorg/persistence/sqlite/codebase_structure_map_repo.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/api/controllers/brownfield.py
📚 Learning: 2026-05-16T18:36:31.446Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/reference/conventions.md:787-789
Timestamp: 2026-05-16T18:36:31.446Z
Learning: In Aureliolo/synthorg, do not require adding `<!--RS:...-->` “Doc Numeric Claims (MANDATORY)” numeric macros for Python version numbers mentioned in documentation prose (e.g., “Python 3.14”, “Python 3.15”). The `scripts/check_doc_numeric_macros.py` gate only applies to `README.md`, `docs/index.md`, `docs/roadmap/index.md`, `docs/architecture/decisions.md`, and `docs/reference/convention-gates.md`, and it only flags digits adjacent to specific stat nouns (tests/providers/agents/stars/releases), not language version mentions like “Python 3.14”.

Applied to files:

  • docs/design/persistence.md
  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo, account for the CI gate `check_doc_numeric_macros.py`: it skips fenced code blocks entirely, and it only flags digits that are adjacent to these stat nouns: `tests`, `providers`, `agents`, `stars`, `releases`. Therefore, numeric examples such as CLI flag values (e.g., `--num-workers=4` in fenced bash blocks) and prose version numbers (e.g., `3.14`/`3.15`) are not expected to trigger this check; prioritize changes only when digits appear next to one of the listed nouns (e.g., “5 tests”, “10 stars”, etc.).

Applied to files:

  • docs/design/persistence.md
  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing markdown files for the "Doc Numeric Claims (MANDATORY)" RS-marker rule, only require/flag missing RS markers in the files that are actually in-scope for the rule. The scope is enforced via an identical _SCOPED_FILES allowlist in scripts/check_doc_numeric_macros.py and scripts/inject_runtime_stats.py, and currently includes: README.md; docs/index.md; docs/roadmap/index.md; docs/architecture/decisions.md; docs/reference/convention-gates.md. For any other markdown files (e.g., docs/getting_started.md, docs/guides/*), missing RS markers for numeric claims are no-ops and should NOT be flagged.

Applied to files:

  • docs/design/persistence.md
  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/brownfield-intake.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo against the `check_doc_numeric_macros.py` gate, account for its documented behavior: it skips fenced code blocks entirely, and it only flags digits that are adjacent to specific stat nouns (`tests`, `providers`, `agents`, `stars`, `releases`). As a result, CLI-style numbers (e.g., `--num-workers=4`) inside fenced bash code blocks should never be treated as violations of this gate; only non-fenced text needs checking, and only around those specific nouns.

Applied to files:

  • docs/design/persistence.md
  • docs/DESIGN_SPEC.md
  • docs/design/living-documentation.md
  • docs/design/brownfield-intake.md
🔇 Additional comments (71)
docs/DESIGN_SPEC.md (1)

32-32: LGTM!

docs/design/brownfield-intake.md (1)

1-135: LGTM!

docs/design/living-documentation.md (1)

66-68: LGTM!

docs/design/persistence.md (1)

79-79: LGTM!

src/synthorg/core/codebase_structure_map.py (1)

1-180: LGTM!

src/synthorg/core/enums.py (1)

152-155: LGTM!

Also applies to: 161-161, 203-247, 388-388, 759-759

web/src/api/types/enum-values.gen.ts (1)

278-278: LGTM!

Also applies to: 651-651, 751-751

web/src/api/types/openapi.gen.ts (4)

7835-7847: LGTM!


8047-8053: LGTM!


11679-11685: LGTM!


12268-12274: LGTM!

web/src/pages/agents/TaskHistoryBar.tsx (1)

19-19: LGTM!

web/src/pages/project-docs/DocList.tsx (1)

2-2: LGTM!

Also applies to: 8-8, 11-11

web/src/pages/tasks/TaskFilterBar.tsx (1)

5-5: LGTM!

Also applies to: 14-14

web/src/utils/tasks.ts (1)

82-82: LGTM!

web/src/__tests__/utils/tasks.property.test.ts (1)

3-3: LGTM!

Also applies to: 19-19

tests/e2e/test_brownfield_intake_e2e.py (1)

1-369: LGTM!

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

65-66: LGTM!

Also applies to: 121-122, 130-130, 182-182

src/synthorg/persistence/postgres/schema.sql (2)

493-497: Duplicate: enforce JSONB array shape checks here as well.

Same root issue already raised on the migration file; keep schema/revision parity by adding the same jsonb_typeof(...) = 'array' constraints in this table definition too.


487-492: LGTM!

Also applies to: 498-505, 1728-1747

src/synthorg/persistence/protocol.py (1)

54-56: LGTM!

Also applies to: 124-126, 434-437, 459-462

src/synthorg/persistence/codebase_structure_map_protocol.py (1)

1-87: LGTM!

src/synthorg/persistence/postgres/backend.py (1)

59-61: LGTM!

Also applies to: 148-150, 220-222, 268-269, 320-325, 389-392, 457-460, 725-730, 749-753

src/synthorg/persistence/postgres/codebase_structure_map_repo.py (1)

1-212: LGTM!

src/synthorg/persistence/postgres/revisions/20260522000003_codebase_structure_map.sql (1)

1-15: LGTM!

Also applies to: 21-28

src/synthorg/persistence/sqlite/_backend_accessors.py (1)

49-51: LGTM!

Also applies to: 100-100, 159-159, 164-164, 330-335, 361-364

src/synthorg/persistence/sqlite/backend.py (1)

58-60: LGTM!

Also applies to: 147-149, 225-227, 232-232, 302-302, 307-307, 467-470, 487-490

tests/unit/tools/structure_map/test_query_structure_map.py (1)

1-115: LGTM!

tests/conformance/persistence/test_codebase_structure_map_repository.py (1)

1-158: LGTM!

tests/unit/persistence/test_protocol.py (1)

52-52: LGTM!

Also applies to: 74-74, 1141-1145, 1175-1179, 1507-1512

tests/unit/api/fakes.py (1)

633-662: LGTM!

tests/unit/api/fakes_backend.py (1)

33-33: LGTM!

Also applies to: 60-60, 607-607, 612-612, 731-734, 751-754

src/synthorg/observability/events/brownfield.py (1)

1-37: LGTM!

src/synthorg/observability/events/persistence.py (1)

328-349: LGTM!

Also applies to: 842-868

src/synthorg/observability/events/workspace.py (1)

52-54: LGTM!

src/synthorg/engine/errors.py (1)

230-240: LGTM!

src/synthorg/engine/workspace/git_backend/protocol.py (1)

10-10: LGTM!

Also applies to: 14-14, 20-55, 68-77, 123-145

src/synthorg/engine/workspace/git_backend/__init__.py (1)

26-29: LGTM!

Also applies to: 42-44

src/synthorg/engine/workspace/git_backend/_git_ops.py (1)

13-27: LGTM!

Also applies to: 254-355

src/synthorg/engine/workspace/git_backend/embedded.py (1)

24-45: LGTM!

Also applies to: 182-203, 229-239

src/synthorg/engine/workspace/git_backend/external_remote.py (1)

45-56: LGTM!

Also applies to: 69-70, 333-371

src/synthorg/engine/workspace/git_backend/local_path.py (1)

27-35: LGTM!

Also applies to: 43-44, 225-264

tests/unit/engine/workspace/git_backend/test_external_remote_backend.py (1)

26-29: LGTM!

Also applies to: 50-50, 59-59, 69-69, 123-126, 137-137, 213-213, 235-235, 257-257, 278-279, 308-308, 331-331, 351-351, 362-391

tests/unit/engine/workspace/git_backend/test_seed.py (1)

1-32: LGTM!

Also applies to: 49-159

tests/unit/observability/test_events.py (1)

266-266: LGTM!

Also applies to: 355-356

src/synthorg/engine/brownfield/source_resolver.py (1)

1-140: LGTM!

Also applies to: 147-167

src/synthorg/engine/brownfield/__init__.py (1)

1-9: LGTM!

src/synthorg/engine/brownfield/errors.py (1)

15-60: LGTM!

src/synthorg/engine/brownfield/models.py (1)

10-65: LGTM!

src/synthorg/engine/pipeline/entry/boot.py (1)

30-33: LGTM!

Also applies to: 37-38, 306-375

src/synthorg/engine/pipeline/entry/brownfield_adapter.py (1)

41-105: LGTM!

src/synthorg/engine/pipeline/entry/factory.py (1)

23-24: LGTM!

Also applies to: 31-32, 124-150

scripts/_ghost_wiring_manifest.txt (1)

84-103: LGTM!

src/synthorg/engine/pipeline/models.py (1)

40-40: LGTM!

src/synthorg/api/app.py (1)

1453-1544: LGTM!

Also applies to: 1564-1570

src/synthorg/api/controllers/__init__.py (1)

17-17: LGTM!

Also applies to: 188-188, 225-225

src/synthorg/api/controllers/brownfield.py (1)

1-117: LGTM!

Also applies to: 127-152

src/synthorg/api/rate_limits/policies.py (1)

86-87: LGTM!

src/synthorg/api/state.py (1)

181-184: LGTM!

Also applies to: 229-230, 325-326, 340-340, 392-392, 454-455, 535-537, 1169-1210, 1941-2020

tests/unit/engine/brownfield/test_scanner.py (1)

1-233: LGTM!

tests/unit/engine/brownfield/test_service.py (1)

1-124: LGTM!

tests/unit/engine/brownfield/__init__.py (1)

1-1: LGTM!

src/synthorg/engine/brownfield/scanner/__init__.py (1)

1-27: LGTM!

src/synthorg/engine/brownfield/scanner/_common.py (1)

1-88: LGTM!

src/synthorg/engine/brownfield/scanner/aggregator.py (1)

1-85: LGTM!

src/synthorg/engine/brownfield/scanner/factory.py (1)

1-71: LGTM!

src/synthorg/engine/brownfield/scanner/generic_scanner.py (1)

1-64: LGTM!

src/synthorg/engine/brownfield/scanner/node_scanner.py (1)

1-143: LGTM!

src/synthorg/engine/brownfield/scanner/python_scanner.py (1)

1-101: LGTM!

Also applies to: 104-147, 152-180

src/synthorg/engine/brownfield/scanner/rust_scanner.py (1)

1-134: LGTM!

src/synthorg/engine/brownfield/scanner/protocol.py (1)

18-53: LGTM!

Comment thread src/synthorg/api/app.py Outdated
Comment thread src/synthorg/api/controllers/brownfield.py
Comment thread src/synthorg/engine/brownfield/scanner/go_scanner.py
Comment thread src/synthorg/engine/brownfield/scanner/python_scanner.py Outdated
Comment thread src/synthorg/engine/brownfield/service.py Outdated
Comment thread src/synthorg/engine/workspace/git_backend/embedded.py
Comment thread tests/unit/engine/brownfield/test_source_resolver.py
Comment thread tests/unit/engine/pipeline/entry/test_brownfield_adapter.py Outdated
Copy link
Copy Markdown
Contributor

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

♻️ Duplicate comments (1)
src/synthorg/engine/brownfield/scanner/go_scanner.py (1)

30-34: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle single-line require directives in go.mod parsing.

The regex now avoids retract false positives, but it still skips valid lines like require github.com/pkg/errors v0.9.1, so dependency extraction is incomplete.

♻️ Proposed fix
 _REQUIRE_RE: Final[re.Pattern[str]] = re.compile(
-    r"^\s*([\w.\-+]+/[\w.\-+/]+)\s+(v[\w.\-+]+)",
+    r"^\s*(?:require\s+)?([\w.\-+]+/[\w.\-+/]+)\s+(v[\w.\-+]+)",
     re.MULTILINE,
 )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/synthorg/engine/brownfield/scanner/go_scanner.py` around lines 30 - 34,
The regex in go_scanner.py that matches module path/version pairs currently
expects the line to start with the module path and thus misses single-line
directives like "require github.com/pkg/errors v0.9.1"; update the pattern (the
r"^\s*([\w.\-+]+/[\w.\-+/]+)\s+(v[\w.\-+]+)" literal) to allow an optional
"require" token before the module (e.g. use a non-capturing optional prefix like
(?:require\s+)?), keeping the existing slash requirement so "retract v1.2.3"
remains excluded; adjust the same regex usage locations in go_scanner.py where
it is compiled or referenced.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/synthorg/engine/brownfield/scanner/go_scanner.py`:
- Around line 30-34: The regex in go_scanner.py that matches module path/version
pairs currently expects the line to start with the module path and thus misses
single-line directives like "require github.com/pkg/errors v0.9.1"; update the
pattern (the r"^\s*([\w.\-+]+/[\w.\-+/]+)\s+(v[\w.\-+]+)" literal) to allow an
optional "require" token before the module (e.g. use a non-capturing optional
prefix like (?:require\s+)?), keeping the existing slash requirement so "retract
v1.2.3" remains excluded; adjust the same regex usage locations in go_scanner.py
where it is compiled or referenced.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: a256a069-5d50-44c5-b311-426cff4703c7

📥 Commits

Reviewing files that changed from the base of the PR and between 4b9748c and 2b2e086.

📒 Files selected for processing (15)
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/persistence/postgres/revisions/20260522000003_codebase_structure_map.sql
  • src/synthorg/persistence/postgres/schema.sql
  • src/synthorg/persistence/sqlite/revisions/20260522000003_codebase_structure_map.sql
  • src/synthorg/persistence/sqlite/schema.sql
  • src/synthorg/settings/definitions/api.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
📜 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). (15)
  • GitHub Check: Build Backend
  • GitHub Check: Build Web Assets (melange)
  • GitHub Check: Test Integration
  • GitHub Check: Test Conformance (SQLite)
  • GitHub Check: Test E2E
  • GitHub Check: Test Unit
  • GitHub Check: Dashboard Test
  • GitHub Check: Lighthouse Site
  • GitHub Check: Lighthouse Dashboard
  • GitHub Check: CodSpeed Python benchmarks
  • GitHub Check: CodSpeed Web benchmarks
  • GitHub Check: Build Preview
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{py,ts,tsx,jsx,md}

📄 CodeRabbit inference engine (CLAUDE.md)

No region/currency/locale privileged; use metric units; British English per docs/reference/regional-defaults.md

Files:

  • src/synthorg/settings/definitions/api.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • src/synthorg/api/app.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/controllers/brownfield.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Only src/synthorg/persistence/ may import sqlite/psycopg or emit raw SQL; new repository protocols inherit from generic categories in persistence/_generics.py; bespoke methods permitted only under ADR-0001 D7
Configuration Precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1) or env > code default (Cat-2, read_only_post_init); Cat-3 bootstrap secrets pure env; YAML is ingestion format only, not precedence tier; no os.environ.get outside startup
No hardcoded numeric values; numerics live in settings/definitions/; allowlist only 0/1/-1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants (NAME: int|float|Final); enforced by scripts/check_no_magic_numbers.py
Comments document WHY only; no reviewer citations, issue back-refs, or migration framing; enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py
No from __future__ import annotations (Python 3.14 has PEP 649); use PEP 758 except: except A, B: no parens unless binding
Type hints on public functions; mypy strict; Google-style docstrings; line length 88; functions <50 lines; files <800 lines
Errors follow <Domain><Condition>Error pattern from DomainError; never inherit Exception/RuntimeError directly; enforced by check_domain_error_hierarchy.py
Pydantic v2 frozen + extra="forbid" on every frozen model project-wide; gate check_frozen_model_extra_forbid.py; @computed_field auto-exempt; per-line # lint-allow: frozen-extra-forbid -- <reason> for extra="allow"/"ignore" boundaries; use @computed_field for derived; use NotBlankStr for identifiers
Args models at every system boundary; parse_typed() for every external dict ingestion; enforced by check_boundary_typed.py
Immutability: use model_copy(update=...) or copy.deepcopy(); deepcopy at system boundaries
Async: use asyncio.TaskGroup for fan-out/fan-in; helpers catch Exception (re-raise MemoryError/`RecursionError...

Files:

  • src/synthorg/settings/definitions/api.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/api/app.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
src/**/*.py

⚙️ CodeRabbit configuration file

This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.

Files:

  • src/synthorg/settings/definitions/api.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/api/app.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Timeout/slow failures = source-code regression; never edit tests/baselines/unit_timing.json or any scripts/*_baseline.{txt,json} / scripts/_*_baseline.py; both families PreToolUse-blocked; per-invocation bypass requires explicit approval (ALLOW_BASELINE_GROWTH=1 git commit)
Test markers: @pytest.mark.{unit,integration,e2e,slow}; async auto; timeout 30s global; coverage 80% min
xdist -n 8 --dist=loadfile auto-applied via pyproject addopts; Windows unit tests use WindowsSelectorEventLoopPolicy; subprocess tests override back
Test doubles: FakeClock for Clock seam, mock_of[T](**overrides) for typed-boundary substitutions, SimpleNamespace for attribute-bags; bare MagicMock at typed boundary blocked by scripts/check_mock_spec.py
Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...)); never skip/xfail flaky tests; fix fundamentally

Files:

  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py

⚙️ CodeRabbit configuration file

Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare @settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which @given() honors automatically.

Files:

  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • tests/unit/engine/brownfield/test_source_resolver.py
🧠 Learnings (5)
📚 Learning: 2026-05-05T09:04:46.195Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1760
File: scripts/_dual_backend_parity_lib.py:215-216
Timestamp: 2026-05-05T09:04:46.195Z
Learning: This repository targets Python 3.14+ and follows PEP 758. Therefore, reviewer tooling should NOT treat unparenthesized multi-exception `except` clauses written without an `as` clause (e.g., `except MemoryError, RecursionError:`) as syntax errors. Only flag `except`-clause problems when they are genuinely invalid for Python 3.14+.

Applied to files:

  • src/synthorg/settings/definitions/api.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • src/synthorg/api/app.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/controllers/brownfield.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
📚 Learning: 2026-05-21T22:55:20.496Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 2035
File: src/synthorg/meta/toolsmith/models.py:114-114
Timestamp: 2026-05-21T22:55:20.496Z
Learning: In this repo’s “magic number” review standard, the existing gate in `scripts/check_no_magic_numbers.py` intentionally does NOT flag numeric literals used as raw call-site arguments. So, do not flag numeric literals passed as keyword arguments to Pydantic `Field()` (e.g., `Field(ge=0, le=100)` / `Field(ge=1, le=50)`)—this is an established idiom. Only treat numeric literals as “magic numbers” when they occur in the locations the gate checks (module-level assignments and function/method parameter defaults).

Applied to files:

  • src/synthorg/settings/definitions/api.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • tests/unit/engine/pipeline/entry/test_brownfield_adapter.py
  • src/synthorg/api/app.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/controllers/brownfield.py
  • tests/unit/engine/brownfield/test_source_resolver.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
📚 Learning: 2026-05-17T11:45:11.839Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1952
File: src/synthorg/settings/definitions/api.py:594-638
Timestamp: 2026-05-17T11:45:11.839Z
Learning: In SynthOrg (Aureliolo/synthorg) pre-alpha, apply the strict no-backward-compat policy: any setting-key rename must be fully completed in the same change/PR with all repo callers updated, and you should not keep legacy aliases or compatibility fallbacks. When reviewing, do not flag a setting-key rename as a breaking upgrade hazard if the rename is repo-wide and fully implemented within the same PR.

Applied to files:

  • src/synthorg/settings/definitions/api.py
📚 Learning: 2026-05-17T11:45:11.839Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1952
File: src/synthorg/settings/definitions/api.py:594-638
Timestamp: 2026-05-17T11:45:11.839Z
Learning: In this repository, SynthOrg is pre-alpha and uses a strict no-backward-compat policy for setting-key renames. When reviewing code under src/synthorg/settings, do NOT flag a setting-key rename as an “upgrade-safety” issue if the rename is complete/atomic in the same PR: all callers/usages of the old key are updated simultaneously, and the PR does not keep any legacy aliases, compatibility fallbacks, or migration/rollback paths for the old key.

Applied to files:

  • src/synthorg/settings/definitions/api.py
📚 Learning: 2026-05-21T22:55:09.289Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 2035
File: src/synthorg/meta/toolsmith/config.py:29-30
Timestamp: 2026-05-21T22:55:09.289Z
Learning: For this repo’s Pydantic configuration idiom, do not treat numeric literals passed directly as arguments to `pydantic.Field(...)` as “magic numbers” during review. This includes call-site usages like `Field(default=0.2, ge=0.0, le=1.0)` (e.g., in config models such as `ToolAuthoringConfig`, `ToolValidationConfig`, `ToolsmithConfig`). Do not request extracting those `Field(...)` numeric arguments into named constants, since the repo’s `scripts/check_no_magic_numbers.py` intentionally excludes call-site `Field(...)` numerics and relies on `Field(...)` as the canonical way to express these constraints/defaults.

Applied to files:

  • src/synthorg/settings/definitions/api.py
  • src/synthorg/engine/workspace/git_backend/embedded.py
  • src/synthorg/api/app.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/controllers/brownfield.py
  • src/synthorg/engine/brownfield/scanner/go_scanner.py
  • src/synthorg/engine/brownfield/source_resolver.py
  • src/synthorg/engine/brownfield/scanner/python_scanner.py
  • src/synthorg/engine/brownfield/service.py
🔇 Additional comments (14)
src/synthorg/settings/definitions/api.py (1)

4-5: LGTM!

Also applies to: 62-66

src/synthorg/persistence/postgres/revisions/20260522000003_codebase_structure_map.sql (1)

16-25: LGTM!

src/synthorg/persistence/sqlite/schema.sql (1)

479-488: LGTM!

src/synthorg/persistence/sqlite/revisions/20260522000003_codebase_structure_map.sql (1)

16-25: LGTM!

src/synthorg/persistence/postgres/schema.sql (1)

493-502: LGTM!

src/synthorg/engine/workspace/git_backend/embedded.py (1)

19-20: LGTM!

Also applies to: 45-46, 218-220, 227-229

tests/unit/engine/pipeline/entry/test_brownfield_adapter.py (1)

83-84: LGTM!

Also applies to: 86-86

src/synthorg/api/app.py (1)

1561-1573: LGTM!

src/synthorg/api/rate_limits/policies.py (1)

36-37: LGTM!

Also applies to: 254-255

src/synthorg/api/controllers/brownfield.py (1)

21-24: LGTM!

Also applies to: 128-128

tests/unit/engine/brownfield/test_source_resolver.py (1)

35-38: LGTM!

src/synthorg/engine/brownfield/source_resolver.py (1)

143-147: LGTM!

src/synthorg/engine/brownfield/scanner/python_scanner.py (1)

102-105: LGTM!

Also applies to: 151-153

src/synthorg/engine/brownfield/service.py (1)

53-57: LGTM!

Also applies to: 140-146, 174-177

Aureliolo added 4 commits May 22, 2026 22:03
CI:
- Add analysis/codebase_analysis enum keys to frontend Records + filters (Dashboard Type Check/Build, melange, Lighthouse)
- Bump starlette 1.0.0 to 1.0.1 for PYSEC-2026-161 (Python Security Audit)

CodeRabbit:
- brownfield-intake.md flow block converted to a mermaid flowchart
- source_resolver: allow ssh:// usernames, still block passwords and http(s) usernames
- _git_ops seed guard: detect untracked files too (ls-files plus ls-files --others)
- query_structure_map: narrow arg-validation except scope away from repository errors
- test_enums: assert TaskType.ANALYSIS value
- external_remote tests: vendor-neutral hosts

Gemini:
- python_scanner: root __init__.py maps to a dot
- python_scanner: pytest detection via tool table key, not str()
- node_scanner: test-framework checks dependencies and devDependencies

Skipped CR7 (stale): the git-backend dir conftest already provides the subprocess event_loop_policy that test_seed inherits.
frontend-reviewer (3 MAJOR):
- TaskFilterBar.tsx: source TASK_TYPES from generated TASK_TYPE_VALUES
- DocList.tsx: source DOC_TYPES from generated DOC_TYPE_VALUES
- tasks.property.test.ts: source ALL_TASK_TYPES from generated TASK_TYPE_VALUES
Kills the hand-maintained enum-literal drift hazard at the source.

docs-consistency (1 MAJOR):
- brownfield-intake.md: clarify credential rejection policy (password in any scheme + http(s) username rejected; bare ssh git@host username allowed)

docs-consistency / conventions (1 MAJOR):
- test_external_remote_backend.py: finish vendor-neutralisation (_catalog_github to _catalog_forge, "github-main" to "forge-main"); ConnectionType.GITHUB enum stays as legitimate forge-type domain

conventions-enforcer (1 MEDIUM):
- _git_ops.py: extract _assert_workspace_empty helper; keeps import_source_into_worktree under the 50-line guideline (round 1 had pushed it to 84)
app.py: wrap _wire_brownfield_intake in try/except (best-effort + idempotent like _wire_research_engine)
controllers/brownfield.py: add per-user inflight concurrency cap to /import
rate_limits/policies.py + settings/definitions/api.py: BROWNFIELD_IMPORT_INFLIGHT_MAX (single-slot per user)
scanner/go_scanner.py: tighten _REQUIRE_RE to require a slash in the module path (skip "retract v1.2.3")
scanner/python_scanner.py: guard against non-table "project" key in pyproject (isinstance dict check)
brownfield/service.py: index before save in both _fresh_import and _reimport so a failed index does not strand an unindexed map
brownfield/service.py: _URL_USERINFO regex now uses RFC 3986 scheme syntax so git+ssh:// etc. redact correctly
brownfield/source_resolver.py: IPv6 hostname wrapped in brackets before composing netloc
git_backend/embedded.py: seed-phase push + rev-parse now raise GitBackendSeedError / GIT_BACKEND_SEED_FAILED (not push types)
persistence migrations + schema.sql: JSON array CHECK constraints on modules / entry_points / test_suites / build_files / dependencies (both backends)
test_source_resolver.py: assert resolved fetch_url for file:// case
test_brownfield_adapter.py: assert_awaited_once_with(submission) for stronger payload check

Skipped CR-duplicate (test_seed.py event_loop_policy): the dir conftest at tests/unit/engine/workspace/git_backend/conftest.py already provides session-scoped event_loop_policy returning DefaultEventLoopPolicy (Proactor on Windows), which test_seed inherits.
go_scanner _REQUIRE_RE: prepend optional (?:require\s+)? so the regex matches single-line directives like "require github.com/pkg/errors v0.9.1" AND the indented lines inside a require ( ... ) block; still rejects "retract v1.2.3" (no slash).
@Aureliolo Aureliolo force-pushed the feat/1975-brownfield-codebase-intake branch from 8054aab to 56eee1b Compare May 22, 2026 20:08
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 22, 2026 20:10 — with GitHub Actions Inactive
@Aureliolo Aureliolo merged commit e287621 into main May 22, 2026
78 checks passed
@Aureliolo Aureliolo deleted the feat/1975-brownfield-codebase-intake branch May 22, 2026 20:17
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 22, 2026 20:17 — with GitHub Actions Inactive
Aureliolo pushed a commit that referenced this pull request May 24, 2026
<!-- HIGHLIGHTS_START -->
## Highlights

> _AI-generated summary (model: `openai/gpt-4.1-mini` via GitHub
Models). Commit-based changelog below._

### What you'll notice
- New brownfield codebase intake mode supports merger and acquisition
scenarios.
- Added deep CEO interview feature to improve project charter creation.
- Introduced mission control and flight recorder operator cockpit for
better operational oversight.
- Research mode added for enhanced exploratory work.
- Runtime services now log safety-spine state at boot for clearer
diagnostics.

### What's new
- Research mode feature enables deeper data exploration.
- CEO interview integration helps shape project charters.
- Mission control and flight recorder cockpit introduced for operational
tracking.

### Under the hood
- Improved codebase modularity with module-size gates and lint
tightening.
- Added __init__.py to 21 test directories for better test discovery.
- Promoted six transitive dependencies to direct dependencies for
clarity.
- Split codespell ignore list into vocabulary and source renames.
- Decomposed oversized web utilities, hooks, and libraries for
maintainability.
- Enhanced CI with Lychee link checker integration and retry logic for
cosign signing.
- Sharded unit and integration tests and added Postgres service
container in CI.
- Updated infrastructure and web dependencies; maintained lock files.

<!-- HIGHLIGHTS_END -->

:robot: I have created a release *beep* *boop*
---


##
[0.8.8](v0.8.7...v0.8.8)
(2026-05-24)


### Features

* brownfield codebase intake (merger/acquisition entry mode)
([#2042](#2042))
([e287621](e287621)),
closes [#1975](#1975)
* deep CEO interview to project charter
([#2045](#2045))
([904f2fb](904f2fb))
* mission control + flight recorder operator cockpit
([#2044](#2044))
([1c2660b](1c2660b))
* research mode
([#2041](#2041))
([f81a5ac](f81a5ac)),
closes [#1989](#1989)
* surface safety-spine state in runtime-services boot log (closes
[#2096](#2096))
([#2097](#2097))
([f187b31](f187b31))


### Refactoring

* add __init__.py to 21 leaf test directories (INP001)
([#2081](#2081))
([2592118](2592118)),
closes [#2064](#2064)
* codebase modularity (1/4) - module-size gates + lint tightening +
tools ([#2078](#2078))
([556fbd9](556fbd9)),
closes [#2047](#2047)
[#2040](#2040)
* promote 6 transitive deps to direct deps
([#2083](#2083))
([adedc6a](adedc6a))
* split codespell ignore-words-list into vocab + source renames
([#2085](#2085))
([917d98a](917d98a)),
closes [#2074](#2074)
* **web:** PR A foundation, decompose oversized utils/hooks/lib
([#2092](#2092))
([#2098](#2098))
([aedbba5](aedbba5))


### CI/CD

* exclude slsa.dev from lychee (transient timeout on canonical badge)
([#2090](#2090))
([346c51d](346c51d))
* fix paths-filter shallow-clone race and scorecard allowlist
([#2089](#2089))
([7cd7ce8](7cd7ce8))
* refresh .test_durations.{unit,integration}
([#2087](#2087))
([ddf2d86](ddf2d86))
* retry cosign sign on transient GHCR/Rekor failures
([#2100](#2100))
([da9422a](da9422a))
* shard test-unit + test-integration, sysmon coverage, Postgres service
container ([#2080](#2080))
([0768787](0768787))
* wire Lychee link-checker (workflow + installer + pre-push hook)
([#2084](#2084))
([1c0694a](1c0694a))


### Maintenance

* Lock file maintenance
([#2086](#2086))
([a78810a](a78810a))
* Update Infrastructure dependencies
([#2055](#2055))
([041ad8b](041ad8b))
* Update Web dependencies
([#2054](#2054))
([4d57b9a](4d57b9a))

---
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: synthorg-repo-bot[bot] <279117679+synthorg-repo-bot[bot]@users.noreply.github.com>
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.

Brownfield codebase intake

1 participant