Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ac23254
Create maintain-docs.md
BillChirico Mar 4, 2026
d13361c
refactor(web): replace channel/role ID inputs with selectors (#242)
BillChirico Mar 5, 2026
25e73d3
Refactor dashboard config-editor into maintainable section architectu…
BillChirico Mar 5, 2026
20de28e
refactor(ai): rewrite triage prompts and add channel context
AnExiledDev Mar 5, 2026
3cdf10e
📝 Add docstrings to `refactor/triage-prompt-rewrite`
coderabbitai[bot] Mar 5, 2026
4779199
fix(triage): escape channel metadata, fix @mention precedence, clarif…
Mar 7, 2026
850bd7a
docs: fix maintain-docs.md — add heading, fix hardcoded branch date, …
Mar 7, 2026
ef9478b
fix(types): alertChannelId nullable, moderationLogChannel nullable, G…
Mar 7, 2026
ce862b6
refactor(dashboard): extract shared inputClasses, update config-edito…
Mar 7, 2026
78cbe0b
fix(dashboard): mobile grids, threshold guard, role identity, aria-la…
Mar 7, 2026
c39f28b
test(config-updates): add immutability assertions to update helpers
Mar 7, 2026
71f8f3b
fix: restore correct post-rebase state for config-editor, ModerationS…
Mar 7, 2026
cb2e33d
Merge branch 'main' into refactor/triage-prompt-rewrite
BillChirico Mar 7, 2026
96700bb
docs(maintain-docs): fix permissions write and copilot/ branch prefix
Mar 8, 2026
43f2405
fix(prompts): align moderation ladder and classifier rule example
Mar 8, 2026
8bbd31b
fix(dashboard): import shared inputClasses in AiAutoModSection, GitHu…
Mar 8, 2026
08d265b
fix(dashboard): postTime type=time, blockedDomains onChange, transcri…
Mar 8, 2026
dc43dcd
fix(dashboard): StarboardSection stale state and channelId null-coerce
Mar 8, 2026
05634f1
fix(dashboard): restore ChannelSelector for moderationLogChannel in T…
Mar 8, 2026
1e80640
fix(lib): restrict section type in config-updates, fix Ctrl+S prevent…
Mar 8, 2026
2abf756
style: apply biome auto-fixes (import order, formatting)
Mar 8, 2026
47db485
fix(dashboard): address remaining 10 PR #248 review threads
Mar 10, 2026
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
90 changes: 90 additions & 0 deletions .github/workflows/maintain-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Maintain Docs

---
on:
schedule:
- cron: '0 9 * * *' # 4 AM EST = 9 AM UTC
workflow_dispatch: {}

permissions:
contents: write
pull-requests: write
issues: write

tools:
github:
edit:

engine: copilot

---

# Maintain AGENTS.md Documentation

## Purpose

Keep the AGENTS.md file accurate and current by:
- Reviewing merged pull requests since last run
- Checking updated source files (src/, web/, tests/, etc.)
- Updating AGENTS.md to reflect any architectural or pattern changes
- Creating a pull request if updates are needed

## Instructions for the Agent

1. **Fetch Recent Changes**: Query the repository for merged PRs and updated files from the past 24 hours

2. **Review Architecture Changes**: Check if any of these directories have significant changes:
- `src/modules/` - New modules or modified patterns
- `src/api/` - API route or middleware changes
- `src/commands/` - New slash commands
- `src/utils/` - Utility additions or pattern changes
- `web/` - Dashboard updates
- `tests/` - Testing patterns

3. **Analyze Merged PRs**: Look at PR titles and descriptions to identify:
- New features added
- Architecture decisions
- Pattern changes
- Testing approach changes
- Breaking changes

4. **Update AGENTS.md if Needed**:
- Architecture Overview section: Add new modules or directories
- Key Patterns section: Document new patterns or changes
- Common Tasks section: Update task examples if workflows changed
- Resources section: Add new links if applicable

5. **Create Pull Request**: If changes are needed:
- Create a branch named `copilot/maintain-docs-YYYY-MM-DD`
<!-- NOTE: Replace YYYY-MM-DD with the actual run date on each execution,
e.g. copilot/maintain-docs-2026-03-07. A static date causes branch collisions
on repeated daily runs. Use a date expression or ${{ github.run_id }}.
The `copilot/` prefix is required for GitHub Copilot coding agent branches. -->
- Update AGENTS.md with discovered changes
- Create a PR with:
- Title: "docs: update AGENTS.md from merged PRs and source changes"
- Description: List the changes reviewed and what was updated
- Label: `documentation`
- Auto-merge enabled if all checks pass

6. **Quality Checks**:
- Ensure Markdown formatting is correct
- Verify all links and references are accurate
- Check that code examples match current patterns
- Ensure sections remain organized and readable

7. **If No Changes Needed**: Close silently or note in logs that AGENTS.md is current

## Context

AGENTS.md documents:
- Code quality standards (ESM, single quotes, semicolons, 2-space indent, Winston logger)
- Architecture overview (src/, web/ structure)
- Key patterns (config system, caching, AI integration, database)
- Common tasks (adding features, commands, API endpoints)
- Testing requirements (80% coverage)
- Git workflow and review bots
- Troubleshooting guides
- Resources

Always maintain accuracy and completeness of this documentation file.
41 changes: 41 additions & 0 deletions TASK2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# TASK: Fix remaining 21 review threads on PR #248

Branch: `refactor/triage-prompt-rewrite`
Work in: `/home/bill/worktrees/volvox-bot-248`

## Threads to fix

### maintain-docs.md
1. Add `# Maintain Docs` top-level heading (markdownlint)
2. Replace hardcoded date `2026-03-04` with `YYYY-MM-DD` placeholder + comment
3. Capitalize "Markdown" as proper noun
4. Line 20 — fix whatever workflow issue CodeRabbit flagged (read the file)
5. Line 61 — branch naming: CodeRabbit says `copilot/` prefix is required for GitHub Copilot coding agent branches — read the file and fix the branch naming if it uses a non-compliant format

### Backend
6. `tests/modules/triage-prompt.test.js` line 278 — add test that channel metadata with tag-like chars is escaped via `escapePromptDelimiters()`
7. `src/prompts/community-rules.md` line 15 — change `mute` to `timeout` in the moderation ladder (classifier only supports `warn`, `timeout`, `kick`, `ban`, `delete`)
8. `src/prompts/triage-classify.md` line 26 — update stale example `Rule 4: No spam/shilling` to match current rule `Rule 4: No spam or drive-by promotion`

### Frontend — config-sections
9. `web/src/components/dashboard/config-sections/AiAutoModSection.tsx` line 16 — import `inputClasses` from the shared module (`config-sections/shared.ts`) instead of defining it locally
10. `web/src/components/dashboard/config-sections/ChallengesSection.tsx` line 73 — constrain `postTime` to a real clock value (use `type="time"` input or validate `HH:MM` format before saving)
11. `web/src/components/dashboard/config-sections/ModerationSection.tsx` line 259 — `blockedDomains` currently only updates `draftConfig` on `onBlur`. Change to update on `onChange` (or both) so saves don't miss in-progress edits
12. `web/src/components/dashboard/config-sections/TicketsSection.tsx` line 139 — read the file and fix whatever issue CodeRabbit found
13. `web/src/components/dashboard/config-sections/TriageSection.tsx` line 225 — `moderationLogChannel` was regressed to a plain text input; restore it to use a `ChannelSelector` component
14. `web/src/components/dashboard/config-sections/StarboardSection.tsx` — fix whatever major issue was flagged (read file)
15. `web/src/components/dashboard/config-sections/GitHubSection.tsx` line 43 — read and fix
16. `web/src/components/dashboard/config-sections/ChallengesSection.tsx` — read and fix the major issue
17. `web/src/components/dashboard/config-sections/CommunityFeaturesSection.tsx` line 76 — use stricter type for feature config entries instead of `as { enabled?: boolean } | undefined`

### Frontend — lib
18. `web/src/lib/config-updates.ts` — restrict `section` type to object-valued config sections (not `keyof GuildConfig` which includes scalars)
19. `web/src/lib/config-normalization.ts` line 80 — clamp `decimalToPercent` to [0, 100] for symmetry with `percentToDecimal`

### Frontend — config-editor
20. `web/src/components/dashboard/config-editor.tsx` line 451 — Ctrl+S silently fails and blocks browser save when there are validation errors. Fix: only call `e.preventDefault()` when we're actually handling the save (i.e., `hasChanges && !hasValidationErrors`), otherwise let the browser default fire

## Rules
- Commit each logical group separately with conventional commits
- Run `pnpm format && pnpm lint` and `pnpm --prefix web lint && pnpm --prefix web typecheck`
- Do NOT push
Comment on lines +1 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove this PR-local checklist before merge.

This is transient scratch work with a machine-specific path and review-state notes, so it will stale immediately and leaks local environment details into the repo.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TASK2.md` around lines 1 - 41, Delete the transient PR-local checklist block
(the “Remove this PR-local checklist before merge.” note and any
machine-specific paths or review-state lines) from TASK2.md so no local
environment or ephemeral review notes remain in the committed file; if the whole
file is only transient scratch work, remove TASK2.md entirely or replace it with
a short, permanent task list without local paths or private notes.

85 changes: 85 additions & 0 deletions TASK3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# TASK: Fix 10 remaining PR #248 review threads

Branch: `refactor/triage-prompt-rewrite`
Work in: `/home/bill/worktrees/volvox-bot-248`

## Fixes

### 1. EngagementSection.tsx — stable badge keys
- File: `web/src/components/dashboard/config-sections/EngagementSection.tsx` line 53
- Currently uses index-based key `badge-row-${i}`. When badges are reordered or deleted, React reuses wrong DOM nodes.
- Fix: give each badge a stable `id` (e.g. `badge.id ?? badge.name ?? index`) as the key

### 2. AiAutoModSection.tsx — clamp threshold before converting
- File: `web/src/components/dashboard/config-sections/AiAutoModSection.tsx` line 99
- `150` or `-5` gets saved as `1.5`/`-0.05` without clamping
- Fix: clamp parsed value to [0, 100] before `percentToDecimal()`:
```tsx
const clamped = Math.min(100, Math.max(0, parsed));
onThresholdChange(percentToDecimal(clamped));
```

### 3. ChallengesSection.tsx — single quotes in JSX strings
- File: `web/src/components/dashboard/config-sections/ChallengesSection.tsx` line 84
- JSX string literals use double quotes; repo convention is single quotes
- Fix: change double-quoted JSX string attributes to single quotes where applicable (biome can auto-fix this)

### 4. ChallengesSection.tsx — validate IANA timezone
- File: `web/src/components/dashboard/config-sections/ChallengesSection.tsx` line 84
- Timezone is still free-text; typos silently break scheduling
- Fix: Use `Intl.supportedValuesOf('timeZone')` to validate, or add a `<datalist>` with common timezones, and show an error if the entered value isn't a valid IANA zone:
```tsx
const isValidTimezone = (tz: string) => {
try { Intl.DateTimeFormat(undefined, { timeZone: tz }); return true; }
catch { return false; }
};
```
Show a red error message below the input if invalid.

### 5. GitHubSection.tsx — sync pollIntervalMinutes with draft state
- File: `web/src/components/dashboard/config-sections/GitHubSection.tsx` line 63
- When `pollIntervalMinutes` is unset, renders `5` but never writes it to draftConfig
- Fix: use `value={draftConfig.github?.pollIntervalMinutes ?? 5}` AND write back on change (including the default 5):
```tsx
onChange={(e) => {
const val = Math.max(1, parseInt(e.target.value, 10) || 5);
onFieldChange('pollIntervalMinutes', val);
}}
```

### 6. ModerationSection.tsx — mobile-responsive rate-limit grids
- File: `web/src/components/dashboard/config-sections/ModerationSection.tsx` line 229
- Fix `grid-cols-2` and `grid-cols-3` → `grid-cols-1 sm:grid-cols-2` and `grid-cols-1 sm:grid-cols-3`

### 7. StarboardSection.tsx — use `''` not `null` for cleared channelId
- File: `web/src/components/dashboard/config-sections/StarboardSection.tsx` line 57
- `StarboardConfig.channelId` is `string`, not `string | null`
- Fix: `onChange={(val) => onFieldChange('channelId', val ?? '')}` instead of `val ?? null`

### 8. StarboardSection.tsx — ignoredChannels updates on change not just blur
- File: `web/src/components/dashboard/config-sections/StarboardSection.tsx` line 133
- Save can fire while input has focus; latest value missed if user saves before blur
- Fix: update `draftConfig` on `onChange` too (keep raw state for display but also flush to draft):
```tsx
onChange={(e) => {
setIgnoredChannelsRaw(e.target.value);
// also flush to draft so Ctrl+S captures current value
const parsed = e.target.value.split(',').map(s => s.trim()).filter(Boolean);
onIgnoredChannelsChange(parsed);
}}
```

### 9. TriageSection.tsx — mobile-responsive numeric grids
- File: `web/src/components/dashboard/config-sections/TriageSection.tsx` line 182
- Same as ModerationSection — `grid-cols-2` → `grid-cols-1 sm:grid-cols-2`

### 10. config-updates.ts — fix updateArrayItem early return
- File: `web/src/lib/config-updates.ts` line 137
- Early return on missing array breaks the empty-array initialization case
- Check existing tests in `web/tests/lib/config-updates.test.ts` to understand the expected behavior
- Fix: instead of returning `prev` when the array is missing, initialize it as `[]` and proceed with the update

## Rules
- Commit each logical group (backend fixes together, frontend sections together, lib fixes together)
- Run `pnpm format && pnpm lint` and `pnpm --prefix web lint && pnpm --prefix web typecheck`
- Do NOT push
Comment on lines +1 to +85
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Keep ad-hoc review task docs out of version control.

Like TASK2.md, this is branch/worktree-specific planning state rather than durable docs, and it currently adds markdownlint noise on top of the stale local-path details.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~42-~42: The official name of this software platform is spelled with a capital “H”.
Context: ...ver writes it to draftConfig - Fix: use value={draftConfig.github?.pollIntervalMinutes ?? 5} AND write b...

(GITHUB)

🪛 markdownlint-cli2 (0.21.0)

[warning] 8-8: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 15-15: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 16-16: Ordered list item prefix
Expected: 1; Actual: 6; Style: 1/2/3

(MD029, ol-prefix)


[warning] 17-17: Ordered list item prefix
Expected: 2; Actual: 7; Style: 1/2/3

(MD029, ol-prefix)


[warning] 18-18: Ordered list item prefix
Expected: 3; Actual: 8; Style: 1/2/3

(MD029, ol-prefix)


[warning] 20-20: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 21-21: Ordered list item prefix
Expected: 1; Actual: 9; Style: 1/2/3

(MD029, ol-prefix)


[warning] 22-22: Ordered list item prefix
Expected: 2; Actual: 10; Style: 1/2/3

(MD029, ol-prefix)


[warning] 23-23: Ordered list item prefix
Expected: 3; Actual: 11; Style: 1/2/3

(MD029, ol-prefix)


[warning] 24-24: Ordered list item prefix
Expected: 4; Actual: 12; Style: 1/2/3

(MD029, ol-prefix)


[warning] 25-25: Ordered list item prefix
Expected: 5; Actual: 13; Style: 1/2/3

(MD029, ol-prefix)


[warning] 26-26: Ordered list item prefix
Expected: 6; Actual: 14; Style: 1/2/3

(MD029, ol-prefix)


[warning] 27-27: Ordered list item prefix
Expected: 7; Actual: 15; Style: 1/2/3

(MD029, ol-prefix)


[warning] 28-28: Ordered list item prefix
Expected: 8; Actual: 16; Style: 1/2/3

(MD029, ol-prefix)


[warning] 29-29: Ordered list item prefix
Expected: 9; Actual: 17; Style: 1/2/3

(MD029, ol-prefix)


[warning] 31-31: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 32-32: Ordered list item prefix
Expected: 1; Actual: 18; Style: 1/2/3

(MD029, ol-prefix)


[warning] 33-33: Ordered list item prefix
Expected: 2; Actual: 19; Style: 1/2/3

(MD029, ol-prefix)


[warning] 35-35: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 36-36: Ordered list item prefix
Expected: 1; Actual: 20; Style: 1/1/1

(MD029, ol-prefix)


[warning] 38-38: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TASK3.md` around lines 1 - 85, Remove the ad-hoc TASK3.md from the PR: delete
the file from the repo (or run git rm --cached TASK3.md if you want to keep it
locally) and amend the commit so it is not part of the branch; to prevent
recurrence add TASK3.md to a local ignore (e.g., .git/info/exclude) or your
global gitignore rather than committing it to the project. Ensure no other
planning docs like TASK2.md are staged before finalizing the commit.

2 changes: 2 additions & 0 deletions src/modules/triage-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const CHANNEL_INACTIVE_MS = 30 * 60 * 1000; // 30 minutes
* @property {string} messageId - Discord message ID
* @property {number} timestamp - Message creation timestamp (ms)
* @property {{author: string, userId: string, content: string, messageId: string}|null} replyTo - Referenced message context
* @property {string|null} channelName - Discord channel name
* @property {string|null} channelTopic - Discord channel topic/description
*/

/**
Expand Down
46 changes: 28 additions & 18 deletions src/modules/triage-prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,13 @@ export function escapePromptDelimiters(text) {
// ── Conversation text formatting ─────────────────────────────────────────────

/**
* Build conversation text with message IDs for prompts.
* Splits output into <recent-history> (context) and <messages-to-evaluate> (buffer).
* Includes timestamps and reply context when available.
* Build a structured conversation text for prompts including optional channel metadata.
*
* User-supplied content (message body and reply excerpts) is passed through
* {@link escapePromptDelimiters} to neutralise prompt-injection attempts.
* Produces sections: an optional <channel-context> (Channel and optional Topic) taken from the first entry that contains channel metadata, a <recent-history> block for `context` messages (when present), and a <messages-to-evaluate> block for `buffer` messages. Each message line contains an optional timestamp, messageId, author, user mention, optional reply excerpt, and the message content. User-supplied content is escaped to neutralize XML-style delimiters and reduce prompt-injection risk.
*
* @param {Array} context - Historical messages fetched from Discord API
* @param {Array} buffer - Buffered messages to evaluate
* @returns {string} Formatted conversation text with section markers
* @param {Array} context - Historical messages to include in <recent-history>.
* @param {Array} buffer - Messages to include in <messages-to-evaluate>.
* @returns {string} The formatted conversation text containing the assembled sections.
*/
export function buildConversationText(context, buffer) {
const formatMsg = (m) => {
Expand All @@ -49,6 +46,19 @@ export function buildConversationText(context, buffer) {
};

let text = '';

// Extract channel metadata from the first available entry
const allEntries = [...buffer, ...context];
const channelEntry = allEntries.find((m) => m.channelName);
if (channelEntry) {
text += '<channel-context>\n';
text += `Channel: #${escapePromptDelimiters(channelEntry.channelName)}\n`;
if (channelEntry.channelTopic) {
text += `Topic: ${escapePromptDelimiters(channelEntry.channelTopic ?? '')}\n`;
}
text += '</channel-context>\n\n';
}

if (context.length > 0) {
text += '<recent-history>\n';
text += context.map(formatMsg).join('\n');
Expand Down Expand Up @@ -80,19 +90,20 @@ export function buildClassifyPrompt(context, snapshot, botUserId) {
}

/**
* Build the responder prompt from the template.
* @param {Array} context - Historical context messages
* @param {Array} snapshot - Buffer snapshot (messages to evaluate)
* @param {Object} classification - Parsed classifier output
* @param {Object} config - Bot configuration
* @param {string} [memoryContext] - Memory context for target users
* @returns {string} Interpolated respond prompt
*/
* Construct the responder prompt by combining conversation text, community rules, the system prompt, classification results, optional memory context, and search guardrails.
* @param {Array} context - Historical context messages used to build conversation text.
* @param {Array} snapshot - Buffer snapshot containing messages to evaluate.
* @param {Object} classification - Classifier output containing decision details.
* @param {string} classification.classification - The classification label.
* @param {string} classification.reasoning - Explanatory reasoning for the classification.
* @param {Array<string>} classification.targetMessageIds - IDs of messages targeted by the classification.
* @param {Object} config - Bot configuration; `config.ai.systemPrompt` (if present) overrides the default system prompt.
* @param {string} [memoryContext] - Optional serialized memory context to include for target users.
* @returns {string} The fully interpolated responder prompt ready for the model. */
export function buildRespondPrompt(context, snapshot, classification, config, memoryContext) {
const conversationText = buildConversationText(context, snapshot);
const communityRules = loadPrompt('community-rules');
const systemPrompt = config.ai?.systemPrompt || 'You are a helpful Discord bot.';
const antiAbuse = loadPrompt('anti-abuse');
const searchGuardrails = loadPrompt('search-guardrails');

return loadPrompt('triage-respond', {
Expand All @@ -103,7 +114,6 @@ export function buildRespondPrompt(context, snapshot, classification, config, me
reasoning: classification.reasoning,
targetMessageIds: JSON.stringify(classification.targetMessageIds),
memoryContext: memoryContext || '',
antiAbuse,
searchGuardrails,
});
}
23 changes: 15 additions & 8 deletions src/modules/triage-respond.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,20 @@ function logAssistantHistory(channelId, guildId, fallbackContent, sentMsg) {
// ── Channel context fetching ─────────────────────────────────────────────────

/**
* Fetch recent messages from Discord's API to provide conversation context
* beyond the buffer window. Called at evaluation time (not accumulation) to
* minimize API calls.
* Retrieve recent channel messages to provide additional conversation context.
*
* @param {string} channelId - The channel to fetch history from
* @param {import('discord.js').Client} client - Discord client
* @param {Array} bufferSnapshot - Current buffer snapshot (to fetch messages before)
* @param {number} [limit=15] - Maximum messages to fetch
* @returns {Promise<Array>} Context messages in chronological order
* Returns an array of context message objects in chronological order. Each object contains:
* - `author`: display name (appended with " [BOT]" for bot accounts),
* - `content`: sanitized message text truncated to the context character limit,
* - `userId`, `messageId`, `timestamp`,
* - `isContext`: true,
* - `channelName`, `channelTopic`.
*
* @param {string} channelId - ID of the channel to fetch history from.
* @param {import('discord.js').Client} client - Discord client used to access the channel messages API.
* @param {Array} bufferSnapshot - Current buffer snapshot; messages are fetched before the oldest entry if present.
* @param {number} [limit=15] - Maximum number of messages to fetch.
* @returns {Promise<Array<Object>>} Context message objects in chronological order.
*/
export async function fetchChannelContext(channelId, client, bufferSnapshot, limit = 15) {
try {
Expand All @@ -75,6 +80,8 @@ export async function fetchChannelContext(channelId, client, bufferSnapshot, lim
messageId: m.id,
timestamp: m.createdTimestamp,
isContext: true, // marker to distinguish from triage targets
channelName: channel.name ?? null,
channelTopic: channel.topic ?? null,
}));
} catch (err) {
warn('fetchChannelContext failed', { channelId, error: err.message });
Expand Down
2 changes: 2 additions & 0 deletions src/modules/triage.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,8 @@ export async function accumulateMessage(message, msgConfig) {
messageId: message.id,
timestamp: message.createdTimestamp,
replyTo: null,
channelName: message.channel.name ?? null,
channelTopic: message.channel.topic ?? null,
};

// Fetch referenced message content when this is a reply
Expand Down
11 changes: 0 additions & 11 deletions src/prompts/anti-abuse.md

This file was deleted.

Loading