wip(microsteps): B3.3 + B3.10 part 1 — prompts + microstep_patterns schema
Storage-side scaffolding for B3.3 (granularity prompt variants) and B3.10 (mastery fade). The user-facing wiring (decompose_and_store granularity threading, complete_subtask_cmd count bump, MicroSteps inline prompt + skip-check, Settings UI) is part 2 of this batch. B3.3 (prompts.rs): three new system-prompt constants DECOMPOSE_LIGHT_SYSTEM (3 atomic verb-first steps), DECOMPOSE_DEFAULT_SYSTEM (4-5 balanced steps), DECOMPOSE_DETAILED_SYSTEM (6-7 with brief context) all preserve the cue-anchored "When [cue], [action]" framing from PR 1.1. DECOMPOSE_TASK_SYSTEM remains as an alias of Default for back-compat with existing callers and tests. 4 snapshot tests assert the framing survives across variants and the alias matches. B3.10 (storage): migration v18 adds microstep_patterns (normalized_title PK, sample_title, completed_count, skip_breakdown, prompted_at) plus an index on completed_count. New storage functions: normalize_microstep_title (lowercase + whitespace-collapse + trim), get_microstep_pattern, upsert_microstep_pattern_increment, set_microstep_pattern_decision. 5 storage tests cover normalisation, upsert/bump semantics, decision persistence, and the threshold query. 74 storage tests pass (was 69), 9 prompts tests pass (was 5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,40 @@
|
||||
pub const DECOMPOSE_TASK_SYSTEM: &str = "\
|
||||
pub const DECOMPOSE_LIGHT_SYSTEM: &str = "\
|
||||
You are a task-decomposition assistant. Given a task description, produce \
|
||||
between 3 and 7 concrete, physical micro-steps. Each step must be a short \
|
||||
exactly 3 concrete, physical micro-steps. Each step must be a short, \
|
||||
verb-first imperative sentence — atomic enough to do without thinking. \
|
||||
No commentary. Where the task description contains a natural cue (a \
|
||||
place, a time, a preceding action, an object the user will already be \
|
||||
holding), phrase that step as \"When [cue], [action]\" so the cue \
|
||||
triggers the action. Use this framing only where the cue is genuinely \
|
||||
present in the input — do not invent cues. Output ONLY a JSON array of \
|
||||
strings.";
|
||||
|
||||
pub const DECOMPOSE_DEFAULT_SYSTEM: &str = "\
|
||||
You are a task-decomposition assistant. Given a task description, produce \
|
||||
between 4 and 5 concrete, physical micro-steps. Each step must be a short \
|
||||
imperative sentence, actionable today, with no commentary. Where the task \
|
||||
description contains a natural cue (a place, a time, a preceding action, an \
|
||||
object the user will already be holding), phrase that step as \
|
||||
\"When [cue], [action]\" so the cue triggers the action. Use this framing \
|
||||
only where the cue is genuinely present in the input — do not invent cues. \
|
||||
Steps without a natural cue stay as plain imperatives. Output ONLY a \
|
||||
JSON array of strings.";
|
||||
description contains a natural cue (a place, a time, a preceding action, \
|
||||
an object the user will already be holding), phrase that step as \
|
||||
\"When [cue], [action]\" so the cue triggers the action. Use this \
|
||||
framing only where the cue is genuinely present in the input — do not \
|
||||
invent cues. Steps without a natural cue stay as plain imperatives. \
|
||||
Output ONLY a JSON array of strings.";
|
||||
|
||||
pub const DECOMPOSE_DETAILED_SYSTEM: &str = "\
|
||||
You are a task-decomposition assistant. Given a task description, produce \
|
||||
between 6 and 7 concrete, physical micro-steps. Each step must be a short \
|
||||
imperative sentence, actionable today. Brief context (one short clause) \
|
||||
is allowed where it makes the next move obvious; otherwise no commentary. \
|
||||
Where the task description contains a natural cue (a place, a time, a \
|
||||
preceding action, an object the user will already be holding), phrase \
|
||||
that step as \"When [cue], [action]\" so the cue triggers the action. \
|
||||
Use this framing only where the cue is genuinely present in the input — \
|
||||
do not invent cues. Steps without a natural cue stay as plain imperatives. \
|
||||
Output ONLY a JSON array of strings.";
|
||||
|
||||
/// Back-compat alias — existing callers and tests that reference
|
||||
/// `DECOMPOSE_TASK_SYSTEM` continue to compile unchanged.
|
||||
pub const DECOMPOSE_TASK_SYSTEM: &str = DECOMPOSE_DEFAULT_SYSTEM;
|
||||
|
||||
// Phase 9 content-tag extraction. The model emits a {topic, intent}
|
||||
// JSON pair under a strict GBNF (see grammars::CONTENT_TAGS_GRAMMAR).
|
||||
@@ -139,6 +166,42 @@ pub fn build_conditioned_system_prompt(base: &str, examples: &[FeedbackExample])
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// --- B3.3 snapshot tests ---
|
||||
|
||||
#[test]
|
||||
fn light_prompt_contains_cue_anchored_framing() {
|
||||
assert!(
|
||||
DECOMPOSE_LIGHT_SYSTEM.contains("When [cue], [action]"),
|
||||
"DECOMPOSE_LIGHT_SYSTEM must contain the cue-anchored framing"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_prompt_contains_cue_anchored_framing() {
|
||||
assert!(
|
||||
DECOMPOSE_DEFAULT_SYSTEM.contains("When [cue], [action]"),
|
||||
"DECOMPOSE_DEFAULT_SYSTEM must contain the cue-anchored framing"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detailed_prompt_contains_cue_anchored_framing() {
|
||||
assert!(
|
||||
DECOMPOSE_DETAILED_SYSTEM.contains("When [cue], [action]"),
|
||||
"DECOMPOSE_DETAILED_SYSTEM must contain the cue-anchored framing"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_alias_matches_default_const() {
|
||||
assert_eq!(
|
||||
DECOMPOSE_TASK_SYSTEM, DECOMPOSE_DEFAULT_SYSTEM,
|
||||
"DECOMPOSE_TASK_SYSTEM must be the same value as DECOMPOSE_DEFAULT_SYSTEM"
|
||||
);
|
||||
}
|
||||
|
||||
// --- existing conditioned-prompt tests ---
|
||||
|
||||
#[test]
|
||||
fn builds_plain_prompt_when_no_examples() {
|
||||
let out = build_conditioned_system_prompt(DECOMPOSE_TASK_SYSTEM, &[]);
|
||||
|
||||
Reference in New Issue
Block a user