Florian "flowdy" Heß 6e79d8bf22 init
2026-06-19 07:26:28 +02:00
2026-06-19 07:26:28 +02:00
2026-06-19 07:26:28 +02:00

Vue3.js prototyping test - Prompt to Claude

There are two public interlinked repositories in the Gitlab account of some guy, where the second relies on the first, but the first does not depend on the second, because it can be run stand-alone quite like a Unix tool ("Do one thing and do it well" philosophy) and the second is always to be kept as an optional layer:

  • /sompyler. Sompyler is a text-controlled synthesizer, in the typology between computer-parsible notation systems (MusicML, ABC) and fully-featured audio-programing languages like CSound or ChucK. It proudly documents to cover both the realm of sound and the realm of tone arrangement ("music"). The Neusik syntax is specified in doc/rfc.md.

    The information below relate to sompyler version v0.43-20-gcb42c3e. Older versions might not emit an ast.log complete enough. Please ensure an existing local repository is uptodate.

  • /neusician. Flask-based web application server, kind of an interface to some server-side sompyler instance, usable via a browser that way.

    Recommended version to deploy: v0.80-75-g023941c or later. Please ensure an existing local repository is uptodate.

In the current version of Neusician the user basically has a text area to fill with Neusik code, rendered by Sompyler to audio if it is all syntactically valid. At a mobile device however, it is tedious to use in that state, "for nerds only, others keep far off to retain mental health". I want to test Claude Code to develop a vue3js single page application, deployable as a Flask blueprint. Let's regard it as a experimental web-user interface on-top of that "pure Neusician for nerds bare-coding into a text area". By using the blue-print conventions in Flask, people operating Neusician could code there own Neusik coder web-gui environment, or choosing one among a collection of blueprints for this task.

What I deem common for all those SPA web-guis, and especially for that prototype:

  • They can but do not need to be fed with input from Sompyler abstract syntax tree tracing log (requestable Neusician /sompyle/ast.log). The user can start from scratch, too, but if they want to ingest a prepared Neusik score file, they need to log in via basic auth to /sompyle endpoint and process it once in "check only" mode, no rendering required for ast.log to be generated. There has been tough decision consideration between two kinds of technical debt: dependency vs. redundancy. It is not a requirement, or rather it is a should-not, that the SPA can read that score in the yaml format. The dependency on a sompyler instance is considered rather a win. The ast.log parsing routines are difficult enough to realize, redundancy of yaml parser is an unnecessary burden, while yaml can be written without a dedicated general yaml.js module.

    Example of how ast.log looks like for Beethovens Pathétique, 1st mov. has been the result of syntracer() and deeper_level() throughout the Sompyler score-parsing code, with both defined in Sompyler/syntaxtracer.py module.

    The "original" Neusik score

  • They enable the user to create, manipulate. move and delete any object in the score, i.e. the hierarchical model of that score, and provide user-friendly widget for every property item these objects consists of.

  • They write out a score in the original YAML format. It is not a requirement, or rather it is a should-not, that the SPA can read that score in that format. The dependency on a sompyler instance for that is intended. The ast.log parsing routines are difficult enough to realize.

Concerning the prototype to implement

  1. The vue3js SPA needs to ingest that log into an internal hierarchical data structure. For every item of that model, the SPA provides following views:

    • A basic view highlighting the identifier, if any, and further identifying items from its properties as simple concatenated text of label and value pairs.

    • A short view consisting only of the identifier. Where none exists, identical with basic views. Should have an arrow-down button to extend the view to basic.

    • An extended view that lists all properties as a DL HTML5 element, each DD element containing an appropriate form element. If a property is optional, say, the envelope of an AM or FM modulation, the on/off slide-switch is off by default. When turning it on, the form element is shown. Turning it off, it gets hidden and any final rendering trigger will skip its data structure, so the property, no matter if filled, is not part of the output score.

    • Some, yet not all custom types according to doc/rfc.md are composite types: e.g. SHAPEs and stressor patterns. Implement appropriate widgets with suitable form controls.

  2. The interface layout of the SPA consists of one or more overlay panes the handles of which are positioned horizontally at the bottom. The handles show icons only, with img alt= attribute being the initials of the pane name:

    • Current position (alt=CP). Header on the top with the (in-place editable) title of the score. Left of the header is the Arrow-Right icon for import function (once a score is imported and any objects are changed, grayed out), right of the header is the export/render-to-score function. The center of the interface covers 70% of the screen and lists vertically, without bullets, the short views of the objects of the current matter of focus. Clicking an object above the bottommost will update the panes and their handles after this pane, reflecting the new state of focus. Any sub-objects remain listed until the user selects another direct sub-object.

      Import function requests endpoint url, username and password on demand. The authentication method is HTTP(S) basic auth. Export function sends the code to the public /sompyle endpoint or /sompyle/reserve-a-worker-for-tests, depending on the optional credentials provided.

    • The second pane (alt=FO) displays and offers editing of the properties of the focus object. Composite properties (e.g. shapes, continua, patterns, pitches, ...) stuff into accordion menu sub-panes to pull down and close up. Include their show/hide switches (optional properties) in the accordion menu property headers, if this is possible.

    • Any sub-objects deserve their own additional panes. Some parent objects have more than one sort of child objects. E.g. variations in instrument specifications have, besides their basic properties ATTR, O, A, S, T, R, FM, AM, WS, VOLUMES, TIMBRE, SPREAD, MORPH, following sorts: labelled groups (alt=LG), PROFILE items (alt=PI), sub-ordinated variations (alt=SV). Read and interprete the rfc.md spec carefully to find out which objects should provide which additional panes. If the user clicks a sub-object in these panes, all panes need to adapt even pane #1 (current position) must list the newly focussed object under prior focussed object, and none below. It is not requested, but a nice-to-have to save the old path.

Registry of objects and their details you found

(Following text has been extracted as-is from an output in a Claude session, and is perhaps not to be re-fed if kept in context memory. For answers to the doubts see next sections. Yet, look out for exceptions to this noted by "User remark:" and by footnotes.)

This section is the user's explicit request. Derived from doc/rfc.md. For each object: parent context, identifier, simple props, composite props, sub-object kinds (→ additional panes), and known UX doubts.

Notation: R = required, O = optional. Composite entries get their own widget or accordion.

Score (document root)

  • Parent: none.
  • Identifier: none.
  • Simple: title O, composer O, source O, encrypter O.
  • Composite: measures[1], tuning, room, articles.
  • Sub-objects → panes: stage entries, measures, embedded instruments (instrument NAME keys), embedded room (if not external), embedded tuning (if not external).
  • UX doubts: should measures[1] be edited at score level or always per-measure_meta? The RFC permits both.

Stage / Voice entry

  • Parent: stage mapping on Score.
  • Identifier: the mapping key.
  • Simple (string form): direction R, distance R, instrument-ref O.
  • Composite (mapping form): same fields, plus articles O and tuning[2] O (voice-level).
  • Sub-objects → panes: instrument (either drilled into the embedded def, or a "go to file" pointer if a PATH), voice-level articles.
  • Doubts: how to represent "compact string vs mapping" in the editor? Suggest internal model is always mapping; emit compact form only when neither articles nor tuning[2] is defined.
  • Also lives here: _space (orchestra cone). Treat as a sibling settings sub-pane.

Instrument

  • Parent: score (embedded) or external .spli.
  • Identifier: name (key on score level).
  • Simple: NOT_CHANGED_SINCE O[3] .
  • Composite: character R (a MAYBE_LIST of Variation).
  • Sub-objects → panes: variations (always at least one). When more than one, the panes list them; each variation drills into its own three-pane group below.

User remarks: Instrument objects cannot be focussed and are to display "disabled" i.e. greyed out when an external specification is referenced or when the ast.log just lists them as cached=True. Show a message "Please check 'Force refresh of cached embedded instrument specification no matter the timestamp' on re-rendering and import". And no, I am not quite content with that quirk, but at least it is planned.

Variation (the heaviest object)

  • Parent: Instrument's character.
  • Identifier: ATTR field (composite: NAME [= STRING | (STRING|...) ]), or position-in-list if none.
  • Basic uppercase-letter properties (each composite, each optional, each with a SHAPE-bearing widget):
    • O Oscillator (enum or identifier)
    • A Attack envelope (DURATION:SHAPE)
    • S Sustain envelope (NOMINAL_DURATION:START;SHAPE)
    • T Tail envelope (DURATION:START;SHAPE)
    • R Release envelope (DURATION:START;SHAPE)
    • FM Frequency modulation (FREQUENCY[f|F][@OSC]SHAPE;MOD:BASE)
    • AM Amplitude modulation (same shape)
    • FV Frequency variation (BASE[±MIN][±MAX];SHAPE)
    • WS Wave shape (CENTER;SHAPE)
  • Variation-named composite props:
    • VOLUMES (LIST | RESOLUTION:SHAPE)
    • SPREAD (same form)
    • PROFILE (LIST of partials)
    • TIMBRE (SPECTRUM_WIDTH:SHAPE)
    • MORPH (LIST: PARTIAL_SEQNUMS [WEIGHT] ":" SHAPE)
    • RAILSBACK_CURVE (minF, maxF, 88×INT or 88:SHAPE)
  • Sub-object kinds → THREE additional panes as the brief calls out:
    1. Labelled property groups — keys ≥3 lowercase chars, mapping to basic O/A/S/T/R/AM/FM/FV/WS plus @LABEL references.
    2. PROFILE items — the list elements in PROFILE (each can be REVERSED_DBFS, REVERSED_DBFS@LABEL, or a mapping with match, deviance/D, volume/V, plus basic props).
    3. Sub-variations — sibling variations whose ATTR binds to an attribute value or sub-label[4].
  • Doubts:
    • Sensible defaults when toggling an envelope ON: A → 0,100;…, etc. Need user guidance per the brief's "approve findings" step.
    • Implicit attributes (pitch, length, stress) — always available — show as informational/read-only? Or hide?
    • @LABEL resolution UI: dropdown of in-scope labels + manual override?
    • Circular references must be detected (RFC requires error).

Room

  • Parent: score (embedded) or external .splr.
  • Identifier: none.
  • Simple: none.
  • Composite (all O except at least one of levels / delays):
    • levels (POSITIVE_INT:SHAPE | LEFT|RIGHT or mapping with left/right)
    • delays (FLOAT:SHAPE | LEFT|RIGHT or mapping with left/right)
    • freq_lanes (LIST: first BANDS:SHAPE; rest DIST:SHAPE)
    • border (MSECONDS:SHAPE; default ≈35 ms; Haas effect)
    • jitter (SHAPE; 0..1 randomization)
    • deldiffs (LEFT|RIGHT PATTERN or mapping)
    • diffusion (PATTERN)
  • Sub-objects → panes: each composite gets an accordion in Pane #2; no additional kinds.
  • Doubts: stereo toggle (mono LEFT|RIGHT form vs explicit left/right mapping) — tab selector vs explicit "Stereo?" switch?

Tuning

  • Parent: score (embedded) or external .splt.
  • Identifier: none.
  • Simple: base (PATH, R if embedded), ref_key_offset O, base_frequency O, intervals O.
  • Composite: chords O (mapping under), scales O (mapping under).
  • Sub-objects → panes: chord defs and scale defs as two sub-panes.

Intonation file (.splt)

  • Parent: standalone or referenced.
  • Identifier: filename.
  • Simple: ref_frequency, ref_key_number, ref_octaves_number, span_octaves.
  • Composite sections: intervals, scales, chords, tones.
  • Doubts: editor for .splt — in-scope for v1 or out? The brief focuses on score editing; .splt may be read-only with "open externally" link.

Measure

  • Parent: score (sequence).
  • Identifier: _id O (auto-incremented int otherwise).
  • Simple: cut O, skip O, repeat_unmentioned_voices O, is_last O, offset_seconds O.
  • Composite _meta (each inheritable from prior measure or score-level measures):
    • stress_pattern (R for first measure)
    • beats_per_minute (POSITIVE_INT | START-END | START;SHAPE)
    • lower_stress_bound O
    • upper_stress_bound O
    • elasticks_pattern O
    • elasticks_shape O
    • tuning O (per-tick base shift / scale type)
  • Per-voice keys (each becomes a sub-object): voice-specific _meta, articles, named materials, numeric offsets.
  • Sub-objects → panes: voices, named materials, offsets (or fold the latter two into the voice pane).
  • Loop sugar: _loop (POSITIVE_INT) — represent as a numeric toggle on the measure with an array of cycle-values for |-separated meta/articles.

Articles (global, voice-level, measure+voice-level)

  • Parent: score | stage voice | measure voice.
  • Identifier: mapping key.
  • Composite: attribute mapping; each attribute may be:
    • Static value (INT/FLOAT/STRING/BOOL)
    • Continuum (START-END or START;SHAPE)
    • LPU-Pattern (L:SHAPE;P:STRESSOR;U:SHAPE)
  • Special keys: o: (nested attrs for the o article), :extension, all.
  • Doubts: how to disambiguate "single-letter heads in chains" vs "extended labels"? A flag on the article entry, or two distinct lists?

Stem Note (mapping form)

  • Parent: voice offsets in measures.
  • Simple: pitch/P R, length/L O, weight/W O, overlength O, damp O, extra_adj_pitch O, adj_pitch_cent_per_key O, adj_stress O, _LRpos O, _Zpos O, write_to O.
  • Composite: chain O.
  • Sub-object → pane: chain editor (its own pane because chains are non-trivial).

Stem Note (string form)

  • Same model, render compactly. The editor stores the structured form and decides format at export.

Chain

  • Parent: Stem Note.
  • Structure: subchain *("; " subchain); subchain = clauses; clauses contain article_stack plus length, or nested (chain). Quantifiers *N.
  • Sub-objects → pane: chain clauses are visually linear; v1 can use a horizontal list widget with insert/delete/duplicate.

Material line

  • Parent: voice offsets.
  • Forms: Simple Material Clause (SMC) <material_ref,…:PITCH … or Complex Material Clause (CMC) <…<material_ref…>….
  • Sub-objects → pane: material-ref editor.
  • Doubts: nesting depth via leading < count — display as tree indent? Probably yes.

SHAPE

  • Universal composite. Used everywhere envelope-like behaviour is needed.
  • Nodes: x,y[*z][!]. x strictly increasing.
  • Widget: a single shared ShapeEditor component — table input with optional inline curve preview (SVG). The same widget powers A/S/T/R, AM, FM, FV, WS, VOLUMES (resolution form), SPREAD, TIMBRE, MORPH (per-partial SHAPE), elasticks_shape, dynamics/tempo continua, room levels/delays, deldiffs, diffusion, jitter, border, freq_lanes lanes.
  • Pre-tested by chain-tool.js does some of this; not directly reusable but we can cannibalize the SVG render approach.

PITCH

  • Forms: pitch name (C4, A&major7, Cis), key position int, caret position ^28, frequency float, modifier syntax C4+2k-50c.
  • Widget: PitchInput with a tab/radio selector across forms.[3]

Continuum

  • START-END or START;SHAPE.
  • Widget: range form vs SHAPE accordion.

LPU-Pattern

  • L:SHAPE;P:STRESSOR;U:SHAPE.
  • Widget: three sub-fields wrapped in an accordion ("Advanced").

Stress Pattern

  • Recursive subdivision *(";" division), where division = subdivision *("/" subdivision) and level = INT | high-low.
  • Widget: visual pattern editor — rows for division levels, cells for ticks, / alternatives as an extra row. v1 can ship as a text input with live validation if the visual editor is too much for v1.

PROFILE Item

  • Three forms: scalar REVERSED_DBFS list; REVERSED_DBFS@LABEL; mapping with match, deviance/D, volume/V + basic props.
  • Widget: form-tagged with kind switch; match syntax 2n+1 style needs UX help (preset chips: "even partials", "every 3rd partial", custom).

Generic short-view rule

  • For objects with an identifier: identifier only.
  • For objects without: short view = basic view.
  • Down-chevron always toggles to basic view.

AST log shape (for the parser)

Each line: ^(?P<depth>\d{2})\s+(?P<slot>\w+(?:\.\w+)*)\s+(?P<rest>.*)$. rest is a mix of repr'd positionals and key=repr(value) pairs. Parsing recipe:

  1. Tokenise rest with a simple state machine handling '…', numbers, and bare Y/N.
  2. Build a tree by tracking the previous depth: depth+1 ⇒ child; same depth ⇒ sibling; lower depth ⇒ pop.
  3. Slot-prefixes (PARENT.SLOT) indicate the message is logged under a slotted deeper_level; treat them as namespaced children.
  4. Cross-reference slots against the call-site map established during exploration:
Slot Source Becomes model node
instrument orchestra/__init__.py Instrument
label_spec orchestra/instrument/variation.py InstrumentLabel
variation orchestra/instrument/variation.py Variation
*.prop (slot-prefixed) orchestra/instrument/protopartial.py PropertySpec on variation
bar score/measure.py Measure
article score/measure.py (deferred) Article
article_shapes.voice_property score/measure.py VoiceArticleProperty
stressor, tempo, elasticks, lower_stress, upper_stress score/measure.py MeasureMetaEntry
voice score/measure.py VoiceInMeasure
stem_note score/note.py StemNote
cluster, cluster.number score/note.py Cluster + RepeatCount
chain score/note.py Chain wrapper
motif score/chord.py Motif
shape, coords.point synthesizer/shape/__init__.py Shape + ShapePoint
modulation synthesizer/modulation.py Modulation

Unknowns flagged by exploration (carry to the open-questions list below):

  • Whether deferred messages flush on deeper_level exit or on next non-deferred call.
  • Whether *.prop prefixing is uniform across all properties.
  • Whether shape coords are always emitted in x, y, z, is_sharp order.

Your follow-up questions, my answers

What I noticed when reading the plan and your commits

The STRUCTURE dict in syntaxtracer.py is out of date, so ignore it. For the bindings please use in Javascript what you infer as attribute names in the syntracer calls. Originally, syntracer() was to double-check against the structure, but validation is post-poned out of that stage.

Now pondering your design doubts ...

Score (Root): should _meta be edited at score level or always per-measure?

The RFC permits both for a reason, but in the reference implementation Sompyler this is may be yet to be fixed. So, for this quest session, let's basically pretend all flaws and bugs of Sompyler are fixed, so anyway, whatever discrepancy is not your business but be welcome to notify me about it when stumbling upon and at any rate stick to the authorative source of truth, doc/rfc.md:

What is defined in "measures" slot, serves as fallback value store for each measure or multi-measure, while definitions in _meta are inherited from one measure to the next, until it is overwritten. So, prior to adopting fallbacks from the previous measure, it should be looked up in score-level "measures".

The properties of "measures" are all optional. In Sompyler, there will be sensible calculated defaults. These defaults, however, will have lower priority than the properties inherited from previous measures.

how to represent "compact string vs mapping" in the editor? Suggest internal model is always mapping; emit compact form only when no articles.

Yes, provide compact text input only as last resort here and basically where a compact string form is supported by spec. As part of the overall internal model, I recommend to construct an ordered list of pairs the left-hand item of which is an alphabetically ordered list of VARIABLE_REFS, the right-hand item the template where all these refs are used in. When selecting a template, find all defined refs, sort them and retrieve the appropriate template from the list of pairs. In Python (unfortunately not in Javascript), you would best use a dictionary of tuples as keys and strings or template objects as values.

Sensible defaults when toggling an envelope ON: A → 0,100;…, etc. Need user guidance per the brief's "approve findings" step.

Not quite sure what is meant by this, but for attack, and release ask for the length separately, as length is required. Attack be "1,1" as default shape (coord 0 is implicitly at 0), release be "1;1,0". Sustain be optional, length is default 1 in Sompyler realm, so let's have it as placeholder in the length field before the shape node entries.

Implicit attributes (pitch, length, stress) — always available — show as informational/read-only? Or hide?

The ATTR field should rather be rendered as drop-down menu with these basic note attributes. Add a "[custom]" entry that, when clicked, provides a modal dialog with a text input that checks its content for all the constraints:

  • name is lower-case alphabetic and not equals any label of a labelled group
  • that is not entered as ATTR already for a sibling of this variation, its parent variation or of any child variation, and
  • may be extended by regular expression \s*=\s*[a-z]+((?:\s*\|\s*)(?:[a-z]+))*

Make sure the user provides sub-variations for all the provided labels in whatever order (the fixed stacking order depends on the indications in the ATTR line). Lacking an = extension of the line, allow but do not require number-keyed sub-variations. Without an ATTR entry in a variations, disallow labelled as well as number-keyed sub-variations. Check these constraints when the variation object is requested by the user to close.

@LABEL resolution UI: dropdown of in-scope labels + manual override?

O like Oscillator

The following does refer to 'O' / oscillator in a restricted sense: only #1 is possible, but then before the label drop-down insert a bright/inverse-colored toggle labelled "@", optional prefix to the label when exported to convey that the oscillator is taken from the referenced group and enriched with all its properties. The "@" cannot be toggled for the options in the optgroup "primitives" (sine, etc.), so it disables that optgroup or is untoggled with a message when a primitive waveform is currently selected.

A, S, D, R, AM, FM, FV, WS, other

Split the widget of each 1-2-uppercase-letter optional base props (plus "other"), arranged in an accordion, in two parts each radio-buttoned and labelled:

  1. Refer label(s)

    If checked, provide lines of drop-down menu + integer weight (min: 1).

    Check that labels are not equal to labels of stacked subvariations. In export, normalize a single label ref to @{label}.

  2. Literal value

    Choose appropriate widget, e.g. length + shape nodes.

Envelopes for AM/FM

If in a modulation widget #2 is selected, extend the form fields with sub-heading "envelope" and, seemlessly. with the same widget as defined in #1 above. A literal envelope shape must be exported wrapped in square brackets. Caution, an envelope shape for a modulation is, like a frequency variation envelope shape, a shape, not a multi-shape ENVELOPE.

WS

Add checks that the coords start with an explicit node at x=0: "0,y;...". Instead of length, require CENTER. After confirming the message but choosing not to change a thing in this widget, do not enerve the user with another warning, they shall hear their probable mistake.

Circular references must be detected (RFC requires error).

Yes, I recommend to move all labels not allowed because of this constraint in a final disabled optgroup of the drop down, label "not possible".

When the drop-down is realised as an auto-suggest text input, forbid these inputs with following message: "The labelled group '{label}' cannot be referred as following labelled groups referring this, or groups referring those directly or not, would result in circular look-ups: [LIST]"

Well, I am not sure, double-check there is no braino on my part.

stereo toggle (mono LEFT|RIGHT form vs explicit left/right mapping) — tab selector vs explicit "Stereo?" switch?

Both is stereo. By LEFT|RIGHT the RFC means the mapping can be serialized to a string with a vertical bar as separator. But do not use it. Provide one widget, then a "binaural left ↑ / right ↓ side"-labelled check. If checked, show another widget of the same kind. I am cautious with mono/stereo and "ear" terminology here, binaural audio is a different kind of beast than mono/stereo, and understood my way.

For the tuning, provide a drop down, the topmost option being the default, but left unmentioned in the export:

  • tones_de+en
  • other .splt files found in lib/ directory and listed in $SOMPYLER/introspectables.txt

Tone naming specs + property ref_octave_number in the file do consider not editable. However, could you ingest the tone names splt files via javascript (fetch and process)? When they provide multiple alternatives of addressing tones (e.g. B3 vs. h in german/russ.), ask which to use to initialize the PITCH widget? Handle this as a virtual i.e. not exported score-level property.

Do not write many more than 200 LoC for that, more is what I deem complicated and please do not obfuscate just for the sake of the limit. If in doubt that that is too complicated for compliance, just stick to the default file and anglosaxon tone names with octave numbering. After all, it is v1 and a prototype.

how to disambiguate "single-letter heads in chains" vs "extended labels"? A flag on the article entry, or two distinct lists?

The spec should be clear about it, isn't it? Extended labels are attached with prefix colon (no space before or after) to the one-letter note head.

nesting depth via leading < count — display as tree indent? Probably yes.

Yes, but alas, observe the fact that Sompyler reference implementation is yet to enable support for all that. Actually it is under development in a local branch. Apply a warning that it probably chokes. But do not drop it altogether, I am eager to see what the software will export, so let easy-goingly the rendering fail.

Open questions

I adopt your question numbering, and am going answer it in Q&A style.

1. No direct reading of the spls file.

Q: The brief says the SPA should not read the score YAML directly — dependency on Sompyler's ast.log is intended. Confirmed? In that case, an authenticated user who has no existing AST log (fresh session) can't ingest a score they pasted in. Is that acceptable, or should we add a "paste raw .spls, send to /sompyle as draft, fetch ast.log" import sub-flow?

A: For the sake of relative code simplicity lol, do not ingest the YAML directly. The author of Sompyler does not want to happen to change things redundantly at two places, neither to notify contributors (forkers) with syntax changes that do not change the ast.log while syntax in the Neusik score format established earlier is still supported.

When it comes to convenience, a change of the analyze button on sompyle/status template is considered. So the score editor blueprint is requested to read prepared ast.log, just as convenience compared to access to the score editor and clicking import. Clicking analyze/edit button, request /sompyle/score-editor/?import=1 could be issued.

2. "Litmus test"

Q: import → export unchanged should equal the input score "modulo whitespace and comments." Does this include comments authored by the user (e.g., the YAML # … lines our smart-indent allows)? If yes, comments must be preserved through the model — which means parsing the .spls anyway, contradicting point 1. Please clarify which side wins.

A: I do not consider comments to be important for score editor users, mostly not worth keeping in an import/export round-trip and overcomplicating code. Well, there may be comments worth reading, though, concerning music theory and analysis and stuff, but users interested in these comments are welcome to read the score as is, without score editors in between.

3. Build tooling

Q: I propose CDN + native ESM + Vue 3 latest, no build step. OK, or do you want me to set up Vite? The latter unlocks .vue SFCs but adds Node/npm to the dev story.

A: No build step provided the author of Neusician, who regards himself as a nerd and is a fan of small footprint of the dev tool chain, shall be appealed to look into one's score editor sub-project.

4. Blueprint URL prefix

Q: I propose /score-editor as the blueprint URL prefix and score-editor as its Flask name. Acceptable, or do you want something neutral like /gui/ so future GUI blueprints share a parent?

A: The registering of the blueprint should be in the realm of Neusician core configuration by a SCORE_EDITOR_BLUEPRINT setting.

5. Auth UX

Q: Import dialog asks for username+password and uses HTTP BasicAuth (per brief). Should the SPA persist credentials in sessionStorage for the session, or re-prompt for every state-changing call? Persisting is friendlier; re-prompting is safer on shared devices.

A: Do not reinvent the wheel, leave it to the browser to cache the BasicAuth credentials.

As a surplus value in terms of persistence, someone might design their score editor blueprint (not this prototype) with a SQLite3 database in the worker directory of the active user. Let's not think too server-centric. It should not be a problem to import a score from one Neusician instance and export and render it on another.

Last but not least, in a typical Neusician instance, BasicAuth method supports the registration of new users, via a secret-prefix to password and double prompting. Importing from one user account and exporting to another should not be a trouble for an SPA bound to a single identity. Neusician is identity agnostic, fairness concerning resources is achieved by competing rhythmic tries of access.

Therefore, rather expect that the export of the score may result in a "Service unavailable error" and offer the user auto-retry in rhythmic intervals. Yet, the server promises that once a worker is seized and assigned to the user, it will remain him for an hour at least.

6. Status polling

Q: After export, the server returns Location: /sompyle/status.json. What polling interval do you want — 500 ms, 1 s, 2 s? The status endpoint already supports tail-log to avoid duplicate notes.

A: At least 2s. Polling is not nothing when the server is busy rendering audio. Consider the ETA time reliable after 50% of progress. Polling does not need to consider that the server gets unavailable, though that is not guaranteed.

7. Variation editor depth

Q: Variation is the densest object (≥15 composite props plus 3 sub-object kinds). Do you want all envelopes (A/S/T/R) collapsed by default and only revealed when toggled ON? Brief implies yes (default-off slide-switch).

A: Yes, this is a good idea. When it is a good idea to offer subordinate show/hide toggles for every envelope, you may also consider the subtleties that attack landing on y=0 should disable S/T/R, otherwise requires release, that omitted sustain disables tail and that R must land on y=0.

BTW: Invest some more UX attention to the shape widget.

Also, the envelope very much asks for convenience measures. Provide for every node being possibly dropped via a button labelled &minus;. Provide add-buttons labelled &plus; before the first, after the last, and between all pairs within. If the x-integer of a node is incremented over the next, shift the next so it is greater by 1. If the x-integer of a node is decremented below the previous, shift the previous so it less than it by one but care that it does not get negative. Carry that effect to all nodes in the same direction, as appropriate.

8. Sensible defaults for each envelope when toggled ON — please confirm or supply:

Q:

A: 0;0,100;1,100 (instant attack to full)
S: nominal 4 ticks, START=100, flat
T: off by default
R: 0.1s, START=100, drop to 0
WS: CENTER=1, flat SHAPE
AM/FM: off by default
FV: off by default

A: My suggestions are as follows:

A: LENGTH required, single node 1,10 (start y=0 implied)
S: LENGTH required, two nodes exported to "100;1,100".
R: LENGTH required, "1;1,0"
WS: "1;0,0;1,2" (neutral translation)

9. @LABEL references

Q: @LABEL references in basic property values should resolve through a dropdown of in-scope labels — do you want a manual text-entry fallback as well?

A: No. See above for details. Text entry fallback is needed for creation of a new labelled group.

10. Composite widgets

Q: SHAPE editor v1 — table-only with live SVG preview, or drag-handles on the SVG too? Drag-handles are nice but mobile-finicky.

A: Table style. I ponder the orientation of a node: row or column. Let's choose row for now.

11. Stress-pattern editor v1

Q: text input with validator, or visual grid? Visual is the better UX but ≥2× the code.

A: Number input fields. Consider to support cycling (/) and from-to (-) but let go of cycling, then of from-to if the overall javascript code handling this exceeds 100 lines, but offer subdivisions. Details left up to you.

12. PITCH input

Q: tab selector across {name, key, caret, Hz, modifier-string}, or a single text field with auto-detection? Auto-detect is more elegant but errors are less explainable.

A: Let's go for the tab solution.

13. PROFILE match syntax (2n+1, etc.)

Q: preset chips ("evens", "odd minus one", "every 3rd") + custom raw input, or only raw input with help bubble?

A: help bubble preferred.

14. Sub-pane behaviour

Q: When the user clicks a sub-object in pane #3+, the CP pane updates to include the new focus. Brief says "save the old path" is a nice-to-have. Implement a back button now or defer?

A: I would have requested this if I got an idea where to position it best. If in doubt, just prepare it.

15. Multiple sub-object kinds (Variation has 3).

Q: One pane per kind, side-by-side handles at the bottom? Or one combined pane with tabs?

A: No tabs for this, side-by-side handles. And consider the clip-path strategy for a merged look of pane and handle.

16. External files

Q: Out of scope for v1: editing .spli, .splr, .splt files standalone. Confirmed?

A: No. Every user may use the server-provided spl[irt] files as-is.

17. When the score references an external .spli via PATH, the editor will display the path as read-only.

Q: Should there be a "fetch and embed" action that pulls the file from /files/lib/... and inlines it? Useful but breaks user intent if they want to keep the reference.

A: Embedding worth a thought or two, but no, not in v1.

18. AST log unknowns (raised by exploration of syntaxtracer.py)

Q: Are deferred tracer messages always flushed before the enclosing deeper_level exits? The code path looks incomplete — please confirm intended behaviour. If it isn't deterministic, the parser needs heuristics.

A: Log lines are deferred when they only get a meaning by subordinated objects. When there are no "children", the parent is skipped. So, deferred means logged once a non-deferred child is logged.

19. Properties emitted under deeper_level(article_shapes)

Q: Are they uniformly slot-prefixed, or only some? Affects the regex above.

A: This is somewhat subtle indeed, a quirk, a "yet-to-deal-with" subject for me. The PARENT part is basically implied on level 0 ("score") or when the type of the object in the given SLOT is explicit. When a slot is occupied by type used for different purposes, the type is explicit. I recommend to save in a variable to check against the word after the dot of the prior next higher ordinate subject. Consider equal words before and after the separating dot as syntax error and reason to abort parsing with a message.

20. Shape lines (syntracer("shape", *coords))

Q: Are coords always emitted in x, y, z, is_sharp order?

A: I cannot guess why this is deemed important, but yes, the order is reasonable and will probably not be changed. This is not a promise for all time, however. In Python, keyword arguments to functions are order-agnostic, two. Positionals without attribute label and equal sign are order-sensitive.

21. Post-interpolation?

Q: Do any shapes in the log reflect post-interpolation (synthesised) values? Or always the raw definition? Round-trip needs raw.

A: No, post-interpolation would be an error that the code is not to detect.

22. Example assets

Q: The two example URLs in the brief — are they still live? If yes, fine; if not, please supply a current ast.log + .spls pair to use as the fixture for the round-trip test.

A: They are still live, yes.

To Do Next Prompt

git pull sompyler anew. A commit has been pushed that also includes measure tuning in the ast.log, another to drop outdated STRUCTURE, a third to get alright embedded instrument specs NOT_CHANGED_SINCE slot, if any. A fourth commit updates the doc/rfc.md spec. Pull also neusician anew for the "refresh cached embedded instruments / re-synthesize tones at any rate" checkbox and function. If you cannot find that commit, you have been prompted too early, abort and let me know.

Do realize the project unless important follow-up questions raise and await clarification or decision affecting many percent of the codebase. Follow-ups not that important try to clarify from the context what is best appealing an end-user, number them in comments in the codebase and refer to them by number in a final summary report of your actions.

Description
Prompt und Assets
Readme 210 KiB
Languages
JavaScript 89.1%
CSS 9.3%
HTML 0.9%
Python 0.7%