Repository navigation
feat: allow Firstmate to retitle Discord topic threads - #259
Merged
Merged
Conversation
A thread's base name was fixed by the reply that created it, so a topic that drifted from the first message kept a stale name. bin/fm-ext-emit.sh now takes --thread-retitle, and bin/fm-ext-ask.sh passes it through, so any reply into an existing Firstmate-created topic thread can rename it. The new title passes the same screen and bounds as a creating title and becomes the thread's stored base name, keeping whatever ❓ / ✅ marker the thread wears, so every later marker, auto-clear, and reconciliation builds on the new name. A plain later --thread-title still replaces nothing. The retitle cannot ride the reply that creates the thread. The poster screens the retitle again before recording it and keeps marker eligibility: only a thread this home created in the dedicated channel, never a captain-made thread, another channel, a DM, or an aged-out record. It stays best effort, so a refused, unusable, or ineligible retitle never blocks the reply text, and a failed rename is retried by the next reply and the periodic sweep. Post-merge deployment note: restart the hermes-gateway-fmcomms user unit so the gateway poster runs the new outbox_poster.py. Tests: tests/fm-ext-topic-threads.test.sh gains retitle coverage (rename, marker preservation, later markers, screen refusals, ineligible threads, retry, opened threads) and tests/fm-ext-ask.test.sh covers the ask passthrough.
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
Let Firstmate rename a Discord topic thread's base name after creation, so the name can follow the conversation when it drifts from the first message.
Captain (chat, 18 Oct 2026): "i want a full rename from firstmate based on the conversation. the conversation might have changed from the beginning of the thread."
Change:
bin/fm-ext-emit.sh --thread-retitle "<Project> · <topic>"on any reply into an existing Firstmate-created topic thread. A plain later--thread-titlekeeps its current no-replace meaning..agents/skills/ext-respond/SKILL.md: one short rule for when Firstmate retitles - when the thread's live topic has clearly moved on from its name (Firstmate judges from the conversation), retitle on its next reply as " · "; not on every reply.docs/configuration.md"Topic threads": replace the "later titles do not replace" / "preserve the original base name" wording with the new contract.bin/fm-ext-emit.shheader/help and the shared title screen's owner (bin/fm-ext-topic.sh) describe the new behaviour consistently.Acceptance criteria:
docs/configuration.mdTopic threads,bin/fm-ext-emit.shheader/help, and theext-respondskill describe the new behaviour consistently, with no leftover "later titles do not replace its name" / "preserve the original base name" wording.hermes-gateway-fmcommsuser unit must be restarted after merge for the poster change to take effect.Evidence constraints accepted with firstmate:
What Changed
--thread-retitleto replies and choice posts for existing Firstmate-created Discord topic threads, preserving the current marker and storing the new base for later markers and reconciliation.hermes-gateway-fmcommsuser unit after merge for the poster change to take effect.Risk Assessment
✅ Low: The retitle change is bounded, preserves existing eligibility and retry behavior, and the prior findings are resolved without substantiated new defects.
Testing
Both focused suites, isolated CLI checks, and supplemental HTTP simulation passed. No Discord screenshot was possible without authorized sandbox access. Full-suite and CI validation remain with the outer executor.
Evidence: Real CLI: title screening, warnings, and persisted replies
Evidence: Real choice CLI: retitle passthrough and rejection
Evidence: Supplemental HTTP simulation—NOT live Discord evidence
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 3 issues found → auto-fixed ✅
bin/fm-ext-emit.sh:161- AC2 requires that titles failing the shared screen be refused or ignored safely while “the reply text still posts.” This hunk instead uses|| die, so a safe reply carrying a 61-character or multiline retitle exits before publication. The ask passthrough inherits this at bin/fm-ext-ask.sh:193, and tests/fm-ext-topic-threads.test.sh:1944 explicitly asserts that nothing queues. Ignore the rejected retitle and continue publishing the reply; update those assertions to match AC2.contrib/hermes-gateway-firstmate-comms/outbox_poster.py:1168- AC1 requires retitling while “keeping any current marker prefix,” but this hunk selectsrecorded.get("thread_state")rather than the marker Discord currently shows. If a captain manually clears ❓ before the next retitle-only reply, the retitle restores ❓. The read in apply_thread_state only runs when the entire wanted name already equals the stored name, so it cannot correct this case. Preserve the live marker for retitle-only operations, with a safe fallback when the live name cannot be read.bin/fm-ext-emit.sh:158- Simplification: the unconditional mutual-exclusion branch rejects both flags even for an existing thread, although the intent only requires plain later --thread-title to retain its no-replace meaning. No requirement needs this additional rejection path. Remove the prohibition and let the explicit retitle determine the existing thread's new base. Also remove the corresponding restriction in bin/fm-ext-emit.sh:25 and rejection assertion at tests/fm-ext-topic-threads.test.sh:1947.🔧 Fix applied.
✅ Re-checked - no issues remain.
TMPDIR="$PWD/.test-phase/tmp" bash tests/fm-ext-topic-threads.test.sh— passed.TMPDIR="$PWD/.test-phase/tmp" bash tests/fm-ext-ask.test.sh— passed.python3 .test-phase/drive.py— drove real intake/emit commands against an isolated home and checked persisted payloads and warnings.python3 .test-phase/ask-drive.py— drove real ask commands with real tasks-axi and an isolated backlog.PYTHONDONTWRITEBYTECODE=1 python3 .test-phase/http-drive.py— exercised real poster HTTP transport against a disposable Discord simulator.Reviewed emitted CLI help and changed documentation/skill contracts for consistency.Removed disposable homes, scripts, temporary data, and generated Python caches; verified cleangit status --short.✅ **Document** - passed
✅ No issues found.
🔧 **Lint** - 1 issue found → auto-fixed ✅
🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Push** - passed
✅ No issues found.