Skip to content

feat: goal/objective entry adapter (#1964)#2022

Merged
Aureliolo merged 4 commits into
mainfrom
feat/goal-objective-entry-adapter
May 20, 2026
Merged

feat: goal/objective entry adapter (#1964)#2022
Aureliolo merged 4 commits into
mainfrom
feat/goal-objective-entry-adapter

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Closes #1964

Part of EPIC #1955.

Summary

Thin high-altitude work-entry adapter: a human-stated objective enters
the pipeline spine as a WorkItem(source=OBJECTIVE) and is decomposed
into projects/tasks by the existing MultiAgentCoordinator, then
executed solo or as a team (automatic; never a user choice). No new
decomposition logic — reuses the spine + coordinator end to end.

Wire-up

  • src/synthorg/engine/pipeline/entry/objective_adapter.py — new
    ObjectiveSubmission (frozen Pydantic, extra="forbid") and
    ObjectiveEntryAdapter (thin: __slots__ = ("_default_project", "_work_pipeline")).
  • src/synthorg/engine/pipeline/entry/factory.py — adds the
    WorkSource.OBJECTIVE arm. Coordinates with Entry adapter: task board to live runtime #1963 on this shared
    seam; the task-board adapter rebases when it lands.
  • src/synthorg/engine/pipeline/entry/protocol.py — generalised to
    PEP 695 generic class WorkEntryAdapter[T_Request](Protocol) so the
    intake and objective adapters can each be typed against their own
    domain input.
  • src/synthorg/engine/pipeline/entry/boot.py — new
    wire_real_objective_entry() (cold boot + hot-reload via
    hot_swap=True); _ensure_project lifted as a shared helper.
  • src/synthorg/api/state.pyobjective_entry_adapter slot +
    property + once-only set_ + atomic set_if_absent_ + swap_
    seams + objective_background_tasks: set[Task] for spawned
    pipeline runs.
  • src/synthorg/api/controllers/objectives.py — new POST /objectives
    returning 202 + submission_id (server-minted, propagated as the
    WorkItem.correlation_id); pipeline runs as a background task so
    the HTTP boundary never blocks on team coordination. Guarded by
    require_write_access + per-op rate-limit objectives.submit.
  • src/synthorg/api/app.py + controllers/setup/agent_helpers.py
    the new wire call is appended right after the intake wire, both at
    cold boot and on provider-reinit.
  • New OBJECTIVES settings namespace + default_project definition
    (read_only_post_init=True, restart_required=True).

Manifest discipline (parent epic hard criterion)

scripts/_ghost_wiring_manifest.txt ships an ENFORCED ObjectiveEntryAdapter #1964 ... line in this same PR;
scripts/check_no_ghost_wiring.py passes.

Test plan

  • Unit (all green; tests/unit/engine/pipeline/entry/ +
    tests/unit/api/controllers/test_objectives.py):
    • ObjectiveSubmission: frozen, rejects unknown fields, blank
      title/description/requested_by, blank acceptance-criteria
      elements; submission_id defaults to uuid4.
    • ObjectiveEntryAdapter: maps submission to
      WorkItem(source=OBJECTIVE); correlation_id == submission_id;
      default project enforced; optional fields fall through to
      WorkItem defaults; pipeline errors propagate unchanged.
    • Factory dispatch: OBJECTIVE arm returns ObjectiveEntryAdapter;
      unwired sources still raise UnknownStrategyError.
    • Boot hook: no-op without work_pipeline; creates the objectives
      project when absent; skips create when it exists; hot_swap uses
      the swap seam (and still ensures the project exists).
    • Controller: 202 + minted submission_id; background task tracked
      on AppState; controller never blocks on the pipeline run;
      done-callback removes completed tasks from the set; payload
      rejects unknown fields, blank fields, and unknown enum strings.
  • E2E (tests/e2e/test_real_objective_entry_e2e.py, run under
    -m e2e): builds the real runtime via the production
    build_runtime_services with a deterministic ScriptedDriver.
    Two cases:
    1. Default leaf-threshold policy — proves the path is wired and
      the spawned task advances past CREATED.
    2. Forced always-team policy — proves the objective decomposes:
      asserts verdict=SPLITTABLE, execution_path=TEAM, and the
      root task advances past CREATED.

Review coverage

Reviewed via /pre-pr-review with the core agent roster only
(thin-adapter scope): python-reviewer, security-reviewer,
test-quality-reviewer, conventions-enforcer, issue-resolution-verifier.

Agent Result
python-reviewer APPROVE, zero findings
security-reviewer APPROVE, zero findings (SEC-1 wrapping, auth, rate-limit, background-task lifecycle, settings injection verified)
conventions-enforcer Zero violations
issue-resolution-verifier PASS, all 7 acceptance criteria at confidence 100
test-quality-reviewer 0 critical; 5 minor refinements applied (defensive double-yield on done-callback test, invalid-enum-rejection coverage, blank-acceptance-criteria coverage, _result helper docstring, hot_swap project-create assertion)

All ruff / mypy strict / pre-commit / pre-push gates green; 9485
affected-area unit tests pass locally.

Out of scope

  • First-class Objective persistence (no model, repository, or
    migration). Submission is ephemeral; state lives on the spawned
    root task.
  • /objectives/{id} GET / list / cancel surfaces.
  • Frontend integration.
  • Coordinator / decomposition-strategy / routing-policy changes
    (reused as-is).
  • Add an idempotency_key= query filter to /tasks so HTTP-only
    clients can resolve submission_id → spawned task. Tracked as a
    follow-up; the simulation harness drives the adapter directly so
    this is not blocking acceptance for Entry adapter: goal/objective intake #1964.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

Dependency Review

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

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro

Run ID: 853f1af2-6803-495b-bb2a-058fdbc9056b

📥 Commits

Reviewing files that changed from the base of the PR and between d5d1515 and 010b7a1.

📒 Files selected for processing (1)
  • tests/e2e/test_real_objective_entry_e2e.py
📜 Recent 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). (13)
  • GitHub Check: Deploy Preview
  • GitHub Check: Build Backend
  • GitHub Check: CodSpeed Web benchmarks
  • GitHub Check: CodSpeed Python benchmarks
  • GitHub Check: Build Web Assets (melange)
  • GitHub Check: Lighthouse Dashboard
  • GitHub Check: Test Unit
  • GitHub Check: Test Integration
  • GitHub Check: Test Conformance (SQLite)
  • GitHub Check: Dashboard Test
  • GitHub Check: Test E2E
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Apply no regional/currency/locale privilege; use metric units; use British English for all text
Every convention PR must ship its enforcement gate via scripts/check_*.py or .pre-commit-config.yaml
Apply 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 are pure env at boot site. No os.environ.get outside startup; pre-init Cat-2 reads use settings.bootstrap_resolver.resolve_init_value. YAML is company-template ingestion format only, not a precedence tier.
No hardcoded numeric values; numerics live in settings/definitions/. Allowlist exceptions: 0, 1, -1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants of form NAME: int|float|Final|Final[int]|Final[float] = literal. Enforced by scripts/check_no_magic_numbers.py.
Include comments explaining WHY only; no reviewer citations, issue back-references, or migration framing. Enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py.
Do not use from __future__ import annotations (Python 3.14 has PEP 649). Apply PEP 758 exception: except A, B syntax without parens unless binding.
Type hints required on public functions; mypy strict mode. Use Google-style docstrings. Line length 88; functions under 50 lines; files under 800 lines.
Define errors as <Domain><Condition>Error inheriting from DomainError, never directly from Exception/RuntimeError/etc. Enforced by check_domain_error_hierarchy.py.
Pydantic v2: use frozen + extra="forbid" on every frozen model project-wide (gate check_frozen_model_extra_forbid.py). @computed_field is auto-exempt; use # lint-allow: frozen-extra-forbid -- <reason> per-line for extra="allow"/"ignore" boundaries. Use @computed_field for derived fields.
Use NotBlankStr for identifier fields in Pydantic models
Args models required at every system boundary; use parse_typed() for every ...

Files:

  • tests/e2e/test_real_objective_entry_e2e.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Timeout/slow failures indicate source-code regression; never edit tests/baselines/unit_timing.json or any scripts/*_baseline.{txt,json} / scripts/_*_baseline.py. Both families are PreToolUse-blocked. Per-invocation bypass for gate baselines requires ALLOW_BASELINE_GROWTH=1 git commit ... with explicit user approval.
Test markers: @pytest.mark.{unit,integration,e2e,slow}. Async tests use auto. Global timeout 30s. Minimum coverage 80%. xdist -n 8 --dist=loadfile auto-applied via pyproject addopts (loadfile prevents 3.14+Windows ProactorEventLoop leak).
Windows: unit tests use WindowsSelectorEventLoopPolicy (3.14 IOCP teardown race). Subprocess tests override back.
Use test-double ladder (see conventions.md section 12.1): FakeClock for Clock seam, mock_of[T](**overrides) for typed-boundary substitutions, SimpleNamespace for attribute-bags. Bare MagicMock at typed boundaries is blocked by scripts/check_mock_spec.py (zero-tolerance).
Import FakeClock and mock_of from tests._shared; inject via clock= parameter and helper's spec subscript
Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...)). Never skip/xfail for flaky tests; fix fundamentally. Use asyncio.Event().wait() not sleep(large).

Files:

  • tests/e2e/test_real_objective_entry_e2e.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/e2e/test_real_objective_entry_e2e.py
**/*.{py,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Use d2 for architecture and nested container diagrams; use mermaid for flowcharts, sequence diagrams, and pipelines; use Markdown tables for tabular data

Files:

  • tests/e2e/test_real_objective_entry_e2e.py
🧠 Learnings (1)
📚 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/e2e/test_real_objective_entry_e2e.py
🔇 Additional comments (6)
tests/e2e/test_real_objective_entry_e2e.py (6)

1-66: LGTM!


67-129: LGTM!


132-162: LGTM!


165-232: LGTM!


235-267: LGTM!


270-303: LGTM!


Walkthrough

This PR adds a new objectives entry adapter enabling humans to submit goals that are autonomously decomposed and executed by the pipeline. The implementation generalizes the WorkEntryAdapter protocol to accept any request type, introduces an ObjectiveEntryAdapter that converts ObjectiveSubmission objects into pipeline work items, extends AppState with objective-specific storage and APIs, provides an HTTP endpoint via ObjectiveController that returns 202 Accepted with a minted submission ID, wires initialization via a wire_real_objective_entry boot hook with automatic project creation and settings namespace registration, and includes comprehensive unit and end-to-end test coverage validating the full intake pipeline including coordinator-based task decomposition.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the primary change: introducing a goal/objective entry adapter, which is the main feature added in this PR.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the objective intake adapter, wire-up details, test coverage, and out-of-scope items.
Linked Issues check ✅ Passed The PR fully implements the acceptance criteria from issue #1964: a submitted objective is decomposed and executed end-to-end, validated under simulation harness with E2E tests covering default and team policies.
Out of Scope Changes check ✅ Passed All changes are in scope: new ObjectiveEntryAdapter, factory dispatch, protocol generalization, boot wiring, AppState extensions, controller implementation, and settings namespace are all directly required for the objective intake feature.
Docstring Coverage ✅ Passed Docstring coverage is 52.05% which is sufficient. The required threshold is 40.00%.

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


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

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new entry adapter for human-stated objectives, allowing them to be submitted via a dedicated API endpoint for autonomous decomposition and execution. By leveraging the existing pipeline spine and multi-agent coordinator, the system can now process high-level goals as WorkItem objects, ensuring consistent handling across different work sources. The implementation includes necessary API controllers, boot-time wiring, and configuration settings to support this new workflow, while maintaining the system's existing background task and rate-limiting patterns.

Highlights

  • New Objective Entry Adapter: Introduced the ObjectiveEntryAdapter and ObjectiveSubmission model to allow human-stated goals to enter the pipeline spine as WorkItems.
  • API Endpoint: Added a new POST /objectives endpoint that mints a submission ID and processes pipeline runs as background tasks.
  • Pipeline Integration: Integrated objective processing into the system boot sequence and hot-reload logic, ensuring the objective entry path is correctly wired.
  • Configuration: Created a new OBJECTIVES settings namespace to manage project configuration for objective-based work.
  • Testing: Implemented comprehensive unit tests and an E2E test suite to verify objective decomposition and execution via the multi-agent coordinator.
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 20, 2026 05:16 — with GitHub Actions Inactive
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 introduces the goal/objective intake path, enabling users to submit high-level objectives via a new POST /objectives endpoint. Key additions include the ObjectiveController, the ObjectiveEntryAdapter, and the necessary boot wiring to ensure a default project exists for these submissions. The implementation leverages background tasks to drive the work pipeline asynchronously, returning a 202 Accepted response with a server-minted submission ID for correlation. Feedback was provided to reorder background task tracking operations to prevent a potential race condition where a task might finish before being added to the tracking set.

Comment on lines +118 to +119
task.add_done_callback(app_state.objective_background_tasks.discard)
app_state.objective_background_tasks.add(task)
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 background task should be added to the tracking set before attaching the discard callback. While asyncio.create_task only schedules the task for the next event loop iteration, it is a safer pattern to ensure the task is present in the set before any possibility of it finishing and attempting to remove itself. This avoids a potential race condition where a task that finishes extremely quickly could call discard before it is added to the set, leading to a memory leak as the task remains in the set indefinitely.

Suggested change
task.add_done_callback(app_state.objective_background_tasks.discard)
app_state.objective_background_tasks.add(task)
app_state.objective_background_tasks.add(task)
task.add_done_callback(app_state.objective_background_tasks.discard)

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 20, 2026

Merging this PR will not alter performance

✅ 54 untouched benchmarks


Comparing feat/goal-objective-entry-adapter (010b7a1) with main (5ad3c46)

Open in CodSpeed

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

🤖 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/controllers/objectives.py`:
- Around line 105-109: The info log in objectives.py currently includes a
potentially PII-bearing field `requested_by` when calling logger.info with
OBJECTIVE_SUBMISSION_RECEIVED; remove `requested_by` from that call and only log
non-identifying metadata (e.g., keep `submission.submission_id`) in the
logger.info invocation inside the submission handling function where
OBJECTIVE_SUBMISSION_RECEIVED is emitted to avoid persisting user identifiers.

In `@src/synthorg/engine/pipeline/entry/boot.py`:
- Around line 107-112: Replace uses of the OBJECTIVE_SUBMISSION_RECEIVED event
in the boot/wiring log statements with a dedicated boot/wiring event constant
from observability.events.<domain> (e.g., an OBJECTIVE_ENTRY_BOOTED or
ADAPTER_WIRED-style constant) and keep the same structured kwargs
(service="objective_entry_adapter", mode="disabled"/"wired"/etc., note=...) so
the log reflects the actual state transition; update every logger.info call in
this module that currently uses OBJECTIVE_SUBMISSION_RECEIVED (the
boot/offline/project-created/adapter-disabled logging sites) to use the new
event constant from observability.events and ensure the event name matches the
state being reported.

In `@tests/unit/api/controllers/test_objectives.py`:
- Around line 152-160: The test test_done_callback_discards_task_from_set is
flaky because using two asyncio.sleep(0) to wait for the done-callback to remove
the task from app_state.objective_background_tasks is timing-sensitive; replace
the sleeps with a bounded polling loop (e.g., loop for up to N iterations or
timeout checking len(app_state.objective_background_tasks) == 0 with a short
await asyncio.sleep(small_interval) between checks) or wait on an event that the
callback sets, so the assertion becomes deterministic after calling
submit_objective_impl and awaiting the pending task.
🪄 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: 438fc4ca-edd8-43c5-ab92-2f8f1c0090ad

📥 Commits

Reviewing files that changed from the base of the PR and between 5ad3c46 and 66b81d9.

📒 Files selected for processing (25)
  • scripts/_ghost_wiring_manifest.txt
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/api/controllers/objectives.py
  • src/synthorg/api/controllers/setup/agent_helpers.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/pipeline/entry/__init__.py
  • src/synthorg/engine/pipeline/entry/boot.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/objective_adapter.py
  • src/synthorg/engine/pipeline/entry/protocol.py
  • src/synthorg/observability/events/objectives.py
  • src/synthorg/observability/prometheus_labels.py
  • src/synthorg/settings/definitions/__init__.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/settings/enums.py
  • tests/e2e/test_real_objective_entry_e2e.py
  • tests/unit/api/controllers/test_objectives.py
  • tests/unit/engine/pipeline/entry/test_factory.py
  • tests/unit/engine/pipeline/entry/test_objective_adapter.py
  • tests/unit/engine/pipeline/entry/test_objective_boot.py
  • tests/unit/observability/test_events.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: CodSpeed Python benchmarks
  • GitHub Check: CodSpeed Web benchmarks
  • GitHub Check: Test Conformance (SQLite)
  • GitHub Check: Test Unit
  • GitHub Check: Dashboard Test
  • GitHub Check: Test Integration
  • GitHub Check: Test E2E
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Apply no regional/currency/locale privilege; use metric units; use British English for all text
Every convention PR must ship its enforcement gate via scripts/check_*.py or .pre-commit-config.yaml
Apply 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 are pure env at boot site. No os.environ.get outside startup; pre-init Cat-2 reads use settings.bootstrap_resolver.resolve_init_value. YAML is company-template ingestion format only, not a precedence tier.
No hardcoded numeric values; numerics live in settings/definitions/. Allowlist exceptions: 0, 1, -1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants of form NAME: int|float|Final|Final[int]|Final[float] = literal. Enforced by scripts/check_no_magic_numbers.py.
Include comments explaining WHY only; no reviewer citations, issue back-references, or migration framing. Enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py.
Do not use from __future__ import annotations (Python 3.14 has PEP 649). Apply PEP 758 exception: except A, B syntax without parens unless binding.
Type hints required on public functions; mypy strict mode. Use Google-style docstrings. Line length 88; functions under 50 lines; files under 800 lines.
Define errors as <Domain><Condition>Error inheriting from DomainError, never directly from Exception/RuntimeError/etc. Enforced by check_domain_error_hierarchy.py.
Pydantic v2: use frozen + extra="forbid" on every frozen model project-wide (gate check_frozen_model_extra_forbid.py). @computed_field is auto-exempt; use # lint-allow: frozen-extra-forbid -- <reason> per-line for extra="allow"/"ignore" boundaries. Use @computed_field for derived fields.
Use NotBlankStr for identifier fields in Pydantic models
Args models required at every system boundary; use parse_typed() for every ...

Files:

  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/observability/events/objectives.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/settings/enums.py
  • tests/unit/observability/test_events.py
  • src/synthorg/api/app.py
  • tests/unit/engine/pipeline/entry/test_objective_boot.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/observability/prometheus_labels.py
  • src/synthorg/api/controllers/setup/agent_helpers.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/__init__.py
  • src/synthorg/engine/pipeline/entry/protocol.py
  • tests/unit/engine/pipeline/entry/test_factory.py
  • src/synthorg/api/controllers/objectives.py
  • src/synthorg/settings/definitions/__init__.py
  • src/synthorg/engine/pipeline/entry/objective_adapter.py
  • tests/e2e/test_real_objective_entry_e2e.py
  • tests/unit/api/controllers/test_objectives.py
  • tests/unit/engine/pipeline/entry/test_objective_adapter.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/pipeline/entry/boot.py
**/*.{py,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Use d2 for architecture and nested container diagrams; use mermaid for flowcharts, sequence diagrams, and pipelines; use Markdown tables for tabular data

Files:

  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/observability/events/objectives.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/settings/enums.py
  • tests/unit/observability/test_events.py
  • src/synthorg/api/app.py
  • tests/unit/engine/pipeline/entry/test_objective_boot.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/observability/prometheus_labels.py
  • src/synthorg/api/controllers/setup/agent_helpers.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/__init__.py
  • src/synthorg/engine/pipeline/entry/protocol.py
  • tests/unit/engine/pipeline/entry/test_factory.py
  • src/synthorg/api/controllers/objectives.py
  • src/synthorg/settings/definitions/__init__.py
  • src/synthorg/engine/pipeline/entry/objective_adapter.py
  • tests/e2e/test_real_objective_entry_e2e.py
  • tests/unit/api/controllers/test_objectives.py
  • tests/unit/engine/pipeline/entry/test_objective_adapter.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/pipeline/entry/boot.py
src/synthorg/api/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

API startup has two phases: construction (create_app body) wires synchronous services; on_startup (_build_lifecycle.on_startup) wires services needing connected persistence backend. Construction ordering: agent_registry before auto_wire_meetings; tunnel_provider unconditionally. On-startup ordering: SettingsService before WorkflowExecutionObserver (max_subworkflow_depth), OntologyService after persistence.connect().

Files:

  • src/synthorg/api/controllers/__init__.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup/agent_helpers.py
  • src/synthorg/api/controllers/objectives.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/api/controllers/__init__.py
  • src/synthorg/observability/events/objectives.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/settings/enums.py
  • src/synthorg/api/app.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/observability/prometheus_labels.py
  • src/synthorg/api/controllers/setup/agent_helpers.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/__init__.py
  • src/synthorg/engine/pipeline/entry/protocol.py
  • src/synthorg/api/controllers/objectives.py
  • src/synthorg/settings/definitions/__init__.py
  • src/synthorg/engine/pipeline/entry/objective_adapter.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/pipeline/entry/boot.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Timeout/slow failures indicate source-code regression; never edit tests/baselines/unit_timing.json or any scripts/*_baseline.{txt,json} / scripts/_*_baseline.py. Both families are PreToolUse-blocked. Per-invocation bypass for gate baselines requires ALLOW_BASELINE_GROWTH=1 git commit ... with explicit user approval.
Test markers: @pytest.mark.{unit,integration,e2e,slow}. Async tests use auto. Global timeout 30s. Minimum coverage 80%. xdist -n 8 --dist=loadfile auto-applied via pyproject addopts (loadfile prevents 3.14+Windows ProactorEventLoop leak).
Windows: unit tests use WindowsSelectorEventLoopPolicy (3.14 IOCP teardown race). Subprocess tests override back.
Use test-double ladder (see conventions.md section 12.1): FakeClock for Clock seam, mock_of[T](**overrides) for typed-boundary substitutions, SimpleNamespace for attribute-bags. Bare MagicMock at typed boundaries is blocked by scripts/check_mock_spec.py (zero-tolerance).
Import FakeClock and mock_of from tests._shared; inject via clock= parameter and helper's spec subscript
Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...)). Never skip/xfail for flaky tests; fix fundamentally. Use asyncio.Event().wait() not sleep(large).

Files:

  • tests/unit/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_objective_boot.py
  • tests/unit/engine/pipeline/entry/test_factory.py
  • tests/e2e/test_real_objective_entry_e2e.py
  • tests/unit/api/controllers/test_objectives.py
  • tests/unit/engine/pipeline/entry/test_objective_adapter.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/observability/test_events.py
  • tests/unit/engine/pipeline/entry/test_objective_boot.py
  • tests/unit/engine/pipeline/entry/test_factory.py
  • tests/e2e/test_real_objective_entry_e2e.py
  • tests/unit/api/controllers/test_objectives.py
  • tests/unit/engine/pipeline/entry/test_objective_adapter.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
web/src/**/*.{ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Reuse design tokens and components from web/src/components/ui/; follow Web Dashboard Design System defined in web/CLAUDE.md

Files:

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

📄 CodeRabbit inference engine (CLAUDE.md)

React 19 web dashboard in web/ directory; see web/CLAUDE.md for detailed conventions

Files:

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

📄 CodeRabbit inference engine (CLAUDE.md)

post_setup_reinit() propagates failures; settings_svc.set("api", "setup_complete", "true") runs only if reinit succeeds. Entire check/validate/reinit/persist sequence serialized under COMPLETE_LOCK to prevent concurrent /setup/complete requests from racing on flag write.

Files:

  • src/synthorg/api/controllers/setup/agent_helpers.py
🧠 Learnings (3)
📚 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/api/controllers/__init__.py
  • src/synthorg/observability/events/objectives.py
  • src/synthorg/api/rate_limits/policies.py
  • src/synthorg/settings/enums.py
  • tests/unit/observability/test_events.py
  • src/synthorg/api/app.py
  • tests/unit/engine/pipeline/entry/test_objective_boot.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/observability/prometheus_labels.py
  • src/synthorg/api/controllers/setup/agent_helpers.py
  • src/synthorg/engine/pipeline/entry/factory.py
  • src/synthorg/engine/pipeline/entry/__init__.py
  • src/synthorg/engine/pipeline/entry/protocol.py
  • tests/unit/engine/pipeline/entry/test_factory.py
  • src/synthorg/api/controllers/objectives.py
  • src/synthorg/settings/definitions/__init__.py
  • src/synthorg/engine/pipeline/entry/objective_adapter.py
  • tests/e2e/test_real_objective_entry_e2e.py
  • tests/unit/api/controllers/test_objectives.py
  • tests/unit/engine/pipeline/entry/test_objective_adapter.py
  • src/synthorg/api/state.py
  • src/synthorg/engine/pipeline/entry/boot.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/enums.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/settings/definitions/__init__.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/enums.py
  • src/synthorg/settings/definitions/objectives.py
  • src/synthorg/settings/definitions/__init__.py
🔇 Additional comments (22)
src/synthorg/engine/pipeline/entry/protocol.py (1)

21-35: LGTM!

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

33-93: LGTM!

Also applies to: 123-175

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

23-57: LGTM!

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

14-24: LGTM!

scripts/_ghost_wiring_manifest.txt (1)

46-46: LGTM!

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

261-262: LGTM!

Also applies to: 1082-1092

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

344-346: LGTM!

Also applies to: 404-406, 1398-1610

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

29-29: LGTM!

src/synthorg/settings/definitions/__init__.py (1)

22-22: LGTM!

Also applies to: 48-48

src/synthorg/settings/definitions/objectives.py (1)

1-32: LGTM!

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

62-62: LGTM!

Also applies to: 176-176

src/synthorg/api/controllers/setup/agent_helpers.py (1)

183-183: LGTM!

Also applies to: 187-187

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

150-151: LGTM!

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

1-6: LGTM!

src/synthorg/observability/prometheus_labels.py (1)

296-296: LGTM!

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

291-291: LGTM!

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

621-621: LGTM!

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

10883-10883: ⚡ Quick win

File correctly generated using the generation script.

The file matches the current generated output from uv run python scripts/generate_dto_types_ts.py, confirming it was properly regenerated and not hand-edited.

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

32-33: LGTM!

Also applies to: 76-238

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

24-25: LGTM!

Also applies to: 45-77

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

30-38: LGTM!

tests/e2e/test_real_objective_entry_e2e.py (1)

63-64: LGTM!

Also applies to: 186-255

Comment thread src/synthorg/api/controllers/objectives.py
Comment thread src/synthorg/engine/pipeline/entry/boot.py
Comment thread tests/unit/api/controllers/test_objectives.py
- Remove PII (requested_by) from OBJECTIVE_SUBMISSION_RECEIVED log in
  controller and adapter; submission_id is sufficient correlation.
- Add OBJECTIVE_ENTRY_WIRED constant; boot.py wiring/disabled logs no
  longer contaminate submission metrics by reusing the submission event.
- Reorder background-task tracking so add() happens before the discard
  done-callback, closing the fast-completion race window.
- Replace flaky asyncio.sleep(0) pair with a bounded polling loop in
  test_done_callback_discards_task_from_set.
- Wire IntakeEngine + DirectIntake into the objective e2e test so
  build_runtime_services produces a non-None work_pipeline.
- Add 'objectives' to SETTING_NAMESPACE_TABLE, NAMESPACE_DISPLAY_NAMES,
  and NAMESPACE_ORDER so the new SettingNamespace member type-checks
  and surfaces in the settings UI.
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 20, 2026
- Teach the e2e ScriptedDriver strategy to handle decomposition tool
  calls. The always-team test routes the task through the multi-agent
  coordinator, which invokes the LLM with a submit_decomposition_plan
  tool definition. The prior _StopStrategy returned 'Work complete.'
  STOP content, so the decomposer failed JSON parsing three times and
  raised DecompositionError. The strategy now branches on
  tools-containing-submit_decomposition_plan, returns a single
  research-skill subtask matching the test's lone research agent, and
  keeps the STOP completion for every other turn.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 90.58824% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.01%. Comparing base (5ad3c46) to head (010b7a1).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/synthorg/api/state.py 75.75% 6 Missing and 2 partials ⚠️
src/synthorg/api/controllers/objectives.py 91.07% 3 Missing and 2 partials ⚠️
src/synthorg/engine/pipeline/entry/boot.py 84.21% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2022    +/-   ##
========================================
  Coverage   85.01%   85.01%            
========================================
  Files        1926     1930     +4     
  Lines      114686   114849   +163     
  Branches     9763     9776    +13     
========================================
+ Hits        97496    97644   +148     
- Misses      14790    14801    +11     
- Partials     2400     2404     +4     

☔ 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 merged commit 8646441 into main May 20, 2026
82 checks passed
@Aureliolo Aureliolo deleted the feat/goal-objective-entry-adapter branch May 20, 2026 06:23
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 20, 2026 06:24 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request May 20, 2026
Closes #1964

Part of EPIC #1955.

## Summary

Thin high-altitude work-entry adapter: a human-stated objective enters
the pipeline spine as a `WorkItem(source=OBJECTIVE)` and is decomposed
into projects/tasks by the existing `MultiAgentCoordinator`, then
executed solo or as a team (automatic; never a user choice). No new
decomposition logic — reuses the spine + coordinator end to end.

### Wire-up

- `src/synthorg/engine/pipeline/entry/objective_adapter.py` — new
  `ObjectiveSubmission` (frozen Pydantic, `extra="forbid"`) and
  `ObjectiveEntryAdapter` (thin: `__slots__ = ("_default_project",
  "_work_pipeline")`).
- `src/synthorg/engine/pipeline/entry/factory.py` — adds the
  `WorkSource.OBJECTIVE` arm. Coordinates with #1963 on this shared
  seam; the task-board adapter rebases when it lands.
- `src/synthorg/engine/pipeline/entry/protocol.py` — generalised to
  PEP 695 generic `class WorkEntryAdapter[T_Request](Protocol)` so the
  intake and objective adapters can each be typed against their own
  domain input.
- `src/synthorg/engine/pipeline/entry/boot.py` — new
  `wire_real_objective_entry()` (cold boot + hot-reload via
  `hot_swap=True`); `_ensure_project` lifted as a shared helper.
- `src/synthorg/api/state.py` — `objective_entry_adapter` slot +
  property + once-only `set_` + atomic `set_if_absent_` + `swap_`
  seams + `objective_background_tasks: set[Task]` for spawned
  pipeline runs.
- `src/synthorg/api/controllers/objectives.py` — new `POST /objectives`
  returning 202 + `submission_id` (server-minted, propagated as the
  `WorkItem.correlation_id`); pipeline runs as a background task so
  the HTTP boundary never blocks on team coordination. Guarded by
  `require_write_access` + per-op rate-limit `objectives.submit`.
- `src/synthorg/api/app.py` + `controllers/setup/agent_helpers.py` —
  the new wire call is appended right after the intake wire, both at
  cold boot and on provider-reinit.
- New OBJECTIVES settings namespace + `default_project` definition
  (`read_only_post_init=True`, `restart_required=True`).

### Manifest discipline (parent epic hard criterion)

`scripts/_ghost_wiring_manifest.txt` ships an `ENFORCED
ObjectiveEntryAdapter #1964 ...` line in this same PR;
`scripts/check_no_ghost_wiring.py` passes.

## Test plan

- **Unit** (all green; `tests/unit/engine/pipeline/entry/` +
  `tests/unit/api/controllers/test_objectives.py`):
  - `ObjectiveSubmission`: frozen, rejects unknown fields, blank
    title/description/requested_by, blank acceptance-criteria
    elements; submission_id defaults to uuid4.
  - `ObjectiveEntryAdapter`: maps submission to
    `WorkItem(source=OBJECTIVE)`; correlation_id == submission_id;
    default project enforced; optional fields fall through to
    `WorkItem` defaults; pipeline errors propagate unchanged.
  - Factory dispatch: OBJECTIVE arm returns `ObjectiveEntryAdapter`;
    unwired sources still raise `UnknownStrategyError`.
  - Boot hook: no-op without `work_pipeline`; creates the objectives
    project when absent; skips create when it exists; hot_swap uses
    the swap seam (and still ensures the project exists).
  - Controller: 202 + minted submission_id; background task tracked
    on `AppState`; controller never blocks on the pipeline run;
    done-callback removes completed tasks from the set; payload
    rejects unknown fields, blank fields, and unknown enum strings.
- **E2E** (`tests/e2e/test_real_objective_entry_e2e.py`, run under
  `-m e2e`): builds the real runtime via the production
  `build_runtime_services` with a deterministic `ScriptedDriver`.
  Two cases:
  1. Default `leaf-threshold` policy — proves the path is wired and
     the spawned task advances past `CREATED`.
  2. Forced `always-team` policy — proves the objective decomposes:
     asserts `verdict=SPLITTABLE`, `execution_path=TEAM`, and the
     root task advances past `CREATED`.

## Review coverage

Reviewed via `/pre-pr-review` with the core agent roster only
(thin-adapter scope): python-reviewer, security-reviewer,
test-quality-reviewer, conventions-enforcer, issue-resolution-verifier.

| Agent | Result |
| --- | --- |
| python-reviewer | APPROVE, zero findings |
| security-reviewer | APPROVE, zero findings (SEC-1 wrapping, auth,
rate-limit, background-task lifecycle, settings injection verified) |
| conventions-enforcer | Zero violations |
| issue-resolution-verifier | PASS, all 7 acceptance criteria at
confidence 100 |
| test-quality-reviewer | 0 critical; 5 minor refinements applied
(defensive double-yield on done-callback test, invalid-enum-rejection
coverage, blank-acceptance-criteria coverage, `_result` helper
docstring, hot_swap project-create assertion) |

All ruff / mypy strict / pre-commit / pre-push gates green; 9485
affected-area unit tests pass locally.

## Out of scope

- First-class `Objective` persistence (no model, repository, or
  migration). Submission is ephemeral; state lives on the spawned
  root task.
- `/objectives/{id}` GET / list / cancel surfaces.
- Frontend integration.
- Coordinator / decomposition-strategy / routing-policy changes
  (reused as-is).
- Add an `idempotency_key=` query filter to `/tasks` so HTTP-only
  clients can resolve `submission_id` → spawned task. Tracked as a
  follow-up; the simulation harness drives the adapter directly so
  this is not blocking acceptance for #1964.
Aureliolo pushed a commit that referenced this pull request May 22, 2026
<!-- HIGHLIGHTS_START -->
## Highlights

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

### What you'll notice
- Introduced conversational interface for direct clarify and propose
interactions.
- Cost management now includes forecast gates, hard ceilings, and Pareto
considerations.
- Added living documentation engine combining wiki and
retrieval-augmented generation features.
- Real intake engine is now operational for live data processing.
- Virtual desktop tool with vision verification gate available for
enhanced workspace control.

### What's new
- Per-project reproducible environments for consistent setups.
- Headless browser testing tool integrated for automated UI validation.
- Governed external API and data access tool introduced.
- Hardened external-remote git backend with sandbox mounts and
push-queue dispatching.
- Adversarial red-team gate subsystem for enhanced security testing.
- Self-extending toolkit to dynamically expand capabilities.
- Stakes-aware model routing enables prioritized processing.
- Task-board entry adapter connects live runtime with project
management.
- Persistent project workspace with pluggable git backend and
per-project push queues implemented.
- Knowledge and provenance substrate added to track data lineage.
- Scoring and data contract framework for golden-company benchmark
evaluations.

### Under the hood
- Desktop Dockerfile pinned by digest to improve build stability and
documented publishing gap fixed.

<!-- HIGHLIGHTS_END -->

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


##
[0.8.7](v0.8.6...v0.8.7)
(2026-05-22)


### Features

* conversational interface v1 - 1:1 clarify + propose
([#2019](#2019))
([216ef94](216ef94)),
closes [#1968](#1968)
* cost as a first-class dial (forecast gate, hard ceiling, Pareto)
([#2029](#2029))
([700a59e](700a59e)),
closes [#1982](#1982)
* **env:** reproducible per-project environments
([#2039](#2039))
([d2c0ef9](d2c0ef9)),
closes [#1994](#1994)
* **evals:** [#1980](#1980)
spine -- scoring + data contract for golden-company benchmark
([#2025](#2025))
([53108e8](53108e8))
* goal/objective entry adapter
([#1964](#1964))
([#2022](#2022))
([cb15c3c](cb15c3c))
* governed external API/data access tool
([#1991](#1991))
([#2032](#2032))
([e08b451](e08b451))
* harden external-remote git backend + per-project sandbox mount +
push-queue dispatch
([#2020](#2020))
([#2030](#2030))
([2fa2e1e](2fa2e1e))
* headless browser testing tool
([#1992](#1992))
([#2024](#2024))
([277b52a](277b52a))
* knowledge + provenance substrate
([#2036](#2036))
([48c897b](48c897b))
* living documentation engine (dual-purpose wiki + RAG namespace)
([#2028](#2028))
([3d10da9](3d10da9)),
closes [#1976](#1976)
* real intake engine online
([#2017](#2017))
([9d8eb34](9d8eb34))
* **redteam:** adversarial red-team gate subsystem
([#1986](#1986))
([#2026](#2026))
([d2207e9](d2207e9))
* self-extending toolkit
([#1995](#1995))
([#2035](#2035))
([5ffc545](5ffc545))
* stakes-aware model routing
([#1998](#1998))
([#2038](#2038))
([9b98312](9b98312))
* task-board entry adapter to live runtime
([#1963](#1963))
([#2023](#2023))
([a8f1eea](a8f1eea))
* virtual desktop tool and vision verifier gate
([#2031](#2031))
([dfe8b42](dfe8b42)),
closes [#1993](#1993)
* **workspace:** persistent project workspace + pluggable git backend +
per-project push queue
([#2021](#2021))
([ee58ee7](ee58ee7))


### Bug Fixes

* pin desktop Dockerfile by digest (Scorecard
[#309](#309)) + document
publish gap ([#2034](#2034))
([8fda188](8fda188))

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

Entry adapter: goal/objective intake

1 participant