Implement ADR 0013 so persisted artifacts remain durable without semantic cache poisoning, while enabling emergent promotion by giving the Agent explicit pattern memory.
This plan preserves:
- Stable artifact identity (
role + method_name) from ADR 0012. - Agent-first promotion decisions (runtime provides observations, not decisions).
- Tolerant interface behavior and typed Outcome semantics.
In scope:
- Cacheability metadata and reuse gating for persisted artifacts.
- Runtime capability-pattern extraction from generated code.
- Bounded cross-call pattern memory persistence.
- Prompt injection of
<recent_patterns>for depth-0 calls. - Observability, tests, and evaluation loops for promotion quality.
Out of scope:
- Runtime-autonomous promotion (runtime forcing Forge).
- Semantic LLM classification in v1 pattern extraction.
- Lua runtime parity.
Already implemented:
- Artifact cacheability metadata (
cacheable,cacheability_reason,input_sensitive). - Reuse gate in artifact selector (non-cacheable artifacts are persisted but not reused).
- Legacy compatibility fallback (dynamic methods not reused when cacheability metadata is absent).
- Dynamic dispatch method set (
ask,chat,discuss,host) as non-cacheable by default. - Call-level logging fields for cacheability.
Remaining for ADR 0013 completion:
- Pattern extraction and persistence.
<recent_patterns>prompt injection.- Promotion-signal evaluation and threshold tuning.
- Artifact identity remains
role + method_name; do not expand key shape. - Runtime controls execution eligibility; model cannot force cacheable reuse.
- Pattern memory contains labels/counts/recency only; never inject prior raw code.
- Pattern memory must be bounded and deterministic.
- Runtime ergonomics first: keep implementation simple, inspectable, and recoverable.
Deliver in five phases. Each phase is testable and independently valuable.
Goals:
- Establish deterministic capability tag set and extraction contract.
- Capture baseline behavior for Google/Yahoo/NYT sequence before pattern injection.
Implementation:
- Define capability tags (initial v1 list):
http_fetchrss_parsexml_parsehtml_extractnews_headline_extract- Keep this list intentionally small; do not add speculative tags. Add tags only when traces show a missed promotion signal.
- Define deterministic extraction sources:
require 'rss'->rss_parseRSS::Parser->rss_parserequire 'rexml/document'orREXML::Document->xml_parseNet::HTTPuse ortool("web_fetcher")->http_fetch- collection iteration that extracts both
titleandlinkfields into structured output ->news_headline_extract
- Capture baseline traces from:
runtimes/ruby/examples/assistant.rb- prompts: Google News, Yahoo News, NYT.
Exit criteria:
- Capability extraction contract documented and reviewed.
- Baseline trace fixture committed under
docs/baselines/<date>/.
Goals:
- Tag each generated/repaired call with deterministic capability labels.
- Keep extraction local and low-latency.
Implementation:
- Add
CapabilityPatternExtractormodule:- input: method name, role, generated code, args/kwargs, outcome.
- output: label array + extraction evidence.
- Integrate extractor in call flow after generated code capture (and after repaired code generation).
- Emit extracted labels into log entry.
Suggested files:
runtimes/ruby/lib/recurgent/capability_pattern_extractor.rbruntimes/ruby/lib/recurgent/call_state.rbruntimes/ruby/lib/recurgent/call_execution.rbruntimes/ruby/lib/recurgent/artifact_repair.rbruntimes/ruby/lib/recurgent/observability.rb
Exit criteria:
- Every generated/repaired call log includes
capability_patterns. - Extraction is deterministic for fixed code input.
Goals:
- Persist bounded recent pattern history across sessions.
- Provide fast read API for prompt assembly.
Implementation:
- Add pattern store file:
tools/patterns.json
- Store schema (v1):
schema_version- per-role rolling events (max N, default 50)
- per-role aggregate counts for recent windows (for example 5 and 10)
- Event record shape:
timestamprolemethod_namecapability_patterns[]outcome_statuserror_type
- Write policy:
- append logical event, trim by retention cap, atomic temp+rename write.
- Read API:
recent_patterns_for(role:, method_name:, window:)returning count summaries.
Suggested files:
runtimes/ruby/lib/recurgent/pattern_memory_store.rbruntimes/ruby/lib/recurgent/tool_store_paths.rb(path helper)runtimes/ruby/lib/recurgent/call_execution.rb(write hook)
Exit criteria:
- Pattern memory survives process restart.
- Corrupt file quarantine behavior mirrors registry/artifact strategy.
Goals:
- Expose repetition signal to the depth-0 agent.
- Keep prompt block concise and non-prescriptive.
Implementation:
- Add prompt builder method:
- only for depth-0 calls,
- primarily for dynamic dispatch methods (for example
ask).
- Inject block format:
<recent_patterns>
- rss_parse: seen 3 of last 5 ask calls, tool_present=false
- http_fetch: seen 5 of last 5 ask calls, tool_present=true(web_fetcher)
</recent_patterns>- Add nudge language:
- "If a general capability repeats and no Tool exists, consider Forging now."
- Ensure no raw code inclusion in this block.
Suggested files:
runtimes/ruby/lib/recurgent/prompting.rbruntimes/ruby/lib/recurgent/known_tool_ranker.rb(optional utility reuse)runtimes/ruby/lib/recurgent/call_execution.rb(pass method context to prompt builder if needed)
Exit criteria:
- Debug logs show
<recent_patterns>for depth-0 dynamic calls. - Block is absent for depth>0 and bounded to top-N entries.
Goals:
- Verify that pattern memory increases coherent promotion events.
- Tune thresholds without runtime-autonomous promotion.
Implementation:
- Add derived observability metrics:
promotion_candidate_detected(boolean)promotion_candidate_capabilities[]tool_forged_this_call(already inferable via registry delta)
- Evaluate scenarios:
- repeated news queries (Google, Yahoo, NYT, BBC),
- repeated RSS-like feeds from varied domains.
- unrelated dynamic queries (for example news -> timezone -> haiku) to validate low false-positive promotion signaling.
- Tune defaults:
- initial recommendation: promote general capability at 2+ observed repeats in last 5.
Exit criteria:
- Demonstrated increase in coherent reusable tool creation (for example
rss_parseremergence). - No regression in dynamic-method correctness (no cross-query semantic leakage).
{
"schema_version": 1,
"roles": {
"personal assistant that remembers conversation history": {
"events": [
{
"timestamp": "2026-02-15T07:00:00.000Z",
"method_name": "ask",
"capability_patterns": ["http_fetch", "rss_parse", "news_headline_extract"],
"outcome_status": "ok",
"error_type": null
}
]
}
}
}Constraints:
- Events are newest-last or newest-first (choose one, document clearly).
- Retention cap enforced per role.
- JSON-serializable primitives only.
CapabilityPatternExtractormapping:- RSS code ->
rss_parse - REXML code ->
xml_parse - HTTP fetch patterns ->
http_fetch
- RSS code ->
- Pattern store:
- read/write/trim behavior,
- atomic write,
- corrupt-file quarantine and recovery.
- Prompt rendering:
- includes
<recent_patterns>only when applicable, - excludes raw prior code.
- includes
- Dynamic method non-reuse:
ask("Google")thenask("Yahoo")must generate twice.
- Stable tool reuse remains intact:
web_fetcher.fetch_url(url1/url2)can reuse artifact.
- Pattern-memory persistence:
- restart process;
<recent_patterns>still reflects prior calls.
- restart process;
- News sequence:
- Google -> Yahoo -> NYT
- verify pattern block appears and evolves.
- Promotion behavior:
- verify tool registry gains generalized parser tool in repeated-capability scenario (non-deterministic; validate with seeded deterministic provider tests + manual trace validation).
- Negative promotion case:
- run unrelated dynamic
asksequence and verify pattern memory does not emit spurious promotion candidates.
- run unrelated dynamic
- Ship Phase 1+2 first (observation only, no prompt injection) if needed for safe validation.
- Enable Phase 3 prompt injection once pattern data quality is acceptable.
- Keep runtime read-path behavior unchanged during Phase 1-2.
- Add maintenance command extension (optional):
bin/recurgent-tools patterns --role <role> --window 5
- Risk: noisy/incorrect capability tagging.
- Mitigation: start with deterministic regex + stdlib require signals; evolve taxonomy cautiously.
- Risk: prompt bloat.
- Mitigation: strict top-N and short label summaries.
- Risk: over-promotion due to shallow patterns.
- Mitigation: require repeated counts + no-existing-tool condition in prompt nudge.
- Risk: hidden coupling to implementation syntax.
- Mitigation: maintain extractor fixtures across known code variants.
- Capability extractor implemented and tested.
- Pattern memory store implemented and tested.
-
<recent_patterns>prompt injection implemented and tested. - Observability fields and watcher support updated.
- End-to-end news sequence validated with trace evidence.
- Baseline comparison committed: pre/post pattern-memory traces for Google/Yahoo/NYT showing promotion behavior change.
- ADR 0013 status reviewed for
acceptedtransition after stable rollout.