reasonkit 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reasonkit/__init__.py +20 -0
- reasonkit/__main__.py +6 -0
- reasonkit/_sanitize.py +167 -0
- reasonkit/_utils.py +104 -0
- reasonkit/branching.py +75 -0
- reasonkit/classifier.py +200 -0
- reasonkit/codegen.py +191 -0
- reasonkit/compare.py +67 -0
- reasonkit/core.py +457 -0
- reasonkit/critique.py +79 -0
- reasonkit/errors.py +21 -0
- reasonkit/merge.py +140 -0
- reasonkit/prompts/classify_and_assumptions.txt +44 -0
- reasonkit/prompts/critique_all.txt +50 -0
- reasonkit/prompts/deepen_concrete.txt +29 -0
- reasonkit/prompts/fix_code.txt +9 -0
- reasonkit/prompts/generate_approaches.txt +28 -0
- reasonkit/prompts/generate_code.txt +13 -0
- reasonkit/prompts/merge.txt +43 -0
- reasonkit/prompts/refine_direct.txt +23 -0
- reasonkit/prompts/refine_merge.txt +35 -0
- reasonkit/prompts/verify_code.txt +7 -0
- reasonkit/py.typed +0 -0
- reasonkit/stop_conditions.py +29 -0
- reasonkit/trace.py +56 -0
- reasonkit-0.2.0.dist-info/METADATA +336 -0
- reasonkit-0.2.0.dist-info/RECORD +30 -0
- reasonkit-0.2.0.dist-info/WHEEL +5 -0
- reasonkit-0.2.0.dist-info/licenses/LICENSE +674 -0
- reasonkit-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Classify the following prompt into exactly one category: DECISION, CODE, or DIRECT.
|
|
2
|
+
- DECISION: strategic, advisory, planning, or assessment questions — including
|
|
3
|
+
vague "build me a SaaS / make an app / design a system" requests that ask for a
|
|
4
|
+
strategy, plan, or advice rather than for code you can actually write.
|
|
5
|
+
- CODE: a request to GENERATE, FIX, or REVIEW code — but ONLY when the prompt
|
|
6
|
+
either (a) pastes code, (b) names a concrete programming language AND a concrete
|
|
7
|
+
spec (e.g. "write a Python function that takes a list and returns the sum"), or
|
|
8
|
+
(c) says "fix/review this" with code present. A vague "build me an app that does
|
|
9
|
+
X" with NO code and NO concrete language+spec is NOT code — it is DECISION or
|
|
10
|
+
DIRECT. When in doubt about whether there is anything to actually build code
|
|
11
|
+
from, choose DECISION/DIRECT, not CODE.
|
|
12
|
+
- DIRECT: anything else (factual lookups, simple explanations, casual chat).
|
|
13
|
+
|
|
14
|
+
Also estimate complexity: SIMPLE or COMPLEX.
|
|
15
|
+
|
|
16
|
+
If the prompt is too vague to answer faithfully — it asks you to build/assess/plan
|
|
17
|
+
something but gives no specifics and no code to work from — set
|
|
18
|
+
NEEDS_CLARIFICATION: YES and list (in CLARIFYING_QUESTIONS) what is missing. If the
|
|
19
|
+
prompt is concrete enough to answer, set NEEDS_CLARIFICATION: NO.
|
|
20
|
+
|
|
21
|
+
If DECISION, also identify:
|
|
22
|
+
- the underlying goal the user is likely trying to achieve
|
|
23
|
+
- up to 3 assumptions embedded in the question that may not hold true
|
|
24
|
+
- up to 2 clarifying questions that would meaningfully change the answer (omit if
|
|
25
|
+
none matter)
|
|
26
|
+
|
|
27
|
+
If CODE and the user already supplied code to fix or review, paste that exact
|
|
28
|
+
code verbatim in a CODE_INPUT field. If the user only asked to generate code, or
|
|
29
|
+
did not paste code, leave CODE_INPUT empty. The CODE_INPUT field is for pasted
|
|
30
|
+
code ONLY — never write the final answer here.
|
|
31
|
+
|
|
32
|
+
You are ROUTING ONLY. Do NOT write the final answer. A later, separate call will
|
|
33
|
+
produce the answer; your job is just to categorize and surface context.
|
|
34
|
+
|
|
35
|
+
Return structured output exactly in this shape:
|
|
36
|
+
CATEGORY: DECISION|CODE|DIRECT
|
|
37
|
+
COMPLEXITY: SIMPLE|COMPLEX
|
|
38
|
+
NEEDS_CLARIFICATION: YES|NO
|
|
39
|
+
GOAL: ...
|
|
40
|
+
ASSUMPTIONS: ...
|
|
41
|
+
CLARIFYING_QUESTIONS: ...
|
|
42
|
+
CODE_INPUT: ...
|
|
43
|
+
|
|
44
|
+
Prompt: {prompt}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Read the reply below as if you are a blunt, practical friend who wants to
|
|
2
|
+
protect the person from bad advice. Your job is to catch things that are wrong,
|
|
3
|
+
misleading, unrealistic, or missing — NOT to score it.
|
|
4
|
+
|
|
5
|
+
The context block contains a "Goal:" the user is actually trying to achieve, an
|
|
6
|
+
"Assumptions to revisit:" list (things the original question may have taken for
|
|
7
|
+
granted but that may NOT hold), and "Open clarifying questions:" the reply
|
|
8
|
+
genuinely cannot answer yet. USE these. Concretely check:
|
|
9
|
+
|
|
10
|
+
- Does the reply actually serve the stated goal, or does it avoid the real
|
|
11
|
+
question with a generic answer?
|
|
12
|
+
- Does the reply silently assume something from "Assumptions to revisit" that
|
|
13
|
+
the user never confirmed (e.g. assuming they have capital, time, a specific
|
|
14
|
+
customer, or that the task is well-defined)? Flag it.
|
|
15
|
+
- Does the reply overstate certainty, ignore real costs or risks, or leave out
|
|
16
|
+
a practical reality that changes the advice?
|
|
17
|
+
- Are there important questions the reply should have admitted it can't answer,
|
|
18
|
+
but instead guessed at? Flag the guess.
|
|
19
|
+
- Is the reply a disorganized wall of text, or is it well-organized and
|
|
20
|
+
scannable?
|
|
21
|
+
- Does the reply acknowledge genuine downsides, trade-offs, and alternatives,
|
|
22
|
+
or is it one-sided advice?
|
|
23
|
+
- Does the reply note the assumptions it's making about the user's situation?
|
|
24
|
+
- Is there anything else important the reply left out?
|
|
25
|
+
|
|
26
|
+
Respond with EXACTLY one block labelled "ISSUES:", and NOTHING else
|
|
27
|
+
(no preamble, no rewrite, no scoring). Use this exact format:
|
|
28
|
+
|
|
29
|
+
ISSUES:
|
|
30
|
+
- <one specific, concrete flaw or gap, tied to the goal/assumptions above>
|
|
31
|
+
- <another specific flaw or gap>
|
|
32
|
+
|
|
33
|
+
Rules:
|
|
34
|
+
- Each issue is ONE short, plain-language bullet about something wrong or
|
|
35
|
+
missing. No jargon. No prose.
|
|
36
|
+
- Only list issues that genuinely matter. If the reply is basically sound AND
|
|
37
|
+
already honest about its assumptions and uncertainties, respond with a single
|
|
38
|
+
line: ISSUES: (none)
|
|
39
|
+
- Do NOT restate the reply or praise it.
|
|
40
|
+
- HONEST "NEED MORE INFO" REPLIES: if the reply is already an honest answer
|
|
41
|
+
that says plainly it cannot proceed without information the user hasn't given
|
|
42
|
+
(e.g. "please share the plan", "I need to know X"), that is the CORRECT,
|
|
43
|
+
honest response — do NOT treat the missing information as a flaw. Return
|
|
44
|
+
ISSUES: (none) rather than inventing issues like "the reply doesn't address
|
|
45
|
+
X" when the reply already said it can't until X is provided. Only flag a
|
|
46
|
+
genuine flaw in HOW it says that (e.g. it fabricated specifics it claimed
|
|
47
|
+
to need).
|
|
48
|
+
|
|
49
|
+
Reply to check: {approaches}
|
|
50
|
+
Context: {goal_and_assumptions}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
The answer below is a good start but can be more specific and concrete. Improve
|
|
2
|
+
it by tightening vague descriptions into specifics.
|
|
3
|
+
|
|
4
|
+
Specifically:
|
|
5
|
+
- Replace vague or generic descriptions with specific examples, concrete
|
|
6
|
+
numbers, or named trade-offs where possible. For instance, "costs can be
|
|
7
|
+
high" might become "rent in a prime location runs $5k-8k/month"; "it takes
|
|
8
|
+
time" might become "expect 6-12 months to break even".
|
|
9
|
+
- If the answer doesn't already have one, add a concrete first move the user
|
|
10
|
+
could take in the next 7 days.
|
|
11
|
+
- Strengthen the bottom line — make it more direct and actionable. What should
|
|
12
|
+
the user actually do or decide?
|
|
13
|
+
- If the answer is missing important trade-offs or risks, add them.
|
|
14
|
+
- If the answer doesn't surface assumptions it's making, note them.
|
|
15
|
+
- If the answer sounds overly certain about things that depend on unconfirmed
|
|
16
|
+
context, say so openly.
|
|
17
|
+
- Keep the existing structure, headings, section breaks, and organization
|
|
18
|
+
exactly as they are. Do not flatten, restructure, or add new sections.
|
|
19
|
+
- Use natural, plain language.
|
|
20
|
+
|
|
21
|
+
Answer:
|
|
22
|
+
{answer}
|
|
23
|
+
|
|
24
|
+
Goal / things to keep in mind:
|
|
25
|
+
{goal_and_assumptions}
|
|
26
|
+
|
|
27
|
+
Output ONLY the improved answer. No meta-commentary about what you changed, no
|
|
28
|
+
"Here's the revised version", no "I've improved it by", no explanation. Stop
|
|
29
|
+
writing the moment the answer ends. Do not add process notes.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
The following code has specific issues that must be fixed. Address EVERY issue
|
|
2
|
+
listed, and return the COMPLETE corrected code (not a diff). Keep the same
|
|
3
|
+
language and overall structure; do not add unrelated changes.
|
|
4
|
+
|
|
5
|
+
Issues to fix:
|
|
6
|
+
{issues}
|
|
7
|
+
|
|
8
|
+
Code:
|
|
9
|
+
{code}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{goal_and_assumptions}
|
|
2
|
+
|
|
3
|
+
{n_instruction}
|
|
4
|
+
|
|
5
|
+
General rules for every approach:
|
|
6
|
+
- Give a short, honest bottom line first.
|
|
7
|
+
- Respond to exactly what the user wrote. If their message is vague or asks you
|
|
8
|
+
to assess, review, or plan something they have not actually shared, say plainly
|
|
9
|
+
that you need them to provide it — do not invent specifics they never gave.
|
|
10
|
+
- Lay out the real considerations they should weigh: genuine trade-offs, risks,
|
|
11
|
+
and practical points that matter. Use plain sentences.
|
|
12
|
+
- Offer a concrete recommendation where one is warranted.
|
|
13
|
+
- Suggest a concrete first move the user can take if one follows naturally.
|
|
14
|
+
- Acknowledge downsides and trade-offs candidly — a one-sided answer that hides
|
|
15
|
+
the hard parts is not helpful.
|
|
16
|
+
- Use natural, specific language. Write the way a knowledgeable person would
|
|
17
|
+
explain it to someone they care about.
|
|
18
|
+
- Organize your answer so it's easy to follow. Use clear sections to separate
|
|
19
|
+
different parts of your answer.
|
|
20
|
+
- Surface any assumptions you're making about the user's situation that could
|
|
21
|
+
change the answer, and note any questions you'd need answered to give a more
|
|
22
|
+
precise recommendation.
|
|
23
|
+
- If something is unclear or underspecified, say so honestly. Do not guess.
|
|
24
|
+
|
|
25
|
+
{n_format}
|
|
26
|
+
|
|
27
|
+
Output ONLY the approaches. Do not include any meta-commentary, reasoning about
|
|
28
|
+
what you should write, or process notes — just the approaches themselves.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Write complete, working code for the following request.
|
|
2
|
+
|
|
3
|
+
Return ONLY the code (you may include brief inline comments), with no extra
|
|
4
|
+
prose, explanation, or markdown code fences unless the language requires them.
|
|
5
|
+
The code should be correct, handle obvious edge cases, and be self-contained.
|
|
6
|
+
|
|
7
|
+
If the request is too vague to write code for — for example it describes a
|
|
8
|
+
task without defining a key variable or asks for "an app that does X" without
|
|
9
|
+
explaining what X is — do not guess. Instead, return a short, plain-language
|
|
10
|
+
note saying what detail is missing and what you would need to proceed. Only
|
|
11
|
+
write code when the request gives you enough to do so faithfully.
|
|
12
|
+
|
|
13
|
+
Request: {prompt}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
The text below is a draft reply to the user's question, plus a blunt critique
|
|
2
|
+
of what's wrong or missing in it.
|
|
3
|
+
|
|
4
|
+
Produce the best, most honest version by ADDRESSING the critique — do not
|
|
5
|
+
merely restate the draft:
|
|
6
|
+
- For every issue the critique flagged, either fix it in the body (add the
|
|
7
|
+
missing point, correct an overclaim, name a cost or risk) or, if it can't be
|
|
8
|
+
fixed without information the user hasn't given, note that honestly.
|
|
9
|
+
- Keep what's useful. Drop anything misleading. Add the concrete points the
|
|
10
|
+
critique says were left out.
|
|
11
|
+
- Anchor strictly to the user's actual message and what was actually asked.
|
|
12
|
+
Never invent details, plans, or specifics they never provided.
|
|
13
|
+
- Keep concrete details that are already there: specific first moves,
|
|
14
|
+
constraints, trade-offs, or risks. Do not smooth those into generic advice.
|
|
15
|
+
|
|
16
|
+
Preserve the draft's structure. If the draft is well-organized, keep that
|
|
17
|
+
organization — headings, section breaks, lists, and prose ordinals (First,
|
|
18
|
+
Second, Finally). Do not flatten a structured answer into a generic blob.
|
|
19
|
+
|
|
20
|
+
Write it the way a smart, plain-spoken person would actually answer a friend:
|
|
21
|
+
- Lead with the bottom line.
|
|
22
|
+
- Use natural, specific, everyday language.
|
|
23
|
+
- Be concrete and admit uncertainty where it exists.
|
|
24
|
+
- Note assumptions you're taking for granted about the user.
|
|
25
|
+
- Include trade-offs and downsides honestly.
|
|
26
|
+
- If there are questions the user would need to answer for a more tailored
|
|
27
|
+
answer, include those.
|
|
28
|
+
|
|
29
|
+
Then, at the very end, include a "Worth clarifying:" section containing any
|
|
30
|
+
open questions from the context (and any unresolved critique issues). If there
|
|
31
|
+
are genuinely none, omit the section entirely.
|
|
32
|
+
|
|
33
|
+
Output ONLY the answer itself. Do not include any meta-commentary, reasoning
|
|
34
|
+
about what you changed, process notes, or phrases like "Here's a refined
|
|
35
|
+
version", "Below is the improved version", "I've revised it", or similar.
|
|
36
|
+
Stop writing immediately after the final section. Do not continue with
|
|
37
|
+
notes about your process, what you considered, or what you chose to do.
|
|
38
|
+
|
|
39
|
+
Draft reply + critique: {approaches_with_critiques}
|
|
40
|
+
Goal / things to keep in mind: {goal_and_assumptions}
|
|
41
|
+
|
|
42
|
+
The user's actual message (anchor your answer to this, never to details they
|
|
43
|
+
didn't provide): {goal_and_assumptions}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Refine the draft: make it more honest, concrete, and useful while preserving its
|
|
2
|
+
good substance.
|
|
3
|
+
|
|
4
|
+
- Check for any assumptions the draft makes about the user's context that it
|
|
5
|
+
doesn't acknowledge.
|
|
6
|
+
- If the draft references any invented name, product, or specific that the user
|
|
7
|
+
never gave, either use a generic placeholder or clearly label it as an
|
|
8
|
+
illustration.
|
|
9
|
+
- If the draft is overly certain about things that depend on unconfirmed input,
|
|
10
|
+
flag that uncertainty.
|
|
11
|
+
- Keep the bottom line near the front.
|
|
12
|
+
|
|
13
|
+
Write naturally. End with a "Worth clarifying:" section listing any open
|
|
14
|
+
context questions or unresolved assumptions that would change the answer, if
|
|
15
|
+
there are any. If there are none, omit that section entirely.
|
|
16
|
+
|
|
17
|
+
Output ONLY the refined answer.
|
|
18
|
+
|
|
19
|
+
Draft answer:
|
|
20
|
+
{draft}
|
|
21
|
+
|
|
22
|
+
Context:
|
|
23
|
+
{goal_and_assumptions}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Below is a draft answer. Review it for completeness and strengthen any
|
|
2
|
+
weak dimensions — without rewriting the answer from scratch.
|
|
3
|
+
|
|
4
|
+
Check for:
|
|
5
|
+
1. **Organization:** Is the answer well-structured and easy to scan? If it's a
|
|
6
|
+
dense wall of text, add section breaks and clear formatting. Keep any
|
|
7
|
+
existing structure — only add where it's genuinely missing.
|
|
8
|
+
|
|
9
|
+
2. **Honest reasoning:** Does the answer acknowledge genuine trade-offs,
|
|
10
|
+
downsides, risks, and alternatives where appropriate? If it's one-sided
|
|
11
|
+
advice, add the missing nuance.
|
|
12
|
+
|
|
13
|
+
3. **Assumptions and clarifying questions:** Does the answer note assumptions
|
|
14
|
+
it's making about the user's situation? If the answer would change
|
|
15
|
+
materially under different circumstances, that belongs in the answer (or
|
|
16
|
+
identified as a question to the user).
|
|
17
|
+
|
|
18
|
+
4. **Honesty about unknowns:** Does the answer honestly flag what it doesn't
|
|
19
|
+
know? If it sounds overly certain about things that depend on unconfirmed
|
|
20
|
+
context, say so. Do not fabricate specificity.
|
|
21
|
+
|
|
22
|
+
CRITICAL RULES:
|
|
23
|
+
- Keep the existing content, structure, and sections. Only add what's missing.
|
|
24
|
+
- Never flatten, restructure, or replace the existing answer.
|
|
25
|
+
- Use natural, plain language.
|
|
26
|
+
- If all dimensions are already strong, return the answer unchanged.
|
|
27
|
+
|
|
28
|
+
Draft answer:
|
|
29
|
+
{answer}
|
|
30
|
+
|
|
31
|
+
Goal / things to keep in mind:
|
|
32
|
+
{goal_and_assumptions}
|
|
33
|
+
|
|
34
|
+
Output ONLY the strengthened answer. No meta-commentary, no "Here's the revised
|
|
35
|
+
version", no explanation. Stop writing the moment the answer ends.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Review this code for correctness issues, edge cases, and bugs.
|
|
2
|
+
|
|
3
|
+
Respond with ONLY a plain bulleted list of specific issues, and NOTHING else
|
|
4
|
+
(no preamble, no summary, no corrected code). Each issue is ONE short concrete
|
|
5
|
+
bullet. If there are no issues, respond with a single line: (none)
|
|
6
|
+
|
|
7
|
+
{test_results}Code: {code}
|
reasonkit/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def count_issues(issues_by_approach: list[list[str]]) -> int:
|
|
7
|
+
# Total number of concrete issues across all approaches.
|
|
8
|
+
return sum(len(iss) for iss in issues_by_approach)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def should_stop(
|
|
12
|
+
cycle: int,
|
|
13
|
+
max_cycles: int,
|
|
14
|
+
issues_by_approach: list[list[str]],
|
|
15
|
+
previous_issue_count: Optional[int],
|
|
16
|
+
) -> tuple[bool, str]:
|
|
17
|
+
# Return (stop, reason) with reason in no_issues/no_improvement/max_cycles.
|
|
18
|
+
total = count_issues(issues_by_approach)
|
|
19
|
+
|
|
20
|
+
if total == 0:
|
|
21
|
+
return True, "no_issues"
|
|
22
|
+
|
|
23
|
+
if previous_issue_count is not None and total >= previous_issue_count:
|
|
24
|
+
return True, "no_improvement" # list didn't shrink
|
|
25
|
+
|
|
26
|
+
if cycle >= max_cycles:
|
|
27
|
+
return True, "max_cycles"
|
|
28
|
+
|
|
29
|
+
return False, ""
|
reasonkit/trace.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class CallRecord:
|
|
9
|
+
# One call ReasonKit made through the wrapped function.
|
|
10
|
+
|
|
11
|
+
stage: str # classify | generate | critique | merge | answer
|
|
12
|
+
prompt: str # exact prompt sent to fn
|
|
13
|
+
response: str # raw string fn returned
|
|
14
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Trace:
|
|
19
|
+
# Everything that happened inside one enhance() run.
|
|
20
|
+
|
|
21
|
+
mode: str = "unknown" # decision | code | direct
|
|
22
|
+
calls: list[CallRecord] = field(default_factory=list)
|
|
23
|
+
cycles: int = 0
|
|
24
|
+
stopped_reason: str = "unknown" # no_issues | no_improvement | max_cycles
|
|
25
|
+
classification: dict[str, Any] = field(default_factory=dict)
|
|
26
|
+
notes: list[str] = field(default_factory=list)
|
|
27
|
+
code_versions: list[str] = field(default_factory=list) # each draft/fix
|
|
28
|
+
|
|
29
|
+
def add_call(self, stage: str, prompt: str, response: str, **metadata: Any) -> CallRecord:
|
|
30
|
+
rec = CallRecord(stage=stage, prompt=prompt, response=response, metadata=dict(metadata))
|
|
31
|
+
self.calls.append(rec)
|
|
32
|
+
return rec
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def call_count(self) -> int:
|
|
36
|
+
return len(self.calls)
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> dict[str, Any]:
|
|
39
|
+
return {
|
|
40
|
+
"mode": self.mode,
|
|
41
|
+
"cycles": self.cycles,
|
|
42
|
+
"stopped_reason": self.stopped_reason,
|
|
43
|
+
"call_count": self.call_count,
|
|
44
|
+
"classification": self.classification,
|
|
45
|
+
"notes": self.notes,
|
|
46
|
+
"code_versions": self.code_versions,
|
|
47
|
+
"calls": [
|
|
48
|
+
{
|
|
49
|
+
"stage": c.stage,
|
|
50
|
+
"prompt": c.prompt,
|
|
51
|
+
"response": c.response,
|
|
52
|
+
"metadata": c.metadata,
|
|
53
|
+
}
|
|
54
|
+
for c in self.calls
|
|
55
|
+
],
|
|
56
|
+
}
|