feat: goal/objective entry adapter (#1964)#2022
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 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)
🧰 Additional context used📓 Path-based instructions (3)**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
tests/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
⚙️ CodeRabbit configuration file
Files:
**/*.{py,md}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-05-05T09:04:46.195ZApplied to files:
🔇 Additional comments (6)
WalkthroughThis 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)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request 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
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize 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 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
|
There was a problem hiding this comment.
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.
| task.add_done_callback(app_state.objective_background_tasks.discard) | ||
| app_state.objective_background_tasks.add(task) |
There was a problem hiding this comment.
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.
| 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) |
There was a problem hiding this comment.
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
📒 Files selected for processing (25)
scripts/_ghost_wiring_manifest.txtsrc/synthorg/api/app.pysrc/synthorg/api/controllers/__init__.pysrc/synthorg/api/controllers/objectives.pysrc/synthorg/api/controllers/setup/agent_helpers.pysrc/synthorg/api/rate_limits/policies.pysrc/synthorg/api/state.pysrc/synthorg/engine/pipeline/entry/__init__.pysrc/synthorg/engine/pipeline/entry/boot.pysrc/synthorg/engine/pipeline/entry/factory.pysrc/synthorg/engine/pipeline/entry/objective_adapter.pysrc/synthorg/engine/pipeline/entry/protocol.pysrc/synthorg/observability/events/objectives.pysrc/synthorg/observability/prometheus_labels.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/settings/definitions/objectives.pysrc/synthorg/settings/enums.pytests/e2e/test_real_objective_entry_e2e.pytests/unit/api/controllers/test_objectives.pytests/unit/engine/pipeline/entry/test_factory.pytests/unit/engine/pipeline/entry/test_objective_adapter.pytests/unit/engine/pipeline/entry/test_objective_boot.pytests/unit/observability/test_events.pyweb/src/api/types/enum-values.gen.tsweb/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 viascripts/check_*.pyor.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. Noos.environ.getoutside startup; pre-init Cat-2 reads usesettings.bootstrap_resolver.resolve_init_value. YAML is company-template ingestion format only, not a precedence tier.
No hardcoded numeric values; numerics live insettings/definitions/. Allowlist exceptions: 0, 1, -1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants of formNAME: int|float|Final|Final[int]|Final[float] = literal. Enforced byscripts/check_no_magic_numbers.py.
Include comments explaining WHY only; no reviewer citations, issue back-references, or migration framing. Enforced bycheck_no_review_origin_in_code.py+check_no_migration_framing.py.
Do not usefrom __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>Errorinheriting fromDomainError, never directly fromException/RuntimeError/etc. Enforced bycheck_domain_error_hierarchy.py.
Pydantic v2: use frozen +extra="forbid"on every frozen model project-wide (gatecheck_frozen_model_extra_forbid.py).@computed_fieldis auto-exempt; use# lint-allow: frozen-extra-forbid -- <reason>per-line forextra="allow"/"ignore"boundaries. Use@computed_fieldfor derived fields.
UseNotBlankStrfor identifier fields in Pydantic models
Args models required at every system boundary; useparse_typed()for every ...
Files:
src/synthorg/api/controllers/__init__.pysrc/synthorg/observability/events/objectives.pysrc/synthorg/api/rate_limits/policies.pysrc/synthorg/settings/enums.pytests/unit/observability/test_events.pysrc/synthorg/api/app.pytests/unit/engine/pipeline/entry/test_objective_boot.pysrc/synthorg/settings/definitions/objectives.pysrc/synthorg/observability/prometheus_labels.pysrc/synthorg/api/controllers/setup/agent_helpers.pysrc/synthorg/engine/pipeline/entry/factory.pysrc/synthorg/engine/pipeline/entry/__init__.pysrc/synthorg/engine/pipeline/entry/protocol.pytests/unit/engine/pipeline/entry/test_factory.pysrc/synthorg/api/controllers/objectives.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/engine/pipeline/entry/objective_adapter.pytests/e2e/test_real_objective_entry_e2e.pytests/unit/api/controllers/test_objectives.pytests/unit/engine/pipeline/entry/test_objective_adapter.pysrc/synthorg/api/state.pysrc/synthorg/engine/pipeline/entry/boot.py
**/*.{py,md}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
d2for architecture and nested container diagrams; usemermaidfor flowcharts, sequence diagrams, and pipelines; use Markdown tables for tabular data
Files:
src/synthorg/api/controllers/__init__.pysrc/synthorg/observability/events/objectives.pysrc/synthorg/api/rate_limits/policies.pysrc/synthorg/settings/enums.pytests/unit/observability/test_events.pysrc/synthorg/api/app.pytests/unit/engine/pipeline/entry/test_objective_boot.pysrc/synthorg/settings/definitions/objectives.pysrc/synthorg/observability/prometheus_labels.pysrc/synthorg/api/controllers/setup/agent_helpers.pysrc/synthorg/engine/pipeline/entry/factory.pysrc/synthorg/engine/pipeline/entry/__init__.pysrc/synthorg/engine/pipeline/entry/protocol.pytests/unit/engine/pipeline/entry/test_factory.pysrc/synthorg/api/controllers/objectives.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/engine/pipeline/entry/objective_adapter.pytests/e2e/test_real_objective_entry_e2e.pytests/unit/api/controllers/test_objectives.pytests/unit/engine/pipeline/entry/test_objective_adapter.pysrc/synthorg/api/state.pysrc/synthorg/engine/pipeline/entry/boot.py
src/synthorg/api/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
API startup has two phases: construction (
create_appbody) wires synchronous services; on_startup (_build_lifecycle.on_startup) wires services needing connected persistence backend. Construction ordering:agent_registrybeforeauto_wire_meetings;tunnel_providerunconditionally. On-startup ordering:SettingsServicebeforeWorkflowExecutionObserver(max_subworkflow_depth),OntologyServiceafterpersistence.connect().
Files:
src/synthorg/api/controllers/__init__.pysrc/synthorg/api/rate_limits/policies.pysrc/synthorg/api/app.pysrc/synthorg/api/controllers/setup/agent_helpers.pysrc/synthorg/api/controllers/objectives.pysrc/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__.pysrc/synthorg/observability/events/objectives.pysrc/synthorg/api/rate_limits/policies.pysrc/synthorg/settings/enums.pysrc/synthorg/api/app.pysrc/synthorg/settings/definitions/objectives.pysrc/synthorg/observability/prometheus_labels.pysrc/synthorg/api/controllers/setup/agent_helpers.pysrc/synthorg/engine/pipeline/entry/factory.pysrc/synthorg/engine/pipeline/entry/__init__.pysrc/synthorg/engine/pipeline/entry/protocol.pysrc/synthorg/api/controllers/objectives.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/engine/pipeline/entry/objective_adapter.pysrc/synthorg/api/state.pysrc/synthorg/engine/pipeline/entry/boot.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Timeout/slow failures indicate source-code regression; never edittests/baselines/unit_timing.jsonor anyscripts/*_baseline.{txt,json}/scripts/_*_baseline.py. Both families are PreToolUse-blocked. Per-invocation bypass for gate baselines requiresALLOW_BASELINE_GROWTH=1 git commit ...with explicit user approval.
Test markers:@pytest.mark.{unit,integration,e2e,slow}. Async tests useauto. Global timeout 30s. Minimum coverage 80%. xdist-n 8 --dist=loadfileauto-applied via pyproject addopts (loadfile prevents 3.14+Windows ProactorEventLoop leak).
Windows: unit tests useWindowsSelectorEventLoopPolicy(3.14 IOCP teardown race). Subprocess tests override back.
Use test-double ladder (see conventions.md section 12.1):FakeClockfor Clock seam,mock_of[T](**overrides)for typed-boundary substitutions,SimpleNamespacefor attribute-bags. BareMagicMockat typed boundaries is blocked byscripts/check_mock_spec.py(zero-tolerance).
ImportFakeClockandmock_offromtests._shared; inject viaclock=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. Useasyncio.Event().wait()notsleep(large).
Files:
tests/unit/observability/test_events.pytests/unit/engine/pipeline/entry/test_objective_boot.pytests/unit/engine/pipeline/entry/test_factory.pytests/e2e/test_real_objective_entry_e2e.pytests/unit/api/controllers/test_objectives.pytests/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.pytests/unit/engine/pipeline/entry/test_objective_boot.pytests/unit/engine/pipeline/entry/test_factory.pytests/e2e/test_real_objective_entry_e2e.pytests/unit/api/controllers/test_objectives.pytests/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 usecreateLoggerfrom@/lib/logger; never bareconsole.warn/console.error/console.debugin application code. Variable name must always belog. Onlylogger.tsitself may use bare console methods. Uselog.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 throughsanitizeArg
Attacker-controlled fields inside structured objects must be wrapped insanitizeForLog()before embedding in log calls
Error-code constants (MANDATORY): importErrorCodeandErrorCategoryfrom@/api/types/errors(re-exported from the generatedweb/src/api/types/error-codes.gen.ts). Discriminate onErrorCode.<NAME>, never on raw integer literals.
Use@eslint-react/web-api-no-leaked-fetchto detectfetch()in effects withoutAbortControllercleanup
Files:
web/src/api/types/openapi.gen.tsweb/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 withuv 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.tsweb/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-promisesto 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(withchecksVoidReturn: { attributes: false }) to forbid passing async functions where the callsite ignores the returned promise. React 19asyncevent handlers stay allowed via theattributes: falseexemption.
Files:
web/src/api/types/openapi.gen.tsweb/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 inweb/CLAUDE.md
Files:
web/src/api/types/openapi.gen.tsweb/src/api/types/enum-values.gen.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
React 19 web dashboard in
web/directory; seeweb/CLAUDE.mdfor detailed conventions
Files:
web/src/api/types/openapi.gen.tsweb/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 underCOMPLETE_LOCKto prevent concurrent/setup/completerequests 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__.pysrc/synthorg/observability/events/objectives.pysrc/synthorg/api/rate_limits/policies.pysrc/synthorg/settings/enums.pytests/unit/observability/test_events.pysrc/synthorg/api/app.pytests/unit/engine/pipeline/entry/test_objective_boot.pysrc/synthorg/settings/definitions/objectives.pysrc/synthorg/observability/prometheus_labels.pysrc/synthorg/api/controllers/setup/agent_helpers.pysrc/synthorg/engine/pipeline/entry/factory.pysrc/synthorg/engine/pipeline/entry/__init__.pysrc/synthorg/engine/pipeline/entry/protocol.pytests/unit/engine/pipeline/entry/test_factory.pysrc/synthorg/api/controllers/objectives.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/engine/pipeline/entry/objective_adapter.pytests/e2e/test_real_objective_entry_e2e.pytests/unit/api/controllers/test_objectives.pytests/unit/engine/pipeline/entry/test_objective_adapter.pysrc/synthorg/api/state.pysrc/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.pysrc/synthorg/settings/definitions/objectives.pysrc/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.pysrc/synthorg/settings/definitions/objectives.pysrc/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 winFile 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
- 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.
- 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 Report❌ Patch coverage is 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. 🚀 New features to boost your workflow:
|
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.
<!-- 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>
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 decomposedinto projects/tasks by the existing
MultiAgentCoordinator, thenexecuted 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— newObjectiveSubmission(frozen Pydantic,extra="forbid") andObjectiveEntryAdapter(thin:__slots__ = ("_default_project", "_work_pipeline")).src/synthorg/engine/pipeline/entry/factory.py— adds theWorkSource.OBJECTIVEarm. Coordinates with Entry adapter: task board to live runtime #1963 on this sharedseam; the task-board adapter rebases when it lands.
src/synthorg/engine/pipeline/entry/protocol.py— generalised toPEP 695 generic
class WorkEntryAdapter[T_Request](Protocol)so theintake and objective adapters can each be typed against their own
domain input.
src/synthorg/engine/pipeline/entry/boot.py— newwire_real_objective_entry()(cold boot + hot-reload viahot_swap=True);_ensure_projectlifted as a shared helper.src/synthorg/api/state.py—objective_entry_adapterslot +property + once-only
set_+ atomicset_if_absent_+swap_seams +
objective_background_tasks: set[Task]for spawnedpipeline runs.
src/synthorg/api/controllers/objectives.py— newPOST /objectivesreturning 202 +
submission_id(server-minted, propagated as theWorkItem.correlation_id); pipeline runs as a background task sothe HTTP boundary never blocks on team coordination. Guarded by
require_write_access+ per-op rate-limitobjectives.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.
default_projectdefinition(
read_only_post_init=True,restart_required=True).Manifest discipline (parent epic hard criterion)
scripts/_ghost_wiring_manifest.txtships anENFORCED ObjectiveEntryAdapter #1964 ...line in this same PR;scripts/check_no_ghost_wiring.pypasses.Test plan
tests/unit/engine/pipeline/entry/+tests/unit/api/controllers/test_objectives.py):ObjectiveSubmission: frozen, rejects unknown fields, blanktitle/description/requested_by, blank acceptance-criteria
elements; submission_id defaults to uuid4.
ObjectiveEntryAdapter: maps submission toWorkItem(source=OBJECTIVE); correlation_id == submission_id;default project enforced; optional fields fall through to
WorkItemdefaults; pipeline errors propagate unchanged.ObjectiveEntryAdapter;unwired sources still raise
UnknownStrategyError.work_pipeline; creates the objectivesproject when absent; skips create when it exists; hot_swap uses
the swap seam (and still ensures the project exists).
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.
tests/e2e/test_real_objective_entry_e2e.py, run under-m e2e): builds the real runtime via the productionbuild_runtime_serviceswith a deterministicScriptedDriver.Two cases:
leaf-thresholdpolicy — proves the path is wired andthe spawned task advances past
CREATED.always-teampolicy — proves the objective decomposes:asserts
verdict=SPLITTABLE,execution_path=TEAM, and theroot task advances past
CREATED.Review coverage
Reviewed via
/pre-pr-reviewwith the core agent roster only(thin-adapter scope): python-reviewer, security-reviewer,
test-quality-reviewer, conventions-enforcer, issue-resolution-verifier.
_resulthelper 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
Objectivepersistence (no model, repository, ormigration). Submission is ephemeral; state lives on the spawned
root task.
/objectives/{id}GET / list / cancel surfaces.(reused as-is).
idempotency_key=query filter to/tasksso HTTP-onlyclients can resolve
submission_id→ spawned task. Tracked as afollow-up; the simulation harness drives the adapter directly so
this is not blocking acceptance for Entry adapter: goal/objective intake #1964.