# Form field map

`form-field-map` · version 1.0.0 · Forms · free, no key needed

Rename form fields with an explicit id map and reject collisions.

**Use when you need to: map form field ids · migrate form fields.**

## Supported

- map form field ids
- migrate form fields

## Not supported

- inferred renames
- transitive closure
- fuzzy matching
- silent collision merge

## Behavior

- mapping rows are explicit {from, to} pairs. from must be a current field id. The step is not applied transitively.
- unmapped is required and is keep or drop. Identity mappings are allowed.
- Two sources for one target, or a kept field that already uses the target id, throw a collision naming the target and sources.
- Dropped answers are echoed on the dropped row. Unknown answer keys throw instead of being dropped.
- Output field order follows the original order. Prototype-named ids stay ordinary own keys.

## Input

- `definition` (object, required)
- `answers` (object, optional)
- `mapping` (array of object, required)
- `unmapped` (one of "keep", "drop", required)

## Output

- `definition` (object, required)
- `answers` (object, optional)
- `renamed` (array of any, required)
- `dropped` (array of any, required)
- `unchanged_ids` (array of string, required)
- `counts` (object, required)

## Limits

- max input bytes: 262144
- max output bytes: 262144
- max input depth: 16
- max input nodes: 20000
- max fields: 100
- max choices: 50
- max respondents: 100
- max id bytes: 128
- max label bytes: 256
- max choice bytes: 128
- max answer string bytes: 4096
- max answer depth: 6
- max answer nodes: 50
- max changes: 500
- max mapping: 100

## Example

Request input:

```json
{
  "definition": {
    "fields": [
      {
        "id": "email",
        "label": "Email",
        "type": "string",
        "required": true
      },
      {
        "id": "name",
        "label": "Name",
        "type": "string",
        "required": false
      }
    ]
  },
  "answers": {
    "email": "a@b.test",
    "name": "Ada"
  },
  "mapping": [
    {
      "from": "email",
      "to": "email_address"
    }
  ],
  "unmapped": "keep"
}
```

Response:

```json
{
  "result": {
    "definition": {
      "fields": [
        {
          "id": "email_address",
          "label": "Email",
          "type": "string",
          "required": true
        },
        {
          "id": "name",
          "label": "Name",
          "type": "string",
          "required": false
        }
      ]
    },
    "answers": {
      "email_address": "a@b.test",
      "name": "Ada"
    },
    "renamed": [
      {
        "from": "email",
        "to": "email_address"
      }
    ],
    "dropped": [],
    "unchanged_ids": [
      "name"
    ],
    "counts": {
      "fields_in": 2,
      "fields_out": 2,
      "renamed": 1,
      "dropped": 0,
      "unchanged_ids": 1,
      "answers_moved": 1,
      "answers_dropped": 0,
      "answers_kept": 1
    }
  }
}
```

## How to call it

### MCP

Connect `https://computefirst.net/mcp` ([setup](/docs#connect)), then call `execute` with:

```json
{
  "id": "form-field-map",
  "version": "1.0.0",
  "input": {
    "definition": {
      "fields": [
        {
          "id": "email",
          "label": "Email",
          "type": "string",
          "required": true
        },
        {
          "id": "name",
          "label": "Name",
          "type": "string",
          "required": false
        }
      ]
    },
    "answers": {
      "email": "a@b.test",
      "name": "Ada"
    },
    "mapping": [
      {
        "from": "email",
        "to": "email_address"
      }
    ],
    "unmapped": "keep"
  }
}
```

### HTTP (no key)

```sh
curl -X POST https://computefirst.net/v1/tools/form-field-map/versions/1.0.0/execute \
  -H "Content-Type: application/json" \
  -d '{"definition":{"fields":[{"id":"email","label":"Email","type":"string","required":true},{"id":"name","label":"Name","type":"string","required":false}]},"answers":{"email":"a@b.test","name":"Ada"},"mapping":[{"from":"email","to":"email_address"}],"unmapped":"keep"}'
```

The machine-readable contract is at [/v1/tools/form-field-map/versions/1.0.0](/v1/tools/form-field-map/versions/1.0.0).

### CLI

```sh
node cli.mjs run form-field-map 1.0.0 --input input.json --base-url https://computefirst.net
```

Get the client at [/clients/cli/](/clients/cli/).

## Related tools

- [Form definition diff](/tools/form-definition-diff): Diff two form definitions by stable field id, including choice lists and field order.
- [Form answer diff](/tools/form-answer-diff): Diff two answer maps against one shared form definition.
- [Form compare](/tools/form-compare): Compare two filled form snapshots and return compact field and answer changes.
- [Form response check](/tools/form-response-check): Report missing required answers, nulls, type failures, and choice failures.
- [Form response diff](/tools/form-response-diff): Reconcile two form response sets by exact respondent id.
