Skip to content

perf(prompt): progressively disclose fresh context - #5077

Merged
Hmbown merged 7 commits into
mainfrom
agent/minimal-fresh-session-context
Aug 6, 2026
Merged

perf(prompt): progressively disclose fresh context#5077
Hmbown merged 7 commits into
mainfrom
agent/minimal-fresh-session-context

Conversation

@Hmbown

@Hmbown Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • keep AGENTS.md / CLAUDE.md project authority eager, matching Pi's host-side discovery model
  • cap the complete ambient skills block at 2,400 characters while keeping every enabled skill discoverable through first-turn load_skill name="list"; skill bodies stay lazy
  • move the session-relay template out of every fresh system prompt and inject it only into /relay; automatic compaction keeps its own structured successor brief
  • make doctor --context-json report the prompt that is actually configured instead of counting a disabled project pack and approximate phantom layers
  • reduce the always-on constitution to a first-turn kernel while test-locking user intent, irreversible-action authorization, binding gates, ground truth, verified completion, mechanism, and the exact precedence chain

Receipts

Same workspace and conservative characters / 3 estimator throughout: /Volumes/VIXinSSD/CW/codewhale.

Receipt Before After Change
doctor --context-json source-entry total 17,839 7,908 -9,931 (-55.67%)
model-facing system blocks only 13,185 7,844 -5,341 (-40.51%)
ambient skills block 4,522 794 -3,728 (-82.44%)
bundled constitution entry before/after kernel pass 2,647 1,428 -1,219 (-46.05%)
disabled project pack reported as active 4,006 0 now truthful
always-on relay template 394 0 action-local

The 64-token difference between the current doctor and model-facing totals is diagnostic-only accounting: a project-context warning (33) and provider facts (31). Separately transported provider tool schemas are not included in this system-message receipt.

Pi comparison

Installed Pi 0.80.3 was measured through its SDK in the same working directory with its actual default read, bash, edit, and write prompt snippets and extensions disabled.

Pi fresh system variant Characters Conservative tokens
Default context and 16 discovered skills 27,671 9,224
Context, skills disabled 17,719 5,907
Skills, context disabled 12,485 4,162
Base and actual tool snippets only 2,533 845

Pi host-discovers and eagerly reads applicable project files; it loaded /Volumes/VIXinSSD/CW/AGENTS.md (1,635 chars) and /Volumes/VIXinSSD/CW/codewhale/AGENTS.md (13,280 chars). It does not leave discovery to the model. Pi advertises skill metadata eagerly and reads skill bodies on demand.

The full configured Codewhale system is 7,844 tokens, 1,380 below the full configured Pi receipt in this environment. With skill indexes removed from both, Codewhale is approximately 7,050 versus Pi's 5,907: the 1,143-token premium is the deliberate constitutional, mode, and runtime-special-feature budget. Codewhale stays smaller overall here because its skill routing index is bounded at 794 tokens; Pi's 16 discovered skill entries added 3,318.

Constitutional boundary

Still eager and test-locked:

  • the current user's request and exact precedence chain
  • express current-request authorization for irreversible actions, publication, spending, credentials, and material scope expansion; otherwise name the decision and ask
  • tool, approval, sandbox, skill, role, and project gates, including anti-workaround language
  • tool evidence, honest failures/uncertainty, and no invented facts
  • test-output verification, tool-confirmed external actions, running-work status, and no partial-as-whole completion claims
  • mechanism for authorization, ordering, stopping, schemas, limits, and required checks

Deeper execution cadence, causal debugging, candidate comparison, simplification, verification, and continuity procedures remain available through mode doctrine, bundled on-demand skills, and /relay. This is not a claim that deleted prose was byte-for-byte relocated. See docs/CONSTITUTIONAL_KERNEL_AUDIT.md.

Verification

Current head:

  • cargo fmt --all -- --check: PASS
  • git diff --check: PASS
  • prompt suite: 102 passed
  • context-report/diagnostic suite: 13 passed
  • skills suite: 91 passed
  • procedural skill-home contract: passed
  • runtime-contract budget: all 55 metrics exactly at budget
  • warnings-as-errors workspace Clippy with all features: PASS
  • debug build for CLI + TUI: PASS
  • current debug binary reproduced 7,908 doctor / 7,844 model-facing tokens
  • Claude, Kimi, and Grok read-only reviews completed; all concrete safety/test/accounting findings were addressed
  • Codewhale CLI with deepseek-v4-flash: BLOCKED by Responses API request failed; no review result claimed

A release build passed on the earlier 4a54bbe head. It has not been rerun after the constitutional-kernel pass, so packaged/release-binary proof for 7,908 remains UNRUN. The current receipt is from the freshly built debug binary.

Relates #4704.
Relates #4710.

No-Issue: this is a tested partial implementation of #4704 and #4710, but it does not satisfy every umbrella acceptance criterion yet.

Keep project authority eager while bounding the ambient skills index and
retaining complete discovery through load_skill. Move the session relay
template onto the relay action instead of every fresh system prompt.

Make context diagnostics count the configured prompt rather than a disabled
project pack and approximate phantom layers, and pin the lazy boundaries with
provider-free tests.
Copilot AI review requested due to automatic review settings August 2, 2026 03:00
@cursor

cursor Bot commented Aug 2, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 4m 14s —— View job


Review complete

Summary

This is a well-scoped, mechanically clean progressive-disclosure PR: relay template moved out of the eager system prompt, ambient skills index capped and budget-checked against a hard char ceiling, and context_report.rs's doctor --context-json entries switched from hand-maintained approximate estimates to the actual rendered constants (mode_doctrine, CORE_EXECUTION_PROFILE_PROMPT, render_environment_block, effective_authority_recap). No provider/model-prefix inference logic touched — invariant #2608 is not implicated by this diff.

Good choices worth calling out:

  • context_report.rs:520-533 gating the project-context-pack entry on project_pack_enabled (and reusing the existing SourceEntry::omitted/ActivationReason::Omitted helpers rather than inventing new ones) directly fixes the "disabled pack reported as active" over-count the PR describes.
  • skills/mod.rs budget accounting (fixed_reserve, per-line reserve for the warnings loop) is careful about reserving space for the eventual omission-notice lines before appending them, and it's backed by a debug_assert! plus catalog_matrix.rs tests that actually assert the complete rendered block stays <= MAX_AVAILABLE_SKILLS_CHARS.
  • Moving COMPACT_TEMPLATE's content into a single constant shared by both the (now dormant) system-prompt path and relay.rs (crates/tui/src/commands/groups/session/relay.rs:57-58) removes what used to be two independently-hand-maintained copies of the same structure.

Minor / non-blocking observations:

  1. crates/tui/src/skills/mod.rs:1379SKILL_OMISSION_RESERVE hardcodes a 4-digit "9999" placeholder to reserve space for the eventual "{omitted} additional skills omitted..." line. If the omitted count ever exceeds 9999 (5+ digits), the real line is longer than what was reserved and the hard MAX_AVAILABLE_SKILLS_CHARS budget could be exceeded by a few bytes, only caught by debug_assert! in debug builds (compiled out in release). Given real-world skill counts this is extremely unlikely to matter — flagging only because the budget is explicitly meant to be a hard ceiling.

  2. crates/tui/src/context_report.rs:253-256build_context_report(app) (used by the interactive /context report|json|summary commands) infers whether the project-context-pack is active by scanning app.system_prompt's already-rendered text for <project_context_pack>, rather than reading a config flag directly. Since app.system_prompt is None until the first turn builds it (crates/tui/src/tui/app.rs:1280), running /context json before any turn will always report the project pack as omitted/disabled even if [context] project_pack = true is configured. This doesn't affect doctor --context-json (which correctly uses build_headless_context_reportconfig.project_context_pack_enabled() directly, per main.rs:6148-6151), so the PR's headline receipts are unaffected — just a small blind spot in the interactive command for a narrow pre-first-turn window.

Neither observation blocks merge; both are edge cases well outside the scenarios the PR's receipts and test suite exercise.

Note: I could not execute cargo build/cargo test in this sandbox (shell commands required approval that wasn't available), so this review is based on static reading of the diff plus cross-referencing call sites; it does not independently re-verify the PR's stated token-count receipts or test-pass counts.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The new hard-budget skill index can still exceed its ceiling due to under-reserving omission-line length, and the context report currently mislabels an always-included environment block as per-request.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR reduces fresh-session prompt footprint by progressively disclosing skill context, making the relay template action-local, and tightening doctor --context-json to report what’s actually configured/active.

Changes:

  • Cap the ambient skills index to a hard 2,400-character budget while keeping full discovery via load_skill name="list".
  • Remove the session-relay template from the default system prompt and inject it only for /relay.
  • Make context reporting more faithful (e.g., core execution prompt text is counted directly; project pack/reporting is conditioned; new authority/environment entries).
File summaries
File Description
crates/tui/src/tools/skill.rs Updates tool docs to emphasize name="list" progressive discovery.
crates/tui/src/skills/tests.rs Adjusts expectations for the new budgeted/renamed skills block sections.
crates/tui/src/skills/mod.rs Implements the 2,400-char hard ceiling and new “Usage”/omission behavior in the ambient skills block.
crates/tui/src/skills/catalog_matrix.rs Updates catalogue tests to accept progressive subsets and enforce the hard block budget.
crates/tui/src/prompts/text.rs Reworks COMPACT_TEMPLATE into a session-relay template intended for /relay injection only.
crates/tui/src/prompts.rs Removes eager relay-template inclusion from fresh prompts; exposes helpers used by diagnostics.
crates/tui/src/core/engine/tool_catalog.rs Ensures load_skill stays active by default for first-turn discovery.
crates/tui/src/core/engine/tests.rs Updates default-native-tool contract expectations to include load_skill.
crates/tui/src/context_report.rs Refactors prompt source accounting (skills mode/plugins, core execution counted as text, new authority/environment entries, project pack conditioning).
crates/tui/src/commands/groups/session/relay.rs Injects the relay template into the /relay instruction message instead of hardcoding it inline.
crates/tui/src/commands/groups/session/acceptance.rs Updates session-relay acceptance expectations for the injected template headings.
Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 2
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread crates/tui/src/skills/mod.rs Outdated
Comment thread crates/tui/src/context_report.rs
The context report now uses the mode-and-plugin-aware renderers directly.
Limit older convenience wrappers to tests or remove them so the production
binary remains warning-free under the workspace CI clippy gate.
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 3m 8s —— View job


Review complete

Summary

Reviewed the diff since my last pass, including the new commit b0cbf85 ("fix(skills): remove superseded discovery wrappers"). No new correctness or provider/route-safety issues found. No EPIC #2608 concerns — this diff never inspects a model/provider prefix string.

b0cbf85 is a clean, correct cleanup. It #[cfg(test)]-gates discover_in_workspace, discover_in_workspace_with_mode, and render_available_skills_context_for_workspace, and deletes the now-fully-unused render_available_skills_context_for_workspace_and_dir(_with_mode) wrappers. I confirmed by grep that every remaining call site for the gated functions is in skills/tests.rs, and the deleted wrappers have zero callers anywhere in crates/. This matches the stated intent (avoid clippy dead_code under the CI gate) without changing production behavior — context_report.rs and prompts.rs already call the mode-and-plugin-aware variants directly.

On the two Copilot-flagged items (re-verified against current HEAD, not just the earlier commit):

  1. skills/mod.rs:1353 (SKILL_OMISSION_RESERVE 4-digit "9999" placeholder) — confirmed still present, still only a debug_assert!-enforced ceiling in practice. Given MAX_AVAILABLE_SKILLS_CHARS = 2_400 and per-skill lines running well over 20 chars, the catalogue physically cannot hold enough entries to produce a 5-digit omitted count, so this stays non-blocking as previously noted.
  2. context_report.rs:617 (EnvironmentBlock labeled ActivationReason::PerRequest) — I traced this through git diff origin/main...HEAD: this label is pre-existing, not introduced by this PR (only the surrounding workspace/content plumbing changed here). Copilot's underlying observation is accurate though: render_environment_block is called unconditionally in prompts.rs:1332 on every prompt build, which reads more like AlwaysOn/RuntimeState (the pattern used elsewhere in this file for provider facts, conversation history) than PerRequest, which this file otherwise reserves for content that's only sometimes present in a given request (tool schemas already sent, latest user message). Worth a follow-up, but out of scope for this PR's diff.

Good choices:

  • skills/mod.rs's budget accounting (fixed_reserve, per-line checks in both the skill loop and the warnings loop) correctly reserves room for the trailing USAGE block and omission notices before they're appended, and the final debug_assert! matches what the catalog_matrix.rs tests assert about the complete rendered block.
  • catalog_matrix.rs's loosened invariant (rendered.is_subset(&expected) instead of assert_eq!, dropping the "shipped pack always fits" guarantee) correctly reflects the new tighter 2,400-char budget — the bundled pack can now legitimately need truncation, and the test now asserts truncation always advertises load_skill name="list".
  • compaction.rs's structured successor-brief prompt (line ~1848) is independent of COMPACT_TEMPLATE and untouched by this diff, so the PR's claim that "automatic compaction keeps its own structured successor brief" checks out by inspection.

Note on verification: I don't have cargo available in this sandbox (same limitation as the earlier automated review), so this is a static read of the diff plus cross-referencing call sites — it does not independently re-run the test suite or reproduce the token-count receipts.

Reserve omission notices from actual catalogue cardinality so the ambient skill index stays inside its runtime character cap even above 9,999 entries.

Track project-pack configuration on App for truthful pre-first-turn diagnostics, and label the always-injected environment block consistently.
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 31s —— View job


Review complete

Summary

This synchronize pushed one new commit, 4a54bbe, which resolves both issues Copilot flagged on the prior revision. No new correctness or provider/route-safety issues found; no EPIC #2608 concerns (this diff never inspects a model/provider prefix string).

Both Copilot findings are now fixed, and correctly so:

  1. Omission-line budget (crates/tui/src/skills/mod.rs:1353-1368) — SKILL_OMISSION_RESERVE's fixed "9999" placeholder is replaced with skill_omission_reserve/warning_omission_reserve strings formatted from registry.list().len() / registry.warnings().len(). Since an actual omitted count can never exceed the registry's total count, it can never have more decimal digits than the reserve — this holds for catalogues of any size, not just ≤9,999. The final budget check was also upgraded from debug_assert! to assert! (mod.rs:1458), so the ceiling is now enforced in release builds too, matching Copilot's "hard ceiling" framing. Backed by a new test (skills/tests.rs:202-241) that constructs an 11,000-skill/11,000-warning registry and asserts both omission counts exceed 9,999 while the rendered block still respects MAX_AVAILABLE_SKILLS_CHARS.
  2. Environment block mislabeled PerRequest (context_report.rs:614) — now ActivationReason::AlwaysOn, matching that render_environment_block is called unconditionally in prompts.rs. Covered by a new assertion in the existing test at context_report.rs:1162-1167.

Also fixed, beyond what Copilot flagged: my own earlier review noted build_context_report(app) inferred project-pack activation by string-scanning app.system_prompt, which was always None pre-first-turn — a blind spot in /context json before the first turn. This commit adds a dedicated App.project_context_pack_enabled field (tui/app.rs:1236-1239), populated in App::new (init.rs:658) and kept in sync on workspace switch in apply_workspace_runtime_state (ui.rs:12597) — the same two-call-site pattern already used for the analogous skills_scan_codewhale_only field, so it doesn't introduce a new staleness risk relative to existing conventions. build_context_report now reads this field directly instead of scanning rendered prompt text (context_report.rs:253-257), and a new test (context_report.rs:1174-1207) exercises the report before any turn runs and asserts the project pack is correctly reported as ConfigEnabled.

Reuse/simplification: no new duplication introduced; the fix reuses the existing registry.list()/registry.warnings() accessors rather than threading counts through separately.

Note on verification: cargo is unavailable in this sandbox (same limitation as prior automated reviews on this PR), so this is a static read of the diff plus cross-referencing call sites and existing test patterns — it does not independently re-run the test suite or reproduce the PR's stated token-count receipts. Nothing in this commit's diff suggests a reason those receipts or the previously-passing suites would regress.

@Hmbown

Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Review follow-up on 4a54bbe: besides the two inline Copilot fixes, interactive context diagnostics now retain the configured project-pack flag on App, so a pre-first-turn /context report no longer infers false from an unassembled system prompt. Focused receipts on this head: 13 context-report tests pass; 90 skill tests pass; cargo fmt --all -- --check and git diff --check pass; the exact warnings-as-errors workspace clippy command passes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The /relay instruction currently embeds a template header that can conflict with the requirement to title the artifact # Session relay, and should be made unambiguous before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (3)

crates/tui/src/commands/groups/session/relay.rs:60

  • The /relay instruction says the artifact should be titled # Session relay, but it inlines COMPACT_TEMPLATE starting with a separate ## Session Relay Template heading. This makes the recommended structure ambiguous (the model may copy the leading H2 into the file, making # Session relay no longer the top title). Consider stripping the template label when embedding it into the instruction message so the first heading in the structure is # Session relay.
    let _ = writeln!(out, "Use this relay structure:");
    let _ = writeln!(out);
    let _ = writeln!(out, "{}", crate::prompts::COMPACT_TEMPLATE.trim());
    let _ = writeln!(out);

crates/tui/src/skills/mod.rs:1240

  • This doc comment says the helper is for callers like prompts.rs, but the function is now #[cfg(test)] and prompts.rs no longer calls it. Updating the comment to reflect that it’s test-only will avoid sending readers to a non-existent production call site.
/// Render the system-prompt skills block from every workspace
/// candidate directory plus the global default (#432). Wraps
/// [`discover_in_workspace`] for callers (e.g. `prompts.rs`) that
/// only have the workspace path to hand.

crates/tui/src/commands/groups/session/acceptance.rs:581

  • This test currently asserts on the presence of the template label (## Session Relay Template), which is an internal instruction wrapper rather than the required relay artifact structure. That makes the acceptance test brittle to harmless template/instruction wording changes; it should assert only on the structural headings that matter to the relay output (e.g. # Session relay, ## Verification).
    assert!(message.contains("# Session relay"));
    assert!(message.contains("## Session Relay Template"));
    assert!(message.contains("## Verification"));
  • Files reviewed: 14/14 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Start the action-local relay template at the required artifact title and keep the acceptance contract focused on user-visible structure.

Refresh the provider-free runtime receipt for the intentional first-turn load_skill activation while locking in the smaller prompt measurements.
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 33s —— View job


Review complete

Summary

This synchronize pushed one new commit, db9e46c (fix(relay): make artifact heading unambiguous), which resolves the second round of Copilot-flagged issues on relay.rs/text.rs/acceptance.rs. No new correctness or provider/route-safety issues found; no EPIC #2608 concerns — grepped the full diff for deepseek-ai/, deepseek/, anthropic/, openai/, qwen/ prefixes and the only hit is the unrelated .deepseek/handoff.md file-path literal in a test assertion.

Both remaining Copilot findings are now fixed, correctly:

  1. Ambiguous artifact heading (crates/tui/src/prompts/text.rs:360-363) — COMPACT_TEMPLATE no longer opens with ## Session Relay Template followed by # Session relay; it now starts directly at # Session relay. Since relay.rs:59 still embeds the raw constant (crate::prompts::COMPACT_TEMPLATE.trim()) into the /relay instruction message, the model-visible structure is now unambiguous — # Session relay is the true top heading of the artifact to write, matching the explicit instruction on relay.rs:52-55.
  2. Brittle acceptance assertion (crates/tui/src/commands/groups/session/acceptance.rs:580) — the assert!(message.contains("## Session Relay Template")) line is removed; the test now only asserts on the structural headings that matter (# Session relay, ## Verification), matching Copilot's suggestion.

Also cleaned up in this commit, beyond what Copilot flagged: the stale doc comment on render_available_skills_context_for_workspace (crates/tui/src/skills/mod.rs:1237-1238) that pointed to prompts.rs as a caller — now correctly documents it as a test-only wrapper, consistent with the #[cfg(test)] gating landed in b0cbf85.

Verified the skill-budget reservation math holds end-to-end (re-checked since it's the one place a boundary error would silently regress): fixed_reserve (built during the skill-placement loop) reserves USAGE + skill_omission_reserve (sized off registry.list().len()) + WARNING_HEADING/warning_omission_reserve (sized off registry.warnings().len()) before any skill line is appended. The actual omitted/warnings_omitted counts used in the final rendered lines can never exceed the registry totals used to size the reserve, so the reserved space is always ≥ the real content. The trailing assert! (skills/mod.rs near the end of render_skills_block) enforces the MAX_AVAILABLE_SKILLS_CHARS ceiling in release builds too, not just via debug_assert!. No gap found.

runtime-contract-budget.json — the receipt refresh is consistent with the code changes: active tool lists for plan/act/operate modes now include load_skill (matching tool_catalog.rs's change to keep it active by default for first-turn discovery), and all system_prompt_bytes/total_tokens_est figures shrank in line with the smaller skills-block and relay-template-removal changes elsewhere in the PR. Nothing here touches provider/model selection.

Note on verification: cargo is unavailable in this sandbox (same limitation as every prior automated review on this PR), so this is a static read of the diff plus tracing call sites and manual verification of the budget-reservation arithmetic — it does not independently re-run the test suite or reproduce the PR's stated token-count/byte-count receipts. Nothing in this commit's diff suggests a reason the previously-passing suites or receipts would regress.

@Hmbown

Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Current-head follow-up on db9e46c: the action-local relay template now starts directly at # Session relay; its acceptance contract no longer depends on the removed internal wrapper label; and the test-only skill helper comment is accurate. The CI runtime-contract failure was also fixed by refreshing the checked receipt for the intentional first-turn load_skill activation while locking in the reduced prompt ceilings. Receipts: session acceptance 11 scenarios / 62 steps passed; prompt suite 101 passed; runtime-contract budget 55/55 exactly at budget; exact workspace -D warnings clippy passed; release doctor reproduced 9,127 active estimated tokens.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The updated prompt tests include assertions that don’t actually validate relay-template absence (they check for a substring that never appears), and render_skills_block can still drop warnings entirely when no skills are loaded.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (4)

crates/tui/src/prompts.rs:3108

  • Same issue as above: asserting that the prompt does not contain "## Session Relay Template" is ineffective because that substring never appears in COMPACT_TEMPLATE. Use a real template anchor (e.g. "# Session relay") so the test fails if the template is accidentally injected.
        // Session goal remains volatile content below the stable static
        // layers. The relay template is injected only when relay/compaction
        // actually needs it.
        assert!(goal_pos > 0);
        assert!(!prompt.contains("## Session Relay Template"));
        assert!(!prompt.contains("src/lib.rs"));

crates/tui/src/prompts.rs:3585

  • This assertion is checking for a substring ("## Session Relay Template") that does not exist in the relay template, so it will never catch accidental reintroduction. Prefer asserting against a real template marker like "# Session relay".
        assert!(
            execution_pos < handoff_pos,
            "## Core Execution must precede the relay block"
        );
        assert!(!prompt.contains("## Session Relay Template"));
    }

crates/tui/src/skills/mod.rs:1342

  • render_skills_block returns None when registry.is_empty() (no skills), even if registry.warnings() is non-empty. That means a workspace with only discovery warnings (e.g. all skills failed to parse) will hide those warnings from the model-facing prompt block, despite later code rendering a dedicated warnings section when the block is present.
fn render_skills_block(registry: &SkillRegistry, locale: &str, workspace: &Path) -> Option<String> {
    if registry.is_empty() {
        return None;
    }

crates/tui/src/prompts.rs:3074

  • The test checks for the absence of "## Session Relay Template", but that string does not exist in the relay template (COMPACT_TEMPLATE starts with "# Session relay"). This assertion can pass even if the relay template is accidentally reintroduced, so it isn't guarding the intended behavior.

This issue also appears in the following locations of the same file:

  • line 3103
  • line 3580
    fn compact_template_is_lazy_in_fresh_prompt() {
        let tmp = tempdir().expect("tempdir");
        let prompt =
            system_prompt_flat_text(&system_prompt_for_mode_with_context(tmp.path(), None));
        assert!(!prompt.contains("## Session Relay Template"));
        assert!(!prompt.contains("## Verification"));
    }
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Keep authority, current user intent, authorization gates, truthfulness, verified completion, mechanism, and exact precedence eager. Move procedural detail to mode/action/skill boundaries, lock first-turn invariants and skill homes with tests, document measured Pi parity, and surface warning-only skill discovery.
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 2m 57s —— View job


Review complete

Summary

This synchronize pushed one new commit, a987a01 ("perf(prompt): reduce constitution to first-turn kernel"), which condenses BASE_PROMPT from six procedural sections down to four (Ground truth, User intent and scope, Truthful completion, Put guarantees in mechanism, Whose word wins), fixes the warnings-dropped bug Copilot flagged on render_skills_block, and — as a side effect — repairs the three ineffective test assertions Copilot flagged in the previous round (prompts.rs:3091/3125/3602 now check the real heading "# Session relay" instead of the never-present "## Session Relay Template"). No EPIC #2608 concerns: grepped the full commit diff for provider-prefixed model strings (deepseek-ai/, deepseek/, anthropic/, openai/, qwen/) — no hits outside an unrelated test fixture literal.

Verified correct:

  • skills/mod.rs:1340render_skills_block now returns a block when registry.warnings() is non-empty even if registry.list() is empty, exactly fixing the "all-skills-failed-to-parse hides warnings" bug from the last Copilot round. Backed by the new render_skills_block_surfaces_warnings_when_no_skill_loaded test (skills/tests.rs), which also asserts the block still respects MAX_AVAILABLE_SKILLS_CHARS.
  • constitutional_kernel_keeps_first_turn_authority_safety_and_completion (prompts.rs:1718) — checked every asserted phrase against the actual BASE_PROMPT raw string in prompts/text.rs for line-break placement, since .contains() is a literal substring match and the constant is a raw multi-line string with real embedded \ns. All 15 phrases sit fully within a single source line — none straddle a line break — so the test isn't accidentally vacuous the way the pre-fix relay-template assertions were.
  • procedural_playbooks_are_not_eager_constitution correctly asserts the six removed headings (### Keep momentum, ### Think in causes, ### Honor constraints before preferences, ### Skill and role constraints are binding, ### Restraint, ### Leave continuity) are absent from the composed fresh prefix, and I confirmed via grep that none of these headings survive anywhere else in crates/ that would be eagerly composed into that prefix.
  • skills/system.rs's new procedural_skill_homes_remain_bundled_and_lazy test confirms debug, best-of-n, simplify, verify, test, and review are still registered bundled skills (pre-existing, not added by this PR) — consistent with the PR's claim that removed constitution prose remains reachable on demand rather than deleted outright.

Worth flagging for the maintainer (design tradeoff, not a bug): docs/CONSTITUTIONAL_KERNEL_AUDIT.md is candid that this is "not a byte-for-byte relocation of the deleted prose." Checking the old vs. new text directly: "Skill and role constraints are binding" survives condensed inside the new "User intent and scope" section ("Skill prohibitions stay binding; convenience creates no exception"), and "Keep momentum"'s authorization-boundary clause survives condensed into the same section. But "Restraint" (prefer reusing/repairing/deleting over adding, minimize new surface) has no condensed analog left in the eager kernel at all — it's now only reachable if the model happens to invoke the simplify skill. Since restraint/minimalism is arguably a per-turn coding-quality property rather than an on-demand procedure, this is a real behavioral bet, not just token accounting. The doc discloses it, so this isn't a hidden regression — just flagging it as the one substantive content change worth a maintainer's explicit sign-off alongside the token receipts.

Reuse: no new duplication; the omission-reserve and warning-rendering logic in skills/mod.rs is unchanged from the previously-reviewed and already-fixed version.

Note on verification: cargo is unavailable in this sandbox (same limitation as every prior automated review on this PR), so this is a static read of the diff plus manual substring/line-break tracing on the raw string literals — it does not independently re-run the test suite or reproduce the refreshed runtime-contract-budget.json byte/token receipts. Nothing in this commit's diff suggests a reason the previously-passing suites would regress.

@Hmbown

Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Pushed a987a016f with the constitutional-safe context pass and the third-round Copilot fixes.

Copilot findings fixed:

  • all fresh-prompt relay checks now assert against the real # Session relay anchor
  • warning-only skill discovery now renders instead of returning None, with a regression test

Kernel review findings fixed:

  • irreversible steps require express authorization in the current request; otherwise name the decision and ask
  • skill prohibitions remain binding and convenience creates no exception
  • verification explicitly reads test output rather than trusting exit status
  • first-turn tests lock every irreversible category, gate anti-circumvention, external confirmation, running work, and partial-result honesty
  • procedural skill homes are test-locked as bundled/on-demand
  • audit now distinguishes constitutional duties from deeper pre-existing procedures and includes an actual Pi SDK comparison

Measured in /Volumes/VIXinSSD/CW/codewhale:

  • doctor: 9,127 -> 7,908 for this pass; 17,839 -> 7,908 from installed baseline
  • model-facing system: 9,063 -> 7,844 for this pass; 13,185 -> 7,844 from baseline
  • constitution entry: 2,647 -> 1,428
  • actual configured Pi 0.80.3: 9,224 tokens in the same folder; Pi with skills disabled: 5,907

Local verification: prompt 102/102, diagnostic 13/13, skills 91/91, skill-home contract PASS, runtime contract 55/55 exact, fmt/diff checks PASS, workspace all-features warnings-as-errors Clippy PASS, debug build PASS.

The release build has not been rerun after the kernel pass; current 7,908/7,844 proof is from the fresh debug binary. Codewhale + deepseek-v4-flash review was attempted but the configured Responses API returned an error, so no result is claimed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The workspace-only skills rendering path does not apply .into_enabled(), which can cause disabled skills to appear in the ambient skills block when skills_dir is None.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (1)

crates/tui/src/skills/mod.rs:1255

  • render_available_skills_context_for_workspace_with_mode_and_plugins builds the ambient skills block from discover_in_workspace_with_mode_and_plugins(...) without applying SkillRegistry::into_enabled(). This makes the workspace-only path inconsistent with the workspace+dir variant (which calls .into_enabled()), and can cause disabled skills to be listed in the system prompt whenever skills_dir is None (see prompts.rs match arm).
pub fn render_available_skills_context_for_workspace_with_mode_and_plugins(
    workspace: &Path,
    mode: SkillDiscoveryMode,
    locale: &str,
    plugins: Option<&crate::plugins::PluginRegistry>,
) -> Option<String> {
    let registry = discover_in_workspace_with_mode_and_plugins(workspace, mode, plugins);
    render_skills_block(&registry, locale, workspace)
}
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

@Hmbown

Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Current-head follow-up (e90d1b9fd): fixed Copilot’s workspace-only prompt finding by applying the shared exact-name activation filter before rendering, and added a production-wrapper regression proving a disabled workspace skill is omitted while an enabled sibling remains visible. Verification: targeted regression PASS; skills 92/92 PASS; prompts 102/102 PASS; diagnostics 13/13 PASS; runtime-contract budgets 55/55 exact PASS; warnings-as-errors workspace clippy PASS; debug CLI+TUI build PASS. Fresh doctor receipt is unchanged at 7,908 diagnostic tokens / 7,844 model-facing tokens. Please re-review the current head.

@Hmbown
Hmbown requested a review from Copilot August 2, 2026 04:23
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 6s —— View job


Review complete

Summary

This synchronize pushed one new commit, e90d1b9 ("fix(skills): honor disabled state in workspace prompt"), which resolves the last outstanding Copilot finding (the fourth review round). No new correctness or provider/route-safety issues found; no EPIC #2608 concerns — the diff touches only skill-registry filtering, nothing model/provider-prefix related.

The fix is correct and minimal (crates/tui/src/skills/mod.rs:1253-1254):

let registry =
    discover_in_workspace_with_mode_and_plugins(workspace, mode, plugins).into_enabled();

This makes render_available_skills_context_for_workspace_with_mode_and_plugins (the path taken in prompts.rs:1302 whenever skills_dir is None) apply the same .into_enabled() filter that its sibling render_available_skills_context_for_workspace_and_dir_with_mode_and_plugins (mod.rs:1281) already applied — closing the gap where a disabled skill could still appear in the ambient system-prompt block for workspaces without a configured skills directory.

I also checked into_enabled()'s implementation (mod.rs:764-790) since it's now on a second call path: it's a plain Vec::retain keyed on SkillStateStore::is_enabled, with a fail-closed branch on state-load errors (native skills survive, plugin skills are hidden and a warning is pushed) — no panics, no unwrap/expect on the fallible path.

Test coverage is adequate: the new workspace_prompt_omits_disabled_skills_without_configured_directory test (skills/tests.rs) exercises exactly the previously-broken path — writes an enabled and a disabled skill under a workspace with no explicit skills_dir, disables one via SkillStateStore, and asserts the rendered block contains the enabled skill's name but not the disabled one's.

Reuse: no duplication — the fix reuses the existing into_enabled() helper rather than reimplementing filtering logic, matching the pattern already used by the sibling function.

This closes out every issue Copilot raised across all four review rounds on this PR (omission-line budget sizing, environment-block activation label, relay-template heading ambiguity, workless test assertions, warnings-only skill rendering, and now this workspace-only activation filter). Combined with the constitutional-kernel condensation in a987a01 (already reviewed in a prior pass — no issues beyond the previously-flagged, disclosed "Restraint" prose tradeoff), I have no further findings on the current head.

Note on verification: cargo is unavailable in this sandbox (same limitation as every prior automated review on this PR), so this is a static read of the diff plus tracing call sites and the into_enabled_with_state implementation — it does not independently re-run the test suite or reproduce the PR's stated token-count/test-pass receipts. Nothing in this commit's diff suggests a reason the previously-passing suites would regress.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Human review recommended

It changes multiple high-leverage prompt assembly and diagnostic surfaces (constitution/kernel, skills disclosure, tool activation, relay injection), so it warrants final human verification of behavioral/regression risk despite strong test coverage.

Review details

Suppressed comments (1)

crates/tui/src/skills/mod.rs:1360

  • skill_omission_reserve uses registry.list().len() (which includes ExplicitOnly skills that are intentionally excluded from the ambient index). This over-reserves digits/space and can cause avoidable truncation of user-visible skills under the 2,400-char cap even when all displayable skills would otherwise fit. Reserving based on the count of displayable (non-ExplicitOnly) skills keeps the invariant while maximizing useful entries.
    let skill_omission_reserve = format!(
        "- ... {} additional skills omitted; call `load_skill` with `name=\"list\"` for the complete catalogue.\n",
        registry.list().len()
    );
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

@Hmbown

Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Current-head follow-up (69a04c5c7): addressed Copilot’s fifth-pass optimization finding. The omission reserve now counts only model-selectable skills; explicit-only skills remain loadable by exact user request but cannot steal characters from the eager index. Added a boundary regression with six visible skills plus 10,000 explicit-only skills proving byte-identical ambient output. Verification: targeted regression PASS; skills 93/93 PASS; prompts 102/102 PASS; diagnostics 13/13 PASS; runtime budgets 55/55 exact PASS; warnings-as-errors workspace clippy PASS; debug CLI+TUI build PASS. Fresh receipt remains 7,908 diagnostic / 7,844 model-facing tokens. Please re-review current head.

@Hmbown
Hmbown requested a review from Copilot August 2, 2026 04:33
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 15s —— View job


Review complete

Summary

This synchronize pushed one new commit, 69a04c5 ("perf(skills): reserve prompt budget for visible entries"), touching only crates/tui/src/skills/mod.rs and crates/tui/src/skills/tests.rs. It resolves the fifth Copilot finding (over-reservation from counting ExplicitOnly skills in the omission-line budget). No new correctness or provider/route-safety issues found; no EPIC #2608 concerns — this diff is skill-registry-only and never touches a model/provider string.

The fix is correct (crates/tui/src/skills/mod.rs:1354-1365):

let model_selectable_skill_count = registry
    .list()
    .iter()
    .filter(|skill| skill.invocation != SkillInvocation::ExplicitOnly)
    .count();
let skill_omission_reserve = format!(
    "- ... {} additional skills omitted; call `load_skill` with `name=\"list\"` for the complete catalogue.\n",
    model_selectable_skill_count
);

I traced this against the render loop at mod.rs:1381-1423: for skill in registry.list() explicitly continues past SkillInvocation::ExplicitOnly entries (line 1382-1388), so the actual omitted counter can only ever count a subset of model_selectable_skill_count, never a larger figure. The reserve therefore stays a true upper bound — the same invariant the previous round established (registry-total reservation), just now scoped to the subset of skills that can actually appear as omitted catalogue entries. SkillInvocation derives PartialEq, Eq (mod.rs:203), so the != comparison is valid.

This also correctly stops explicit-only "power skills" from stealing budget from the ambient index they're deliberately excluded from displaying in — consistent with the existing continue logic's stated intent (opt-in skills shouldn't become ambient instructions or consume prompt budget).

Test coverage is solid: explicit_only_skills_do_not_reduce_ambient_index_capacity (skills/tests.rs) builds a registry with 6 visible skills at max description length, renders a baseline, then adds 10,000 ExplicitOnly skills and asserts the rendered block is byte-identical to the baseline — a strong regression guard directly targeting the over-reservation bug, not just a budget-ceiling check.

Reuse: no duplication introduced; reuses the existing SkillInvocation enum and filter pattern already used in the render loop.

This closes out Copilot's fifth review round. Combined with all prior rounds (omission-line budget sizing, environment-block activation label, relay-template heading ambiguity, ineffective test assertions, warnings-only skill rendering, workspace-only activation filter, and the constitutional-kernel condensation — all previously reviewed with no outstanding issues beyond the disclosed "Restraint" prose tradeoff), I have no further findings on the current head.

Note on verification: cargo is unavailable in this sandbox (same limitation as every prior automated review on this PR), so this is a static read of the diff plus manual tracing of the omission-counting logic — it does not independently re-run the test suite or reproduce the PR's stated token-count/test-pass receipts. Nothing in this commit's diff suggests a reason the previously-passing suites would regress.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Human review recommended

It makes broad, behavior-defining changes to prompt assembly, tool activation, and diagnostics, and should receive a final human review despite strong test coverage.

Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

@Hmbown

Hmbown commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Final current-head gate receipt for 69a04c5c7: all reported PR checks are green or intentionally skipped. Full CI: macOS PASS (26m39s), Windows PASS (18m8s), Ubuntu PASS, lint PASS, Rust/JS/Python/actions CodeQL PASS, OHOS PASS, Buildkite PASS, DCO/GitGuardian/link/type checks PASS. Claude current-head review: no findings. Copilot current-head review: 17/17 files, 0 new comments; human review recommended because prompt assembly is high-leverage. Local optimized release CLI+TUI build also PASS (8m17s), and the release binary reproduces the 7,908-token diagnostic receipt / 7,844 model-facing estimate. PR remains OPEN, CLEAN, MERGEABLE; no merge performed.

@Hmbown
Hmbown merged commit 21e7335 into main Aug 6, 2026
25 checks passed
Hmbown pushed a commit that referenced this pull request Aug 6, 2026
Harvested from PR #5238 by @bistack

MCP Registry discovery with Registry-first tool selection: registry_sync
surfaces the eligible local stdio catalog as a complete model-side
candidate set, connect-failure messages classify early-exit/help output
and point recovery at the next Registry candidate, and the bundled
mcp-discovery skill documents the flow.

Conflict resolutions (keep BOTH features where #5077 overlaps):
- engine/tests.rs: import union — the PR's merge_new_runtime_mcp_tools
  alongside main's workspace_write_carve_out_applies.
- engine/context.rs: stacked both compaction guards — main's
  evidence_available pass-through and the PR's registry_sync intact-set
  preservation.
- skills/system.rs: kept main's external tests file; the PR's only new
  inline tests were the uninstall pair already dropped with #5077 (main's
  dead-code audit removed uninstall_system_skills).
- tools/runtime_mcp.rs: kept both new free functions — main's
  reject_shell_metacharacters guard and the PR's connect_failure_message.
- budgets: source-structure raised for the new 1283-line mcp_registry.rs
  (175 large modules, 673293 aggregate lines); runtime-contract re-measured
  exactly at budget (registry tools sit outside the no-mcp default surface
  the fixture profiles).
Hmbown pushed a commit that referenced this pull request Aug 6, 2026
Adds #5242 (sub-agent checkpoint resume), #5240 (real shell wait elapsed
time), #5234 (#5223 alternate-scroll under mouse capture), #5077
(progressive fresh-context disclosure), and #5238 (MCP Registry
discovery); credits @SparkofSpike and @bistack in Contributors. Root and
crates/tui CHANGELOGs kept byte-identical in the 0.9.4 section.
@Hmbown
Hmbown deleted the agent/minimal-fresh-session-context branch August 6, 2026 09:36
Hmbown pushed a commit that referenced this pull request Aug 6, 2026
…merged surface

- tool_category_classifies_the_names_the_registry_actually_registers:
  load_skill became default-active with the progressive-disclosure kernel
  (#5077); pin it as "other" (read-only catalogue loader).
- contributor_onboarding_ships_at_generation_8_and_keeps_its_refusals:
  the current catalog generation is 10 (mcp-discovery, #5238).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants