docs/StrategyEngine/06-ImplementationPlan.md
This document turns the Strategy Engine spec into an implementation sequence suitable for an agent or engineer.
The implementation should be incremental. Do not attempt to replace the existing Strategy Engine in one large change. Preserve current builtin Strategy behavior while introducing the new file format, matching model, and execution hooks.
M1. Domain model and versioned definitions
M2. SharpYaml strategy parser and validation
M3. Hand-written normalizer and `from` source resolution
M4. Skills v1 registry and `skill://id` resolution
M5. Condition DSL and three-valued evaluator
M6. ExtraContext provider pipeline
M7. Visual query DSL subset
M8. Preprocessor execution pipeline
M9. UI/diagnostics integration
M10. Migration cleanup and tests
Each milestone should be independently testable.
Introduce target model types without breaking existing UI:
StrategyDefinitionV1
StrategyDocument
StrategyNormalizationResult
StrategySource
StrategyFromReference
StrategyOptions
StrategyCandidate
ConditionEvaluationResult
StrategyDiagnostic
ExtraContextSnapshot
ExtraContextNode
StrategyExecutionContext
The existing Strategy record should evolve into the runtime model. Because Strategy serialization is not yet established, avoid creating a parallel runtime type if the current Strategy can be adapted cleanly.
Required distinction:
StrategyDefinitionV1 = versioned authoring model parsed from YAML
Strategy = runtime model used by matching, UI, execution, and chat messages
Do not use Dto suffixes. Do not introduce AutoMapper as the semantic conversion layer.
UserStrategyChatMessage.Strategy construction.Implement a parser for Markdown + YAML frontmatter.
Use SharpYaml for YAML serialization/deserialization. Prefer source-generated metadata where practical. v1 does not support comment-preserving roundtrip; Strategy Editor may rewrite frontmatter into canonical formatting.
Input:
path to .strategy.md
raw markdown content
provider id
Output:
StrategyDocument
StrategyDefinitionV1
diagnostics
The parser must not execute code in the file.
Map all v1 fields:
schema
id
from
enabled
name
description
icon
priority
when
tools
preprocessors
systemPrompt
options
body
Implement validation from 05-ConfigurationFormat.md.
Invalid user files should:
.strategy.md files parse into definitions.tools shape returns diagnostics.from Source Resolutionpublic interface IStrategyDefinitionNormalizer
{
string Schema { get; }
Task<StrategyNormalizationResult> NormalizeAsync(
StrategyDocument document,
StrategyLoadContext context,
CancellationToken cancellationToken);
}
The normalizer owns:
from resolution.Do not use AutoMapper-style runtime mapping for this path. Field count is small, and the conversion is closer to compilation than object copying.
public interface IStrategySourceResolver
{
bool CanResolve(StrategyFromReference reference, StrategySource currentSource);
Task<StrategyDocument> ResolveAsync(
StrategyFromReference reference,
StrategySource currentSource,
CancellationToken cancellationToken);
}
Required resolvers:
URL resolver should be interface-ready but may return unsupported until a network policy is defined.
Implement replace-only override:
Strategy.Source points to current file.Strategy.Includes and diagnostics.from rejected in v1../SKILL.md.from produces validation diagnostic.skill://id ResolutionSkills v1 is deliberately small. It is not another Strategy Engine.
Implement:
skill://id resolver for Strategy from.Do not implement:
Suggested model:
public sealed record SkillDescriptor
{
public required string Id { get; init; }
public required string Name { get; init; }
public string? Description { get; init; }
public required string FilePath { get; init; }
public string SourceKind { get; init; } = "user";
public bool Enabled { get; init; }
}
Prompt injection should include only an index, not full skill contents:
Available skills:
- writing.polite: Polite writing style.
Path: E:\Everywhere\Skills\writing.polite\SKILL.md
- coding.review: Code review guidance.
Path: E:\Everywhere\Skills\coding.review\SKILL.md
The enabled skill index must include each skill's complete SKILL.md file path. The model reads skill content by calling read_file with that path. skill://id remains an internal/reference URI for Strategy from; read_file does not need to support skill://id for Skills v1.
Acceptance criteria:
SKILL.md paths.from: skill://id resolves enabled or installed skill according to policy.Represent:
true
false
all
any
none
path condition
visual condition
Path condition stores:
path
operator object
source location
bool? evaluationRules:
all: false beats null; all true => true; otherwise null
any: true beats null; all false => false; otherwise null
none: not(any), preserving null
Only root true recommends the Strategy.
Required operators:
equals
in
contains
startsWith
endsWith
regex
glob
caseSensitive
length
count
min
max
any
all
none
null.false with diagnostic.null.none over missing path returns null, not true.any/all/none works on object item relative paths.Walk condition AST and infer required roots:
extra.file_manager
extra.browser
extra.workspace
clipboard
assistant
visual
No user-authored requires section.
public interface IExtraContextProvider
{
string Id { get; }
string PublicRoot { get; }
IDynamicResourceKey PermissionDescriptionKey { get; }
bool CanCollect(StrategyContext baseContext, ExtraContextRequest request);
Task<ExtraContextNode?> CollectAsync(
StrategyContext baseContext,
ExtraContextRequest request,
CancellationToken cancellationToken);
}
Public root:
extra.file_manager
Windows provider:
Id: windows.explorer
PublicRoot: extra.file_manager
Target fields:
current_folder.path
current_folder.displayName
selection.items[].path
selection.items[].displayName
selection.items[].kind
selection.items[].extension
selection.items[].size
Implementation notes:
extraTimeout.macOS provider:
Id: macos.finder
PublicRoot: extra.file_manager
Implementation notes:
extra.file_manager.selection.items works on supported Windows Explorer scenarios.null, not exception.null and diagnostic.Implement only the subset defined in 05-ConfigurationFormat.md.
Supported:
//Type
/Type/Type
.
*
@name
@text
@process
@selected
@focused
@disabled
@readonly
@offscreen
@password
@bounds.x/y/width/height
[@attr=value]
contains(@attr,'value')
matches(@attr,'regex')
visual.exists, visual.count, and visual.match are the only v1 visual conditions.
visual.exists works with element type and boolean state.visual.count respects min/max.visual.match reads an attribute and applies string operators.@text is only read when explicitly referenced.null.Implement:
public interface IStrategyPreprocessorRegistry
{
bool TryGet(string id, out IStrategyPreprocessor preprocessor);
IReadOnlyList<IStrategyPreprocessor> GetAll();
}
Before sending a Strategy-backed user message:
StrategyExecutionContext.PreprocessorResult.UserStrategyChatMessage.Keep {Argument} alias.
Add path-style variables:
{attachments.selection.text}
{extra.file_manager.selection.items}
{preprocess.file_manager.selection.text}
PreprocessorResult unless explicitly rerun by design.Existing Strategy recommendation UI can continue showing:
icon
name
description
priority-sorted order
Add or prepare a details view showing:
IDynamicResourceKey.Show ordinary-user toast when strategies are slow/skipped:
Some strategies took too long to check and were skipped.
Rate-limit toasts.
After new pipeline works:
Strategy construction, StrategyDefinitionV1, or embedded .strategy.md.Strategy only if it remains useful for serialization.UserStrategyChatMessage.| Test | Expected |
|---|---|
| Minimal valid Strategy | Parses. |
| Missing frontmatter | Parses as markdown only when used via from kind markdown/skill. |
| Invalid YAML | Diagnostic. |
| Invalid duration | Diagnostic. |
| Invalid tools map | Diagnostic. |
| Body preserved | Body matches expected text. |
from tests| Test | Expected |
|---|---|
Relative ./SKILL.md | Source body loaded. |
| Current body exists | Source body replaced. |
| Current body absent | Source body inherited. |
| Override name | Current name wins. |
Nested from | Diagnostic. |
| Test | Expected |
|---|---|
Discover valid SKILL.md | SkillDescriptor created. |
| Missing explicit metadata | Name inferred from H1 or directory. |
| Enable skill | Appears in prompt index. |
| Disable skill | Omitted from prompt index. |
| Duplicate ID | Diagnostic. |
from: skill://id | Resolves to skill source. |
| Test | Expected |
|---|---|
| Missing path | null. |
| Root null | Strategy hidden. |
all false/null | false if any false, otherwise null. |
any true/null | true if any true. |
none over null | null. |
| Regex timeout | null diagnostic. |
| Array any extension | true for matching item. |
| Test | Expected |
|---|---|
Referenced extra.file_manager | Provider inferred. |
| Provider unavailable | path resolves null. |
| Provider timeout | null diagnostic. |
| Virtual item | kind virtual, path null. |
| Test | Expected |
|---|---|
//Button | Finds descendants. |
@name match | Reads attribute. |
@text not referenced | Does not call GetText. |
| Invalid query | Validation diagnostic. |
| Query timeout | null diagnostic. |
| Test | Expected |
|---|---|
| Declared order | Later variable overrides earlier. |
| Unknown ID | Validation/execution failure. |
| Timeout | Execution stopped. |
| Variable interpolation | Rendered body contains value. |
| Retry | Uses persisted preprocessor result. |
| Test | Expected |
|---|---|
| Builtin Strategies still show | No regression. |
User .strategy.md shows when condition true | Recommendation appears. |
User .strategy.md hidden when root null | No recommendation. |
| Strategy ToolRulesets applied | Chat plugins filtered. |
| Invalid user Strategy | App does not crash. |
ToolRulesets behavior must remain.{Argument} must remain.When implementing this spec:
src/Everywhere.Core/StrategyEngine.IExtraContextProvider.SKILL.md; only explicit .strategy.md or imported managed skill references.v1 is complete when:
.strategy.md files can be loaded.StrategyDefinitionV1.Strategy.from can reference local SKILL.md.from: skill://id resolves through the Skills registry.all/any/none, and bool?.extra.file_manager.* schema is implemented on Windows or clearly marked unsupported with null diagnostics.ToolRulesets remains applied.