Skip to content

Feature-preservation matrix

FP-2 review artifact, inspected at cd12d688a19f73f34995c9af6b86e72f5f6d7886 on fix/fp1-metacognition-preservation. It is an outcome inventory, not a declaration that the 11.0 migration preserves every feature. The companion machine-readable inventory is the row-level source of truth; it records the legacy trigger, observable, live owner, required wiring, exact source file, named meaningful public test (or MISSING), risk, next action, and owning FP ticket for every row.

Run the checked-in verifier from a source checkout so imports resolve to the reviewed tree:

PYTHONPATH=src python \
  scripts/validate_feature_preservation_inventory.py

It derives the 38 flat names from RETIRED_SETTINGS, cross-checks the selected partial rows against live cutover tables, requires all evidence fields, and derives the seven continuation contexts from RECONCILED_ROWS. Its high-risk check only detects a missing cited source anchor; the source audit, rather than a marker search, assigns the behavior class. It deliberately does not turn a passing inventory check into behavioral parity.

Reading a classification

Classification Meaning
equivalent-proven A supported public observable has meaningful evidence.
replacement-unverified A live capability/port exists, but automatic composition or old/new outcome parity is not proved.
behavior-changed The replacement has a verified, intentional, or structural semantic difference.
removed-without-equivalent No supported owner currently expresses the old behavior.
legacy-inert The legacy input had no reachable behavior to preserve.
admitted-but-inactive An admitted cutover control does not configure a reachable admitted-route consumer. This says nothing about whether legacy behavior was inert.
unresolved The evidence is insufficient.

Admission, rejection, imports, and a similarly named field are not evidence of parity. A missing proof stays visible as MISSING, with a bounded next action.

Flat retired/replaced settings (38)

The source column below is a readable routing label. The linked JSON carries the exact repository-relative source and test paths, along with the full legacy trigger and observable, without making this table unreasonably wide.

Control Classification Live owner and required wiring Source; evidence Risk → action (owner)
extraction_template_path unresolved Legacy MemoryExtractionSection(template_path=...); no verified migrated consumer src/symfonic/agent/engine.py; MISSING public custom-directive extraction journey this is an HMS directive template, not a phase-12 nap setting → trace prompt and extraction result (FP-3)
phase_12_action_type_from_tool_calls replacement-unverified LearningPolicy → consolidation memory/policy.py; test_phase_12_tool_calls_fallback.py naming/semantics → compare nap (FP-3)
phase_12_llm_max_drafts_per_run replacement-unverified LearningPolicy → extractor memory/policy.py; MISSING public cap cap may not compose → boundary (FP-3)
phase_12_llm_max_episodes_per_run replacement-unverified LearningPolicy.as_kwargs() → extractor memory/policy.py; test_llm_procedural_extractor.py field alone is not end-to-end proof → candidate count (FP-3)
phase_12_llm_model replacement-unverified as_phase_kwargs().procedural_model_namenightly_phases memory/policy.py; MISSING selected-model public assertion provider drift → capture model (FP-3)
phase_12_promote_assistant_content replacement-unverified LearningPolicy → promotion memory/policy.py; test_learning_policy.py mapping only → assistant nap (FP-3)
phase_12_use_llm_extractor replacement-unverified policy plus extractor collaborator memory/policy.py; MISSING composed selector flag can be inert → both branches (FP-3)
promotion_max_drafts_per_run replacement-unverified LearningPolicy → promotion memory/policy.py; test_learning_policy.py missing output cap proof → over-cap journey (FP-3)
promotion_min_pattern_count replacement-unverified LearningPolicy → promotion memory/policy.py; MISSING N-1/N threshold drift → boundary (FP-3)
promotion_recency_days replacement-unverified LearningPolicy → promotion memory/policy.py; MISSING date boundary lookback drift → fixture (FP-3)
synthetic_link_min_co_count replacement-unverified LearningPolicy → synthetic phase memory/policy.py; test_synthetic_min_co_count_config.py composition unproved → public link boundary (FP-3)
nightly_nap_cron legacy-inert Operator scheduler metadata; engine never parsed cron src/symfonic/agent/config.py; MISSING operator-scheduler contract stale retirement prose implied an engine loop → keep operator compatibility separate (FP-4)
nightly_nap_enabled legacy-inert Operator scheduler metadata; engine never started a loop src/symfonic/agent/config.py; MISSING operator-scheduler contract stale retirement prose described automatic scheduling → keep operator compatibility separate (FP-4)
quick_nap_interval replacement-unverified ConsolidationSchedule + coordinator + memory capability memory/schedule.py; test_nap_after_the_turn.py native cadence is tested, legacy disable/per-scope semantics are not → old/new matrix (FP-3)
metacognition_confidence_threshold behavior-changed default SelectiveMetacognitionPolicy governance/stages/metacognition_policy.py; test_metacognition_preservation.py confidence is supplemental → migration guidance (FP-1)
metacognition_gate behavior-changed governance(trigger_policy=...) governance/stages/metacognition.py; test_metacognition_preservation.py callable signature/context changes → example (FP-1)
metacognition_selective_gate behavior-changed governance capability default policy governance/stages/metacognition_policy.py; test_metacognition_preservation.py old spelling rejected → guide (FP-1)
metacognition_sensitive_tags behavior-changed sensitive_tags plus caller state evidence governance/stages/metacognition_policy.py; test_metacognition_preservation.py retrieval must actually carry tags → caller journey (FP-3)
metacognition_trivial_ack_patterns replacement-unverified explicit trivial_ack_patterns policy governance/stages/metacognition_policy.py; test_metacognition_preservation.py custom parity absent → custom test (FP-1)
activation_log_mode removed-without-equivalent No activation-log consumer cutover/retired_settings.py; MISSING prompt comparison footer loss → product decision (FP-4)
prompt_block_self_edit legacy-inert None cutover/retired_settings.py; test_retired_configuration.py stale docs → remove guidance (FP-4)
dev_sqlite_checkpoint_path behavior-changed human_interaction(...) plus AgentHost(continuation_factory=human_continuation(...)) platform/human_continuation.py; test_public_host_continues_a_durable_pause_in_a_fresh_process a bare path is rejected early; the supported port composition proves SQLite recovery, authenticated scope binding and single use (FP-4)
scorer_on_hot_path replacement-unverified Retrieval capability/coordinator cutover/memory_retrieval_rows.py; test_memory_retrieval_lane.py rank semantics unproved → ordered recall (FP-3)
state_class removed-without-equivalent No kernel state-class seam cutover/retired_settings.py; MISSING adopter inventory extension break → survey uses (FP-4)
experimental_tool_decorator legacy-inert Always-public @symfonic_tool cutover/retired_settings.py; test_retired_configuration.py stale config → remove docs (FP-4)
ask_user_pause_ttl_seconds behavior-changed TTLPolicy in human capability cutover/pause_surfaces.py; test_pause_policy_lane.py max rejects rather than clamps → expiry/restart (FP-3)
ask_user_tool_descriptions equivalent-proven InteractionToolSpec.description cutover/pause_surfaces.py; test_pause_policy_lane.py localization not scaffold-tested → scaffold check (FP-4)
procedural_force_first_action_tool replacement-unverified procedural_force_tool_choice='soft' plus live loop cutover/force_lever.py; test_tools_policy_lane.py replacement spelling may remain refused → stateful journey (FP-3)
credential_patterns behavior-changed CredentialHygieneStage cutover/governance_surfaces.py; test_governance_amends.py custom/disable semantics lost → secret matrix (FP-4)
fabrication_refuse_min_confidence behavior-changed FabricationStage grades cutover/governance_surfaces.py; test_egress_stages.py two-threshold semantics → public boundaries (FP-1)
hms_budget_mode behavior-changed PromptBudget cutover/prompt_assembly_policy.py; test_prompt_assembly_lane.py drop order differs → replay (FP-3)
hms_system_prompt_token_budget behavior-changed PromptBudget.max_total_tokens cutover/prompt_assembly_policy.py; test_prompt_assembly_lane.py region differs → prompt replay (FP-3)
on_hms_budget_exceeded removed-without-equivalent No public callback cutover/prompt_assembly_policy.py; MISSING observer operational blind spot → hook decision (FP-4)
jit_manifest_token_budget behavior-changed Shared PromptBudget cutover/prompt_assembly_policy.py; MISSING region test allocation change → fixture (FP-3)
manifest_cache_position behavior-changed Derived cache-region plan cutover/prompt_assembly_policy.py; MISSING provider capture marker changes → outbound capture (FP-3)
memory_extract_cadence removed-without-equivalent No prompt-cadence consumer cutover/prompt_assembly_policy.py; MISSING contract prompt behavior loss → decision (FP-4)
messages_cache_policy removed-without-equivalent Prompt cache has no rolling-history equivalent cutover/prompt_assembly_policy.py; MISSING multi-turn capture cost/latency risk → serialization journey (FP-3)
system_prefix_cache_ttl equivalent-proven Stable PromptContribution cache directive plus provider serializer prompting/assembly.py; test_public_two_turn_cache_reaches_anthropic_wire_with_ttl_marker Anthropic wire capture proves the 1h system marker; history is a separate, uncached contract (FP-4)

FP-1 metacognition update and enforcement boundary

FP-1 changed the reviewed target from the old scalar-only stage. SelectiveMetacognitionPolicy is the default, ConfidenceOnlyMetacognitionPolicy is an explicit opt-out, and tests/platform/test_metacognition_preservation.py covers public run and drained-stream triggers for claims, mutating tools, action/ambiguous intent, fabrication findings, caller-supplied recalled tags, trivial acknowledgments, custom policy, and invalid confidence signals. The matrix therefore no longer calls sensitive tags removed merely because they are not inferred from draft text.

This proves critic invocation coverage, not every historical amendment shape. platform/governance_verdict.py now turns a STEER or ANNOTATE with no amendment content into a typed GovernanceRefused before an egress draft reaches run, stream consumers, or event sinks. A reflector outage retains the pipeline's existing fail-open policy. The public journey proves this refusal contract; it does not claim that a prompt cache is a history cache or that every legacy verdict was textually revised.

PARTIALLY MIGRATED controls (23 unique)

The following controls are distinct from the flat 38. They are source-enumerated from the cutover contract. “Admitted but inactive” never means the legacy control was inert.

Control Classification Live owner/wiring Source; evidence Risk → action (owner)
self_reflection admitted-but-inactive Native reflection phase required cutover/admission_surfaces.py; test_reflection_and_scheduler_surfaces.py admission only → compose/test (FP-4)
reflection_prompt admitted-but-inactive Native reflection phase required cutover/admission_surfaces.py; test_reflection_and_scheduler_surfaces.py custom prompt lost → phase test (FP-4)
domain.core_preferences admitted-but-inactive Governance policy input required cutover/admission_surfaces.py; MISSING native input silent inactivity → decision (FP-4)
read_only_tools admitted-but-inactive governance(read_only_tools=...); old field not mapped cutover/tools_surfaces.py; test_metacognition_preservation.py new port works but old config is inert → guide/adapter (FP-4)
skill_auto_approve admitted-but-inactive Native promotion policy required cutover/tools_surfaces.py; MISSING native journey status drift → composition (FP-4)
domain behavior-changed Description reaches HmsSystemSource cutover/prompting_surfaces.py; test_prompt_assembly_lane.py nested fields omitted → bound contract (FP-4)
domain_description_max_chars behavior-changed non-JIT [0] truncation cutover/prompting_surfaces.py; test_continuation_cutover.py JIT [1] unreachable → decide (FP-4)
hydration_min_relevance behavior-changed RetrievalCoordinator._gate cutover/memory_retrieval_rows.py; test_memory_retrieval_lane.py composite score → boundary (FP-3)
episodic_telemetry_sink admitted-but-inactive Native lifecycle writer required cutover/memory_retrieval_rows.py; MISSING sink journey telemetry missing → wire (FP-4)
working_memory_recent_turns behavior-changed WorkingWindow.read cutover/memory_retrieval_rows.py; test_memory_retrieval_lane.py zero refused → disabled-window contract (FP-4)
working_layer_exclude_speakers behavior-changed Working window only cutover/memory_retrieval_rows.py; test_memory_retrieval_lane.py episodic quotes stay → two-source test (FP-3)
stm_summary_mode admitted-but-inactive Native summary contribution required cutover/memory_retrieval_rows.py; MISSING contribution silent inactivity → define composition (FP-4)
scope_blend_mode behavior-changed Constructed retrieval engine cutover/memory_retrieval_rows.py; test_memory_retrieval_lane.py injected precedence → hierarchy test (FP-3)
enabled_layers behavior-changed Constructed orchestrator config cutover/memory_orchestrator_rows.py; test_continuation_cutover.py injected precedence → both paths (FP-3)
phase1_spreading_weight replacement-unverified LearningPolicy → phase factory memory/policy.py; test_phase1_spreading_decomposition.py no public composition → nap boundary (FP-3)
enable_entity_linker replacement-unverified Policy plus extractor collaborator memory/policy.py; test_entity_linker_model_wiring.py flag alone insufficient → off/on (FP-3)
entity_linker_extractor replacement-unverified entity_linker_extractor_kind plus collaborator memory/policy.py; test_entity_linker_model_wiring.py runtime unproved → each-kind journey (FP-3)
entity_linker_min_mention_count replacement-unverified LearningPolicy → entity phase memory/policy.py; MISSING N-1/N threshold drift → fixture (FP-3)
entity_linker_max_episodics_per_run replacement-unverified LearningPolicy → entity phase memory/policy.py; MISSING over-cap cost cap unproved → capture (FP-3)
entity_linker_confidence_threshold replacement-unverified LearningPolicy → entity phase memory/policy.py; MISSING threshold score boundary → fixture (FP-3)
episodic_summarization_max_entries replacement-unverified LearningPolicy → quick phase memory/policy.py; test_phase_10_threshold_plumbing.py no Agent lifecycle proof → post-turn (FP-3)
episodic_summarization_batch_size replacement-unverified LearningPolicy → quick phase memory/policy.py; MISSING batch journey batch drift → exact-count (FP-3)
enable_semantic_merge replacement-unverified quick_phases collaborator composition; no LearningPolicy field memory/phases/quick.py; test_learning_phase_parity.py field absence is not capability absence → composed off/on (FP-3)

Continuation boundary and exclusions

Seven continuation contexts are audited separately and are not seven additional controls: enabled_layers, domain, hydration_min_relevance, working_memory_recent_turns, domain_description_max_chars, working_layer_exclude_speakers, and scope_blend_mode. continuation_admission.RECONCILED_ROWS, tests/retirement/test_continuation_reconciliation.py, and tests/agent/cutover/test_continuation_cutover.py establish cutover context only. They do not establish durable process-restart recovery.

The inventory excludes nested agent.ask_user_pause_ttl_seconds (the same TTLPolicy behavior change), per-call is_admin (refused by governance authority), and all other nested/per-call options. This is an explicit scope boundary, not a claim that no other configuration needs review.

Derived totals and release implication

The validator prints totals directly from the checked-in rows. The current evidence leaves a large set of high-risk replacement-unverified, removed-without-equivalent, and behavior-changed controls. That blocks a blanket no-feature-loss claim. FP-3 owns the discriminating public journeys; FP-4 owns supported composition, explicit refusals, and deliberate product decisions. FP-1 owns the metacognition policy implementation and its remaining custom-pattern and verdict-enforcement evidence.