---
id: ATS-PFM-LLM-001
scope: CAP-PFM-LLM-001
product_area: platform
module: llm
revision: 2
status: proposed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-LLM-001-01
    title: Catalog admission rejects unknown or unpriced work
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-01
    preconditions: A catalog contains a priced operation and a model without a rate.
    steps: 'Execute the priced operation, resolve the unpriced model and submit an unknown operation.'
    expected: >-
      Priced work can run; missing prices and unknown keys prevent admission, with the unknown key creating no
      request.
    negative: true
    data_needs: 'Authorized and unauthorized fixtures for the scenario, with controlled request and usage records.'
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    category: validation
    test_sources: []
  - id: ATS-PFM-LLM-001-02
    title: Interrupted work remains discoverable
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-02
      - INV-DOM-PFM-LLM-001-01
    preconditions: A scripted worker stops after creating its usage record.
    steps: Interrupt the request after creation and invoke recovery when eligible.
    expected: The early-state record survives and recovery can settle it.
    negative: false
    data_needs: Fixtures representing a scripted worker stops after creating its usage record.
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    category: failure
    test_sources: []
  - id: ATS-PFM-LLM-001-03
    title: 'Settlement distinguishes measured, unknown and absent usage'
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-03
      - INV-DOM-PFM-LLM-001-04
    preconditions: 'Scripts respectively report usage, answer without usage or never answer.'
    steps: Execute all three conversations and inspect their charges and holds.
    expected: >-
      Measured usage is priced, unknown usage charges the estimate without cents, and unanswered work releases
      its hold with no charge.
    negative: false
    data_needs: 'Fixtures representing scripts respectively report usage, answer without usage or never answer.'
    bound_to:
      - TST-PFM-LLM-020
    provenance: test
    source: >-
      services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#records the
      invocation as settled on the actual usage
    category: rule
    test_sources:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#records
        the invocation as settled on the actual usage
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#charges
        the estimate rather than nothing, because a call that happened and cost nothing is spend nobody sees
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#charges
        nothing, because the provider never answered: there is no call to settle at an estimate
  - id: ATS-PFM-LLM-001-04
    title: Persistence gates normal transitions and permits terminal settlement
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-04
      - INV-DOM-PFM-LLM-001-02
    preconditions: Requests occupy normal and terminal persistence states.
    steps: Exercise compare-and-set transitions and settlement from each state.
    expected: >-
      Normal transitions require their expected state, while settlement accepts any nonterminal state and
      rejects a terminal request.
    negative: true
    data_needs: Fixtures representing the declared transition catalog is available.
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    category: transition
    test_sources: []
  - id: ATS-PFM-LLM-001-05
    title: Request attribution comes from context
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-05
      - INV-DOM-PFM-LLM-001-06
    preconditions: A signed caller context encloses a declared execution.
    steps: Make a model request with the execution context.
    expected: >-
      The request identifies its application, feature, access type, enclosing request and execution from the
      authoritative context and routing.
    negative: false
    data_needs: Fixtures representing a signed caller context encloses a declared execution.
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    category: invariant
    test_sources: []
  - id: ATS-PFM-LLM-001-06
    title: Refusal response categories remain distinct
    level: unit
    proves:
      - BR-CAP-PFM-LLM-001-06
    preconditions: Instances represent each supported refusal classification.
    steps: Convert each refusal to its API response.
    expected: >-
      Allowance and concurrency map to rate limits, disabled features to conflict, provider problems to
      distinct unavailable codes and depleted supplier credit to server failure.
    negative: true
    data_needs: Fixtures representing instances represent each supported refusal classification.
    bound_to:
      - TST-PFM-LLM-075
    provenance: test
    source: >-
      services-platform:modules/llm/tests/unit/services/llm-metering-errors.spec.ts#answers 429, because it is
      this tenant’s limit and not a failure
    category: rule
    test_sources:
      - >-
        services-platform:modules/llm/tests/unit/services/llm-metering-errors.spec.ts#answers 429, because it
        is this tenant’s limit and not a failure
      - >-
        services-platform:modules/llm/tests/unit/services/llm-metering-errors.spec.ts#carries its own code,
        distinct from an outage, because no retry fixes a refusal
      - >-
        services-platform:modules/llm/tests/unit/services/llm-metering-errors.spec.ts#answers 429 for the
        in-flight cap, because it is this tenant’s limit and clears by itself
  - id: ATS-PFM-LLM-001-07
    title: Exhausted turns return a bounded result
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-07
    preconditions: A scripted conversation continues beyond its allowed turns.
    steps: Execute it under the declared turn budget.
    expected: The feature receives the limit outcome without a final answer and pays for usage already consumed.
    negative: false
    data_needs: Fixtures representing a scripted conversation continues beyond its allowed turns.
    bound_to:
      - TST-PFM-LLM-020
    provenance: test
    source: >-
      services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#returns
      rather than throwing
    category: edge
    test_sources:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#returns
        rather than throwing
  - id: ATS-PFM-LLM-001-08
    title: Provider failure retains a Rhythm explanation
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-08
    preconditions: The provider never produces an answer.
    steps: Execute the request and inspect the returned error.
    expected: Rhythm wording identifies the operation and usage request rather than exposing supplier wording.
    negative: true
    data_needs: Fixtures representing the provider never produces an answer.
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    category: failure
    test_sources: []
  - id: ATS-PFM-LLM-001-09
    title: Only the permitted adapter crosses the provider boundary
    level: unit
    proves:
      - BR-CAP-PFM-LLM-001-09
    preconditions: Tracked Platform source files are available.
    steps: Run the SDK and provider-host boundary scan across those files.
    expected: >-
      The Platform repository permits its designated adapter only; prohibited SDK imports and extra direct
      provider boundaries are refused. The console prototype remains a separately recorded gap.
    negative: true
    data_needs: Fixtures representing tracked Platform source files are available.
    bound_to:
      - TST-PFM-LLM-086
    provenance: test
    source: >-
      services-platform:tests/unit/llm-provider-boundary.spec.ts#reaches the anthropic sdk and its host from
      the adapter alone
    category: invariant
    test_sources:
      - >-
        services-platform:tests/unit/llm-provider-boundary.spec.ts#reaches the anthropic sdk and its host from
        the adapter alone
      - >-
        services-platform:tests/unit/llm-provider-boundary.spec.ts#refuses an import of the openai sdk even in
        the adapter
  - id: ATS-PFM-LLM-001-10
    title: Absent credentials have a configuration result
    level: unit
    proves:
      - BR-CAP-PFM-LLM-001-10
    preconditions: Configuration omits the model secret or its usable value.
    steps: Resolve model credentials.
    expected: The result is the dedicated not-configured refusal rather than an allowance classification.
    negative: true
    data_needs: Fixtures representing configuration omits the model secret or its usable value.
    bound_to:
      - TST-PFM-LLM-063
    provenance: test
    source: >-
      services-platform:modules/llm/tests/unit/runtime/anthropic-credentials.spec.ts#answers
      llm_not_configured in the body, so a console says "nobody configured this" and not "try again"
    category: validation
    test_sources:
      - >-
        services-platform:modules/llm/tests/unit/runtime/anthropic-credentials.spec.ts#answers
        llm_not_configured in the body, so a console says "nobody configured this" and not "try again"
  - id: ATS-PFM-LLM-001-11
    title: Bounded answers retain their charge
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-07
      - BR-CAP-PFM-LLM-002-01
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-002
    preconditions: A metered operation has a two-turn limit and a scripted model that never accepts a final answer.
    steps: Run the operation to its turn limit and read its request and period.
    expected: The bounded outcome and recorded turns agree; settlement charges reported usage and releases the hold.
    negative: false
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to:
      - TST-PFM-LLM-020
    provenance: test
    source:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#returns
        rather than throwing
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#charges
        for every turn the model did take, because they happened
    test_sources:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#returns
        rather than throwing
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#charges
        for every turn the model did take, because they happened
  - id: ATS-PFM-LLM-001-12
    title: Task totals agree with request settlement
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-03
      - BR-CAP-PFM-LLM-003-05
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-003
    preconditions: A declared task runs three metered requests on its supplied context.
    steps: 'Complete the requests and compare task, request and period totals.'
    expected: Only associated settlements contribute to the task; the period charge equals the sum of those requests.
    negative: false
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to:
      - TST-PFM-LLM-018
    provenance: test
    source:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/executions.integration.spec.js#totals the
        credits the three settlements charged
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/executions.integration.spec.js#charges the
        period exactly what the execution totalled
    test_sources:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/executions.integration.spec.js#totals the
        credits the three settlements charged
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/executions.integration.spec.js#charges the
        period exactly what the execution totalled
  - id: ATS-PFM-LLM-001-13
    title: Capture follows metered execution
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-02
      - BR-CAP-PFM-LLM-004-01
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-004
    preconditions: A scripted request contains a credential field and ordinary question text.
    steps: Run it and inspect both capture results through an eligible diagnostic reader.
    expected: >-
      The request and response are captured around dispatch; the credential is absent and ordinary text
      remains.
    negative: false
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:docs/llm.md#The order of the steps, which is the design'
      - 'services-platform:modules/llm/services/execution/run-operation.ts:recordCapture'
  - id: ATS-PFM-LLM-001-14
    title: Published prices determine the next request
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-01
      - BR-CAP-PFM-LLM-005-05
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-005
    preconditions: An operation has a published rate and one settled request.
    steps: 'Publish a changed rate, resolve the operation afresh and run the same reported usage again.'
    expected: >-
      The earlier request keeps its rate reference; the new request uses the new rate after a fresh
      resolution.
    negative: false
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/llm/services/catalog/catalog-authority.ts:resolveLlmOperation'
      - >-
        services-platform:modules/llm/tests/integration/services/persistence/rate-versions.integration.spec.js#leaves
        the old version at the old price, because an invocation settled under it still names it
  - id: ATS-PFM-LLM-001-15
    title: Scripted execution uses production accounting
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-03
      - BR-CAP-PFM-LLM-006-03
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-006
    preconditions: Stub mode is enabled before collection and a declared operation has a script.
    steps: Execute the script through the shared request boundary and read settlement.
    expected: The script supplies model usage without a network call and settlement uses the published prices.
    negative: false
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/llm/services/execution/run-operation.ts:settleInvocation'
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#charges
        what that usage costs at the published rate, not the estimate
  - id: ATS-PFM-LLM-001-16
    title: Refusal creates history without spending
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-06
      - BR-CAP-PFM-LLM-007-03
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-007
    preconditions: A first scripted request consumes the available allowance.
    steps: 'Run a second request and inspect its record, period and unused script.'
    expected: >-
      The refusal retains needed and remaining capacity without consuming the next turn, adding a hold or
      charging credits.
    negative: true
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to:
      - TST-PFM-LLM-020
    provenance: test
    source:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#never
        asked the provider, so a tenant out of credit costs nothing to refuse
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#holds
        nothing for the refused call
    test_sources:
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#never
        asked the provider, so a tenant out of credit costs nothing to refuse
      - >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#holds
        nothing for the refused call
  - id: ATS-PFM-LLM-001-17
    title: Global disablement stops metered dispatch
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-06
      - BR-CAP-PFM-LLM-013-09
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-013
    preconditions: The operation has an active exemption but organization-wide AI is disabled.
    steps: Invoke the operation and inspect refusal history and the period.
    expected: Global disablement prevents dispatch and records the disabled-feature refusal without holding credits.
    negative: true
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/llm/services/metering/llm-metering-errors.ts'
      - >-
        services-platform:modules/llm/tests/integration/services/limits/tenant-limits.integration.spec.js#refuses
        it when AI is off, whatever exemption is in force
  - id: ATS-PFM-LLM-001-18
    title: Refusal wording follows the metering classification
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-LLM-001-06
      - BR-CAP-PFM-LLM-018-01
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-018
    preconditions: 'Allowance, running-slot and unavailable-provider refusals are represented.'
    steps: Run each refusal through the customer sentence helper.
    expected: >-
      The customer receives the corresponding renewal, short-wait or temporary-service guidance without
      supplier details.
    negative: false
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/llm/services/metering/llm-metering-errors.ts'
      - >-
        services-platform:modules/llm/tests/unit/services/usage/usage-sentences.spec.ts#tells an organization
        that has used its allowance when it resumes
  - id: ATS-PFM-LLM-001-19
    title: General chat exposes the unmetered boundary
    category: interaction
    level: browser
    proves:
      - BR-CAP-PFM-LLM-001-09
      - BR-CAP-PFM-LLM-019-02
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-019
    preconditions: A signed-in person has a general conversation while organization AI is off.
    steps: Send a general question and inspect Platform request history before and after.
    expected: >-
      The prototype reply can complete without a Platform request, hold or settlement; this remains a release
      gap.
    negative: true
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:tests/unit/llm-provider-boundary.spec.ts#refuses an import of the openai sdk even in
        the adapter
      - 'react-console:app/api/agent/conversations/[id]/messages/route.ts:MODEL'
  - id: ATS-PFM-LLM-001-20
    title: Live query refusal preserves unsaved work
    category: interaction
    level: browser
    proves:
      - BR-CAP-PFM-LLM-001-06
      - BR-CAP-PFM-LLM-020-02
    exercises:
      - CAP-PFM-LLM-001
      - CAP-PFM-LLM-020
    preconditions: A live query has chosen columns and insufficient allowance for interpretation.
    steps: Ask scoped Jazz AI to refine it and inspect both the query and metered request.
    expected: The refusal has a usage record while the query remains unchanged and unsaved.
    negative: true
    data_needs: 'An isolated workspace with the records, clock instants and caller authority stated in the preconditions.'
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/llm/services/metering/llm-metering-errors.ts'
      - 'react-console:components/queries/query-workspace.tsx:refine'
  - id: ATS-PFM-LLM-001-21
    title: Terminal request states have no successors
    category: transition
    level: unit
    proves:
      - BR-CAP-PFM-LLM-001-04
    preconditions: >-
      The suite owns isolated fixtures representing the valid control and the contrasting case described by
      its steps.
    steps: Inspect successors of settled and refused requests in the declared move list.
    expected: Neither terminal state allows another normal transition.
    negative: false
    data_needs: 'Suite-owned fixtures, with a fixed clock where dates or grant windows matter.'
    bound_to:
      - TST-PFM-LLM-061
    provenance: test
    source: >-
      services-platform:modules/llm/tests/unit/db/invocation-transitions.spec.ts#lets nothing follow settled,
      so a settled call can never be charged a second time
    test_sources:
      - >-
        services-platform:modules/llm/tests/unit/db/invocation-transitions.spec.ts#lets nothing follow
        settled, so a settled call can never be charged a second time
  - id: ATS-PFM-LLM-001-22
    title: Allowance and provider faults have separate measures
    category: rule
    level: unit
    proves:
      - BR-CAP-PFM-LLM-001-13
    preconditions: >-
      The suite owns isolated fixtures representing the valid control and the contrasting case described by
      its steps.
    steps: Emit recorded allowance and provider refusal measures through recording telemetry.
    expected: 'Each measure retains its own name, value and operational properties.'
    negative: false
    data_needs: 'Suite-owned fixtures, with a fixed clock where dates or grant windows matter.'
    bound_to:
      - TST-PFM-LLM-076
    provenance: test
    source: >-
      services-platform:modules/llm/tests/unit/services/llm-metrics.spec.ts#counts the refusal under its
      reason
    test_sources:
      - >-
        services-platform:modules/llm/tests/unit/services/llm-metrics.spec.ts#counts the refusal under its
        reason
evidence:
  - >-
    services-platform at ad3f6a6582843008ed0f5a17b131878d15829af1: bound or cited
    modules/llm/tests/integration/lifecycle/executions.integration.spec.js;
    modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js;
    modules/llm/tests/integration/services/persistence/rate-versions.integration.spec.js;
    modules/llm/tests/integration/services/reconciliation/llm-settlement-sweep.integration.spec.js;
    modules/llm/tests/unit/catalog/llm-executions.spec.ts;
    modules/llm/tests/unit/db/invocation-transitions.spec.ts;
    modules/llm/tests/unit/runtime/anthropic-credentials.spec.ts;
    modules/llm/tests/unit/services/llm-metering-errors.spec.ts; tests/unit/llm-provider-boundary.spec.ts.
coverage:
  rule: 'gap: FND-PFM-LLM-060'
  transition: 'gap: FND-PFM-LLM-060'
  validation: covered
  permission: not-applicable
  edge: covered
  failure: covered
  boundary: 'gap: FND-PFM-LLM-060'
  concurrency: 'gap: FND-PFM-LLM-060'
  invariant: 'gap: FND-PFM-LLM-060'
  interaction: covered
coverage_notes:
  transition: >-
    Existing transition scenarios are retained; the model transition register below records the remaining
    exhaustive mapping obligation.
  permission: >-
    This capability declares no permission key; caller authorization belongs to its consuming operation or a
    related capability.
  interaction: >-
    The related interaction register cites a concrete experiment for every dependency and related capability,
    including cross-capability workflow seams.
  invariant: >-
    The domain-invariant register maps each relevant invariant to a scenario or to the capability coverage
    finding; an example does not establish every invariant.
  rule: >-
    All must-prove rules have scenario references, but the coverage finding retains untested clauses and
    combined outcomes; scenario presence alone is not exhaustive rule proof.
related_interactions:
  - with: CAP-PFM-LLM-002
    scenarios:
      - ATS-PFM-LLM-001-11
    source: >-
      services-platform:modules/llm/tests/unit/runtime/run-tool-loop.spec.ts#stops a conversation that will
      not converge
  - with: CAP-PFM-LLM-003
    scenarios:
      - ATS-PFM-LLM-001-12
    source: 'services-platform:modules/llm/services/execution/with-llm-execution.ts'
  - with: CAP-PFM-LLM-004
    scenarios:
      - ATS-PFM-LLM-001-13
    source: 'services-platform:modules/llm/services/execution/run-operation.ts:recordCapture'
  - with: CAP-PFM-LLM-005
    scenarios:
      - ATS-PFM-LLM-001-14
    source: 'services-platform:modules/llm/catalog/pricing.ts'
  - with: CAP-PFM-LLM-006
    scenarios:
      - ATS-PFM-LLM-001-15
    source: 'services-platform:tests/unit/llm-stub-mode-config.spec.ts#forces stub mode in the integration tier'
  - with: CAP-PFM-LLM-007
    scenarios:
      - ATS-PFM-LLM-001-16
    source: 'services-platform:modules/llm/services/persistence/allowance-periods.ts'
  - with: CAP-PFM-LLM-013
    scenarios:
      - ATS-PFM-LLM-001-17
    source: >-
      services-platform:modules/llm/tests/e2e/llm-limits.e2e.spec.js#is refused the write before a handler
      runs, whatever the customer’s scope grants
  - with: CAP-PFM-LLM-018
    scenarios:
      - ATS-PFM-LLM-001-18
    source: >-
      services-platform:modules/llm/tests/unit/services/usage/usage-sentences.spec.ts#tells an organization
      that has used its allowance when it resumes
  - with: CAP-PFM-LLM-019
    scenarios:
      - ATS-PFM-LLM-001-19
    source: 'react-console:components/console/nav-config.ts:unlistedNav'
  - with: CAP-PFM-LLM-020
    scenarios:
      - ATS-PFM-LLM-001-20
    source: 'react-console:lib/agent/store.ts:createConversation'
state_models:
  - STATE-PFM-LLM-001
coverage_obligations:
  must_prove:
    - rule: BR-CAP-PFM-LLM-001-01
      scenarios:
        - ATS-PFM-LLM-001-01
        - ATS-PFM-LLM-001-14
      source: 'services-platform:modules/llm/services/catalog/catalog-authority.ts:resolveLlmOperation'
      coverage: specified
    - rule: BR-CAP-PFM-LLM-001-02
      scenarios:
        - ATS-PFM-LLM-001-02
        - ATS-PFM-LLM-001-13
      source: 'services-platform:docs/llm.md#The order of the steps, which is the design'
      coverage: partial
      gap: FND-PFM-LLM-060
    - rule: BR-CAP-PFM-LLM-001-03
      scenarios:
        - ATS-PFM-LLM-001-03
        - ATS-PFM-LLM-001-12
        - ATS-PFM-LLM-001-15
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:settleInvocation'
      coverage: partial
      gap: FND-PFM-LLM-060
    - rule: BR-CAP-PFM-LLM-001-04
      scenarios:
        - ATS-PFM-LLM-001-04
        - ATS-PFM-LLM-001-21
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationSettled'
      coverage: partial
      gap: FND-PFM-LLM-060
    - rule: BR-CAP-PFM-LLM-001-05
      scenarios:
        - ATS-PFM-LLM-001-05
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:createInvocation'
      coverage: partial
      gap: FND-PFM-LLM-060
    - rule: BR-CAP-PFM-LLM-001-06
      scenarios:
        - ATS-PFM-LLM-001-06
        - ATS-PFM-LLM-001-16
        - ATS-PFM-LLM-001-17
        - ATS-PFM-LLM-001-18
        - ATS-PFM-LLM-001-20
      source: 'services-platform:modules/llm/services/metering/llm-metering-errors.ts'
      coverage: partial
      gap: FND-PFM-LLM-060
    - rule: BR-CAP-PFM-LLM-001-07
      scenarios:
        - ATS-PFM-LLM-001-07
        - ATS-PFM-LLM-001-11
      source: >-
        services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#returns
        rather than throwing
      coverage: specified
    - rule: BR-CAP-PFM-LLM-001-08
      scenarios:
        - ATS-PFM-LLM-001-08
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:providerFailure'
      coverage: specified
    - rule: BR-CAP-PFM-LLM-001-09
      scenarios:
        - ATS-PFM-LLM-001-09
        - ATS-PFM-LLM-001-19
      source: >-
        services-platform:tests/unit/llm-provider-boundary.spec.ts#refuses an import of the openai sdk even in
        the adapter
      coverage: partial
      gap: FND-PFM-LLM-060
    - rule: BR-CAP-PFM-LLM-001-10
      scenarios:
        - ATS-PFM-LLM-001-10
      source: >-
        services-platform:modules/llm/tests/unit/runtime/anthropic-credentials.spec.ts#answers
        llm_not_configured in the body, so a console says "nobody configured this" and not "try again"
      coverage: specified
  state_transitions:
    - model: STATE-PFM-LLM-001
      transition: 1
      from: estimated
      to: refused
      trigger: The access check rejects the AI or operation switch.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    - model: STATE-PFM-LLM-001
      transition: 2
      from: estimated
      to: refused
      trigger: Admission cannot fit the reservation or allocate a running slot.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    - model: STATE-PFM-LLM-001
      transition: 3
      from: estimated
      to: reserved
      trigger: Admission successfully reserves credits and a slot.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationReserved'
    - model: STATE-PFM-LLM-001
      transition: 4
      from: reserved
      to: dispatched
      trigger: Request capture has returned and its metadata was written.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationDispatched'
    - model: STATE-PFM-LLM-001
      transition: 5
      from: dispatched
      to: completed
      trigger: The loop returns an outcome other than failed.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationCompleted'
    - model: STATE-PFM-LLM-001
      transition: 6
      from: dispatched
      to: failed
      trigger: The loop reports failure after provider execution or attempt recording.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationFailed'
    - model: STATE-PFM-LLM-001
      transition: 7
      from: completed
      to: pending
      trigger: A completed loop result contains no reported usage.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationPending'
    - model: STATE-PFM-LLM-001
      transition: 8
      from: completed
      to: settled
      trigger: Runtime accounting closes a completed result.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:settleInvocation'
    - model: STATE-PFM-LLM-001
      transition: 9
      from: pending
      to: settled
      trigger: Runtime or stale-request recovery closes an unmeasured result.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:settleInvocation'
    - model: STATE-PFM-LLM-001
      transition: 10
      from: failed
      to: settled
      trigger: Runtime accounting closes a failed loop result.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:settleInvocation'
    - model: STATE-PFM-LLM-001
      transition: 11
      from: dispatched
      to: settled
      trigger: An exception escapes the protected execution block.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    - model: STATE-PFM-LLM-001
      transition: 12
      from: estimated
      to: settled
      trigger: Recovery selects a stale estimated request.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: >-
        services-platform:modules/llm/services/reconciliation/llm-settlement-sweep.ts:sweepUnsettledInvocations
    - model: STATE-PFM-LLM-001
      transition: 13
      from: reserved
      to: settled
      trigger: Recovery selects a stale reserved request.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: >-
        services-platform:modules/llm/services/reconciliation/llm-settlement-sweep.ts:sweepUnsettledInvocations
    - model: STATE-PFM-LLM-001
      transition: 14
      from: dispatched
      to: settled
      trigger: Recovery selects a stale dispatched request.
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: >-
        services-platform:modules/llm/tests/integration/services/reconciliation/llm-settlement-sweep.integration.spec.js#settles
        it at its estimate, because its real cost was never learned
  domain_invariants:
    - invariant: INV-DOM-PFM-LLM-001-01
      scenarios:
        - ATS-PFM-LLM-001-02
      provenance: documented
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    - invariant: INV-DOM-PFM-LLM-001-02
      scenarios:
        - ATS-PFM-LLM-001-04
      provenance: documented
      source: 'services-platform:modules/llm/db/llm-invocations.table.ts:LLM_INVOCATION_TRANSITIONS'
    - invariant: INV-DOM-PFM-LLM-001-03
      scenarios: []
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationSettled'
    - invariant: INV-DOM-PFM-LLM-001-04
      scenarios:
        - ATS-PFM-LLM-001-03
      provenance: documented
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationSettled'
    - invariant: INV-DOM-PFM-LLM-001-05
      scenarios: []
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationRefused'
    - invariant: INV-DOM-PFM-LLM-001-06
      scenarios:
        - ATS-PFM-LLM-001-05
      provenance: documented
      source: 'services-platform:modules/llm/services/execution/run-operation.ts:runOperation'
    - invariant: INV-DOM-PFM-LLM-001-11
      scenarios: []
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:docs/llm.md#The tables'
    - invariant: INV-DOM-PFM-LLM-001-12
      scenarios: []
      gap: FND-PFM-LLM-060
      provenance: proposed
      source: 'services-platform:modules/llm/db/llm-invocations.table.ts:LLM_INVOCATION_ERROR_CLASSIFICATIONS'
coverage_limits:
  finding: FND-PFM-LLM-060
  statement: >-
    Interruption proof is missing between request creation, reservation metadata, capture metadata, settlement
    and the separate period movement. Recovery from every early state and a losing cleanup writer need
    explicit accounting checks.
  provenance: proposed
  source:
    - 'services-platform:modules/llm/services/catalog/catalog-authority.ts:resolveLlmOperation'
    - 'services-platform:docs/llm.md#The order of the steps, which is the design'
    - 'services-platform:modules/llm/services/execution/run-operation.ts:settleInvocation'
    - 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationSettled'
    - 'services-platform:modules/llm/services/persistence/invocations.ts:createInvocation'
    - 'services-platform:modules/llm/services/metering/llm-metering-errors.ts'
    - >-
      services-platform:modules/llm/tests/integration/lifecycle/run-operation.integration.spec.js#returns
      rather than throwing
    - 'services-platform:modules/llm/services/execution/run-operation.ts:providerFailure'
    - >-
      services-platform:tests/unit/llm-provider-boundary.spec.ts#refuses an import of the openai sdk even in
      the adapter
    - >-
      services-platform:modules/llm/tests/unit/runtime/anthropic-credentials.spec.ts#answers
      llm_not_configured in the body, so a console says "nobody configured this" and not "try again"
    - 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationSettled'
    - 'services-platform:modules/llm/services/persistence/invocations.ts:markInvocationRefused'
    - 'services-platform:docs/llm.md#The tables'
    - 'services-platform:modules/llm/db/llm-invocations.table.ts:LLM_INVOCATION_ERROR_CLASSIFICATIONS'
  invariants_without_scenarios:
    - INV-DOM-PFM-LLM-001-03
    - INV-DOM-PFM-LLM-001-05
    - INV-DOM-PFM-LLM-001-11
    - INV-DOM-PFM-LLM-001-12
---

# undefined

## Coverage

The scenarios identify the rules or journey assertions they are intended to prove. A test binding names existing evidence; an unbound proposal remains work to verify.

| Scenario | Title | Level | Provenance |
|---|---|---|---|
| `ATS-PFM-LLM-001-01` | Catalog admission rejects unknown or unpriced work | api | proposed |
| `ATS-PFM-LLM-001-02` | Interrupted work remains discoverable | api | proposed |
| `ATS-PFM-LLM-001-03` | Settlement distinguishes measured, unknown and absent usage | api | test |
| `ATS-PFM-LLM-001-04` | Persistence gates normal transitions and permits terminal settlement | api | proposed |
| `ATS-PFM-LLM-001-05` | Request attribution comes from context | api | proposed |
| `ATS-PFM-LLM-001-06` | Refusal response categories remain distinct | unit | test |
| `ATS-PFM-LLM-001-07` | Exhausted turns return a bounded result | api | test |
| `ATS-PFM-LLM-001-08` | Provider failure retains a Rhythm explanation | api | proposed |
| `ATS-PFM-LLM-001-09` | Only the permitted adapter crosses the provider boundary | unit | test |
| `ATS-PFM-LLM-001-10` | Absent credentials have a configuration result | unit | test |

## Interactions With Related Capabilities

The interaction register links concrete experiments with bound ai conversations and handle recoverable failures; keep one account for a multi-request ai task; retain redacted ai evidence and remove it safely; publish ai operation definitions and historical prices; check ai behavior with scripted models and deliberate live runs; admit ai work against the organization’s monthly allowance; set an organization’s ai access and recurring limits; give people understandable ai refusal messages; use jazz ai conversations and project folders; refine queries and directory filters with jazz ai. Each experiment checks the outcome at the shared boundary; an unbound experiment remains proposed.

Interruption proof is missing between request creation, reservation metadata, capture metadata, settlement and the separate period movement. Recovery from every early state and a losing cleanup writer need explicit accounting checks.
