heart-frequency

Community@xixi/heart-frequency
Community skill — not reviewed. It was shared by 西西 and has not been checked by Neta. Read SKILL.md below before letting an agent use it.
Use it in Cohub

Paste this into your agent's chat — it fetches the skill and follows it.

Use the skill: heart-frequency. Run `npx -y @neta-art/neta-search-cli@latest skills use @xixi/heart-frequency --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @xixi/heart-frequency
Summary

Turn a character into a page where one typed sentence becomes glowing particles that either reach their heart or scatter.

  • You get one small web page built around a single character. The player types a sentence and watches it turn into a stream of light.
  • Each sentence falls into one of five feelings: warm, teasing, direct, sweet or apologetic. Each feeling has its own colour and motion.
  • The character accepts some feelings and rejects others. Accepted ones are absorbed and raise a resonance meter. Rejected ones scatter, and the meter drops slightly.
  • The character answers with one line in their own voice, and their mood shifts as resonance climbs. It is not a chat, and there is no score to chase.
  • Works best with a character who has a distinct voice and clear likes and dislikes. Give three sample lines if you have no character card.
SKILL.md
# Heart Frequency

The player types one short sentence. The page classifies it into one of five emotional frequencies, emits a particle wave in that emotion's colour and motion, and judges the hit at the character's heart. A frequency the character accepts is absorbed and raises resonance; a frequency they reject hits their guard and scatters. The result is one reply line and a changed mood — not a chatbot, not a score game.

Read this file fully before generating anything or writing files. Resolve relative paths from this skill's directory.

## Language

Reply in the user's language, whatever language this file is in. This holds for every message of the run, above all the final handover; translate what the scripts print, don't paste it. Text the player sees — Work title, labels, placeholders, buttons, preset sentences, reply lines — follows the user's language; text the user typed stays as they wrote it.

## When to use / when not

Use when the user has a character with a voice and wants a small, repeatable emotional interaction built around one sentence at a time. This skill makes one web Work.

Not for an ongoing chat roleplay (that is `create-roleplay`), a branching visual novel (that is `create-avg`), or a static character poster. For those, say what this skill makes and stop.

## Inputs

| Item | Required | Counts as given when |
|---|---|---|
| Character | yes | A character material exists in this world, or the user names a character and gives at least three lines of how they speak. "Someone" or "a boy" alone does not count. |
| Emotional stance | no — default inferred | The user says what the character accepts or rejects ("他只吃直球", "she softens when you apologise"). Otherwise infer five affinities from their lines and the plan's `affinity`. |
| Language | no — default the user's | The user writes in a language or names one. |
| Reply pools | no — default from the material | The user supplies lines, or the character material has quotable lines. Otherwise write 3 hit + 3 miss lines per emotion in the character's voice and say they are written, not quoted. |

If the character is missing, ask once for the character or three sample lines, then stop. If everything is given, do not ask and do not wait for a go-ahead.

## Why the mechanic works

Three rules carry the whole piece; keep them instead of inventing a new scoring system.

1. **Five frequencies, one axis.** `warm / tease / direct / sweet / sorry`. Each has a fixed particle budget, colour, spread, wave frequency, speed and size (see `references/plan-schema.md`). The visual difference must come from these numbers, not from a random colour.
2. **Affinity is a gate, not a score.** A frequency with affinity `>= 0.55` reaches the heart; below it, the particles scatter on the guard. The original tuning is `direct 1.0, warm 0.85, sorry 0.55, tease 0.35, sweet 0.15` — a character who hates clinginess should reject `sweet` even when the sentence is lovely.
3. **Resonance moves in visible steps.** A hit adds `round(affinity * 18)` (max 100); a miss subtracts 4. Mood lines change at 30 / 60 / 85. This keeps a session from maxing out in three sentences.

## Steps

1. **Read the character.** `neta atom list` then `neta atom get <id>` for the chosen character, or use the lines the user gave. Extract: how they address the player, what they hide, three things they would say when moved, three when deflecting. Write `$RUN/character.md` with quotes and their source.
2. **Write the plan.** Copy the shape in `references/plan-schema.md` to `$RUN/plan.json`. Every emotion needs at least two hit replies and one miss reply; `default` miss lines cover emotions without their own. Preset sentences are examples of *the player's* voice, not the character's.
3. **Validate the plan.** `node scripts/build.mjs --plan $RUN/plan.json --out $RUN/site --lang <locale> --check` — exits non-zero on a missing name, an emotion with no replies, affinity outside 0–1, or fewer than 3 presets.
4. **Build the page.** Same command without `--check`, into a new Work folder:
   ```bash
   node /mods/neta/neta work init web works/webs/<slug> --title "<title in the user's language>"
   node scripts/build.mjs --plan $RUN/plan.json --out works/webs/<slug> --lang <locale>
   ```
   The builder writes `index.html` from `assets/template.html`, injecting `window.PLAN` and `window.LOCALE`. Do not hand-edit the generated page unless a visual fix is needed; fix the template or plan instead so the next run inherits it.
5. **Check the interaction in a browser.** Serve `works/webs/<slug>` locally and test: typing each of the five emotions, a hit, a miss, resonance crossing 30/60/85, empty input ignored, portrait and landscape layouts. Record what you saw in `$RUN/qa.md`. A page that only looks right in one orientation is not finished.
6. **Publish and hand over.** See Deliver.

`$RUN` = `_runs/heart-frequency/<timestamp>/` under the workspace root.

## Deliver

One browser web Work.

1. Publish: `node /mods/neta/neta work publish web works/webs/<slug> --title "<same title>"`.
2. Confirm the published entry loads and the first preset produces particles.
3. In the user's language, name the character, the five frequencies and which ones this character rejects.
4. **Hand over with a card — the run is not delivered until this step is done.** One `interaction-components` card on its own line, target `{ "type": "work", "workId": "<id>" }`, the id taken from the publish output (fallback: `cohubWorkId` in `works/webs/<slug>/meta.json`). Never a made-up id, a folder path, or a `world-file` link to `index.html`.

## Out of scope

- Do not change world settings (including `WORLD.md` config, visual style or slug) or delete files that existed before the run.
- Do not modify memory, character cards, installed scripts, existing Works or roleplays.
- Do not build a chat backend, save conversation history, or let the character answer free text. The reply is always one line from the plan.
- Make only the requested Work; do not act on your own next-step suggestions.

## When to stop

- No character and no sample lines: ask once, in one message, then stop.
- The world has no publishable Work context: say exactly what is missing and stop. Do not borrow another world.
- Asked for a chat roleplay or a branching story: say this skill makes a one-sentence particle interaction and stop.

## Gotchas

- The judge fires when the *first* particle reaches the heart, not when the player presses send. If you judge on click, the reply appears before the visual payoff and the page feels broken.
- `travelLen` shrinks to the heart's radius; the travel time is `(travelLen / (speed * 3)) * 16` ms. Keep that formula when you change layout, or particles will pile up at the edge.
- On a narrow portrait screen the heart sits at 24% height and the source at 70%; on landscape it is 82% / 22% horizontally. Copying the landscape positions into portrait puts the heart under the input bar.
- A keyword classifier that only covers one language will send every English sentence to `warm`. Keep both language sets in the plan and let the user extend them.
- The page has no images, so do not generate any. Every cost in this skill is the build and the publish.