feat(procevent): add Discord mention watch adapter for Firstcrew channel - #81
Merged
Merged
Conversation
…re reaching cursor
…ce=bin/fm-discord-lib.sh` directive before `source "$SCRIPT_DIR/fm-discord-lib.sh"` in bin/fm-procevent-discord-mention.sh:11, causing SC1091 "does not exist" since ShellCheck could not resolve path without hint (sibling scripts fm-discord-poll.sh, fm-discord-notify.sh, etc. all carry this directive). Behavior portable serial 3 failed because docs/plans/discord-mention-watch-adapter-20261002.md (added in PR) was tracked but missing from docs/documentation-audiences.json, failing tests/fm-documentation-audiences.test.sh's completeness check; classified it maintainer-architecture, matching sibling internal decision docs. Verified: shellcheck clean on changed file, fm-documentation-audiences.test.sh, fm-vendor-auth-probe.test.sh, fm-harness-adapter-references.test.sh, and fm-procevent-discord-mention.test.sh all pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Add a Firstmate process-event adapter that wakes on human mentions of the Claude bot in the Firstcrew Discord channel, with approved channel-only scope and durable capture.
What Changed
bin/fm-procevent-discord-mention.pyandbin/fm-procevent-discord-mention.sh, a process-event adapter that polls the approved Firstcrew Discord channel and durably captures human mentions of the Claude bot.bin/fm-watch.shand document the adapter's config indocs/configuration.md.tests/fm-procevent-discord-mention.test.shcovering the adapter, and record the design indocs/plans/discord-mention-watch-adapter-20261002.md.Risk Assessment
✅ Low: Both prior rounds' fixes (terminal PollError on pagination-cap-exceeded in Python, and matching shell classifier entry) are correctly and minimally applied; pagination control flow traced and sound; remaining diff (fm-watch.sh ensure hook, docs, tests) is consistent with existing sibling adapter patterns and exercises real adapter behavior rather than source-text matching.
Testing
Built disposable FM_HOME/state under /tmp, ran the Python adapter in its built-in FM_DISCORD_TEST_MODE fixture mode and the shell wrapper's classify/terminal subcommands directly against produced result files; both review-round fixes (PollError pagination-cap-exceeded raised before the cursor silently advances, and the shell terminal classifier retiring the source on that error) verified live, plus happy-path mention capture and classifier regressions on missing-token/http-429 all passed. Lab directory removed after capturing evidence; worktree left clean.
bin/fm-procevent-discord-mention.sh terminal result_cap_exceeded.jsonexits 0 (terminal=yes)bin/fm-procevent-discord-mention.sh terminal result_missing_token.jsonexits 0bin/fm-procevent-discord-mention.sh terminal result_429.jsonexits nonzeroEvidence: pagination-cap-exceeded poll result
Source: pagination-cap-exceeded poll result
Evidence: mention happy-path result
Source: mention happy-path result
Evidence: missing-token terminal regression result
Source: missing-token terminal regression result
Evidence: http-429 non-terminal regression result
Source: http-429 non-terminal regression result
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed (2) ✅
bin/fm-procevent-discord-mention.py:142- new_messages() walks backward viabeforeuntiloldest <= cursoror a short page signals end-of-history, but it also stops whenpageshits MAX_PAGES (100 pages × 100 msgs = 10,000 messages) without ever reaching the cursor. In that case the returned batch does not actually cover (cursor, oldest_fetched]; poll() (line ~223:cursor = message_id(messages[-1])) then advances the checkpoint straight to the newest fetched id regardless, so any genuine bot mention sitting in the unfetched gap between the old cursor andoldest_fetchedis permanently skipped with no error or trace — next poll starts from the new, higher cursor and never looks back. Concrete trigger: the watcher is down (or the channel sees a burst) long enough that more than ~10,000 messages accumulate since the last successful checkpoint; a mention inside that backlog never surfaces. The fix is mechanical and local to this function (e.g. raise a terminal PollError, mirroring the existingpagination-did-not-advancecase, when the MAX_PAGES cap is hit withoutoldest <= cursor, instead of silently trusting the batch as complete) and does not require new state or a new subsystem.🔧 Fix applied.
1 error still open:
bin/fm-procevent-discord-mention.sh:85- Fix round d9f2e77 added a new python-side terminal PollError codepagination-cap-exceeded(bin/fm-procevent-discord-mention.py:157) to close the prior finding's silent-skip gap, but did not add that code to this shell script'sterminalsubcommand jq allowlist (line 85), which is the separate classifier fm-procevent.sh:336 (adapter_result_is_terminal) uses to decide whether to retire the registered source after a captured poll-error result. Concrete sequence: the watcher accumulates a 10,000+ message backlog, new_messages() raisespagination-cap-exceeded(terminal=True in Python), poll() emits apoll-errorresult immediately — but fm-procevent.sh's jq check at line 85 does not matchpagination-cap-exceeded, soadapter_result_is_terminalreturns false, the source is NOT retired, and it stays armed. Every subsequent reconcile cycle re-polls from the same stuck, never-advanced cursor, reproduces the identical cap-exceeded error, and is captured again — forever — without ever reaching the captain-relevant terminal-retirement path thatmissing-token,invalid-cursor,pagination-did-not-advance, etc. all get. This defeats the purpose of the fix (surfacing the gap so it gets human attention) and leaves the adapter silently looping on a known-bad state. Minimal remedy: add.error == "pagination-cap-exceeded"to the jq condition at line 85, mirroring the existingpagination-did-not-advanceentry; mechanical, no new state or subsystem required.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bin/fm-procevent-discord-mention.sh terminal result_cap_exceeded.jsonexits 0 (terminal=yes)bin/fm-procevent-discord-mention.sh terminal result_missing_token.jsonexits 0bin/fm-procevent-discord-mention.sh terminal result_429.jsonexits nonzeropython3 bin/fm-procevent-discord-mention.py (FM_DISCORD_TEST_MODE=1, 10200-message fixture) -> poll-error/pagination-cap-exceededbin/fm-procevent-discord-mention.sh terminal <result> on pagination-cap-exceeded resultbin/fm-procevent-discord-mention.sh classify <result> on pagination-cap-exceeded resultpython3 bin/fm-procevent-discord-mention.py (fixture with bot mention) -> status mentionbin/fm-procevent-discord-mention.sh terminal on missing-token result (regression)bin/fm-procevent-discord-mention.sh terminal on http-429 result (regression, expect non-terminal)✅ **Document** - passed
✅ No issues found.
🔧 **Lint** - 1 issue found → auto-fixed ✅
🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Push** - passed
✅ No issues found.