Skip to content

Mathias-Simonsen/Slack-Bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Splinterlog

Time to code the bot.

Turn small, recurring team frictions into shared evidence, time-boxed improvement trials, and lessons the team can reuse.

Splinterlog is a Slack-native friction lab. It is not a stand-up bot, reminder bot, poll, generic task list, retrospective facilitator, or AI chat wrapper. A teammate catches a small workflow snag, other people add independent signals, and the team turns the strongest splinter into one measurable experiment. On the check date, Splinterlog asks what actually happened and keeps the lesson.

The problem

Teams lose surprising amounts of time to tiny repeated annoyances: copying release notes into three places, remembering a slightly different checklist, hunting for the newest handoff template, or repeating a manual status update. Each incident feels too small for a ticket or retrospective, so the pattern stays invisible.

Splinterlog gives those paper cuts a lightweight path:

  1. Catch the friction while it is fresh.
  2. Signal that it affects more than one person.
  3. Trial one small change with a success measure and review date.
  4. Learn from the outcome, including mixed and unsuccessful experiments.

The bot's story is deliberately circular. A failed trial does not disappear or become fake success; the splinter reopens with a recorded lesson so the team can try a better change.

What makes it original

Most team bots begin with a meeting, task, poll, or reminder. Splinterlog begins with micro-friction and uses teammate evidence to decide whether a small experiment is worth running. Its commands share one persistent state model instead of acting like unrelated utilities.

The implementation does not depend on an external AI service. Its originality comes from the collaboration workflow, Slack interactions, state transitions, evidence rules, scheduled review, and the language of splinters, signals, trials, and lessons.

Command collision research

Slack's developer documentation warns that slash commands are not truly namespaced: if two apps install the same command, the most recently installed command wins. The initial naming review therefore avoided Slack's built-ins such as /remind, broad words such as /help and /stats, and common bot categories and command families around polls, retrospectives, stand-ups, tracking, and decisions.

The shared /splinterlog-* namespace is memorable, project-specific, and had no matching Slack Marketplace result during the July 2026 naming check. That lowers collision risk but is not a global uniqueness guarantee. Before publishing publicly, repeat the Marketplace and web search and check the target workspace's installed commands.

Useful naming references:

Commands and functions

Command or function What it does Example
/splinterlog-catch Opens a guided modal and posts a real, persistent friction card. Run it in the channel where the snag happens.
/splinterlog-board Shows open, trial, learned, or all splinters ranked by teammate signals. /splinterlog-board open
/splinterlog-trial Opens a modal for a measurable experiment tied to one open splinter. /splinterlog-trial 4
/splinterlog-guide Shows compact onboarding, examples, and the central workflow. /splinterlog-guide
Catch a splinter message shortcut Opens capture from an existing Slack message and stores its timestamp as context. Open a message's shortcuts menu.
This snags me too button Adds one signal per person and refreshes the shared count. Click a friction card.
Scheduled trial check Posts one review card when a running trial reaches its check date. Use Record what happened.
App Home Shows the workflow, meaningful totals, and the five most-signaled open splinters. Open Splinterlog from Slack's Apps area.

There are more than three genuinely different functions across the complete bot:

  • direct slash-command discovery and capture;
  • interactive multi-user evidence and modal workflows;
  • scheduled, event-driven trial review;
  • App Home publication in response to Slack events.

All slash commands use the collision-resistant splinterlog namespace. There is intentionally no generic /help, /stats, /settings, or /remind command.

Feature quality review

These are cautious design estimates, not competition-score guarantees.

Feature Originality Technical value Usability Why it does not feel generic
Friction capture 7/9 7/9 9/9 It captures recurring cost and frequency, not a generic task or note.
Shared signal board 8/9 7/9 8/9 One signal per teammate turns repeated experience into evidence without becoming a poll.
Improvement trials 8/9 8/9 8/9 Hypothesis, action, success measure, owner, and check date form one connected experiment.
Scheduled lesson loop 8/9 8/9 8/9 The bot asks what happened and preserves mixed or failed results instead of sending a reminder only.
App Home and guide 6/9 6/9 9/9 They explain and surface the same friction workflow rather than acting as a generic dashboard.

Two-minute demo

You can demonstrate the complete story with two people in one test channel:

  1. Run /splinterlog-guide and show the concise onboarding blocks.
  2. Run /splinterlog-catch and capture ?Release notes are copied by hand.?
  3. Have a second teammate click This snags me too twice. The first click adds one signal; the second explains that the signal was already counted.
  4. Run /splinterlog-board open and show that the signaled item rises to the top.
  5. Click Try a small fix and create a trial with today's date.
  6. Run the scheduler once or wait for its interval. Open Record what happened.
  7. Record helped, mixed, or did-not-help and show the lesson post and updated board state.
  8. Open App Home and show the summary and top open splinters.

For a credential-free proof, run the seven local tests. They exercise real SQLite writes, ranking, deduplication, permission checks, trial state changes, daily nudge state, and rollback.

Architecture

Splinterlog uses a small, direct Python architecture:

Slack Socket Mode
      |
      v
slack_app.py  ---- Block Kit ----> blocks.py
      |
      v
 service.py   <---- scheduler.py
      |
      v
 database.py  ----> SQLite
  • app.py loads settings, initializes the database, starts the scheduler, and opens Socket Mode.
  • splinterlog/slack_app.py acknowledges Slack payloads, checks retry keys, translates UI values, and returns friendly errors.
  • splinterlog/blocks.py builds reusable modals, cards, board views, review prompts, and App Home content.
  • splinterlog/service.py owns validation, workspace scoping, state transitions, signal uniqueness, and permission rules.
  • splinterlog/database.py owns SQLite schema creation, transactions, rollback, and idempotency keys.
  • splinterlog/scheduler.py finds due trials, retries one Slack rate limit, posts review cards, and records daily nudge state.

The code favors ordinary functions, dictionaries, a dataclass, and short classes. It should be readable to a newer Python developer while still separating Slack UI, business rules, persistence, and background work.

Persistent data

Table Purpose
frictions Workspace-scoped splinters, cost, frequency, source timestamp, and current state.
signals One supporting signal per person per splinter.
trials Owner, hypothesis, action, success measure, check date, outcome, lesson, and nudge state.
processed_actions Idempotency keys for commands, views, buttons, shortcuts, and events.

SQLite foreign keys and transactions are enabled on every connection. A failed multi-step operation rolls back. The bot never responds to an error by deleting or rewriting the project.

Slack permissions

The manifest requests three bot scopes:

Scope Why it is needed
commands Register the four slash commands and message shortcut.
chat:write Post friction cards, trial confirmations, review prompts, lessons, and ephemeral feedback.
users:read Verify whether a non-owner resolving a trial is a workspace admin or owner.

The app-level Socket Mode token needs connections:write. Splinterlog does not request message-history scopes, file access, channel administration, or user tokens. The message shortcut stores a source timestamp, not a copy of the original message body.

Setup

1. Create the Slack app

  1. Open Slack API - Your Apps.
  2. Choose Create New App, then From an app manifest.
  3. Select the test workspace and paste slack-manifest.yaml.
  4. Review the commands, shortcut, App Home event, interactivity, and three bot scopes.
  5. Create the app and install it to the workspace.
  6. Under Socket Mode, create an app-level token with connections:write.
  7. Copy the bot token, app token, and signing secret.

If an admin controls app installation, send the manifest and scope table with the approval request. A missing scope is reported to users with a reinstall instruction.

2. Prepare local Python

Windows PowerShell:

py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
Copy-Item .env.example .env

Edit .env with the real Slack credentials:

SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
SLACK_SIGNING_SECRET=...
SPLINTERLOG_DB_PATH=splinterlog.db
SPLINTERLOG_REVIEW_INTERVAL_SECONDS=60
LOG_LEVEL=INFO
Variable Required Meaning
SLACK_BOT_TOKEN Yes Bot token created when the app is installed.
SLACK_APP_TOKEN Yes App-level Socket Mode token with connections:write.
SLACK_SIGNING_SECRET Yes Slack signing secret used by Bolt.
SPLINTERLOG_DB_PATH No SQLite path; defaults to splinterlog.db.
SPLINTERLOG_REVIEW_INTERVAL_SECONDS No Positive scheduler interval; defaults to 60.
LOG_LEVEL No Python log level; defaults to INFO.

3. Run locally

python app.py

A successful start logs the selected database path and opens a Socket Mode connection. Invite Splinterlog to the demonstration channel if workspace policy requires it, then run /splinterlog-guide.

Testing

Run every local test:

python -m unittest discover -s tests -v

Run a syntax/import check:

python -m compileall -q .
python -c "import app; import splinterlog.slack_app; import splinterlog.scheduler"

The current suite has seven passing tests covering:

  • capture validation and persistence;
  • workspace isolation and signal-based ranking;
  • one signal per teammate;
  • trial ownership, resolution, and learned state;
  • due-trial nudge suppression for the rest of the day;
  • one-time action-key claims;
  • transaction rollback after a simulated failure.

The tests use temporary SQLite files and do not need Slack credentials or network access.

Failure and edge-case behavior

Situation Behavior
Missing or invalid arguments Modal field error or ephemeral example with the exact expected format.
Missing Slack permission Safe denial and a request to have an admin reinstall the manifest.
Slack retry or duplicate button/view Persistent idempotency key prevents a second state change.
Same person signals twice The count stays unchanged and the user gets private feedback.
Two trials requested for one splinter The service rejects the second running trial.
Non-owner resolves a trial Denied unless Slack confirms workspace admin or owner status.
Slack rate limit Scheduler waits for Retry-After and retries once; commands return a retry message.
Missing or deleted channel The database state remains safe; posting failure is logged with IDs.
Unexpected exception Logged with payload type; a private ?nothing was deleted? notice is attempted when possible.
Process stops SQLite state remains; the scheduler restarts from due, not-yet-nudged trials.

Security and privacy

  • SQL values are parameterized. The only interpolated SQL fragment is selected from an internal status allowlist.
  • Every friction/trial read used by Slack is scoped through the workspace ID.
  • Secrets are loaded from environment variables and are never included in Slack blocks or logs.
  • No external AI or analytics service receives workspace content.
  • The bot stores Slack IDs and user-provided friction/trial text. Teams should apply their own retention and access policy before production use.

Project layout

app.py
slack-manifest.yaml
requirements.txt
splinterlog/
  blocks.py
  config.py
  database.py
  scheduler.py
  service.py
  slack_app.py
tests/
  test_database.py
  test_service.py
docs/
  ARCHITECTURE.md
  DEVELOPMENT_LOG.md
  DEMO_GUIDE.md

Known limitations

  • SQLite schema creation is suitable for this version, but production upgrades need explicit migrations.
  • The in-process scheduler assumes one bot process. Multiple replicas need a database-backed job lease before posting.
  • A permanently missing channel remains due and will be retried on later loops; there is no admin repair screen yet.
  • The source message timestamp is stored but not rendered as a permalink.
  • There is no edit, archive, export, retention, or workspace-settings interface in version 0.1.0.
  • Admin verification depends on users:read and workspace role flags.
  • A real Slack workspace demo and screenshots still require valid credentials; none are fabricated in this repository.

Future plans

  1. Add versioned database migrations and a backup/restore command.
  2. Add workspace timezone and review-channel settings in App Home.
  3. Add a distributed scheduler lease before supporting multiple processes.
  4. Add safe edit/archive actions with confirmation and undo.
  5. Turn source timestamps into permission-safe Slack permalinks.
  6. Add mocked Slack payload tests for every handler and rate-limit response.

Proof and supporting docs

  • docs/ARCHITECTURE.md - boundaries, data flow, state transitions, and reliability choices.
  • docs/DEVELOPMENT_LOG.md - what changed, real challenges, fixes, lessons, and next steps.
  • docs/DEMO_GUIDE.md - a short live demo, test data, and screenshot/GIF plan.
  • slack-manifest.yaml - commands, shortcut, events, settings, and least-privilege scopes.
  • tests/ - executable proof of core state and failure behavior.

Credits

Built with Slack Bolt for Python, Slack Block Kit, Python's built-in sqlite3, and a lot of attention to small team paper cuts.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages