# FT3 Editor Handoff

## Purpose

This tool edits Fronimo `.ft3` files for the lute music site.

Current workflow:

1. User chooses an existing `.ft3` file, uploads one, selects one from the server directory, or uses a template file.
2. The app parses metadata from that file and uses it to pre-populate a form.
3. The user reviews and corrects the metadata.
4. On submit, the form values are treated as authoritative and written into the output `.ft3`.

Important rule:

- The input file supplies initial values only.
- The submitted form supplies final values.

## Current Stack

- Prototype is a Flask + WTForms app.
- Long-term target is likely Django + React.
- The Python parsing/writing logic should be reused.
- The Flask web layer should be treated as prototype code, not final architecture.

## Core Files

- `run.py`: routes, session flow, field-validation endpoint, directory browser endpoint
- `form.py`: WTForms definitions, defaults, suggestion lists, output filename generation
- `vals.py`: field validators, canonical data loading, source/document lookup logic
- `proc.py`: `.ft3` parsing and writing
- `templates/form.html`: live suggestions, blur validation, source/document prompts, compact layout

## Implemented Behavior

### File selection

- First screen accepts a typed file name.
- If blank, uses `template.ft3`.
- There is also an in-app `/directory` browser listing available `.ft3` files.
- Uploaded `.ft3` files are supported in the route logic if the upload field is present.

### Form population and submit

- Parsed/template values pre-populate the form.
- Submitted values are passed to `process_form(...)`.
- Output filename can be left blank; a safe name is generated automatically.

### Validation and live UX

- Most fields validate on blur using the live Python validators through `/validate-field`.
- Old field errors clear as the user edits.
- Suggestions are clickable for:
  - ensemble
  - part
  - type
  - composer
  - original composer
  - source
  - document

### Ensemble / Part rules

- `ensemble` is a comma-separated list.
- An ensemble item may be either:
  - a canonical instrument name
  - `designation:instrument`
- `part` is optional.
- `part` may contain:
  - `score`
  - a plain ensemble item
  - the left side of a `designation:instrument` ensemble item
  - a comma-separated list of valid part items
- If `ensemble` is blank and `part` is filled, validation says `Enter ensemble first.`
- The first time `ensemble` changes from its initial value, `part` is cleared.
- In the clickable part suggestions, `score` is offered if ensemble has more than one distinct member.

### Instrument validation

- Uses canonical values from `insts.tsv`.
- No substring matching for validation.
- Input and allowed values are normalized:
  - lowercase
  - trim whitespace
  - collapse repeated spaces
- Exact normalized match is required.
- Close suggestions are shown on failure.

### Type validation

- Uses canonical values from `types.tsv`.
- Treated as a comma-separated list.
- Normalized exact matching with suggestions on failure.

### Composer validation

- `composer` and `original composer` validate against canonical names from `names.tsv`.
- Clickable partial-match suggestions appear while typing.

### Source validation

- Existing `source` values are now taken from authoritative root metadata:
  - `D:\website\dft.json`
  - fallback: `D:\website\settings.json`
- If a source is not recognized, the user is prompted:
  - `New source (y/n)?`
- If yes, the source is accepted for the current submit.
- If no, the field remains invalid.

### Document validation

- Suggested documents are keyed by source.
- Existing `document` values are taken from authoritative root metadata:
  - `D:\website\dft.json`
  - fallback: `D:\website\settings.json`
- If a source is known and the entered document is not one of the known documents for that source, the user is prompted:
  - `New document (y/n)?`
- If yes, the document is accepted for the current submit.
- If no, the field remains invalid.
- Known bad placeholder values from root metadata such as `mus.ms.` are filtered out from suggestions.

### Page validation

- Bare page numbers are not accepted.
- Accepted forms:
  - `p.13`
  - `f.13`
  - `pp.13,14`
  - `ff.13,14`
- `p.` and `f.` are for a single designation.
- `pp.` and `ff.` are for comma-separated lists.
- Footnote generation preserves the exact submitted page prefix.

### Other field rules

- `part` is optional.
- `subtitle` is optional.
- `date` accepts both `c1605` and `c.1605`.
- `editor` is required.
- `outputfile` can be blank; a filename is generated.

### Layout

- The main form has been compacted with CSS to reduce vertical space.

## Current Metadata Sources

- `insts.tsv`: canonical instruments
- `types.tsv`: canonical music types
- `names.tsv`: canonical person names
- `D:\website\dft.json`: authoritative source/document values
- `D:\website\settings.json`: fallback for the same

## Known Prototype Limitations

- This is still a Flask prototype, not production architecture.
- Some route/file-path logic still assumes local Windows-style paths.
- User permissions are not yet integrated with the main website auth system.
- Upload handling and contributor-directory isolation are not yet implemented as a full production workflow.

## Intended Website Integration

Target model:

- Main site is Django + React.
- This editor should eventually be part of that site, not a separate Flask app.
- Django should own:
  - authentication
  - roles
  - contributor directory resolution
  - upload permissions
  - email notification
- React should own the editor page UI.
- Current Python parsing/writing/validation logic should be reused as backend modules.

## Intended Roles

- `admin`
- `editor`

Only `admin` or `editor` should see the `Edit` button or access the editor.

## Intended Contributor Directory Rule

Each editor should have a contributor directory:

- `contributors/<lastname lowercase><FirstInitial uppercase>`

Example:

- `gerbodeS`

That directory should be created when the editor account is created.

The editor tool should only allow that user to access that directory.

## Intended Upload Workflow

Future workflow should support:

- upload of existing `.ft3`
- upload of non-`.ft3` contributor files
- metadata-only submission when no `.ft3` exists yet

After submit, the site should generate an email to the main editor with:

- contributor identity
- uploaded filenames
- written metadata/output location
- any files awaiting conversion by the main editor

## Recommended Migration Path

1. Preserve the Python FT3 parsing/writing code.
2. Preserve the validation rules and field behavior.
3. Re-implement the web layer in Django + React.
4. Integrate with the main site login and role system.
5. Add contributor-directory isolation.
6. Add production upload and notification flow.

## Notes

- If behavior in code and this document disagree, the intended behavior described here should be reviewed against the latest thread decisions before further development.
- This file exists so the project can be resumed later or handed off without relying only on chat history.
