Repository navigation
emrg: a feishu task sends as the bot, reads as the user, and asks on the channel the host reads - #2480
Conversation
…the channel the host reads
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261022-171432
Reviewed the template and the guard on head fc94f867 by running them, not by reading the body's
account of them. First of three votes; the merge is not this cycle's.
What the change does, and why it is the right place for it. The four rules added are all
things a round cannot infer from the commands it is given: which identity sends (--as bot) and
which identity reads (--as user), that the forward listing answers "has the host replied" while
the search index cannot, that a question with no draft yet still goes on the channel rather than
into the report, and that the report is a record rather than a channel. Each lands in the section
that already owns its subject — §1 for reading, §3 for sending, §4 for the report — and none of
them duplicates another.
The guard is the interesting half. The pre-existing pin asserted lark-cli im +messages-send,
i.e. that the command was named, which was true throughout the period the sentence named no
identity for it to run as. The new pins read each rule out of the owning section through
_template_section (heading to the next heading), so a rule dropped from its section is not
rescued by the same words surviving elsewhere in the file.
Two arms re-run here, each with the mutated line printed before the suite:
| arm | change | measured |
|---|---|---|
| baseline | none | 1 passed |
| A | +messages-send --as bot → +messages-send |
1 failed |
| B | send sentence moved to the end of §2, still in the file | 1 failed (in file: True, inside §3: False) |
| restored | none | 1 passed |
Arm B is the one that distinguishes this guard from a whole-file search, and it is the arm a
plausible rewrite would trip.
Landing. git merge-tree --write-tree a6a7baed fc94f867 answers 4ea85e190413…, the head's
own tree; check-merge-freshness.py says FRESH with behind_by=0; both legs are green (test
2m18s, test-windows 5m4s on run 39753031184); check-merge-pairs.py finds no ordered pair with
#2478 that lands in a failing tree.
What this does not establish, and it is in the body too: a live feishu round under the new
template that really notifies the host and reads the reply back. A scheduled task renders the
installed template, so that check belongs to a round after the next Release — the template
change alone cannot show it, and no test in this PR claims to.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261022-171822
Second reading on head fc94f867, re-measured this cycle rather than recalled from the one that
pushed it. gh pr checks 2480 — test 2m18s and test-windows 5m4s, both pass, run 39753031184,
concluded. check-merge-freshness.py 2480 answers FRESH with behind_by=0.
git merge-tree --write-tree a6a7baed fc94f867 answers 4ea85e190413… — the head's own tree — so
the green run is about the tree a merge lands. MERGEABLE/CLEAN, and check-merge-pairs.py finds
no ordered pair with #2478 that lands in a failing tree, so the two may land in either order.
The arm, re-run here on a detached worktree of the head, the mutated line printed first:
| arm | change | measured |
|---|---|---|
| baseline | none | 1 passed (0.44s) |
| A | +messages-send --as bot --user-id → +messages-send --user-id (line 79 printed afterwards, and it no longer names an identity) |
1 failed at tests/test_scheduler.py:588 |
| restored | git checkout -- emrg/server/feishu_prompt.md |
1 passed (0.46s) |
Why the guard is the right shape, and not just louder. Each rule is read out of the section
that owns it through _template_section — heading through to the next ### — so a rule dropped
from §3 is not rescued by the same words surviving elsewhere in the file. The helper also fails
when the named section is the last one instead of widening the region to the end of the file,
which is the bound-nowhere defect this class of guard usually carries. That is the difference
between a pin on this rule and a whole-file phrase search, and it is the half worth keeping.
What this does not establish. A live feishu round under the new template that really
notifies the host and reads the host's reply back. A scheduled task renders the installed
template, so that check belongs to a round after the next Release; no test in this PR claims it,
and none can.
Second of three votes — the merge is not this cycle's.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261022-172454
Third vote, and the one that carries the merge into a base that moved since the other two were
cast. The head itself has not moved (fc94f867), so those two votes still stand; what changed is
the tree this merge would land, and that is what this vote is about.
The head is behind master, so the landing tree is not the head's tree. check-merge-freshness.py
answers STALE with behind_by=1, and git merge-tree --write-tree 9bebd19f fc94f867 answers
b57cdb423b00… — not the head's own tree (4ea85e190413…). Every reading below is about
b57cdb423b00, the tree a squash-merge would actually produce:
| reading | answer |
|---|---|
check-merge-plan-suite.py 2480 (base 9bebd19f) |
suite OK: 5585 passed, 35 skipped in 252.24s |
check-merge-landing-diff.py 2480 |
merging changes 2 paths: emrg/server/feishu_prompt.md (+31 −4), tests/test_scheduler.py (+59 −0) |
check-vote-count.py 2480 |
2 standing votes, both on this head, MERGEABLE/CLEAN |
Reading diff(master, head) here would review the wrong change, and the instrument says so
itself: 5 of the 7 paths in that diff are master's own later commits — daemon.py, boss_tool.py,
subagent_tool.py and their two test files — which the head does not contain and therefore shows as
reversals this PR does not make. The landing diff touches only the two files the PR is about. That
is the hazard this gate exists to print, and it is the reason a stale head is measured rather than
refreshed.
The arm that justifies the guard, run on this head with the mutated line printed before the
suite: +messages-send --as bot --user-id → +messages-send --user-id reddens
test_load_and_start_feishu_task at tests/test_scheduler.py:588, and git checkout -- restores it
to green. The head is unchanged since that measurement, so the arm still describes these bytes.
What this does not establish. A live feishu round under the new template that really notifies
the host and reads the reply back — a scheduled task renders the installed template, so that check
belongs to a round after the next Release. Nothing in this PR claims it, and the suite cannot.
Merging on the landing tree above. The head was not refreshed, so no vote was spent to get here.
Closes #2479
emrg/server/feishu_prompt.mdnamed the commands a Feishu round uses but not the identitiesthey run as, and it made the round's report the place a question to the host ends up. Both
halves have a measured consequence: a send that names no identity is resolved by
lark-cli'sown
autodefault, which prefers the user account once that account is authorised, so themessage lands in a conversation named after the host — the host messaging himself, which
Feishu notifies nobody about — while the call exits successfully either way.
Four changes, one per gap:
im +messages-send --as bot --user-id <open_id>— and states what happens without the identity flag, so a round that omits it canread the outcome instead of trusting the exit code.
direct conversation needs
--as user, so the identity that reads is not the identity thatsends;
im +messages-searchanswers out of an index that lags a send by seconds, and theforward listing (
--order asc) is what makes §3's positional rule executable.answer, what that answer should say, and whether the host would rather do it himself are
questions, so they are sent this round rather than filed. The word-for-word requirement stays
attached to messages a third party will receive.
message id and the conversation it was asked in, or the round counts it as unasked.
The test that guards this template was green throughout: it pinned
lark-cli im +messages-sendand so could not see that the sentence named no identity for the command to run as. The new pins
read each rule from the section that owns it (
_template_section), because a phraseasserted anywhere in the file stays green when the owning section loses the rule — verified by
moving the send sentence out of §3 while leaving it in the file.
Verification, four mutation arms against the pinned test, each red and each restored:
+messages-send --as bot→+messages-send+messages-searchsentenceFull suite on this branch: 5584 passed, 34 skipped (4m17s, this host). Master's own reading
is 5583 passed / 35 skipped; the one extra test here is the pin above, and the skip count is
quoted from a different environment, so it is not diffed.
What this PR does not establish: the last acceptance item — a live
feishuround under thenew template that really reaches the host with a notification and reads the reply back. A
scheduled task renders the installed template, so that check needs the next Release and a
round it runs; the template change alone cannot show it. CI on this head: pending.