jevstrudel.git / worker / src / primer.ts

What an MCP client's model reads once, at initialize, about writing a song with Jev: the hosted MCP's instructions end with it (hosted-mcp.ts). The whole of each function is in api_reference, from jevCore.mjs's jsdoc; this is only enough to write a first song and know where to look. PRIMER_SONG is evaluated and played to its end against a stand-in Jev in website/src/jev/reference.test.mjs, so it cannot go stale silently.

8export const PRIMER_SONG = `setcps(.5)
9const song = { title: 'FIRST LIGHT', what: 'a pad that builds into a drop with bass and drums', key: 'C major' }
10const formJev = jev({
11  state: song,
12  questions: {
13    section: choice('Pick the section that plays next; the outro ends the song', {
14      intro: 'the pad alone',
15      drop: 'the pad with bass and drums',
16      outro: 'the pad fading out: the end',
17    }),
18  },
19})
20const djJev = jev({
21  state: song,
22  questions: {
23    energy: score('How hard should the section being entered (decidedThisSection) hit?', ['held back', 'steady', 'all out']),
24    hats: noul('Should that section add sixteenth hats?'),
25  },
26})
27const { section } = formJev.every(4)
28const dj = djJev.every(4, { after: { section }, fallback: { energy: 2, hats: 0 } })
29const form = walk(section, {
30  max: 8,
31  sections: {
32    intro: { at: 0, next: ['drop'] },
33    drop: { at: 4, next: ['drop', 'outro'], times: 3 },
34    outro: { at: 8, next: [] },
35  },
36})
37stack(
38  form.arrange(stack(
39    note("<c3,e3,g3 a2,c3,e3 f2,a2,c3 g2,b2,d3>").s('sawtooth').lpf(1000),
40    note("<c2 a1 f1 g1>").s('sawtooth').lpf(400).mask("<0!4 1!4 0!4>"),
41    s("bd*4, ~ sd").mask("<0!4 1!4 0!4>"),
42  )).velocity(dj.energy.score.div(2).range(.5, 1)),
43  form.arrange(s("hh*16").gain(.4)).mask(dj.hats.noul.gt(.5)),
44)`;
46export const JEV_PRIMER = `Jev is TypeSafe AI's System One model. It never writes text or music: it makes typed decisions over options the song writes down, in about a tenth of a second, with calibrated probabilities. A song asks Jev to arrange it while it plays, and composes the answers in code:
47- jev({ state, questions }) is TypeSafe's request exactly, and takes nothing else. state is what Jev judges (title, key, what each section is). Build each question with choice('instructions', { option: 'what it is' }), score('instructions', ['lowest level', …, 'highest']) (2 to 10 levels), or noul('instructions', { true: '…', false: '…' }).
48- .every(cycles, { fallback }) asks again every cycles cycles (a section) and returns each answer as patterns, one value per section. A choice gives .choice, .confidence and .probabilities. A score gives .score (0 to levels−1, fractional; .round() it for a step), .confidence and .probabilities. A noul gives .noul, the probability of true. A score or noul must name its fallback; a choice falls back to its first option.
49- Compose the answers with Strudel: dj.x.choice.pick({ … }), .velocity(dj.energy.score.div(n)), .mask(dj.y.noul.gt(.5)). walk(section, { sections: { name: { at, next } } }) makes a choice the song's form, and form.arrange(pat) plays the sections Jev picks. A second jev() with .every(n, { after: { section } }) is asked once the section is settled, so it can arrange it.
50- Jev's text goes in 'single quotes': "double quotes" and backticks are mini-notation, and jev() refuses them.
51
52A complete song:
53${PRIMER_SONG}
54
55api_reference with name jev, choice, score, noul or walk gives each one whole, with every option and an example; query jev lists them. get_song on a site song shows a full one.`;