polish: finish the rebrand in agent-facing surfaces

- system prompt environment key deepseek_version -> codewhale_version
- drop legacy .deepseek/instructions.md from the Local Law prompt tier
  (the engine still reads it for back-compat)
- instructions-file truncation marker now states how many bytes were
  omitted so the model knows what it is missing
- CODEWHALE_CHANGELOG const + user-facing /change strings
- codewhale metrics doc headers
This commit is contained in:
Hunter B
2026-06-09 23:36:32 -07:00
parent 6dcdc19077
commit fad04a016f
4 changed files with 32 additions and 27 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
//! `deepseek metrics` — reads the audit log and session/task stores and prints
//! `codewhale metrics` — reads the audit log and session/task stores and prints
//! a human-readable usage rollup.
//!
//! Data sources:
@@ -17,7 +17,7 @@ use serde_json::Value;
// Public entry-point
// ──────────────────────────────────────────────────────────────────────────────
/// Arguments accepted by `deepseek metrics`.
/// Arguments accepted by `codewhale metrics`.
#[derive(Debug, Default)]
pub struct MetricsArgs {
/// Emit machine-readable JSON instead of human text.
+16 -16
View File
@@ -3,7 +3,7 @@
//!
//! Usage: `/change [version]`
//!
//! Uses the DeepSeek-TUI changelog embedded at compile time. With no argument,
//! Uses the CodeWhale changelog embedded at compile time. With no argument,
//! extracts the most recent section. With a version argument like `0.8.32`,
//! extracts that specific version's section. When the UI locale is not
//! English and the current session can reach a model, the command also fires a
@@ -19,7 +19,7 @@ use super::CommandResult;
/// If the changelog section exceeds this, we truncate and show a notice.
/// 4096 chars is large enough for most version entries.
const MAX_INLINE_CHANGELOG_CHARS: usize = 4096;
const DEEPSEEK_TUI_CHANGELOG: &str = include_str!("../../CHANGELOG.md");
const CODEWHALE_CHANGELOG: &str = include_str!("../../CHANGELOG.md");
/// Execute the `/change` command.
///
@@ -29,12 +29,12 @@ pub fn change(app: &mut App, version: Option<&str>) -> CommandResult {
let section = if let Some(ver) = version {
let ver = ver.trim();
if ver.is_empty() {
extract_latest_changelog_section(DEEPSEEK_TUI_CHANGELOG)
extract_latest_changelog_section(CODEWHALE_CHANGELOG)
} else {
extract_changelog_section_by_version(DEEPSEEK_TUI_CHANGELOG, ver)
extract_changelog_section_by_version(CODEWHALE_CHANGELOG, ver)
}
} else {
extract_latest_changelog_section(DEEPSEEK_TUI_CHANGELOG)
extract_latest_changelog_section(CODEWHALE_CHANGELOG)
};
let latest_section = match section {
@@ -43,16 +43,16 @@ pub fn change(app: &mut App, version: Option<&str>) -> CommandResult {
let msg = if let Some(ver) = version {
let ver = ver.trim();
if ver.is_empty() {
"Could not find a version section in the bundled DeepSeek-TUI changelog. \
"Could not find a version section in the bundled CodeWhale changelog. \
Expected a line starting with `## [`."
.to_string()
} else {
format!(
"Could not find version \"{ver}\" in the bundled DeepSeek-TUI changelog."
"Could not find version \"{ver}\" in the bundled CodeWhale changelog."
)
}
} else {
"Could not find a version section in the bundled DeepSeek-TUI changelog. \
"Could not find a version section in the bundled CodeWhale changelog. \
Expected a line starting with `## [`."
.to_string()
};
@@ -63,7 +63,7 @@ pub fn change(app: &mut App, version: Option<&str>) -> CommandResult {
let locale = app.ui_locale;
let header = tr(locale, MessageId::CmdChangeHeader);
let prev_hint = if let Some(prev_ver) = previous_version_hint(DEEPSEEK_TUI_CHANGELOG, version) {
let prev_hint = if let Some(prev_ver) = previous_version_hint(CODEWHALE_CHANGELOG, version) {
let template = tr(locale, MessageId::CmdChangePreviousVersion);
format!("\n\n{}", template.replace("{version}", &prev_ver))
} else {
@@ -130,7 +130,7 @@ fn inline_changelog_section(section: &str) -> String {
format!(
"{truncated}\n\
\n\
[... {} characters omitted from the bundled DeepSeek-TUI changelog]",
[... {} characters omitted from the bundled CodeWhale changelog]",
section.len() - MAX_INLINE_CHANGELOG_CHARS
)
}
@@ -437,7 +437,7 @@ Previous release.\n";
let result = change(&mut app, None);
assert!(!result.is_error);
let msg = result.message.expect("should have a message");
let expected = extract_latest_changelog_section(DEEPSEEK_TUI_CHANGELOG)
let expected = extract_latest_changelog_section(CODEWHALE_CHANGELOG)
.expect("bundled changelog should have a release section");
assert!(msg.contains(expected.lines().next().unwrap()));
}
@@ -465,7 +465,7 @@ Previous release.\n";
let result = change(&mut app, None);
assert!(!result.is_error);
let msg = result.message.expect("should have a message");
let expected = extract_latest_changelog_section(DEEPSEEK_TUI_CHANGELOG)
let expected = extract_latest_changelog_section(CODEWHALE_CHANGELOG)
.expect("bundled changelog should have a release section");
assert!(msg.contains(expected.lines().next().unwrap()));
assert!(
@@ -493,10 +493,10 @@ Previous release.\n";
result.action
);
if let Some(AppAction::SendMessage(prompt)) = &result.action {
let expected = extract_latest_changelog_section(DEEPSEEK_TUI_CHANGELOG)
let expected = extract_latest_changelog_section(CODEWHALE_CHANGELOG)
.expect("bundled changelog should have a release section");
assert!(prompt.contains(expected.lines().next().unwrap()));
let prev_ver = extract_previous_version_number(DEEPSEEK_TUI_CHANGELOG)
let prev_ver = extract_previous_version_number(CODEWHALE_CHANGELOG)
.expect("bundled changelog should have a previous release");
assert!(
prompt.contains(&prev_ver),
@@ -871,10 +871,10 @@ Older release.\n";
let mut app = make_app(&tmp, Locale::En, false);
// Derive versions from the bundled changelog: it only embeds a recent
// slice of releases, so hardcoded versions would age out of it.
let explicit = extract_previous_version_number(DEEPSEEK_TUI_CHANGELOG)
let explicit = extract_previous_version_number(CODEWHALE_CHANGELOG)
.expect("bundled changelog should have a previous release");
let expected_prev =
extract_previous_version_number_after_version(DEEPSEEK_TUI_CHANGELOG, &explicit)
extract_previous_version_number_after_version(CODEWHALE_CHANGELOG, &explicit)
.expect("bundled changelog should have at least three releases");
let result = change(&mut app, Some(&explicit));
assert!(!result.is_error);
+13 -8
View File
@@ -65,7 +65,7 @@ const LEGACY_HANDOFF_RELATIVE_PATH: &str = ".deepseek/handoff.md";
/// Per-file size cap for `instructions = [...]` entries (#454). Mirrors
/// the existing project-context cap in `project_context::load_context_file`
/// so a malicious / oversized include can't blow the prompt budget on
/// its own. Files larger than this are truncated with an `[…elided]`
/// its own. Files larger than this are truncated with an explicit `[…truncated: N bytes omitted]`
/// marker rather than skipped entirely so the model still sees the head.
const INSTRUCTIONS_FILE_MAX_BYTES: usize = 100 * 1024;
@@ -142,7 +142,7 @@ for the current turn."
/// guess from the user's first message. `locale_tag` is resolved by
/// the caller from `Settings` so this function stays I/O-free.
fn render_environment_block(workspace: &Path, locale_tag: &str) -> String {
let deepseek_version = env!("CARGO_PKG_VERSION");
let codewhale_version = env!("CARGO_PKG_VERSION");
let platform = std::env::consts::OS;
let shell = crate::shell_dispatcher::global_dispatcher()
.kind()
@@ -154,7 +154,7 @@ fn render_environment_block(workspace: &Path, locale_tag: &str) -> String {
"## Environment\n\
\n\
- lang: {locale_tag}\n\
- deepseek_version: {deepseek_version}\n\
- codewhale_version: {codewhale_version}\n\
- platform: {platform}\n\
- shell: {shell}\n\
- pwd: {pwd}"
@@ -236,7 +236,12 @@ fn render_instructions_block(sources: &[InstructionSource]) -> Option<String> {
.rev()
.find(|&i| trimmed.is_char_boundary(i))
.unwrap_or(0);
format!("{}\n[…elided]", &trimmed[..head_end])
format!(
"{}\n[…truncated: {} of {} bytes omitted — consider splitting this instructions file]",
&trimmed[..head_end],
trimmed.len() - head_end,
trimmed.len()
)
} else {
trimmed.to_string()
};
@@ -1680,7 +1685,7 @@ mod tests {
assert!(block.starts_with("## Environment"));
assert!(block.contains("- lang: zh-Hans"));
assert!(block.contains(&format!(
"- deepseek_version: {}",
"- codewhale_version: {}",
env!("CARGO_PKG_VERSION")
)));
assert!(block.contains(&format!("- pwd: {}", tmp.path().display())));
@@ -2025,7 +2030,7 @@ mod tests {
};
assert!(prompt.contains("## Environment"));
assert!(prompt.contains("- lang: ja"));
assert!(prompt.contains("- deepseek_version:"));
assert!(prompt.contains("- codewhale_version:"));
}
#[test]
@@ -2838,7 +2843,7 @@ mod tests {
std::fs::write(&big, "X".repeat(200 * 1024)).unwrap();
let block = super::render_instructions_block(&[big.into()]).expect("non-empty");
assert!(block.contains("[…elided]"), "truncation marker missing");
assert!(block.contains("[…truncated:"), "truncation marker missing");
// Block should be much smaller than the original file.
assert!(
block.len() < 110 * 1024,
@@ -2872,7 +2877,7 @@ mod tests {
content: "Y".repeat(200 * 1024),
};
let trimmed = super::render_instructions_block(&[big_inline]).expect("non-empty");
assert!(trimmed.contains("[…elided]"));
assert!(trimmed.contains("[…truncated:"));
// File + Inline 混用,顺序保持。
let tmp = tempdir().expect("tempdir");
+1 -1
View File
@@ -52,7 +52,7 @@ When directives from different sources conflict, resolve in this order:
4. **Regulations.** Composition patterns, sub-agent strategy, language rules, thinking budget. Best-practice guidance that yields to user intent when the two conflict.
5. **Local Law.** Project instructions — AGENTS.md, CLAUDE.md, `.codewhale/instructions.md`, `.deepseek/instructions.md`, **and any file configured via `EngineConfig.instructions` (rendered as `<instructions source="…">` blocks above)**. Project-specific rules that are subordinate to all higher tiers but supersede Memory (Tier 7), even when written in imperative voice — `EngineConfig.instructions` files are declared by the embedder (not user-collected like memory), so their imperatives are Local Law, not Memory preferences.
5. **Local Law.** Project instructions — AGENTS.md, CLAUDE.md, `.codewhale/instructions.md`, **and any file configured via `EngineConfig.instructions` (rendered as `<instructions source="…">` blocks above)**. Project-specific rules that are subordinate to all higher tiers but supersede Memory (Tier 7), even when written in imperative voice — `EngineConfig.instructions` files are declared by the embedder (not user-collected like memory), so their imperatives are Local Law, not Memory preferences.
6. **Evidence.** Tool output, file contents, command results, live repository state. Evidence is truth. Never contradict verified tool output. If memory and evidence conflict, evidence wins.