# Continuity ledger (per-branch)

## Human intent (must not be overwritten)

- Build a structured output (JSON schema) form UI for the workflow designer properties panel.
- Convert between JSON Schema ↔ form properties for editing.

## Goal (incl. success criteria)

- Implement structured output dialog with form-based JSON Schema editing.
- Bidirectional conversion: JSON Schema → form properties and form properties → JSON Schema.
- All code should be type-safe without `as` casts.

## Constraints/Assumptions

- Follow project conventions: kebab-case files, Biome formatting, Zod v4, "less is more".
- Use `Schema` type from `@giselles-ai/protocol` as the source of truth for JSON Schema structure.

## Key decisions

- Exported `StructuredOutputPropertyType` from `@giselles-ai/protocol` so consumers can import it directly.
- Used exhaustive `switch` on the discriminated union's `type` field for safe narrowing, eliminating all `as` casts.
- Merged `convertArrayItem` into `convertProperty` (only difference was `name: ""`).
- Chose discriminated union over flat interface for `FormField`: type safety outweighs the slight verbosity in type-change handlers (`handleTypeChange` uses explicit `switch`). Value preservation across type changes is intentionally dropped (switching type clears type-specific data, which is more intuitive UX).

## State

- Branch has new files for structured output form UI (types, conversion functions, tests, dialog, property-row).

## Done

- Removed all `as` type assertions from `json-schema-to-form-properties.ts` by properly typing with `StructuredOutputPropertyType` and using `switch` narrowing.
- Exported `StructuredOutputPropertyType` from protocol package (was previously internal-only).
- Renamed UI types/functions: `FormProperty`→`FormField`, `PropertyType`→`FieldType`, `isPropertyType`→`isFieldType`, `createEmptyProperty`→`createEmptyField`.
- Renamed conversion functions: `formPropertiesToJsonSchema`→`formFieldsToJsonSchema`, `jsonSchemaToFormProperties`→`jsonSchemaToFormFields`, `convertProperty`→`convertToFormField`.
- Renamed files: `*form-properties*`→`*form-fields*`, `*json-schema-to-form-properties*`→`*json-schema-to-form-fields*`.
- Updated local variables in `property-row.tsx` and `structured-output-dialog.tsx` for consistency.
- Renamed protocol type: `StructuredOutputPropertyType`→`SubSchema` (JSON Schema spec calls nested schemas "subschemas").
- Internal Zod validator renamed: `StructuredOutputProperty`→`SubSchemaValidator`.
- Unified function naming to `convert[Source]To[Target]` pattern.
- Changed return key of `convertSchemaToFormFields` from `properties` to `fields`.
- Renamed `property-row.tsx`→`field-row.tsx`, `PropertyRow`→`FieldRow`.
- Renamed `generateId`→`generateFieldId`.
- Tests pass; SDK rebuilt; check-types pass.
- Refactored `FormField` from flat interface to discriminated union (6 variant types: `StringFormField`, `NumberFormField`, `BooleanFormField`, `EnumFormField`, `ObjectFormField`, `ArrayFormField`).
  - Each variant carries only its own properties (e.g., `enumValues` only on `EnumFormField`, `children` only on `ObjectFormField`, `items` only on `ArrayFormField`).
  - `ArrayFormField.items` is non-nullable (was `FormField | null`).
  - `createEmptyField()` returns `StringFormField` specifically.
  - Rewrote `handleTypeChange` and `handleItemsTypeChange` in `field-row.tsx` to use explicit `switch` per variant.
  - Updated exhaustive check in `convertFormFieldToSubSchema` from `field.type` to `field` (discriminated union pattern).
  - `ObjectChildren` component now accepts `ObjectFormField` instead of `FormField`.
  - All tests pass; types check; tidy warnings are pre-existing (dialog not wired in yet).
- Wired `StructuredOutputDialog` into `OutputFormatPanel`:
  - Replaced raw textarea with an "Edit schema" button (using `Braces` icon) that opens the dialog.
  - Removed unused `useState`, `SettingDetail` imports and `schemaText` local state.
  - All checks pass (format, build-sdk, check-types, test).

## Now

- Minor cleanup: hoisted `generateFieldId()` call above `switch` in `convertSubSchemaToFormField` to reduce repetition.

## Next

- (No remaining tasks for the structured output form UI feature.)

## Open questions (UNCONFIRMED if needed)

- 

## Working set (files/ids/commands)

- `internal-packages/workflow-designer-ui/src/editor/properties-panel/structured-output/types.ts`
- `internal-packages/workflow-designer-ui/src/editor/properties-panel/structured-output/convert-schema-to-form-fields.ts`
- `internal-packages/workflow-designer-ui/src/editor/properties-panel/structured-output/convert-form-fields-to-schema.ts`
- `internal-packages/workflow-designer-ui/src/editor/properties-panel/structured-output/field-row.tsx`
- `internal-packages/workflow-designer-ui/src/editor/properties-panel/structured-output/structured-output-dialog.tsx`

