[EPIC] Add declarative always-visible activation to prompt_unit tools #449

Closed
opened 2026-09-10 21:18:22 +00:00 by nsaspy · 1 comment
Owner

Goal

Extend the existing prompt_unit interface so any tool/unit may declaratively opt into always-visible model context without introducing a separate core-tool registry or parallel interface.

This is an implementation epic only. The design deliberately reuses the current prompt compiler/catalog/unit machinery.

Research / current behavior

Current prompt compiler behavior is evidence-driven:

  • registered tool schemas are imported into the prompt catalog as ordinary prompt_unit{...} values;
  • mandatory_context:true currently means only that once selected, context packing may not choose an omitted representation;
  • normal compiled mode still requires positive activation evidence before a unit becomes a candidate;
  • a registered tool can therefore remain available in the runtime while disappearing from the model-visible projection on unrelated turns;
  • selected_tool_schemas/2 emits schemas only from surviving selected entries, so a non-selected tool is absent from the provider-visible tool list;
  • the test context_deactivation_does_not_unregister_runtime_tool explicitly proves this behavior;
  • over-budget mandatory units already fail structurally rather than silently disappearing.

Relevant existing research: research/RLM-RESEARCH-011-managed-context-tool-discovery.org establishes that contextual activation/deactivation is correct for ordinary tools, but also states that mandatory host units and dependencies must not compete with untrusted metadata ranking.

Design decision

Use the same prompt_unit interface. Add one normalized field:

activation:relevant

with supported values:

activation:relevant
activation:always

Default remains relevant so existing behavior is unchanged.

Example:

prompt_unit{
    unit:tool(task),
    kind:tool,
    ...,
    activation:always,
    provider_visible:true,
    mandatory_context:true
}.

No core_tool/1 registry. No second catalog. No privileged side channel. Any ordinary tool/unit may opt in declaratively.

Exact semantics

activation:relevant

Current behavior:

  • candidate requires explicit selection, trigger evidence, lexical evidence, needs(...), dependency closure, or compatibility mode;
  • candidate limit applies normally;
  • negative evidence may reject it;
  • normal conflict/supersession resolution applies;
  • if selected and mandatory_context:true, token packing cannot omit it.

activation:always

When a unit is registered and otherwise eligible, the compiler must seed it into the candidate set without requiring prompt evidence.

An always-active unit MUST NOT disappear merely because:

  • the current user message is unrelated;
  • lexical/trigger score is zero;
  • candidate narrowing would otherwise exclude it;
  • candidate_limit is exhausted by ordinary relevant candidates.

It must still obey trusted eligibility boundaries:

  • available:true;
  • discovery scope;
  • required execution capability eligibility;
  • dependency eligibility;
  • structural validity.

activation:always is visibility policy, not authorization. Invocation still rechecks the normal runtime capability/authority/tool execution path.

Negative user text

Do not allow ordinary natural-language negation such as "without foo" to remove an activation:always unit. The host explicitly declared the model-visible interface persistent.

Host-controlled denied:[Unit] / explicit policy narrowing may still reject it when that denial represents trusted compile input. Keep this distinction explicit in implementation and tests; do not let untrusted prose rewrite host activation policy.

Conflict / supersession

Always-active units should not be silently removed by ordinary relevance-ranked conflict or supersession logic.

Preferred rule for this slice:

  • two compatible always-active units: retain both;
  • always-active vs relevant conflict: always-active wins, relevant unit is rejected with explicit reason;
  • two always-active units that conflict: fail compilation structurally with an explicit configuration error rather than choosing one by score;
  • an always-active unit may not be superseded by a merely relevant unit;
  • if an always-active unit declares another always-active unit superseded, treat contradictory host configuration as a structural compiler error unless a later explicit policy is designed.

This avoids a host-declared permanent interface being silently mutated by prompt ranking.

Token packing

No new packer behavior is required.

Existing mandatory_context:true semantics remain canonical:

  • selected mandatory units cannot be represented as omitted;
  • if mandatory selected units cannot fit, rlm_context_budget returns a structural failure.

For a tool intended to be permanently callable by the model, recommended declaration is:

activation:always,
mandatory_context:true

activation controls selection; mandatory_context controls packing after selection.

Exact implementation files

1. prolog/rlm_prompt_compiler.pl

A. Normalize the new field

In normalize_unit_spec/2, after availability/visibility-style policy fields are normalized, add:

dict_default(Spec0, activation, relevant, Activation0),
normalize_activation(Activation0, Activation),

Add activation:Activation to the normalized prompt_unit{...} dict.

Add a normalizer with exactly two accepted values:

normalize_activation(relevant, relevant) :- !.
normalize_activation(always, always) :- !.
normalize_activation(Value, _) :-
    throw(prompt_compiler_fault(invalid_activation(Value))).

If string compatibility is desired, normalize through the same name normalization convention used by other enum-like fields, but the canonical stored values must remain atoms relevant / always.

B. Tool-registry import defaults

In tool_schema_unit_spec/3, imported runtime tools should remain:

activation:relevant

by default.

Add an import option that can declaratively mark chosen tools always-active without creating another interface. Preferred shape:

always_visible_tools([task, search_tools, ...])

or a generic unit activation map if one already fits existing option conventions:

activation_overrides([tool(task)-always])

Choose one approach and document it. Do not hard-code tool names in rlm_prompt_compiler.pl.

C. Candidate generation

Refactor initial_candidates/... / root_candidate_status/... so always-active eligible units enter the candidate frontier independently of relevance evidence.

The implementation should make the ordering explicit:

  1. partition/identify host-declared activation:always units;
  2. run trusted eligibility checks;
  3. add eligible always-active units to candidates with a deterministic reason such as:
activation(always)
  1. generate normal relevant candidates using current evidence scoring;
  2. apply candidate_limit only to the ordinary relevant frontier, not to the always-active set;
  3. merge and deterministically sort/dedupe before dependency closure.

Do not fake always-visible behavior by assigning an arbitrarily huge lexical score and leaving it subject to candidate_limit.

D. Negative evidence

Split trusted compile denial from natural-language negative evidence.

For activation:always:

  • trusted explicit Input.denied / host denial may reject;
  • natural-language text_negation(...) must not remove it;
  • ordinary signal negation should be classified according to whether signals are host-trusted in the current API; if mixed trust is possible, make trusted denial explicit rather than assuming all signals are authoritative.

Preserve existing behavior for activation:relevant.

E. Conflict / supersession handling

Update apply_supersession/... and apply_conflicts/... (or introduce a pre-resolution policy helper) so host-declared always-active units cannot be silently displaced by relevance scoring.

Required observable results:

  • relevant conflict loses to always-active with an explicit rejection reason;
  • contradictory always-vs-always configuration returns a structured compiler error;
  • relevant superseder cannot remove always-active target.

F. Explainability

prompt_explain/3 and Compiled.reasons must expose why an always-active unit is present. Expected reason term:

activation(always)

If rejected by trusted policy, explanation must say the actual reason (unavailable, capability denied, discovery scope denied, explicit host denial, dependency failure, etc.), not no_matching_evidence.

G. Fingerprint

Ensure activation is material to catalog/spec fingerprinting. A unit changing from relevant to always must change compiled/catalog fingerprints even if every other field is identical.

2. test/rlm_prompt_compiler_test.pl

Add focused regression coverage.

Required tests:

  1. always_activation_without_lexical_match_is_selected

    • register an ordinary tool with no matching trigger/text;
    • activation:always;
    • capability eligible;
    • assert selected and present in Compiled.tool_schemas.
  2. relevant_activation_without_evidence_remains_hidden

    • same fixture with default/relevant activation;
    • assert current behavior remains unchanged.
  3. always_tool_survives_unrelated_turn_without_reregistration

    • Turn A relevant;
    • Turn B unrelated;
    • Turn C unrelated/different;
    • always tool remains selected in all projections;
    • runtime registry registration count/binding remains unchanged.
  4. candidate_limit_does_not_evict_always_tool

    • create enough high-scoring relevant candidates to exhaust a very small candidate_limit;
    • assert always tool remains selected;
    • ordinary frontier still respects the configured limit.
  5. natural_language_negation_does_not_hide_always_tool

    • input contains without <alias> / do not use <alias>;
    • assert tool remains model-visible.
  6. trusted_explicit_denial_can_reject_always_tool

    • use host compile input denied:[tool(...)];
    • assert rejected with explicit-denial/policy reason.
  7. capability_denied_always_tool_is_not_exposed

    • no execution capability;
    • assert rejected, preserving authority separation.
  8. discovery_scope_denied_always_tool_is_not_exposed

    • child/narrowed scope excludes it;
    • assert rejected.
  9. unavailable_always_tool_is_not_exposed

    • available:false;
    • assert rejected.
  10. always_tool_over_budget_fails_structurally_when_mandatory

    • activation:always, mandatory_context:true;
    • tiny context policy;
    • assert structural context-budget failure, never silent omission.
  11. always_tool_schema_is_rendered_and_callable_surface_present

    • assert prompt_render(...).tool_schemas contains exact schema even on unrelated prompt.
  12. relevant_conflict_cannot_evict_always_tool

    • assert always selected; relevant conflicting unit rejected with deterministic reason.
  13. conflicting_always_units_fail_structurally

    • assert explicit compiler configuration error.
  14. relevant_superseder_cannot_remove_always_tool

    • assert always unit survives.
  15. activation_changes_fingerprint

    • otherwise-identical specs differing only by activation produce different fingerprint/material catalog result.
  16. tool_registry_import_can_mark_selected_tool_always_visible

    • exercise the chosen import option/override API;
    • assert no second registration mechanism is involved.

3. Documentation target

There is currently substantial prompt-compiler design in research/RLM-RESEARCH-010-symbolic-prompt-compiler.org and research/RLM-RESEARCH-011-managed-context-tool-discovery.org, but no obvious dedicated docs/prompt-compiler.md runtime contract surfaced by the current audit.

Implementation should either:

  • add docs/prompt-compiler.md, preferred if the runtime now needs a stable user/operator contract; or
  • update the canonical existing runtime documentation location if one has landed before implementation begins.

The documentation must define:

registered != available != active != authorized

and additionally distinguish:

activation policy != packing policy

activation:relevant      -> evidence-driven selection
activation:always        -> host-declared persistent model visibility
mandatory_context:true   -> selected unit cannot be omitted by packer

Document that activation:always never grants authority and remains constrained by availability, discovery scope, capabilities, dependencies, and final runtime authorization.

4. Research design note

Before implementation, update the canonical research/design record rather than creating a competing architecture.

Preferred target:

research/RLM-RESEARCH-011-managed-context-tool-discovery.org

Add a short follow-up section recording that the original contextual-deactivation rule remains correct for activation:relevant, while host-declared always-visible tools are represented through the same unit algebra using explicit activation policy.

Do not rewrite the original research conclusion into “all tools visible by default.” Default remains contextual narrowing.

Public contract

Normalized unit shape after this epic should be conceptually:

prompt_unit{
    unit:Unit,
    name:Name,
    kind:Kind,
    category:Category,
    description:Description,
    available:Available,
    activation:relevant|always,
    aliases:Aliases,
    triggers:Triggers,
    requires:Requires,
    suggests:Suggests,
    conflicts:Conflicts,
    supersedes:Supersedes,
    requires_capability:Capability,
    priority:Priority,
    provider_visible:ProviderVisible,
    mandatory_context:MandatoryContext,
    schema:Schema,
    content:Content,
    representations:Representations,
    provenance:Provenance
}.

Non-goals

  • no special core_tool subsystem;
  • no second registry/catalog;
  • no hard-coded list of privileged tool names;
  • no bypass of tool capability/authority checks;
  • no “all tools visible” default;
  • no changes to rlm_context_budget unless a failing regression proves current mandatory-unit behavior insufficient;
  • no model-controlled widening of activation policy;
  • no use of huge fake relevance scores as an implementation shortcut.

Acceptance gate

Implementation is complete only when all of the following hold:

  • any normal prompt_unit can declare activation:always;
  • default behavior remains activation:relevant;
  • always-visible tools survive unrelated turns and candidate narrowing;
  • always-visible tools appear in provider tool_schemas without prompt evidence;
  • natural-language relevance/negation cannot silently remove host-pinned tool visibility;
  • trusted scope/capability/availability restrictions still remove ineligible tools;
  • conflicts/supersession cannot silently override host-pinned visibility;
  • contradictory always-active configuration fails structurally;
  • token pressure never silently drops an always+mandatory tool;
  • explainability and fingerprints reflect activation policy;
  • no parallel core-tool interface is introduced;
  • focused prompt-compiler tests and the deterministic aggregate suite pass.

Implementation sequence

  1. Normalize activation in prompt_unit.
  2. Add declarative registry-import override support.
  3. Seed always-active eligible candidates outside the ordinary relevance/candidate-limit frontier.
  4. Separate trusted denial from prose negation for always-active units.
  5. Harden conflict/supersession semantics.
  6. Preserve explainability/fingerprint materiality.
  7. Add focused regression matrix.
  8. Update canonical research/runtime documentation.
  9. Run focused prompt-compiler suite, deterministic aggregate tests, and any provider/render integration tests.

Do not broaden this epic into a separate tool architecture. The point is to make the existing interface expressive enough to represent both contextual and persistent model-visible tools.

## Goal Extend the existing `prompt_unit` interface so **any tool/unit may declaratively opt into always-visible model context** without introducing a separate core-tool registry or parallel interface. This is an implementation epic only. The design deliberately reuses the current prompt compiler/catalog/unit machinery. ## Research / current behavior Current prompt compiler behavior is evidence-driven: - registered tool schemas are imported into the prompt catalog as ordinary `prompt_unit{...}` values; - `mandatory_context:true` currently means only that **once selected**, context packing may not choose an omitted representation; - normal `compiled` mode still requires positive activation evidence before a unit becomes a candidate; - a registered tool can therefore remain available in the runtime while disappearing from the model-visible projection on unrelated turns; - `selected_tool_schemas/2` emits schemas only from surviving selected entries, so a non-selected tool is absent from the provider-visible tool list; - the test `context_deactivation_does_not_unregister_runtime_tool` explicitly proves this behavior; - over-budget mandatory units already fail structurally rather than silently disappearing. Relevant existing research: `research/RLM-RESEARCH-011-managed-context-tool-discovery.org` establishes that contextual activation/deactivation is correct for ordinary tools, but also states that mandatory host units and dependencies must not compete with untrusted metadata ranking. ## Design decision Use the **same `prompt_unit` interface**. Add one normalized field: ```prolog activation:relevant ``` with supported values: ```prolog activation:relevant activation:always ``` Default remains `relevant` so existing behavior is unchanged. Example: ```prolog prompt_unit{ unit:tool(task), kind:tool, ..., activation:always, provider_visible:true, mandatory_context:true }. ``` No `core_tool/1` registry. No second catalog. No privileged side channel. Any ordinary tool/unit may opt in declaratively. ## Exact semantics ### `activation:relevant` Current behavior: - candidate requires explicit selection, trigger evidence, lexical evidence, `needs(...)`, dependency closure, or compatibility mode; - candidate limit applies normally; - negative evidence may reject it; - normal conflict/supersession resolution applies; - if selected and `mandatory_context:true`, token packing cannot omit it. ### `activation:always` When a unit is registered and otherwise eligible, the compiler must seed it into the candidate set **without requiring prompt evidence**. An always-active unit MUST NOT disappear merely because: - the current user message is unrelated; - lexical/trigger score is zero; - candidate narrowing would otherwise exclude it; - `candidate_limit` is exhausted by ordinary relevant candidates. It must still obey trusted eligibility boundaries: - `available:true`; - discovery scope; - required execution capability eligibility; - dependency eligibility; - structural validity. `activation:always` is visibility policy, **not authorization**. Invocation still rechecks the normal runtime capability/authority/tool execution path. ### Negative user text Do **not** allow ordinary natural-language negation such as `"without foo"` to remove an `activation:always` unit. The host explicitly declared the model-visible interface persistent. Host-controlled `denied:[Unit]` / explicit policy narrowing may still reject it when that denial represents trusted compile input. Keep this distinction explicit in implementation and tests; do not let untrusted prose rewrite host activation policy. ### Conflict / supersession Always-active units should not be silently removed by ordinary relevance-ranked conflict or supersession logic. Preferred rule for this slice: - two compatible always-active units: retain both; - always-active vs relevant conflict: always-active wins, relevant unit is rejected with explicit reason; - two always-active units that conflict: fail compilation structurally with an explicit configuration error rather than choosing one by score; - an always-active unit may not be superseded by a merely relevant unit; - if an always-active unit declares another always-active unit superseded, treat contradictory host configuration as a structural compiler error unless a later explicit policy is designed. This avoids a host-declared permanent interface being silently mutated by prompt ranking. ### Token packing No new packer behavior is required. Existing `mandatory_context:true` semantics remain canonical: - selected mandatory units cannot be represented as omitted; - if mandatory selected units cannot fit, `rlm_context_budget` returns a structural failure. For a tool intended to be permanently callable by the model, recommended declaration is: ```prolog activation:always, mandatory_context:true ``` `activation` controls **selection**; `mandatory_context` controls **packing after selection**. ## Exact implementation files ### 1. `prolog/rlm_prompt_compiler.pl` #### A. Normalize the new field In `normalize_unit_spec/2`, after availability/visibility-style policy fields are normalized, add: ```prolog dict_default(Spec0, activation, relevant, Activation0), normalize_activation(Activation0, Activation), ``` Add `activation:Activation` to the normalized `prompt_unit{...}` dict. Add a normalizer with exactly two accepted values: ```prolog normalize_activation(relevant, relevant) :- !. normalize_activation(always, always) :- !. normalize_activation(Value, _) :- throw(prompt_compiler_fault(invalid_activation(Value))). ``` If string compatibility is desired, normalize through the same name normalization convention used by other enum-like fields, but the canonical stored values must remain atoms `relevant` / `always`. #### B. Tool-registry import defaults In `tool_schema_unit_spec/3`, imported runtime tools should remain: ```prolog activation:relevant ``` by default. Add an import option that can declaratively mark chosen tools always-active without creating another interface. Preferred shape: ```prolog always_visible_tools([task, search_tools, ...]) ``` or a generic unit activation map if one already fits existing option conventions: ```prolog activation_overrides([tool(task)-always]) ``` Choose one approach and document it. Do not hard-code tool names in `rlm_prompt_compiler.pl`. #### C. Candidate generation Refactor `initial_candidates/...` / `root_candidate_status/...` so always-active eligible units enter the candidate frontier independently of relevance evidence. The implementation should make the ordering explicit: 1. partition/identify host-declared `activation:always` units; 2. run trusted eligibility checks; 3. add eligible always-active units to candidates with a deterministic reason such as: ```prolog activation(always) ``` 4. generate normal relevant candidates using current evidence scoring; 5. apply `candidate_limit` only to the ordinary relevant frontier, not to the always-active set; 6. merge and deterministically sort/dedupe before dependency closure. Do not fake always-visible behavior by assigning an arbitrarily huge lexical score and leaving it subject to `candidate_limit`. #### D. Negative evidence Split trusted compile denial from natural-language negative evidence. For `activation:always`: - trusted explicit `Input.denied` / host denial may reject; - natural-language `text_negation(...)` must not remove it; - ordinary signal negation should be classified according to whether signals are host-trusted in the current API; if mixed trust is possible, make trusted denial explicit rather than assuming all signals are authoritative. Preserve existing behavior for `activation:relevant`. #### E. Conflict / supersession handling Update `apply_supersession/...` and `apply_conflicts/...` (or introduce a pre-resolution policy helper) so host-declared always-active units cannot be silently displaced by relevance scoring. Required observable results: - relevant conflict loses to always-active with an explicit rejection reason; - contradictory always-vs-always configuration returns a structured compiler error; - relevant superseder cannot remove always-active target. #### F. Explainability `prompt_explain/3` and `Compiled.reasons` must expose why an always-active unit is present. Expected reason term: ```prolog activation(always) ``` If rejected by trusted policy, explanation must say the actual reason (`unavailable`, capability denied, discovery scope denied, explicit host denial, dependency failure, etc.), not `no_matching_evidence`. #### G. Fingerprint Ensure `activation` is material to catalog/spec fingerprinting. A unit changing from `relevant` to `always` must change compiled/catalog fingerprints even if every other field is identical. ### 2. `test/rlm_prompt_compiler_test.pl` Add focused regression coverage. Required tests: 1. `always_activation_without_lexical_match_is_selected` - register an ordinary tool with no matching trigger/text; - `activation:always`; - capability eligible; - assert selected and present in `Compiled.tool_schemas`. 2. `relevant_activation_without_evidence_remains_hidden` - same fixture with default/relevant activation; - assert current behavior remains unchanged. 3. `always_tool_survives_unrelated_turn_without_reregistration` - Turn A relevant; - Turn B unrelated; - Turn C unrelated/different; - always tool remains selected in all projections; - runtime registry registration count/binding remains unchanged. 4. `candidate_limit_does_not_evict_always_tool` - create enough high-scoring relevant candidates to exhaust a very small `candidate_limit`; - assert always tool remains selected; - ordinary frontier still respects the configured limit. 5. `natural_language_negation_does_not_hide_always_tool` - input contains `without <alias>` / `do not use <alias>`; - assert tool remains model-visible. 6. `trusted_explicit_denial_can_reject_always_tool` - use host compile input `denied:[tool(...)]`; - assert rejected with explicit-denial/policy reason. 7. `capability_denied_always_tool_is_not_exposed` - no execution capability; - assert rejected, preserving authority separation. 8. `discovery_scope_denied_always_tool_is_not_exposed` - child/narrowed scope excludes it; - assert rejected. 9. `unavailable_always_tool_is_not_exposed` - `available:false`; - assert rejected. 10. `always_tool_over_budget_fails_structurally_when_mandatory` - `activation:always`, `mandatory_context:true`; - tiny context policy; - assert structural context-budget failure, never silent omission. 11. `always_tool_schema_is_rendered_and_callable_surface_present` - assert `prompt_render(...).tool_schemas` contains exact schema even on unrelated prompt. 12. `relevant_conflict_cannot_evict_always_tool` - assert always selected; relevant conflicting unit rejected with deterministic reason. 13. `conflicting_always_units_fail_structurally` - assert explicit compiler configuration error. 14. `relevant_superseder_cannot_remove_always_tool` - assert always unit survives. 15. `activation_changes_fingerprint` - otherwise-identical specs differing only by activation produce different fingerprint/material catalog result. 16. `tool_registry_import_can_mark_selected_tool_always_visible` - exercise the chosen import option/override API; - assert no second registration mechanism is involved. ### 3. Documentation target There is currently substantial prompt-compiler design in `research/RLM-RESEARCH-010-symbolic-prompt-compiler.org` and `research/RLM-RESEARCH-011-managed-context-tool-discovery.org`, but no obvious dedicated `docs/prompt-compiler.md` runtime contract surfaced by the current audit. Implementation should either: - add `docs/prompt-compiler.md`, preferred if the runtime now needs a stable user/operator contract; or - update the canonical existing runtime documentation location if one has landed before implementation begins. The documentation must define: ```text registered != available != active != authorized ``` and additionally distinguish: ```text activation policy != packing policy activation:relevant -> evidence-driven selection activation:always -> host-declared persistent model visibility mandatory_context:true -> selected unit cannot be omitted by packer ``` Document that `activation:always` never grants authority and remains constrained by availability, discovery scope, capabilities, dependencies, and final runtime authorization. ### 4. Research design note Before implementation, update the canonical research/design record rather than creating a competing architecture. Preferred target: `research/RLM-RESEARCH-011-managed-context-tool-discovery.org` Add a short follow-up section recording that the original contextual-deactivation rule remains correct for `activation:relevant`, while host-declared always-visible tools are represented through the same unit algebra using explicit activation policy. Do not rewrite the original research conclusion into “all tools visible by default.” Default remains contextual narrowing. ## Public contract Normalized unit shape after this epic should be conceptually: ```prolog prompt_unit{ unit:Unit, name:Name, kind:Kind, category:Category, description:Description, available:Available, activation:relevant|always, aliases:Aliases, triggers:Triggers, requires:Requires, suggests:Suggests, conflicts:Conflicts, supersedes:Supersedes, requires_capability:Capability, priority:Priority, provider_visible:ProviderVisible, mandatory_context:MandatoryContext, schema:Schema, content:Content, representations:Representations, provenance:Provenance }. ``` ## Non-goals - no special `core_tool` subsystem; - no second registry/catalog; - no hard-coded list of privileged tool names; - no bypass of tool capability/authority checks; - no “all tools visible” default; - no changes to `rlm_context_budget` unless a failing regression proves current mandatory-unit behavior insufficient; - no model-controlled widening of activation policy; - no use of huge fake relevance scores as an implementation shortcut. ## Acceptance gate Implementation is complete only when all of the following hold: - any normal `prompt_unit` can declare `activation:always`; - default behavior remains `activation:relevant`; - always-visible tools survive unrelated turns and candidate narrowing; - always-visible tools appear in provider `tool_schemas` without prompt evidence; - natural-language relevance/negation cannot silently remove host-pinned tool visibility; - trusted scope/capability/availability restrictions still remove ineligible tools; - conflicts/supersession cannot silently override host-pinned visibility; - contradictory always-active configuration fails structurally; - token pressure never silently drops an always+mandatory tool; - explainability and fingerprints reflect activation policy; - no parallel core-tool interface is introduced; - focused prompt-compiler tests and the deterministic aggregate suite pass. ## Implementation sequence 1. Normalize `activation` in `prompt_unit`. 2. Add declarative registry-import override support. 3. Seed always-active eligible candidates outside the ordinary relevance/candidate-limit frontier. 4. Separate trusted denial from prose negation for always-active units. 5. Harden conflict/supersession semantics. 6. Preserve explainability/fingerprint materiality. 7. Add focused regression matrix. 8. Update canonical research/runtime documentation. 9. Run focused prompt-compiler suite, deterministic aggregate tests, and any provider/render integration tests. Do not broaden this epic into a separate tool architecture. The point is to make the existing interface expressive enough to represent both contextual and persistent model-visible tools.
Author
Owner

Duplicate of #174 (pre-existing Forgejo mirror). Closing this accidental duplicate created by today's open-state sync; #174 stays canonical on Forgejo.

Duplicate of #174 (pre-existing Forgejo mirror). Closing this accidental duplicate created by today's open-state sync; #174 stays canonical on Forgejo.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/prolog-rlm#449
No description provided.