You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .agents/skills/billing/SKILL.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -202,6 +202,8 @@ The same registry also owns the single `CreateLineRouter`. Billing's default rou
202
202
-`ChangeSourceAPIRequest`: user/API-originated line edits. Billing diffs the original invoice against the edited invoice with `diffMutableInvoiceLines`, applies API edits through line engines with `applyAPIInvoiceLineEdits`, and rebuilds the invoice from unchanged lines plus line-engine outputs.
203
203
-`ChangeSourceSystem`: system-originated edits from billing/charges/subscription sync. Billing still computes the line diff, but does not invoke API create/update callbacks. For standard invoices only, deleted lines are dispatched through `OnMutableStandardLinesDeletedBySystem` because charge line updaters currently rely on that cleanup notification. Gathering invoices do not emit system delete callbacks.
204
204
205
+
Subscription-sync charge patches can update or delete invoice lines as a side effect of reconciling charges. Those invoice updates must use `ChangeSourceSystem`: API edit callbacks are for user-initiated invoice-line edits, while system deletes use `OnMutableStandardLinesDeletedBySystem` so charge line engines can clean up detached line-backed runs.
206
+
205
207
The API edit path treats the diff as the owner of invoice lines while engines run:
206
208
207
209
-`applyAPIInvoiceLineEdits` clones the edited invoice and calls `UnsetLines()` before line-engine dispatch so the edited invoice is only the header/context, not a competing source of line truth.
Copy file name to clipboardExpand all lines: .agents/skills/charges/SKILL.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -116,6 +116,14 @@ Intent layer access rules:
116
116
- Subscription sync and repair code targets subscription-owned source state. It should use `GetBaseIntent()` or base-specific helpers, not effective getters, so user/API overrides do not feed back into the subscription target state.
117
117
- Adapter writes should persist the base intent with `GetBaseIntent()` and persist override fields only through the override-specific adapter paths. Do not derive base persistence values from effective intent accessors.
118
118
119
+
Patch target rules:
120
+
121
+
- Charge patch payloads (`PatchShrink`, `PatchExtend`, `PatchDelete`) must carry an explicit `meta.ChangeTarget`. Do not rely on a zero/default target.
122
+
- Subscription sync emits patches against `meta.ChangeTargetBase` because it reconciles subscription-owned source state, not user/API overrides.
123
+
- State machines should mutate the requested patch target, then reconcile customer-facing invoice artifacts from the effective intent. If a base-target patch hits a charge with an active override, updating the base layer should not rewrite effective invoice state.
124
+
- Delete patches follow the same target rule: deleting the base layer while an override is active should mark the base intent deleted but leave the effective override-backed charge behavior intact.
125
+
- Charge listing for subscription-sync persisted-state loading must filter on base-intent deletion state, not effective `DeletedAt`; otherwise an active override can hide a subscription-owned base charge that sync still needs to reconcile.
126
+
119
127
## Usage-Based Invoice Line Mapping
120
128
121
129
Usage-based charge realization runs are not billing standard lines. When mapping a run back to `billing.StandardLine` in `openmeter/billing/charges/usagebased/service/linemapper.go`, preserve the billing-facing semantics:
Copy file name to clipboardExpand all lines: .coderabbit.yaml
+10Lines changed: 10 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -39,6 +39,16 @@ reviews:
39
39
40
40
Only flag `AdvanceAfter` if the specific code path demonstrably persists an invalid value or violates an explicit flat-fee domain invariant in the current diff.
For charge state-machine handlers in this path, do not claim that an in-memory mutation is not persisted until you trace the full patch execution and persistence flow in the current code.
45
+
46
+
When a handler is invoked from `service.TriggerPatch`, follow this call chain before raising a persistence finding: `service.TriggerPatch -> stateMachine.FireAndActivate -> chargestatemachine.Machine.FireAndActivate`.
47
+
48
+
In this flow, mutations made by the handler are persisted after the handler returns via `Persistence.UpdateBase(ctx, m.Charge.GetBase())`.
49
+
50
+
Before reporting that a mutation is "only in memory" or "not saved", verify whether the handler mutates the base/intent state that `UpdateBase(...)` persists. If that persistence path exists in reachable current code, omit the finding. If you cannot verify a missing persistence path from the diff and reachable current code, omit the finding.
51
+
42
52
- path: "**/*.tsp"
43
53
instructions: |
44
54
Review the TypeSpec code for conformity with TypeSpec best practices. When recommending changes also consider the fact that multiple codegeneration toolchains depend on the TypeSpec code, each of which have their idiosyncrasies and bugs.
0 commit comments