ORB-213: Create goals with habit links atomically - #454
Conversation
|
Implementation approach:
The implementation will land in the named goal command, validator, controller, chat tool, and existing goal test files. I am using the aggregate method and existing ownership helpers directly because dispatching LinkHabitsToGoalCommand would replace links, repeat the pay gate, and introduce a second save. I will not extract a shared service because this remains the second use of the validation pattern. |
The drift check failed because architecture.html and architecture.json were not regenerated after CreateGoalCommand gained HabitIds. Habit-linking assertions move from CreateGoalToolTests to CreateGoalCommandHandlerTests, where the linking actually happens. Orbit.Application.Tests: 2984 passed, 0 failed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50dc37d513
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
DEGRADED: same-vendor review Independent xhigh review found four blocking items:
Two non-blocking test-coverage gaps (controller forwarding and Astra cap enforcement) will be tracked separately per the review contract. The first blocking item crosses repository boundaries exactly as the ticket’s own Scope requires, while this PR is already 9 files versus the 8-file cap. No fixer is being launched until Thomas chooses the contract/cap handoff. No merge was performed. |
|
Frozen fixer approach for F2 through F4:
The production changes remain in CreateGoalTool and existing registrations or constructors only. The regression change remains in the current goal command handler test file. I am requiring the dependency instead of adding a null fallback because the published schema promises the capability for every registered tool instance. |
|
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
DEGRADED: same-vendor review Same-vendor bias direction is known, but its magnitude here is unmeasured. Reviewed head: APPROVED BY PR-REVIEW: zero blocking findings Non-blocking findings and existing follow-ups:
No duplicate Linear tickets were filed. ORB-251 already carries the paired optional shared-contract field required by the deploy-API-first rollout. N/A dimensions:
|



DEGRADED: same-vendor review
Links ORB-213.
Summary
habitIdsto the goal creation command and HTTP request.habit_idstocreate_goalso Astra can create and link in one call.Frozen fixer follow-up
CreateGoalToolconstructor the explicit DI constructor, so the registered tool always receives the habit repository advertised by its schema.habit_ids, non-string items, and invalid GUID strings at the tool boundary while preserving absent and empty behavior.Design notes
The create handler calls the existing ownership and cap helpers directly. It does not dispatch
LinkHabitsToGoalCommandbecause that command replaces links, repeats the pay gate, and saves independently.Streak goal creation does not add a speculative sync call. New linked streak goals are already eligible for the hourly passive sync, and goal read paths compute the live value before that sweep. This also preserves the existing completion and gamification path owned by the passive sync service.
Cache invalidation remains the single existing
InvalidateUserAiCachescall after creation. The link command does not invalidate any additional key.Contract and rollout
The request field is append only, optional, and defaults to absent. Existing clients keep the unchanged creation path and response shape. Companion UI ticket ORB-251 carries the shared client contract change.
Validation
dotnet build Orbit.slnx --no-restore: passed with zero errors.dotnet test --no-build --no-restore: analyzer 32, domain 516, application 2,989, infrastructure 2,071; all passed.