{
  "isError" : false,
  "request" : {
    "tool" : "ek9_add_field"
  },
  "response" : {
    "match" : "exact",
    "meta" : {
      "serverMs" : "<timing>"
    },
    "status" : "ok",
    "tool" : {
      "description" : "Inserts the field declaration at the construct's canonical field position; answers status, edits[] and summary, a clashing name as conflicts[] (name-collision).",
      "details" : "Two forms: structured (fieldName + defaultValue; defaultValue REQUIRED for records) or raw (rawDeclaration as typed, e.g. `name as String?` or `logger as Logger!`); mode is inferred from which is given and a contradicting mode is a conflict. Visibility is genus-fixed: class/component fields are always private, record fields always public - no access-modifier syntax exists. A pre-existing field name is a name-collision conflict (structured) or hard error (raw); an UNINITIALISED field can trip E07175/E07170 (public no-arg ctor would build a partial object) → would-fail - fix with an initialiser, a private no-arg ctor, or an explicit ctor.",
      "examples" : [ "{symbol:'CustomerOrder', fieldName:'cachedTotal', defaultValue:'Money(\"0\")', dryRun:true} → status:ready, edits[] one INSERT `cachedTotal <- Money(\"0\")` (type inferred from the default).", "{symbol:'CustomerOrder', rawDeclaration:'logger as Logger!'} → status:applied; the `!` suffix marks the field for DI injection." ],
      "idePrecedent" : "Generate Field (IntelliJ) / Quick Fix - Add Field",
      "inputSchema" : {
        "additionalProperties" : false,
        "properties" : {
          "defaultValue" : {
            "description" : "Default value expression for the field, e.g. '0', '\"\"', 'String()'. Required for records in the structured form.",
            "type" : "string"
          },
          "dirtyOverlay" : {
            "description" : "Universal — see §1.1. Override on-disk content for files with unsaved buffers. Entries are applied at read time; the apply path still writes the (post-edit) result to disk.",
            "items" : {
              "properties" : {
                "content" : {
                  "type" : "string"
                },
                "file" : {
                  "type" : "string"
                }
              },
              "required" : [ "file", "content" ],
              "type" : "object"
            },
            "type" : "array"
          },
          "dryRun" : {
            "default" : false,
            "description" : "Universal — see EK9_TOOL_SPECIFICATIONS.md §1.1. When true, no disk mutation; response shows the would-be edit.",
            "type" : "boolean"
          },
          "expectedWorkspaceHash" : {
            "description" : "Universal — see §1.1. Drift-detection hash from a prior dry-run. Mismatch emits a WORKSPACE_DRIFTED warning.",
            "type" : "string"
          },
          "fieldName" : {
            "description" : "The new field's name (structured form) - with 'type' or 'defaultValue'; a name alone renders a typeless field (E07110).",
            "type" : "string"
          },
          "file" : {
            "description" : "The EK9 source file - OPTIONAL when symbol is a construct name; required to anchor on a member or a use site.",
            "type" : "string"
          },
          "mode" : {
            "description" : "Optional - inferred: rawDeclaration → raw, fieldName → structured.",
            "enum" : [ "structured", "raw" ],
            "type" : "string"
          },
          "rawDeclaration" : {
            "description" : "The whole declaration line as you would type it (raw form), e.g. 'name as String?' or 'logger as Logger!' (DI).",
            "type" : "string"
          },
          "showExamples" : {
            "default" : false,
            "description" : "Universal — the inverse of terseErrors. When true each wouldBeDiagnostics entry is enriched with a 'richExplanation' field inlining that error code's rich explanation (diagnosis + correct-pattern action + 'ek9 -q N' worked-example pointers — the same text ek9_explain_error returns), so a would-fail dry-run carries the corrective pattern without a second call. terseErrors takes precedence if both set.",
            "type" : "boolean"
          },
          "symbol" : {
            "description" : "The class, record or component the field is added to - a bare name ('Order') finds its file workspace-wide; 'mod::Order' when the name is declared in two modules.",
            "type" : "string"
          },
          "terse" : {
            "default" : false,
            "description" : "Universal — token-saver. When true the response omits each edit's before/after bodies (keeping skeletal file/type/line range). Use on an apply after a dryRun already showed the full render — you keep WHAT changed WHERE without re-sending the content.",
            "type" : "boolean"
          },
          "terseErrors" : {
            "default" : false,
            "description" : "Universal — token-saver. When true each wouldBeDiagnostics entry collapses to its one-line message + errorCode/file/line (the multi-paragraph explanation is dropped). Recover full detail on demand with ek9_explain_error <errorCode>.",
            "type" : "boolean"
          },
          "type" : {
            "description" : "The field's type in the structured form, e.g. 'Float', 'List of String' - rendered 'name as Type: Type()' (present, unset until assigned) unless defaultValue is given.",
            "type" : "string"
          },
          "verbosity" : {
            "default" : "full",
            "description" : "Universal response-size control (smaller / less detail / summary) — see §1.6. full (default) reproduces the complete response; summary drops each edit's before/after bodies (keeping file/type/line range); none collapses the edits array to a count. The `terse` boolean is the retained alias for summary.",
            "enum" : [ "full", "summary", "none" ],
            "type" : "string"
          },
          "withConstructor" : {
            "description" : "Insert a NEW pure constructor taking this field, in the SAME change - the fields-mode rendering ek9_add_constructor mode:'fields' uses. Only applies when the field is left with no value ('name as Type?' / rawDeclaration ending '?', or the structured form with 'type' and no 'defaultValue') - that is the one shape a publicly-constructible class can leave uninitialised (E07170/E08070/E08060) until a second ek9_add_constructor call lands one; any other form already has what it needs and the option is a no-op. Default false.",
            "type" : "boolean"
          }
        },
        "required" : [ "symbol" ],
        "type" : "object"
      },
      "name" : "ek9_add_field",
      "whenNotToUse" : [ "Adding a METHOD or CONSTRUCTOR, not a field - use ek9_add_method / ek9_add_constructor.", "The target construct doesn't exist yet - create it with ek9_new_construct first.", "Renaming or removing an existing field - use ek9_rename_field / ek9_remove_field.", "Traits, functions, services, applications, programs, text - these grammatically have no fields; the tool returns a target-construct-is-not-fielded conflict." ],
      "whenToUse" : "'Add a field to CustomerOrder' is one call with symbol:'CustomerOrder', fieldName and defaultValue (or rawDeclaration:'logger as Logger!') - no file or line."
    }
  },
  "scenario" : "exact_match_shape",
  "tool" : "query_tool_detail"
}
