The invocation ID is lov-do-they-love-me, and it uses the Englishsingular they: refers to a person whose gender is unknown or need not be specified,
so it covers both he and she. The verb form of singular they is do, not does—does they is a grammatical error,
this is not a typo, and during later maintenance, renaming, or localization do not "correct" it to does.
The display name is fixed as "Love Index Analysis"; the ID and display name have different roles, do not substitute one for the other.
Turn a real chat between two people into conclusions that can withstand scrutiny: first quantify the interaction rhythm, then do semantic layering, and finally deliver a phone-portrait infographic. The conclusions must state the methodology, sample, and error margin clearly,do not treat work messages as emotional heat, and do not present a custom index as a measurement of the parties' emotions.
The user gets three things: reproducible intermediate data, a card that can be sent out directly, and the error range of these conclusions.
Triggers
Activate when
- "Analyze the chat history between me and someone" "We've been chatting for two months, what kind of relationship is this really".
- "Does he/she love me" "Help me make a love index analysis" "See who is more proactive".
- "Turn our chat into a card".
- The user asks to "analyze our chat history", "make a relationship / love index card", or "is this person into me, based on the messages".
Do not activate when
- If you only need to read, search, or export WeChat records: hand it to
lov-wdb-cli。 - If you already have conclusions and just want to lay it out as a card: hand it to
lov-mobile-infographic; this Skill only starts from the data when there are no quantitative and semantic conclusions. - If you want to make a group chat daily report, WeChat official account article, or marketing graphic card: hand them to the daily report, article, and graphic card Skills respectively.
- If there is no real chat history and you only want a score based on feelings: refuse to fabricate, and explain that data is needed.
User Profile (cross-session)
Every generated Skill is connected to the shared user-profile/v1 contract in
skill.yaml. Read the shared user, brand, workspace, preferences, and this
Skill's skills.<skill_id> namespace at the start of every run. Keep the source
portable: resolved personal values belong in the shared profile, never here.
When the user directly states a durable preference or brand fact, persist it
through scripts/profile_store.py and report the saved profile path. Put
Skill-specific values under records.<field>; use brand.<field> or
user.<field> for shared values. Do not persist inferred secrets or credentials.
See references/user-profile.md for the complete contract.
Skill Group Composition
Read references/skill-composition.md before deciding whether to invoke or
extend any adjacent capability. The record distinguishes optional upstream and
downstream handoffs from embedded Kit modules. Do not silently depend on a
sibling Skill that is not shipped with this source.
Workflow (MANDATORY)
You MUST follow these steps in order.
Step 0: Resolve skill root, dependencies, and runtime context
- Use
SKILL_DIRif the environment provides it. - Otherwise infer the installed skill directory from the current skill context.
- Verify
scripts/chat_metrics.py,scripts/matrix_dataset.py,scripts/export_text.py,scripts/semantic_label.py,scripts/topic_composition.py,scripts/card_figures.py,scripts/verify_figures.py, and the four references exist before work. - If a required resource is missing, name its expected relative path and stop before producing a partial result.
When running scripts manually:
export SKILL_DIR="/path/to/lov-do-they-love-me"
Resolve context.profile on every invocation. The precedence is current request,
project context, Skill-specific profile records, shared preferences, shared
brand/user profile, then safe defaults. A direct user statement about a durable
preference or brand fact should be saved with scripts/profile_store.py record
using --confirm, followed by a concise saved-path report.
Step 1: Understand the requested outcome
- Clarify the target, time window, delivery surface (for yourself / to send to the other party / to send out) and language.
- Read
references/privacy-and-consent.md: this is a third party's private chat, and by default it is processed only on this machine. - First determine the reader and the judgment: which refutable judgment should this card answer? If you cannot write the judgment, go back to Step 3 to find evidence.
Step 1.5: Analyze nearby Skills before implementation
- Inspect related local and installed Skills by routing contract and concrete input/output, not by filename alone.
- Record upstream, core, downstream, overlap, and not-composed decisions in
references/skill-composition.md. - Keep sibling Skills optional and artifact-based. When stages require hard coupling for one outcome, create a self-contained Kit instead.
- This Skill's existing records are in
references/skill-composition.md: upstream islov-wdb-cli, downstream islov-mobile-infographic; unless the user changes the methodology, do not reinvent data extraction or layout.
Step 2: Execute the workflow
Execute the following five sections in order. Each section uses a file as its handoff; if it fails, stop at that section and explain what is missing.
2.1 Data extraction (hand to lov-wdb-cli)
Use the other party's nickname/remark to locate the unique contact, export the private chat within the time window as JSONL, and record the local account and the other party's account:
python3 "$WDB_SKILL/skills/wdb-query/scripts/wdb_cli.py" chats \
--contact "<昵称或备注>" --from <起> --to <止> --limit 5000 --format jsonl > messages.jsonl
First run stats to see the volume and per-day distribution, then decide the window. Record truncated and meta.errors;
do not write accounts, database paths, or table names on the card or in the report.
2.2 Quantification
python3 "$SKILL_DIR/scripts/chat_metrics.py" \
--messages messages.jsonl --me <本机账号> --other <对方账号> --out metrics.json
python3 "$SKILL_DIR/scripts/matrix_dataset.py" \
--messages messages.jsonl --me <本机账号> --other <对方账号> --out matrix.json
See references/chat-metrics.md。idx for detailed methodology; it is only an activity index, so state the weights clearly and do not call it emotion.
2.3 Semantic layering (fully local by default)
python3 "$SKILL_DIR/scripts/export_text.py" \
--messages messages.jsonl --me <本机账号> --other <对方账号> --out label_input.jsonl
python3 "$SKILL_DIR/scripts/semantic_label.py" \
--input label_input.jsonl --out labels.jsonl --model qwen3:8b --batch 20 --context 40
- See
references/semantic-taxonomy.md。 - for the taxonomy, decision order, and failure modes; the annotation isRule layer + model layerTwo levels: messages with no topic (system prompts, pure acknowledgements, pure emoji/numbers,
pure English fragments) are judged by the script according to rules,
other, and the rest are passed to the model together with the preceding context. The rule layer in this project covers 10% of messages and is fully correct on the calibration set;--context 0、--no-prerulesis used only for comparison. - Calibration must come first, then full annotation: manually annotate 40–60 items (including positive examples of both work and emotional categories, andnot overlapping with the prompt
examples) written as
gold.json, first runsemantic_label.py --input label_input.jsonl --eval-gold gold.json --report accuracy.json, and use this configuration'saccuracy.jsonas the conclusion threshold. - Thresholds: if overall agreement rate < 80%, do not output proportion conclusions; when work-category recall < 75%, the work proportion must be written as a lower bound; when emotional-category predicted positives are fewer than 5, the emotional proportion is written only as a "single-digit percentage". If below threshold but still to be delivered, the card's scope line must state "below threshold, proportions for reference only".
- The built-in default prompt uses onlysynthetic examples, containing no real chat sentences. Its measured performance on the project's built-in calibration set is agreement rate 77.1%, work-category recall 0.903: below the 80% threshold, so the default output proportions serve only as rough bands, and the card must state "below threshold, proportions for reference only". After switching to the user's own calibration set, rewrite the scope line according to the new results.
- Review the calibration set itself: correct the few annotations that conflict with the classification definition according to the definition, and record in the report what was changed.
- To switch to a stronger model (which would send chat content to an external provider), the user's explicit consent must first be obtained,
use
--backend remote --api-key-env <ENV>, and keys go only through environment variables.
python3 "$SKILL_DIR/scripts/topic_composition.py" \
--labels labels.jsonl --out composition.json --accuracy accuracy.json \
--weeks-start <第1周周一> --weeks <周数>
2.4 Image generation
python3 "$SKILL_DIR/scripts/card_figures.py" \
--matrix matrix.json --composition composition.json --metrics metrics.json \
--outdir figures --partner-label "<对方昵称>"
Obtain figure-matrix.svg、figure-composition.svg、figure-weekly.svg and card-data.json.
For the layout and injection positions, see references/card-blueprint.md。
2.5 Card creation (handed to lov-mobile-infographic)
Using this Skill's scaffold → author → render → audit process, inject the three SVGs into the corresponding blocks,
use "Love Index Analysis" as the title, write "Analysis subject: <nickname>" as the positioning label, and keep only one conclusion sentence on the whole card.
Step 3: Validate the deliverable
- Machine audit:
lov-mobile-infographicofaudit --strict --human-review passed。 - Geometry review:
python3 "$SKILL_DIR/scripts/verify_figures.py" --card card.html --out verify.json(SVG label overlap, overflow, going outside the canvas, being clipped by its own viewBox). Titles and axis labels on the image must be read back and confirmed one by one. - Scope review: every number has a unit, denominator, and period; semantic proportions must give both the model and the agreement rate; the rule that "work does not count as emotional" must be visible on the card.
- Privacy review: the card and report contain no account, database path, table name, real name, or contact information; quotes are truncated and phone numbers/addresses/ID numbers are removed.
- Finally, read back the PNG (original size + 320px thumbnail) and record the specific findings, then deliver.
- Validate
skill-card.yaml,cases/cases.json, andpricing-card.yamlas the standard trust bundle for this Skill.
Dependencies
- Python 3.9+ standard library (
chat_metrics、matrix_dataset、export_text、topic_composition、card_figuresno third-party packages needed). - Playwright for Python(
verify_figures, as well as downstream card rendering and auditing). - Local Ollama (default semantic annotation backend, example model
qwen3:8b); if not installed, must stop and explain, do not silently switch to an external API. - Upstream
lov-wdb-cli(data retrieval) and downstreamlov-mobile-infographic(card creation) are both optional handoffs, not hidden dependencies: when they are missing, intermediate conclusions such asmetrics.json/composition.jsoncan still be delivered.
Validation
python3 "$SKILL_DIR/scripts/chat_metrics.py" --help
python3 "$SKILL_DIR/scripts/semantic_label.py" --help
python3 "$SKILL_DIR/scripts/verify_figures.py" --card <card.html>
python3 scripts/validate_skill.py .
Runtime context (shared)
Before running, read this Skill package's skill.yaml, provided by the host skill-runtime/v1 Context. Field resolution order: current request, project context, Skill-specific records, personal Preferences, brand/user Profile, general defaults.
- Use only fields declared in the Manifest; Profile stores shared user and brand information,
skills.lov-do-they-love-me.recordsstores persistent records for this Skill. - Long-term preferences or brand facts stated directly by the user are written back atomically to the Profile via
scripts/profile_store.py, and the save path is reported in the result. required: trueWhen a field is missing, ask the user one focused question according to the Manifest's question configuration.- Errors provide a copyable
context_id, field path, and source; diagnostic content avoids secrets, full private paths, and raw configuration.
General feedback loop
When the user raises modification feedback during a Skill-driven task, before continuing the current artifact you must perform:
- First determine whether the feedback is
task-specific(this time only) orreusable(reusable across tasks). task-specificModify only the current task, do not change the Skill.reusableFirst determine the scope: for domain rules, update the corresponding canonical Skill first; for rules that apply to all Skills, update the shared specification first.- After completing rule updates, versioning, lint, and distribution verification, then apply the modifications to the current task.
reusableModifications invalidate previous "confirm," "continue," and "send it"; after completing the current artifact modification and reading it back, you must stop and wait for the user's next instruction, without automatically proceeding to publishing, submission, or other external writes.