---
title: "Preview composed alignment (dry run)"
method: POST
path: "/alignment/platform/{scope_id}/preview-compose"
tags: ["Alignment"]
---

# Preview composed alignment (dry run)

`POST /alignment/platform/{scope_id}/preview-compose`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/alignment/platform/{scope_id}/preview-compose`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`
  - API key in cookie `mnemom_session`

Composes the cascade against a hypothetical body at the platform layer and returns conflicts + the composed view. No DB writes. Used by the dashboard editor for live conflict markers.

## Path parameters

- `scope_id` 'default', required

## Request body

- UnifiedAlignmentCard: Unified alignment card (ADR-008/ADR-039). Authored in YAML or JSON; composed server-side with platform defaults, org template, and active exemptions before storage. This schema matches the runtime validator at src/composition/validate.ts EXACTLY — a card authored strictly to it passes `PUT /v1/agents/{id}/alignment-card` and the preview-compose endpoint. Output-only fields (card_id, issued_at, expires_at, _composition, content_hash, version) are server-assigned and must NOT be sent on a PUT.
  - `card_version` string, required: Card schema version (required, non-empty). Current canonical value: `unified/2026-04-26`.
  - `content_version` string: Optional. Which default content the card carries, e.g. `mnemom-agent-default/2.1.0` (semver within a lineage). Distinct from `card_version`, the schema version. New agents are born with it; composition carries the agent card's value onto the canonical card.
  - `autonomy_mode` 'off' | 'observe' | 'nudge' | 'enforce', required: ADR-039 master switch for the action-policing pipeline (autonomy constraints). Required at the top level post-cutover; the legacy `enforcement.mode` location is rejected.
  - `integrity_mode` 'off' | 'observe' | 'nudge' | 'enforce', required: ADR-039 master switch for the values/conscience pipeline (integrity constraints). Required at the top level post-cutover; the legacy `integrity.enforcement_mode` location is rejected.
  - `card_id` string: Card row id. Server-assigned on PUT (`ac-{uuid}`).
  - `agent_id` string, required: Target agent id. On PUT, server overwrites to match the URL path.
  - `issued_at` string, date-time
  - `expires_at` string, date-time, nullable
  - `principal` object, required: Required object describing whose authority the agent acts under (ADR-039 Decision 10).
    - `type` 'human' | 'organization' | 'agent' | 'unspecified', required
    - `identifier` string: Required (non-empty) when principal.type is not `unspecified`; identifies the human / organization / agent.
    - `relationship` 'delegated_authority' | 'advisory' | 'autonomous', required
    - `escalation_contact` string
  - `values` object, required
    - `declared` union[], required: Ordered list of declared values. Phase 1 cards-as-primitive: each entry is either a catalog-v1 ID string (e.g. `'accuracy'`) or a parameterized map carrying optional `intensity` / `domain` / `severity_on_violation` / `scope` (e.g. `{id: 'accuracy', domain: 'financial', severity_on_violation: 'critical'}`).
      - union
        - string
        - object
          - `id` string, required
    - `definitions` object
    - `conflicts_with` string[]
    - `hierarchy` 'lexicographic' | 'weighted' | 'contextual'
  - `conscience` object
    - `mode` 'augment' | 'replace', required
    - `values` object[], required
      - `type` 'BOUNDARY' | 'FEAR' | 'COMMITMENT' | 'BELIEF' | 'HOPE', required
      - `content` string, required
      - `id` string
      - `severity` 'advisory' | 'mandatory'
  - `autonomy` object, required
    - `bounded_actions` string[], required
    - `forbidden_actions` string[]
    - `escalation_triggers` object[]
      - `condition` string, required
      - `action` 'escalate' | 'deny' | 'log', required
      - `reason` string, required
    - `max_autonomous_value` object
      - `amount` number
      - `currency` string
  - `capabilities` object
  - `enforcement` object: Optional ADR-039 Decision-3 user-facing knobs for unmapped-tool handling. The legacy `mode`, `unmapped_tool_action` and `fail_open` keys are REJECTED by the validator (mode → top-level autonomy_mode; fail_open → gateway env config).
    - `allow_unmapped_tools` boolean: When true, tools not mapped to a capability are allowed by default.
    - `default_unmapped_severity` 'low' | 'medium' | 'high' | 'critical': Severity assigned to an unmapped tool when allow_unmapped_tools is false.
    - `forbidden_tools` object[]
      - `pattern` string, required
      - `reason` string, required
      - `severity` 'critical' | 'high' | 'medium' | 'low', required
    - `grace_period_hours` integer
  - `audit` object, required
    - `trace_format` string
    - `retention_days` integer, required
    - `queryable` boolean, required
    - `query_endpoint` string: Required when audit.queryable is true.
    - `tamper_evidence` 'append_only' | 'signed' | 'merkle' | 'null', nullable
    - `storage` object
      - `type` 'local' | 'remote' | 'distributed'
      - `location` string
  - `extensions` object
  - `_composition` CompositionMetadata: System-managed block describing which scope sources merged into the canonical card. Only returned when `?include_composition=true`.
    - `canonical_id` string
    - `composed_at` string, date-time
    - `scopes_applied` object[]
      - `scope` string: `platform`, `org:<id>`, or `agent:<id>`.
      - `version` integer
      - `template_version` integer
      - `card_id` string
    - `exemptions_applied` string[]
    - `source_card_id` string
    - `source_policy_id` string
  - `content_hash` string: Response-only: content hash of the composed card (`sha256:<hex>`), injected by the GET/PUT response. Server-assigned — do not send on a PUT.
  - `version` integer: Response-only: monotonic card version, injected by the GET/PUT response. Server-assigned — do not send on a PUT.

## Response `200`

Preview-compose result: composed card + conflicts + coherence violations.

- object
  - `ok` boolean: Always true on a 200 (the dry-run completed).
  - `composed` ComposedAlignmentCard: OUTPUT-only variant of `UnifiedAlignmentCard` for the COMPOSED card the server emits on GET `/v1/alignment/{scope}/{id}`, `/effective`, and the `composed` field of preview-compose. Identical to `UnifiedAlignmentCard` except `principal` is optional (a default / org-scope composed card has no agent principal) and `values.declared` / `autonomy.bounded_actions` may be empty (a fresh card declares nothing yet). The strict `UnifiedAlignmentCard` remains the authoring/request contract.
    - `card_version` string, required: Card schema version (required, non-empty). Current canonical value: `unified/2026-04-26`.
    - `content_version` string: Optional. Which default content the card carries, e.g. `mnemom-agent-default/2.1.0` (semver within a lineage). Distinct from `card_version`, the schema version. New agents are born with it; composition carries the agent card's value onto the canonical card.
    - `autonomy_mode` 'off' | 'observe' | 'nudge' | 'enforce', required: ADR-039 master switch for the action-policing pipeline (autonomy constraints). Required at the top level post-cutover; the legacy `enforcement.mode` location is rejected.
    - `integrity_mode` 'off' | 'observe' | 'nudge' | 'enforce', required: ADR-039 master switch for the values/conscience pipeline (integrity constraints). Required at the top level post-cutover; the legacy `integrity.enforcement_mode` location is rejected.
    - `card_id` string: Card row id. Server-assigned on PUT (`ac-{uuid}`).
    - `agent_id` string, required: Target agent id. On PUT, server overwrites to match the URL path.
    - `issued_at` string, date-time
    - `expires_at` string, date-time, nullable
    - `principal` object: Required object describing whose authority the agent acts under (ADR-039 Decision 10).
      - `type` 'human' | 'organization' | 'agent' | 'unspecified', required
      - `identifier` string: Required (non-empty) when principal.type is not `unspecified`; identifies the human / organization / agent.
      - `relationship` 'delegated_authority' | 'advisory' | 'autonomous', required
      - `escalation_contact` string
    - `values` object, required
      - `declared` union[], required: Ordered list of declared values. Phase 1 cards-as-primitive: each entry is either a catalog-v1 ID string (e.g. `'accuracy'`) or a parameterized map carrying optional `intensity` / `domain` / `severity_on_violation` / `scope` (e.g. `{id: 'accuracy', domain: 'financial', severity_on_violation: 'critical'}`).
        - union
          - string
          - object
            - `id` string, required
      - `definitions` object
      - `conflicts_with` string[]
      - `hierarchy` 'lexicographic' | 'weighted' | 'contextual'
    - `conscience` object
      - `mode` 'augment' | 'replace', required
      - `values` object[], required
        - `type` 'BOUNDARY' | 'FEAR' | 'COMMITMENT' | 'BELIEF' | 'HOPE', required
        - `content` string, required
        - `id` string
        - `severity` 'advisory' | 'mandatory'
    - `autonomy` object, required
      - `bounded_actions` string[], required
      - `forbidden_actions` string[]
      - `escalation_triggers` object[]
        - `condition` string, required
        - `action` 'escalate' | 'deny' | 'log', required
        - `reason` string, required
      - `max_autonomous_value` object
        - `amount` number
        - `currency` string
    - `capabilities` object
    - `enforcement` object: Optional ADR-039 Decision-3 user-facing knobs for unmapped-tool handling. The legacy `mode`, `unmapped_tool_action` and `fail_open` keys are REJECTED by the validator (mode → top-level autonomy_mode; fail_open → gateway env config).
      - `allow_unmapped_tools` boolean: When true, tools not mapped to a capability are allowed by default.
      - `default_unmapped_severity` 'low' | 'medium' | 'high' | 'critical': Severity assigned to an unmapped tool when allow_unmapped_tools is false.
      - `forbidden_tools` object[]
        - `pattern` string, required
        - `reason` string, required
        - `severity` 'critical' | 'high' | 'medium' | 'low', required
      - `grace_period_hours` integer
    - `audit` object, required
      - `trace_format` string
      - `retention_days` integer, required
      - `queryable` boolean, required
      - `query_endpoint` string: Required when audit.queryable is true.
      - `tamper_evidence` 'append_only' | 'signed' | 'merkle' | 'null', nullable
      - `storage` object
        - `type` 'local' | 'remote' | 'distributed'
        - `location` string
    - `extensions` object
    - `_composition` CompositionMetadata: System-managed block describing which scope sources merged into the canonical card. Only returned when `?include_composition=true`.
      - `canonical_id` string
      - `composed_at` string, date-time
      - `scopes_applied` object[]
        - `scope` string: `platform`, `org:<id>`, or `agent:<id>`.
        - `version` integer
        - `template_version` integer
        - `card_id` string
      - `exemptions_applied` string[]
      - `source_card_id` string
      - `source_policy_id` string
    - `content_hash` string: Response-only: content hash of the composed card (`sha256:<hex>`), injected by the GET/PUT response. Server-assigned — do not send on a PUT.
    - `version` integer: Response-only: monotonic card version, injected by the GET/PUT response. Server-assigned — do not send on a PUT.
  - `conflicts` object[]
  - `coherence_violations` object[]

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Forbidden
- `413`: Request body exceeded the per-endpoint size cap. Cards-as-primitive sub-resource verbs cap each primitive body at 64 KiB; full-card PUTs cap at 128 KiB (alignment) / 64 KiB (protection).
- `422`: Request was well-formed but semantically invalid (e.g., business-rule validation failure, malformed YAML inside a JSON payload).
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
