Files
ajarbot/.kiro/specs/child-safety-profile/requirements.md
Jordan Ramos 916f86725d feat: RSO observation system, child safety, Discord adapter, Telegram watchdog, email attachments
Core agent improvements:
- RSO (Relevance Scoring & Observation) system: interaction_logger, memory_scorer, signal_detector
- Memory access logging (memory_access_log table) for relevance scoring; high-signal turn detection
- Rich conversation storage for notable turns; compact_conversation truncates long user messages
- Task-type classifier (query/action/analysis/creative) for observation tagging
- Nested sub-agent visibility: deep delegations now register against the main agent's manager

Child safety (Gabriel profile):
- child_safety.py: filtering, audit logging, prompt constants for restricted sessions
- .kiro/specs/child-safety-profile: requirements, design, tasks specs
- GABRIEL_BOT_PROPOSAL.md: initial proposal doc
- Reduced context window (10 msgs) and tutor-mode identity for restricted users

Telegram adapter:
- Polling watchdog: auto-restarts updater if polling drops unexpectedly
- get_me() with exponential-backoff retry on NetworkError at startup
- Correct stop() ordering: signal watchdog before cancelling tasks

Email / Gmail:
- send_email: supports file attachments (attachments list param)
- get_email: surfaces attachment metadata in response

Scheduled tasks / weather:
- Remove OpenWeatherMap API calls from morning-weather task; use wttr.in exclusively
- New scheduled tasks and scheduler state persistence

Discord:
- adapters/discord/__init__.py scaffold
- discord-plugin: MCP plugin for Claude Code Discord integration (server.ts, skills, config)

Infrastructure:
- n8n workflow exports (garvis_webhook, content_pipeline variants)
- memory_workspace: context, homelab-repo-updates, weekly observation summaries, error logs
- UCS C240 migration plan doc
- requirements.txt: new deps
- .claude/settings.json, fix_hooks.py: hook/permission tuning
2026-04-23 07:54:01 -06:00

16 KiB
Raw Blame History

Requirements — Child Safety Profile

Overview

Add a restricted child user profile to Ajarbot that allows a 13-year-old to use the bot as an educational and creative tool — focused on gaming, Lua scripting, and Roblox Studio — while preventing access to age-inappropriate content. Parents retain full oversight via an audit log.


User Stories

REQ-01 — Child User Access

As a parent, I want to add my gabriel as an allowed user on Slack so he can interact with the bot using his own account.

Acceptance Criteria:

  • His Slack user ID is mapped to a named username (e.g., gabriel) in adapters.local.yaml
  • His username appears in the allowed_users list
  • He can send messages and receive responses through the existing Slack adapter
  • His session is isolated from the parent's session (separate conversation history)

REQ-02 — Age-Appropriate System Persona

As a parent, I want the bot to behave differently for my gabriel — patient, educational, and enthusiastic about game dev — rather than presenting the full Garvis homelab persona.

Acceptance Criteria:

  • Child users receive a modified system prompt that replaces homelab/admin context with an educational game-dev tutor persona
  • Tone is encouraging, uses simple language, avoids jargon where possible
  • References to SSH, Proxmox, home network, or admin tooling are suppressed for child users
  • Son's profile (memory_workspace/users/gabriel.md) captures his interests, age, and learning style

REQ-03 — Context-Aware Content Filtering (Input)

As a parent, I want the bot to block genuinely harmful requests without false-positiving on legitimate game development questions that use words like "shoot", "kill", "weapon", or "knife" in a coding/game context.

Acceptance Criteria:

  • A preprocessor runs on every inbound message from a child user before it reaches the LLM
  • The preprocessor uses intent patterns, not keyword matching — a block requires both a harm verb and a real-world target/context
  • Game development context signals (e.g., in my game, roblox, lua, script, code, function, NPC, hitbox) exempt a message from weapon/violence keyword blocks
  • The following are always blocked regardless of context:
    • Real-world harm instructions ("how do I hurt/stab/shoot a person")
    • Requests for actual weapon construction
    • Sexual or explicit content
    • Social engineering or personal data requests
    • Content with no plausible game/educational framing
  • Blocked messages receive a friendly, non-alarming response explaining the bot can't help with that topic
  • The following are always allowed regardless of words used:
    • Lua scripting and Roblox Studio mechanics
    • Horror game design (atmosphere, enemy AI, damage systems, jump scares)
    • Game weapon mechanics, hitboxes, damage values, animations
    • General coding help (Python, JavaScript basics)
    • School subjects, creative writing, general knowledge

REQ-04 — Context-Aware Content Filtering (Output)

As a parent, I want a secondary check on what the bot sends back so that even if the LLM produces something borderline, it is caught before delivery.

Acceptance Criteria:

  • A postprocessor scans every outgoing response to a child user
  • Detects and replaces responses that contain explicit language, adult content, or real-world harm instructions that slipped through the system prompt
  • If a response is flagged, a safe fallback message is sent and the event is logged
  • Clean responses pass through unmodified with zero added latency beyond the scan

REQ-05 — System Prompt Guardrails

As a parent, I want the LLM itself to understand the rules so it handles gray-area questions correctly without requiring every edge case to be coded explicitly.

Acceptance Criteria:

  • Child users receive a guardrail block appended to their system prompt on every turn
  • The guardrail block explicitly tells the LLM:
    • Game dev / horror game design / weapon mechanics in a game context = encouraged
    • Real-world harm, adult content, explicit language = refuse politely
    • If unsure, treat the question as game/educational context if any signal supports it
  • The guardrail block is injected in _build_system_prompt() when the username is in the configured RESTRICTED_USERS list

REQ-06 — Tool Restrictions

As a parent, I want my gabriel to be unable to trigger homelab tools, SSH commands, file system operations, or admin-level actions even if he asks.

Acceptance Criteria:

  • System prompt for child users instructs the LLM never to use SSH, file system, Proxmox, network, or infrastructure tools
  • This is enforced at the system prompt level (model instruction), not by removing MCP servers
  • Tool invocations from child users that attempt admin tooling are logged as anomalies

REQ-07 — Parental Audit Log

As a parent, I want a complete, searchable record of every conversation my gabriel has with the bot so I can review what he's been asking and what the bot responded.

Acceptance Criteria:

  • Every interaction from a child user is written to a dedicated audit log, separate from the RSO/memory-scoring logs
  • Audit log location: memory_workspace/audit/{username}/YYYY-MM-DD.jsonl
  • Each audit entry contains:
    • ISO timestamp
    • Username
    • Full inbound message (not truncated)
    • Filter action taken (allowed / blocked / flagged)
    • Filter reason (if blocked/flagged)
    • Full outbound response
  • Audit writes are non-blocking (background thread, same pattern as InteractionLogger)
  • Audit log retention: 365 days (configurable)
  • Existing RSO interaction logs are not modified — audit log is additive

REQ-08 — Configuration-Driven Restricted Users

As a parent, I want the child safety features to be controlled by config, not hardcoded, so I can add or remove restricted users without modifying Python source.

Acceptance Criteria:

  • A child_safety block in config/adapters.local.yaml defines which usernames are restricted
  • Example:
    child_safety:
      restricted_users:
        - gabriel
      audit_retention_days: 365
    
  • The child_safety.py module reads this config at startup
  • Adding a new restricted user requires only a config change and bot restart

Non-Functional Requirements

ID Requirement
NFR-01 Filtering must add < 50ms latency to message processing
NFR-02 Audit log writes must never block response delivery
NFR-03 A filter failure (exception) must fail safe — block the message, not pass it
NFR-04 Audit log files must not be accessible via any bot tool or command
NFR-05 Restricted user config must survive bot restarts
NFR-06 False positive rate on game dev questions must be near zero for common Roblox/Lua vocabulary

REQ-09 — Guided Learning Approach (Skill Development Over Answer Delivery)

As a parent, I want the bot to teach my gabriel how to think and build, not just hand him answers — so that he develops real coding and problem-solving skills over time rather than becoming dependent on the bot.

Acceptance Criteria:

  • The bot's default mode is guide first, answer second — not the reverse
  • Before giving a solution, the bot asks what the user has already tried or what they think might work, unless the question is purely factual ("what does pairs() do in Lua?")
  • When code is provided, it is always accompanied by an explanation of what it does and why — never a bare code block with no context
  • Explanations use the minimum necessary detail for his age/level — short, plain-language sentences before diving into code
  • The bot breaks problems into smaller steps and guides through each one rather than solving the whole thing at once:
    • "Let's tackle the shooting mechanic first. What do you think needs to happen when the player pulls the trigger?"
  • The bot celebrates attempts and effort, not just correct answers:
    • "Nice — you got the loop right, that's the hard part. The issue is just this one line..."
  • When the user shares broken code, the bot guides them to find the bug rather than pointing straight to it:
    • "Take a look at line 12 — what do you think that variable is at that point in the loop?"
  • After giving code, the bot leaves something for the user to do:
    • "I've written the basic function — can you add the part that checks if the player has enough ammo before it fires?"
  • The bot periodically uses transfer learning to connect new concepts to ones already covered:
    • "Remember the loop we used for the enemy spawner? This is the same idea."
  • Code IS shown when asked — this is not a Socratic-only mode. The teaching layer wraps the code, it does not replace it.
  • Purely factual or lookup questions ("what's the Roblox service for detecting player input?") get a direct answer — no forced Socratic preamble for simple lookups.

REQ-10 — Token Optimization for Child Sessions

As a parent, I want Gabriel's sessions to consume as few tokens as possible since he shares the same API pool as me, without degrading the quality of his experience.

Acceptance Criteria:

  • Gabriel's system prompt skips SOUL.md (the Garvis homelab persona) — irrelevant to him, currently costs ~935 tokens per turn
  • Gabriel's system prompt skips context.md (SSH hosts, Proxmox VMs, networking) — entirely irrelevant to Lua help, currently costs ~227 tokens per turn
  • Gabriel's system prompt uses a lightweight tutor identity block (~100 tokens) in place of SOUL.md — enough to set tone without the homelab baggage
  • The hybrid memory search is skipped for Gabriel — the memory store is Jordan's homelab operational data and returns irrelevant chunks that waste tokens
  • Gabriel's conversation history window is capped at 10 messages (vs Jordan's 20) — Lua help sessions rarely need deep context; this roughly halves history token cost
  • The delegation/sub-agent block is omitted from Gabriel's system prompt — he will never trigger multi-agent tasks (~80 tokens saved)
  • All optimizations are conditional on is_restricted(username) — Jordan's experience is completely unchanged

Expected savings per Gabriel turn:

Removed component Token saving
SOUL.md ~935
context.md ~227
Memory search (5 chunks avg) ~300500
History window 20→10 (avg) ~2050% of history
Delegation block ~80
Total ~1,5001,800 tokens/turn

REQ-11 — AI Literacy as Part of the Teaching Approach

As a parent, I want the bot to teach Gabriel how to use AI tools well — not just what to ask, but how to ask — so he builds self-sufficiency with these tools rather than dependency.

Acceptance Criteria:

  • When Gabriel asks a vague or broad question, the bot models good question-asking by clarifying its understanding before answering:

    "Just to make sure I give you the most useful answer — you want the enemy to deal damage on touch, right? Or is it supposed to chase first?"

  • When Gabriel notices the bot "forgot" something earlier, the bot explains context windows in plain terms, naturally:

    "Yeah — I can only hold so much of our conversation in memory at once. At the start of next session, just remind me what you're building and I'll be straight back up to speed."

  • The bot teaches the ideal coding question format when the opportunity arises naturally:

    "Next time try: what your code does now, what you want it to do, and what you've already tried. That combo gets you a much faster answer."

  • The bot flags its own assumptions so Gabriel learns to spot ambiguity:

    "I'm assuming you want this to reset on respawn — let me know if that's not right."

  • AI literacy is woven into responses naturally — never a separate lecture unless Gabriel directly asks how the bot works.

REQ-12 — Cross-Session Project Continuity

As a parent, I want the bot to remember what Gabriel is building between sessions so he doesn't have to re-explain his project every time, and the teaching approach stays coherent over days and weeks — not just within a single conversation.

Acceptance Criteria:

  • A lightweight project context file exists at memory_workspace/users/gabriel_context.md
  • This file is injected into Gabriel's system prompt on every turn (replaces memory search, which is skipped for Gabriel per REQ-10)
  • The bot updates gabriel_context.md at the end of each session with a brief summary of:
    • What Gabriel is currently building (project name/description)
    • What was worked on in this session (features, bugs fixed, concepts covered)
    • Any open threads or "next steps" Gabriel mentioned
    • Any new concepts introduced this session (feeds into REQ-13)
  • The update is concise — target < 30 lines total; the file is overwritten, not appended
  • On first session (file doesn't exist), the bot starts fresh and creates it after the first substantive exchange
  • The file is human-readable so Jordan can review it directly in Slack's file system or the memory workspace

REQ-13 — Skill Progression Tracking

As a parent, I want the bot to remember what Gabriel has already been taught so it doesn't re-explain concepts he's mastered, and can reference them naturally when introducing related ideas.

Acceptance Criteria:

  • A skills log section exists within gabriel_context.md (same file as REQ-12, separate section)
  • Each entry records: concept name, brief description, date first introduced
  • Example entries:
    • for loops — iterating over tables, introduced 2026-04-21
    • functions — defining and calling, parameters vs arguments, introduced 2026-04-22
    • RemoteEvents — client-server communication in Roblox, introduced 2026-04-25
  • The bot checks this log before explaining a concept — if already introduced, it references it rather than re-explaining from scratch:

    "You've used this before — remember the loop we wrote for the enemy spawner?"

  • The log grows over time; the bot adds an entry the first time it meaningfully teaches a new concept, not for every mention
  • Skills log is appended to gabriel_context.md under a ## Skills Introduced heading

REQ-14 — First-Run Onboarding Experience

As a parent, I want Gabriel to receive a friendly welcome the first time he messages the bot that sets expectations — what it can help him with, how it works, and that it's there to teach him, not do the work for him.

Acceptance Criteria:

  • The bot detects a first-run state by checking whether gabriel_context.md exists
  • On first message from Gabriel, before processing his question, the bot sends a welcome message that covers:
    • What it can help with (Lua, Roblox Studio, game design, coding questions)
    • How the teaching approach works — that it'll guide him and ask questions, not just hand over answers ("I'm here to help you figure it out, not just give you the answer")
    • That it'll remember his projects between sessions
    • An invitation to tell it what he's working on
  • The welcome is sent as a separate message before the response to his first question
  • The welcome is conversational and age-appropriate — not a terms-and-conditions wall
  • After the welcome, his first actual question is answered normally
  • The first-run check only fires once; subsequent sessions go straight to his question

REQ-15 — Slack Allow-List (Gap Fix)

As a parent, I want only authorised users to be able to message the bot on Slack, since the Slack adapter currently processes messages from any workspace member with no restriction.

Acceptance Criteria:

  • The Slack adapter checks an allowed_users list from config before processing any message
  • Messages from users not on the allow-list are silently dropped (no response sent)
  • The allow-list is read from config/adapters.local.yaml under the slack adapter settings, matching the pattern already used by the Slack adapter for other config
  • Jordan's existing Slack user ID remains on the list; Gabriel's is added
  • No change to Telegram adapter behaviour (already has this check)

Out of Scope

  • Time-of-day restrictions (not enforceable at bot level — use Slack parental controls)
  • Per-topic whitelists managed via chat commands
  • Automated parent notifications on blocked requests (future enhancement)
  • Web dashboard for audit log review (future enhancement)