prompt-shape: screen, correct, and structure operator input into a shaped prompt before it is sent to any model — never sends, only prints.
| Tier | tools |
| Role | unclassified (baselined) |
| Path | crates/tools/prompt-shaper |
| Edition | 2021 |
| Targets | prompt-shape, tools_prompt_shaper |
| Public items | 19 across 4 modules |
| Tests | 40 |
What it is for
tools-prompt-shaper — screen, correct, and structure operator input into a shaped prompt before it is sent to any model.
Pipeline order is the design (Sprint 3.21, Gate 1.5.6): hard-rules DLP screening runs FIRST so a credential is redacted before the local model — or any model — ever sees the text. The pipeline never sends anything anywhere; it prints a shaped prompt for the operator to review.
Modules land one per TDD task:
- T2
screen— hard-rules DLP screening + redaction. - T3
model— the local-model typed ask, with degradation when the
model is unreachable or returns malformed output.
- T4
template— deterministic template fill; corrections are applied
as spans, never a rewritten body.
- T5
routeandconfig— lookup routing and config plumbing.
T1 lands the crate skeleton and CLI surface only; modules are added as their task lands.
Capabilities
config (other)
T5: config plumbing. SHAPER_MODEL, OLLAMA_URL, and a hard-rules-only
| Item |
|---|
pub const DEFAULT_OLLAMA_URL: & str |
fn parse_env_file(contents : & str) -> HashMap <String, String> |
Config
T5: config plumbing. SHAPER_MODEL, OLLAMA_URL, and a hard-rules-only
| Item |
|---|
pub struct Config |
fn resolve(cli_model : Option <& str>, cli_ollama_url : Option <& str>, cli_no_model : bool, process_env : & HashMap <String, String>, file_env : & HashMap <String, String>, default_model : & str,) -> Config |
model (other)
T3: the local-model typed ask, and the degradation path when the model
| Item |
|---|
pub const DEFAULT_MODEL: & str |
pub const SYSTEM_PROMPT: & str |
async fn ask(provider : & dyn AiProvider, model : & str, redacted_text : & str,) -> Result <ModelAsk, Degraded> |
Degraded
T3: the local-model typed ask, and the degradation path when the model
| Item |
|---|
pub enum Degraded |
Degraded :: fn message(& self) -> String |
Intent
T3: the local-model typed ask, and the degradation path when the model
| Item |
|---|
pub enum Intent |
ModelAsk
T3: the local-model typed ask, and the degradation path when the model
| Item |
|---|
pub struct ModelAsk |
TypoCorrection
T3: the local-model typed ask, and the degradation path when the model
| Item |
|---|
pub struct TypoCorrection |
ScreenResult
T2: hard-rules DLP screening. Runs FIRST, before any model — local or
| Item |
|---|
pub struct ScreenResult |
ScreenResult :: fn has_findings(& self) -> bool |
fn screen(text : & str) -> ScreenResult |
template (other)
T4: deterministic template fill.
| Item |
|---|
fn fill(intent : Option <Intent>, text : & str, obfuscation_suspected : bool) -> String |
AppliedCorrections
T4: deterministic template fill.
| Item |
|---|
pub struct AppliedCorrections |
fn apply_corrections(text : & str, corrections : & TypoCorrection) -> AppliedCorrections |
DroppedCorrection
T4: deterministic template fill.
| Item |
|---|
pub struct DroppedCorrection |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
tools_prompt_shaper
configmodelscreentemplate
flowchart TD n_tools_prompt_shaper["tools_prompt_shaper"] n_tools_prompt_shaper --> n_config["config"] n_tools_prompt_shaper --> n_model["model"] n_tools_prompt_shaper --> n_screen["screen"] n_tools_prompt_shaper --> n_template["template"]
Public surface
`config`
| Item | What it is |
|---|---|
pub const DEFAULT_OLLAMA_URL: & str | Default Ollama base URL, matching infrastructure_ai::OllamaProvider::local. |
pub struct Config | Resolved configuration for one run. |
fn parse_env_file(contents : & str) -> HashMap <String, String> | Parse a KEY=VALUE config file in the ~/.config/claude-bridge.env convention: blank lines and #-prefixed comment lines are ignored, no quoting or escaping |
fn resolve(cli_model : Option <& str>, cli_ollama_url : Option <& str>, cli_no_model : bool, process_env : & HashMap <String, String>, file_env : & HashMap <String, String>, default_model : & str,) -> Config | Resolve config from explicit sources |
`model`
| Item | What it is |
|---|---|
pub const DEFAULT_MODEL: & str | Default local model (Sprint 3.21): general reasoning, not a coder model — intent classification and orthography are not code-shaped tasks. |
pub const SYSTEM_PROMPT: & str | System prompt for the single typed-ask call |
pub enum Intent | The intent the model assigns to the (already-screened) text |
pub struct TypoCorrection | One correction as a span-and-replacement pair — never a rewritten body |
pub struct ModelAsk | The three typed asks the local model answers in one call. |
pub enum Degraded | Why the model step did not produce a ModelAsk |
Degraded :: fn message(& self) -> String | One-line, operator-facing explanation of what was unavailable and why |
async fn ask(provider : & dyn AiProvider, model : & str, redacted_text : & str,) -> Result <ModelAsk, Degraded> | Ask the local model to classify intent, propose typo corrections, and flag suspected obfuscation over redacted_text |
`screen`
| Item | What it is |
|---|---|
pub struct ScreenResult | Result of the hard-rules screening pass. |
ScreenResult :: fn has_findings(& self) -> bool | Whether screening found anything to redact. |
fn screen(text : & str) -> ScreenResult | Screen text with dlp-detect's zero-config default policy and return the redacted text plus the findings that drove the redaction. |
`template`
| Item | What it is |
|---|---|
pub struct AppliedCorrections | Result of splicing corrections into text: which ones landed, and which were dropped (and why they don't appear in text). |
pub struct DroppedCorrection | A correction that was not applied, and why. |
fn apply_corrections(text : & str, corrections : & TypoCorrection) -> AppliedCorrections | Splice each correction's replacement in place of the first exact, non-fenced occurrence of its span |
fn fill(intent : Option <Intent>, text : & str, obfuscation_suspected : bool) -> String | Fill the deterministic skeleton for intent around text |
No pub use re-exports: every item above is declared in this crate.
Boundary
Reaches into foundation, infrastructure.
Shares tier tools with 84 other crates: tools-advisory-reach, tools-archive-guard, tools-artifact-scaffold, tools-ask-ai-core, tools-ask-ais, tools-ask-gemini, tools-book, tools-book-report, … (84 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | tools |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/tools/prompt-shaper |
| Vocabulary in force (lexicon) | current |
Tier flow. Which tiers this crate's own edges cross.
flowchart LR n_tools["tools"] --> n_foundation["foundation"] n_tools["tools"] --> n_infrastructure["infrastructure"]
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `foundation-bounded-io` | foundation | no | always |
| `infrastructure-ai` | infrastructure | no | always |
| `infrastructure-dlp-detect` | infrastructure | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
clap | ^4 | derive | no | always |
serde | ^1 | derive, derive | no | always |
serde_json | ^1 | — | no | always |
tokio | ^1 | full, macros, rt-multi-thread | no | always |
Development, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `tools-cli-conformance` | tools | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
async-trait | ^0.1 | — | no | always |
Build. None.
Depended on by. Nothing in this workspace.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR SELF["tools-prompt-shaper"] SELF -->|development| n_tools_cli_conformance["tools-cli-conformance"] SELF -->|runtime| n_foundation_bounded_io["foundation-bounded-io"] SELF -->|runtime| n_infrastructure_ai["infrastructure-ai"] SELF -->|runtime| n_infrastructure_dlp_detect["infrastructure-dlp-detect"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.
Targets
| Kind | Name | Source |
|---|---|---|
| bin | prompt-shape | `src/main.rs` |
| lib | tools_prompt_shaper | `src/lib.rs` |
Error model
No public error type was detected: no public item declares a type named *Error, and no public signature returns one.
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | yes |
| async runtime | yes |
| database access | none detected |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | yes |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
| Variable | Read in |
|---|---|
HOME | src/main.rs |
Related capabilities
No workspace crate depends on this one.
Verification
| Kind | Count |
|---|---|
| Unit tests | 40 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
config | 4 | 0 | 0 |
model | 7 | 0 | 0 |
screen | 2 | 0 | 0 |
template | 4 | 0 | 0 |
What the tests establish, by name:
all_defaults_when_nothing_is_set—src/config.rscli_flag_overrides_everything—src/config.rscli_no_model_flag_sets_skip_model_regardless_of_env—src/config.rsfile_env_is_used_when_process_env_absent—src/config.rsollama_url_precedence_matches_model_precedence—src/config.rsparse_env_file_empty_input_yields_empty_map—src/config.rsparse_env_file_skips_comments_and_blank_lines—src/config.rsprocess_env_overrides_file_env—src/config.rsshaper_no_model_env_var_false_or_zero_does_not_skip—src/config.rsshaper_no_model_env_var_sets_skip_model—src/config.rsa_correction_with_no_match_is_reported_as_dropped—src/main.rscli_definition_conforms—src/main.rsfindings_are_reported_and_redacted_in_the_body—src/main.rsprovider_failure_degrades_the_whole_pipeline_not_just_the_model_step—src/main.rsskip_model_bypasses_the_provider_and_notes_it—src/main.rstruncation_is_reported_when_flagged—src/main.rsempty_typo_corrections_defaults_when_omitted—src/model.rsmalformed_json_degrades_without_panicking—src/model.rsollama_dead_port_degrades_without_failing_the_tool—src/model.rsparses_a_well_formed_response—src/model.rsprovider_error_degrades_as_unreachable_not_a_failure—src/model.rsraw_credential_never_reaches_the_model_call—src/model.rssends_the_model_and_json_mode_flag—src/model.rsclean_input_passes_through_unchanged—src/screen.rsempty_input_has_no_findings_and_is_unchanged—src/screen.rsfindings_carry_only_masked_values_never_raw—src/screen.rsraw_value_never_survives_into_redacted_text_across_all_classes—src/screen.rsssn_is_found_and_redacted—src/screen.rsa_correction_inside_a_fenced_block_is_dropped_never_applied—src/template.rsa_correction_outside_a_fence_still_applies_when_another_fence_is_present—src/template.rs- _… 10 more_
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 19 | 19 |
Public modules with a //! block | 4 | 4 |
pie showData
title Public items with rustdoc
"Documented" : 19
"No rustdoc detected" : 0
Metrics
| Metric | Value |
|---|---|
| Rust source files | 6 |
| Source lines | 1217 |
| Code lines | 891 |
| Public API items | 19 |
| Public modules | 4 |
| Tests | 40 |
| Examples | 0 |
| Cargo features | 0 |
| Direct runtime dependencies | 7 |
| Workspace reverse dependencies | 0 |
pie showData
title Public API by kind
"constant" : 3
"enum" : 2
"function" : 6
"method" : 2
"struct" : 6
pie showData
title Rust source composition
"Code" : 891
"Blank or comment" : 326
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.