Skip to content

Add lesson: NPC dispatch and speaker/location disambiguation in roleplay - #1749

Open
huiyuansun28-cmyk wants to merge 1 commit into
Ikalus1988:mainfrom
huiyuansun28-cmyk:lesson-npc-dispatch-speaker-disambiguation
Open

huiyuansun28-cmyk wants to merge 1 commit into
Ikalus1988:mainfrom
huiyuansun28-cmyk:lesson-npc-dispatch-speaker-disambiguation

Conversation

@huiyuansun28-cmyk

Copy link
Copy Markdown

Closes bounty #1655. Converts intake #1643 into comprehensive lesson on narrative consistency:

  1. NPC dispatch and external P.O.V. generalization
  2. active_speaker preservation across dispatch
  3. Spatial unity constraints in speaker resolution
  4. Multi-location scene handling

Includes code examples, verification tests, and edge case analysis.

/claim #1655

Generated by AUTO (AI Agent)

@opirebot

opirebot Bot commented Sep 16, 2026

Copy link
Copy Markdown

😅 Ups... the issue does not have any reward yet!

@github-actions

Copy link
Copy Markdown
Contributor

Welcome to MisakaNet!

Thanks for your first PR!

🔏 Fix DCO First

Some commits are missing Signed-off-by:. Fix and force-push:

git commit --amend --signoff --no-edit   # latest commit
git push --force-with-lease

For several commits: git rebase --signoff HEAD~N && git push --force-with-lease

CI re-scans on every push (including force-pushes). Once all commits are signed, the needs-dco label auto-clears — do NOT push an empty commit.

⏳ First PR: CI waits for one-time maintainer approval

On your first PR from a fork, GitHub requires a maintainer to approve
workflow runs before CI can start (a safety gate). Until then checks may show
as waiting / greythat is expected, not a problem with your PR.
A maintainer usually approves within a day; after that, CI runs automatically
on every push (including force-pushes).

If you see a red needs-dco label or DCO check, fix it now so your PR is
already green once CI is approved (see above — the label auto-clears after
you amend + force-push; no empty commit needed).

Quick Links

Optional: Local Pre-commit Hook

For instant DCO validation before pushing:

pip install pre-commit
pre-commit install --hook-type commit-msg

For Agents & Crawlers

Found a missing lesson? Submit via MCP (no account needed):

curl -sS https://misakanet.org/mcp \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2025-06-18' \
  -H 'Origin: https://misakanet.org' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"misakanet_submit_intake","arguments":{"problem":"YOUR PROBLEM","source":"your-agent"}}}'

After the one-time approval, CI checks run automatically on every push.

@Ikalus1988

Copy link
Copy Markdown
Owner

Thanks — the lesson itself looks good, and this is the last mile. Two mechanical things block it, both small:

1. DCO (this is the red check). Every commit needs a Signed-off-by: trailer; the check's only readable annotation is DCO audit failed.

git rebase --signoff main
git push --force-with-lease

2. Provenance. The file cites no source at all today. That is allowed — an honest "no external source" is better than a link that looks checkable. But there is now a gate for exactly this (docs/maintainer/provenance-gate-2026-09-16.md, landing in #1768), and it works like this:

  • a source: URL must resolve — placeholders (<owner>, TODO) and confirmed 404s fail the build;
  • if you claim evidence_level: E2/E3, you need at least one resolvable source;
  • if this came from your own work with no public link, just say so in the lesson (or drop evidence_level) and the gate is happy.

Reason it matters: four PRs last week passed 24/24 checks while citing github.com/modelcontextprotocol/mcp-memory-service/issues/1652, a repository that does not exist. The gate is the automated replacement for a human reading every PR, so it only asks for a line that a reader can actually follow.

Ping me if the rebase fights you — happy to sort it out.

@Ikalus1988

Copy link
Copy Markdown
Owner

/fix-dco

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Auto-fix not available for fork PRs.

Since this PR is from a fork, the bot can't push changes directly. Please fix DCO manually:

git rebase --signoff HEAD~N   # N = number of commits to fix
git push --force

Or for the latest commit only:

git commit --amend --signoff --no-edit
git push --force

@Ikalus1988

Copy link
Copy Markdown
Owner

Correction to my comment above, and good news: you do not need to rebase locally. This repository has a DCO auto-fix workflow — a /fix-dco comment from the PR author or a maintainer adds the Signed-off-by: trailer for you. I have just triggered it on this PR. Sorry for the extra homework.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Auto-fix not available for fork PRs.

Since this PR is from a fork, the bot can't push changes directly. Please fix DCO manually:

git rebase --signoff HEAD~N   # N = number of commits to fix
git push --force

Or for the latest commit only:

git commit --amend --signoff --no-edit
git push --force

@Ikalus1988

Copy link
Copy Markdown
Owner

Sorry — I have to walk my last comment back. I said you would not need to rebase because this repository has a /fix-dco bot. I triggered it here and read the logs: the workflow runs but stops at a step literally named "Handle fork PR — manual instructions only" — with the default GITHUB_TOKEN it cannot push to a fork, so for fork PRs the manual signoff is the only path. My original instruction stands:

git rebase --signoff main
git push --force-with-lease

That is the only thing standing between this lesson and main; thanks for your patience with my detour.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Auto-fix not available for fork PRs.

Since this PR is from a fork, the bot can't push changes directly. Please fix DCO manually:

git rebase --signoff HEAD~N   # N = number of commits to fix
git push --force

Or for the latest commit only:

git commit --amend --signoff --no-edit
git push --force

@Ikalus1988

Copy link
Copy Markdown
Owner

The blocker is the frontmatter, not (only) DCO — and the template is what is at fault

First, the correction you are owed: this is our bug, not yours.

lessons/TEMPLATE.md shipped a frontmatter block that no parser can read — four YAML keys followed by a legacy JSON line on its own row. In YAML that JSON object is a key with no value, so the whole block fails to parse, lesson_gate ends up with an empty dict, and it reports missing required field: title, domain, tags, status for values that are plainly there in your file. That misleading message is why I told you DCO was the only thing left. It was not. (Template fixed in #1796.)

Your file still carries the template's fingerprints — verification: "metadata-normalized" plus the JSON row — so gate fails on structure for all five of these PRs, and it would still fail after a DCO-only fix.

Three things to change:

  1. Make the block one valid mapping. Delete the JSON row and fold its fields into the YAML — the block below does exactly that with your values.
  2. domain must be a topic from data/domains.json. narrative-consistency is not one of the 46 (that is the domain 计数三种口径并存(18 / 69 / 61):定口径、归一规则与门禁 #1687 vocabulary); for this lesson roleplay-engine is the right one.
  3. evidence_level is required, and summary_plain / trigger / verify are required for new lessons ([Schema] 课程结构化字段:summary_plain(大白话)+ trigger + verify #1783). The three drafts below are literal suggestions — please rewrite them in your own words, summary_plain especially, since it is meant to be repeated verbatim to a non-technical reader.
---
domain: "roleplay-engine"
title: "NPC Dispatch and Indirect Mention: Speaker/Location Disambiguation in Roleplay"
tags:
  - "roleplay"
  - "npc"
  - "speaker-tracking"
  - "spatial-consistency"
  - "pov"
  - "narrative"
status: "published"
evidence_level: "E2"
provenance:
  issue: "#1643"
summary_plain: "An NPC that is dispatched, or only mentioned indirectly, ends up with the wrong speaker and the wrong location."
trigger: "npc dispatch indirect mention speaker location disambiguation roleplay"
verify: "Replay a scripted run containing a dispatch and an indirect mention; every line's speaker and location matches the script"
---

Verified, not asserted. I put that block on top of your file and ran today's gates:

$ python3 scripts/lesson_gate.py lessons/contrib/npc-dispatch-speaker-location-disambiguation.md
OK: 1 file(s) passed the lesson quality gate.
$ python3 scripts/check_provenance.py --check lessons/contrib/npc-dispatch-speaker-location-disambiguation.md
检查 1 篇课程,引用 0 条外链:none=1          # exit 0

There is also a non-blocking advisory from the provenance gate's tier 2 (evidence_level: E2 with no resolvable URLprovenance.issue is the sanctioned form for an intake-sourced lesson, so you can leave it; adding a public repro link would clear the advisory).

After that, only the DCO trailer is left:

git rebase --signoff main
git push --force-with-lease

And if rewriting the commit is a hassle, just say so here — a maintainer can land it for you with the trailer added, keeping you as the author. Sorry again for the detour; the broken template was ours to fix.

@Ikalus1988

Copy link
Copy Markdown
Owner

Two things stand between this lesson and main, and I checked both by running the repository's own
gates against your file rather than by reading the red X:

1. The frontmatter block does not parse. python3 scripts/lesson_gate.py <your file> reports:

FAIL …
  - missing required field: title
  - missing required field: domain
  - missing required field: tags

The cause is visible in the first line of the file: the YAML keys are followed by a raw JSON line
inside the same block:

---
domain: "llm-integration"
title: ""
status: "draft"
verification: "metadata-normalized"
{"title": "…", "domain": "…", "tags": [...], …}   <-- this line makes the whole block parse as nothing
---

Because of that line the parser sees no frontmatter at all, so a title that is right there reads as
missing (the same trap lessons/TEMPLATE.md warns about). Delete the JSON line and put its values into
the YAML keys instead; new lessons also need the three structured fields the corpus indexes by:

---
domain: "llm-integration"          # must be a value from data/domains.json
title: "… (4-120 chars)"
tags: ["gemini", "model-id", "naming-convention"]   # 1-10, each >= 2 chars, unique
status: "published"
evidence_level: "E0"               # E0 until a maintainer promotes it
summary_plain: "one plain sentence, <= 120 chars"
trigger: "the error fragment an agent would search for, <= 160 chars"
verify: "a checkable pass/fail criterion, <= 200 chars"
---

2. The commits are not signed off. The dco check fails because the commit(s) carry no
Signed-off-by: trailer. Fix with:

git commit --amend -s            # for the last commit
git rebase --signoff main        # for a branch whose commits predate the trailer
git push --force-with-lease

Signed-off-by: Your Name <you@example.com> — the name and address must be real, and it means you
certify you wrote or may submit the change (DCO). After that, pushing runs the gates again and I will
take another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:docs area:lessons lessons-only needs-dco Missing Signed-off-by in commit needs-human-review Content needs maintainer judgment (real experience, root cause quality) shape-safe

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants