Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion emrg/server/open_source_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ Claimed by someone else, or closed → back to §2 with that reading; this cycle

**A take-up is a comment, so a comment is where to look for one.** This task claims an issue by saying so on the issue (§1.1, §3.2.1) — the ordinary convention for a contributor who cannot assign themselves, and the one this prompt instructs. None of that reaches `assignees`, so an issue with no assignee and a take-up comment in its thread is **taken**, and a check that read only the assignee list would start work someone else already has. A take-up older than the issue's last activity is still a take-up: ask on the issue before assuming it was abandoned, because the cost of asking is a comment and the cost of assuming is duplicated work.

**A large change is discussed before it is built**: when the contribution is bigger than a fix — a new feature, an API change, a refactor — say what you intend on the issue (or open one) and wait for a maintainer's word. A PR nobody asked for, on a direction nobody agreed to, is the one that gets closed.
**A large change is discussed before it is built**: when the contribution is bigger than a fix — a new feature, an API change, a refactor — say what you intend on the issue (or open one), then **carry on with the rest of this cycle without waiting for a reply**. A cycle is one run: nothing suspends it, and nothing resumes it when the answer lands, so a cycle that waits has spent itself on an answer written tomorrow. Record the question under §4 item 4, so the next cycle reads the answer from that issue's thread (§3.1.1) and inherits the block as state instead of asking again. Asking is neither waiting nor building — a PR nobody asked for, on a direction nobody agreed to, is the one that gets closed.

##### 3.1.2 Rant-driven mode (the host's work order)

Expand Down
45 changes: 45 additions & 0 deletions tests/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1493,6 +1493,51 @@ def test_open_source_entry_check_reads_the_claim_thread():
assert "say so on the issue itself" in out, "§1.1 的留言认领规则仍在"


def test_open_source_large_change_asks_without_waiting_for_a_reply():
"""§3.1.1 raises a large change as a step, never as a wait (issue #2728).

A cycle is one scheduled run: nothing suspends it and nothing resumes it when a reply
lands, so "wait for a maintainer's word" had no executable meaning. Followed literally
it ended in one of two ways — a cycle idling on an answer that arrives tomorrow, or the
question asked with nothing recorded, so the next cycle could not tell "raised, awaiting"
from "nothing done" and asked again. `feishu_prompt.md` states the shape a run can
execute ("carry on … without waiting"); this pins the sibling template to the same rule.

Both directions, over a subject the test first shows to be there: the replacement
renders, **and** the phrase it replaced is gone — a fix that added the new sentence
beside the old one would leave both instructions standing.
"""
import jinja2

template_path = (
Path(__file__).resolve().parent.parent
/ "emrg" / "server" / "open_source_prompt.md"
)
env = jinja2.Environment(undefined=jinja2.Undefined)
template = env.from_string(template_path.read_text(encoding="utf-8"))
out = template.render(
instance_id="test", host_name="host", repo_url="https://github.com/x/y.git", owner="x", repo="y",
local_source="/tmp/os", source_dir="/tmp/os", session_id="s1",
timestamp="20260824",
task={"role": "committer", "agent": "aitokenpool"},
agent={}, git_path="git", gh_path="gh",
)
# 0) the subject is there at all — a template that failed to render past this point must
# not be read as "the forbidden phrase is absent"
assert "A large change is discussed before it is built" in out, "大幅度改动须先讨论"
# 1) what the cycle does instead of waiting
assert "carry on with the rest of this cycle without waiting for a reply" in out, \
"提问不得阻塞本轮:一轮只有一次运行,等待的答案不可能在本次运行内到达"
# 2) where the question is kept, so the next cycle inherits it as state
assert "Record the question under §4 item 4" in out, "未答复的提问须记入 §4 第 4 项"
# 3) and the instruction it replaces is gone — not merely accompanied
assert "wait for a maintainer's word" not in out, "不得保留『等待维护者回复』"
# 4) the rule the ask protects survives the rewrite: an uninvited PR is still the one
# that gets closed, so "do not wait" cannot be read as "do not ask"
assert "a PR nobody asked for, on a direction nobody agreed to, is the one that gets closed" in out, \
"先问后做的实质规则须保留"


def test_open_source_template_empty_recon_names_the_extension_surface():
"""§2's empty-Recon sentence counts §1.6 among the readings that showed nothing (issue #2371).

Expand Down
Loading