Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions inputguard/followups.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,27 @@
"completion criteria": (
"What does 'done' look like — what should you be able to do when the feature works?",
),
"audience": (
"Who is going to read this — a manager, your team, clients, or the public?",
"How familiar will readers be with the topic?",
),
"purpose": (
"What should this piece accomplish — inform, persuade, announce, or request something?",
),
"structure/format": (
"How long should it be, and how should it be organized — bullets, sections, or flowing prose?",
),
"source material": (
"Where is the text to work from — can you paste it or attach the file?",
"Should I preserve its structure, or can I reorganize it freely?",
),
"context": (
"What is the topic or situation this piece should cover?",
),
"completeness": (
"Is there anything it must include — specific points, names, or numbers?",
"Any hard limits, like a word count or a required section?",
),
}

# Slot names a template may reference. A template naming anything else is a
Expand Down
36 changes: 36 additions & 0 deletions inputguard/recommender.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,42 @@
"what_to_provide": "Describe what done looks like. For example: 'the feature is complete when a user can type in the search box and see matching results appear within 200ms' or 'done means the user receives an email notification within 30 seconds of placing an order'. This prevents the AI from stopping too early or going too far.",
"why_it_matters": "Without a clear definition of done, the AI may ship a half-finished feature or over-engineer something well past what you needed.",
},
"audience": {
"gap": "audience",
"what_is_missing": "You haven't said who will read this.",
"what_to_provide": "Name the reader and what they already know. For example: 'for the executive team, keep it high-level', 'for beginners who have never used the tool', 'for the client stakeholders, no jargon'. Even one phrase like 'for my manager' sharpens the tone and level of detail.",
"why_it_matters": "The same topic reads completely differently for a CEO, a new hire, or a customer. Without a named reader, the AI aims the piece at nobody in particular.",
},
"purpose": {
"gap": "purpose",
"what_is_missing": "You haven't said what this piece should accomplish.",
"what_to_provide": "State the goal in one phrase: 'to persuade the steering committee to fund Q1 headcount', 'to announce the launch', 'to explain why the deadline moved'. A goal like 'convince', 'inform', or 'ask for' is enough to aim the writing.",
"why_it_matters": "Informing and persuading lead to different structures, evidence, and tone. Without a goal, the AI produces a generic piece that does neither well.",
},
"structure/format": {
"gap": "structure/format",
"what_is_missing": "You haven't said how long the piece should be or how it should be organized.",
"what_to_provide": "Give a length and a shape. For example: 'under 300 words', 'one page', 'bullets with a short intro', 'three sections: situation, options, recommendation'. Any constraint — even just 'keep it short' — works.",
"why_it_matters": "Without length or organization guidance, the AI picks its own shape. You will often get a bloated draft you then have to cut down yourself.",
},
"source material": {
"gap": "source material",
"what_is_missing": "You asked to work on existing text but didn't provide it.",
"what_to_provide": "Paste the text you want reworked — the draft, notes, or paragraph — directly into the message, or point to where it lives ('the outline is at the bottom'). Include any version details that matter.",
"why_it_matters": "The AI cannot see text that isn't in the message. Without it, you get a generic rewrite of an imaginary document instead of an improvement to yours.",
},
"context": {
"gap": "context",
"what_is_missing": "You haven't said what the piece is about or what situation it responds to.",
"what_to_provide": "Name the subject and the situation. For example: 'about remote work for our company blog', 'regarding the Q3 roadmap', 'the email should tell the team the migration finished'. One sentence of background is enough.",
"why_it_matters": "Without a topic or situation, there is nothing to write about. The AI either invents one or asks you everything you could have said up front.",
},
"completeness": {
"gap": "completeness",
"what_is_missing": "You haven't listed anything the piece must include.",
"what_to_provide": "Name the must-haves: 'include the headline, a quote from the CEO, and pricing', 'must cover current costs, risks, and the timeline', 'mention the new ship date'. Also note any hard limits, like a word count.",
"why_it_matters": "Must-have details left out of the request get left out of the draft. Naming them up front saves a second pass to work them in.",
},
}


Expand Down
22 changes: 17 additions & 5 deletions inputguard/rules/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Built-in rule modules and the registry wiring for the coding domain.
"""Built-in rule modules and the registry wiring for the coding and
writing domains.

Importing this package registers the coding domain — its intent signals and
all 19 built-in rules — through the exact same registry path a user rule
takes. The v0.2 ``run_*_rules`` functions stay exported for backward
compatibility, but the analyzer dispatches through the registry now.
Importing this package registers both first-party domains — their intent
signals and all built-in rules — through the exact same registry path a
user rule takes. The v0.2 ``run_*_rules`` functions stay exported for
backward compatibility, but the analyzer dispatches through the registry
now.
"""

from inputguard.detector import (
Expand All @@ -22,6 +24,7 @@
OPTIMIZATION_RULES,
run_optimization_rules,
)
from inputguard.rules.writing import WRITING_RULES, WRITING_SIGNALS

__all__ = [
"run_coding_rules",
Expand All @@ -45,3 +48,12 @@
*FEATURE_RULES,
),
)

# The writing domain: a single fallback intent ("compose" — globally unique;
# no coding intent name is reused, so no cross-domain rule leakage) and the
# six first-party writing rules, registered through the same path.
REGISTRY.register_domain(
"writing",
WRITING_SIGNALS,
rules=WRITING_RULES,
)
Loading