feat: /config command — live session configuration dashboard#158
Merged
feat: /config command — live session configuration dashboard#158
Conversation
Add optional configurator=None parameter to _make_command_processor() in tests/helpers.py. When configurator is not None, sets cp.configurator on the created CommandProcessor instance. Existing tests are unaffected (parameter defaults to None). Also add tests/test_helpers.py to verify the new configurator parameter behavior through TDD (test written and confirmed failing before implementation).
…redaction - Add _SENSITIVE_KEY_PATTERNS class variable to CommandProcessor - Add _redact_value static method that redacts string values >20 chars when key contains a sensitive keyword (key, token, secret, password, api_key) - Create tests/test_config_commands.py with TestRedactValue class (8 tests) - All 8 redaction tests pass; full test suite (687 tests) unaffected
- Rewrite _get_config_display to render a live dashboard when a
SessionConfigurator is attached, calling all 6 list methods:
context_list, tools_list, hooks_list, providers_list, agents_list,
behaviors_list, plus diff_from_original for change count
- Dashboard renders: header (bundle name, active mode, change count,
/config save hint), session section, providers/tools/hooks/context/
agents sections with [on]/[off] status, behavior provenance tags,
disabled indicators, and config values with sensitive key redaction
- Add _render_legacy_config method that preserves the old display
behavior (delegates to _render_bundle_config); called when no
configurator is attached (getattr fallback pattern)
- Keep _render_bundle_config as-is (now only called from _render_legacy_config)
- Add _make_mock_configurator factory and TestConfigDashboard class to
test_config_commands.py with 3 tests:
* test_config_no_args_renders_dashboard: verifies all 6 list methods called
* test_config_dashboard_shows_disabled_indicator: verifies handle_command returns ''
* test_config_falls_back_without_configurator: verifies no crash when no configurator
All 3 new tests pass; full suite 690/690 green.
Fixed Rich markup escaping for [on], [off], and [disabled] status indicators in the _get_config_display method. Rich was silently stripping these as invalid markup tags. Fixed by using \[on], \[off], and \[disabled] so they render as literal text instead of being interpreted as markup. Applied across all 6 sections (providers, tools, hooks, context, agents, behaviors): - 6 status assignments updated to escape [on]/[off] - 6 disabled tag appends updated to escape [disabled] Generated with Amplifier Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Extract _display_bundle_name property to remove duplicated bundle name stripping logic from _get_config_display and _render_legacy_config. Extract _render_simple_section() helper to consolidate the five near-identical section rendering blocks (providers, tools, hooks, context, agents, behaviors) into a single reusable method. Uses trailing_newline parameter so providers and behaviors can append per-item extras (config values and contribution counts) without layout disruption. Add console.print() after the behaviors section for spacing consistency with all other sections. Rename test_config_dashboard_shows_disabled_indicator to test_config_dashboard_returns_empty_string so the name matches the actual assertion (return value, not console output).
Refactor _get_config_display to accept args and dispatch to subcommand
handlers based on parsed args string.
Changes:
- _get_config_display(args: str = '') now parses args and routes to:
- _render_config_dashboard() for empty args
- _handle_config_diff() for 'diff' subcommand
- _handle_config_save(scope) for 'save' subcommand
- _handle_config_set(path, value) for 'set' subcommand
- _render_config_category(category) for valid category with 1 part
- _handle_config_toggle(category, action, name) for enable/disable mutations
- Extract _render_config_dashboard() from old _get_config_display body
- Add _render_category_summary(console, category, items) helper
- Add _render_config_category(category) for per-category list view
- Add _handle_config_toggle(category, action, name) for mutations with
async/sync dispatch, ValueError/RuntimeError error handling
- Add _handle_config_diff() for diff display
- Add _handle_config_save(scope) for config save with scope
- Add _handle_config_set(path, value) with bool/int/float/str type parsing
- Update handle_command to pass data.get('args', '') to _get_config_display
Tests added (13 new tests):
- TestConfigCategoryList: 6 tests verifying /config <category> calls
the correct list method (tools, context, hooks, providers, agents, behaviors)
- TestConfigMutation: 7 tests verifying enable/disable mutations call
the correct configurator method, including AsyncMock for tool methods
and error handling for ValueError
…ubcommands Add 9 tests covering the diff, save, and set subcommands: - TestConfigDiff (2): verify diff_from_original() called, empty diff returns 'no changes' - TestConfigSave (3): default global scope, explicit --scope project, ValueError → error - TestConfigSet (4): string value, bool parsing (true/false), int parsing, usage error Fix _handle_config_diff to return 'No changes from original' message (instead of printing to console and returning '') so test result assertions work. Fix default save scope from 'project' to 'global' in _get_config_display dispatch.
- Add configurator field to InitializedSession dataclass (defaults to None) - Create SessionConfigurator after session initialization when prepared_bundle is available, with graceful ImportError and Exception handling - Apply saved settings from AppSettings then take snapshot on startup - Attach configurator to CommandProcessor in interactive_chat - Add tests for all new behaviors in test_session_runner.py
Update the COMMANDS dict description for /config from 'Show current configuration' to 'Live session config — /config [category] [disable|enable name]' to reflect the available subcommand syntax. Add test TestConfigHelpEntry.test_config_help_description to verify the description matches the expected subcommand syntax string.
…format test file - Add self.configurator: Any = None to CommandProcessor.__init__ to resolve undeclared dynamic attribute; removes all 6 type: ignore[attr-defined] suppressions across _render_config_dashboard, _render_config_category, _handle_config_toggle, _handle_config_diff, _handle_config_save - Run ruff format on tests/test_config_commands.py to align with project formatter config Resolves two required follow-up actions from code quality review.
…e hooks in dashboard
- Add show_config=True parameter to _render_simple_section: when True,
appends inline {key: val, ...} summary (top 3 pairs, redacted) and
changes source provenance format from '(from X)' to '(X)'
- Add _render_hooks_section: groups shell-* and _auto_* hooks into
collapsed summary lines (with counts) and shows named hooks individually
with their bound event name
- Add _render_behaviors_section: renders behavior contribution counts
inline on the same line as the behavior name (ctx/tools/hooks/providers/agents)
with zero counts shown for uniformity; replaces the old sub-block format
- Update _render_config_dashboard to use the three new renderers:
providers and tools get show_config=True, hooks use _render_hooks_section,
behaviors use _render_behaviors_section
15 new tests cover all rendering behaviors.
…design spec
Change 1 - Routing overhaul:
- /config (no args) now shows a concise help listing of subcommands
- /config show renders the full live dashboard (previous /config behavior)
- Added _render_config_help() method with canonical subcommand documentation
- Added explicit 'show' dispatch in _get_config_display()
Change 2 - Dashboard rendering matches design spec exactly:
- Header: 'Active bundle: <name>' / 'Mode: <mode> | Session changes: ...'
- Section headers: '── <title> (N active) ──' format with em-dash dividers
- Session section: reads from coordinator.config, shows orchestrator config
on indented second line
- Providers: config on second line (not inline), via new _render_providers_section()
- Tools: config inline in {key: val} braces (unchanged)
- Hooks: updated header to '── hooks (N active) ──'
- Behaviors: '── behaviors (N composed) ──' header; full 'context' label
instead of abbreviated 'ctx'; '← disabled' instead of '[disabled]'
- All sections: 'active'/'disabled' terminology, not 'on'/'off'
Tests:
- Added test_config_no_args_shows_help (RED before impl)
- Added test_config_show_renders_dashboard
- Added TestSectionHeaderFormat class (4 tests, all RED before impl)
- Updated test_config_no_args_renders_dashboard to use 'show'
- Updated test_contributions_shown_inline_with_name: 'context' not 'ctx'
- Updated test_header_shows_enabled_count: '1 composed'/'1 disabled'
- Add _render_tools_section(self, console, items, *, trailing_newline=True) method
- Header: '── tools (N active, M disabled) ──'
- Line 1: [green][on][/green] for enabled / [dim][red][off][/red]...[/dim] for disabled
with name left-aligned to 40 chars and dim behavior attribution (comma-joined)
- Line 2: indented 'module: {module_id}' in [dim]
- Line 3+: config tree (config: header + indented key-value pairs)
Large configs (>80 chars inline) collapsed to '{...}'
Values redacted via _redact_value()
- Update _render_config_dashboard to call _render_tools_section instead of
_render_simple_section for tools
New tests in TestNewToolsRendering:
- test_tools_show_module_on_indented_line
- test_tools_show_config_tree_indented
- test_tools_show_multi_claimant_behavior
- test_tools_green_on_red_off
All 755 tests pass.
- Add _render_hooks_section_v2 method to CommandProcessor
- Lists ALL hooks individually with no collapsing of shell-* or _auto_* patterns
- Line 1: green/red/dim status + name (40 chars) + dim behavior attribution
- Line 2: indented 'event: {event}' in [dim]
- Follows same green/red/dim rendering pattern as _render_tools_section
- Update _render_config_dashboard to call _render_hooks_section_v2
- Add TestNewHooksRendering class with 3 tests:
- test_shell_hooks_listed_individually
- test_auto_hooks_listed_individually
- test_hooks_show_event_on_indented_line
Closes task-7-hooks-section-rendering
…and redaction (task-8)
Added _render_providers_section_v2 method to CommandProcessor that renders providers with:
- Status + name + dim behavior attribution on line 1
- Source URI on indented 'source: {source_uri}' line
- Full config tree under 'config:' header with key-value pairs and API key redaction
Updated _render_config_dashboard to call _render_providers_section_v2 instead of
the previous _render_providers_section implementation.
Added TestNewProvidersRendering test class with three test methods:
- test_providers_show_source_uri: verifies source URI display with 'source:' label
- test_providers_show_config_tree: verifies model and max_tokens visibility under 'config:'
- test_providers_redact_api_key: verifies API key redaction in output
All 761 tests pass.
Generated with Amplifier
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…ategory filtering
Add _render_behaviors_section_v2 method to CommandProcessor that:
- Shows non-zero categories with actual item names (not just counts)
- Skips categories with empty contribution lists
- Strips provenance key prefix from display (e.g. 'context:readme' -> 'readme')
- Formats as indented '{label}: {comma-joined names}'
- Uses _CAT_LABELS class attribute for display label mapping
- Handles both v1 integer contributions and v2 list-of-names gracefully
Update _render_config_dashboard to use _render_behaviors_section_v2.
Add TestNewBehaviorsRendering class with:
- test_zero_categories_omitted: verifies empty categories are not shown
- test_item_names_listed: verifies item names appear with prefix stripped
Closes task-9-behaviors-section-rendering
…egory printing Both arms of the if/else at the category line print were identical. Collapse to a single unconditional console.print and update the docstring to accurately describe the actual behavior (uniform dim styling on all category lines, no differential disabled styling).
…avior provenance - Add _render_context_section method: single-line items with [green][on]/[red][off], name, then [dim] behavior attribution. Multi-claimant behaviors comma-separated. Disabled items have entire line dimmed with [red][off]. - Add _render_agents_section method: same pattern as context section. - Update _render_config_dashboard to call new section renderers instead of _render_simple_section for context and agents sections. - Add TestNewContextAgentsRendering tests: - test_context_shows_behavior_dim: verifies name and dim behavior shown - test_agents_shows_multi_claimant: verifies both 'foundation' and 'superpowers' visible - test_disabled_items_are_dimmed: verifies [red] and [dim] in output for disabled items Task: task-10-context-agents-section-rendering Co-authored-by: Amplifier <amplifier@amplifier.dev>
_render_context_section and _render_agents_section were identical except for the section label string. Extract the shared logic into a private _render_items_with_behavior_attribution helper; the two public methods become thin one-liner delegates. Also removes unused _all_calls_str helper from TestNewContextAgentsRendering (that test class uses _find_call_containing instead). All 766 tests pass.
- Update _make_mock_configurator to use multi-claimant format:
- All item types (context, tools, hooks, providers, agents) now use
'behaviors' list instead of 'source' string for attribution
- Tool items include 'module_id' field for _render_tools_section
- behaviors_list contributions use lists of item name strings
(not int counts) for _render_behaviors_section_v2 compatibility
- Add TestMockConfiguratorFormat: 8 tests verifying new mock format
- Remove TestRenderHooksSection: covered by TestNewHooksRendering
(old method used collapsing, new _render_hooks_section_v2 lists all)
- Remove TestRenderBehaviorsSection: covered by TestNewBehaviorsRendering
(old method used int counts, new _render_behaviors_section_v2 uses lists)
- Update TestSectionHeaderFormat: hooks/behaviors tests now call
_render_hooks_section_v2 and _render_behaviors_section_v2 (dashboard path)
Note: _render_config_dashboard already wired to v2 renderers in main.py
(task-11 wiring pre-completed in earlier implementation passes)
…der_behaviors_section Both v1 renderer methods were superseded by their _v2 counterparts and never called anywhere in source or tests. Only _render_hooks_section_v2 (line 997) and _render_behaviors_section_v2 are wired into the dashboard. Also includes the integration test class TestRealConfiguratorRenderIntegration which validates that real SessionConfigurator list method output (using actual 'behaviors' and 'module_id' keys) flows correctly through the renderer methods, detecting any future key-name contract mismatches at development time. - Removed 55 lines: _render_hooks_section (collapsed shell/auto hooks into summaries) - Removed 38 lines: _render_behaviors_section (contribution count format) - Added TestRealConfiguratorRenderIntegration integration tests - All 104 app-cli tests pass, lint clean
…nfig, fix behavior wrapping
Bug fixes:
1. _render_config_tree: new helper that always fully expands config dicts as
indented YAML-like tree (handles nested dicts and lists)
2. _print_wrapped_items: new helper that wraps long item lists with proper
continuation-line indentation (e.g., for behaviors section agent lists)
3. _render_tools_section: attribution moves from name line to module line
as '(behavior1, behavior2)' suffix — prevents wrapping confusion
4. _render_tools_section: config always expanded via _render_config_tree —
never collapsed to '{...}' representation
5. _render_hooks_section_v2: attribution moves from name line to event line
as '(behavior1, behavior2)' suffix — consistent with tools design
6. _render_behaviors_section_v2: item lists rendered via _print_wrapped_items
for proper continuation-line indentation
Update test_tools_show_multi_claimant_behavior to expect attribution on module
line. Update test_real_tools_list_behavior_renders_as_string similarly.
- _render_config_tree: add 'dim' parameter; wraps every output line in
Rich [dim] markup when dim=True. Propagates to recursive calls.
- _render_tools_section: config: header and all key-value tree lines are
now dim — top-level tool name stands out visually.
- _render_providers_section_v2: config: header and key-value lines are
now dim — top-level provider name stands out.
- _render_behaviors_section_v2: apply [green]\[on][/green] and
[dim][red]\[off][/red] status colors (was bare \[on]/\[off]).
Remove '<- disabled' text — the red color conveys disabled status.
Strip root_namespace prefix from behavior's own items (e.g.
'superpowers:implementer' -> 'implementer' for superpowers-methodology-behavior).
- _render_config_dashboard session section: replace inline {k: v, ...}
config format with properly expanded, dim tree renderer.
Issue 1 (foundation): _get_behavior_root_namespace() was returning None for
behaviors like 'foundation', 'shadow', 'python-dev', and 'routing-matrix'
that have no non-behavior sibling namespace at the same source path.
This caused items to display with their full namespace prefix
(e.g. 'foundation:bug-hunter' instead of 'bug-hunter').
The foundation fix (committed to amplifier-foundation) makes
_get_behavior_root_namespace() return behavior_name itself when no sibling
is found — these behaviors ARE their own namespace.
Issue 2 (CLI): The namespace-stripping logic in _render_behaviors_section_v2
was already correct — it strips "{root_namespace}:" from item names and
keeps foreign-namespace items intact. It just wasn't triggering because
root_namespace was None. Tests now cover the full stripping logic.
Issue 3 (wrapping): _print_wrapped_items already correctly computes
continuation-line indentation via 'continuation = " " * len(prefix)'.
Tests now verify:
- continuation lines align with first item on first line
- short item lists fit on one line without wrapping
- empty item lists produce no output
Tests added (5 new in TestNewBehaviorsRendering):
- test_root_namespace_strips_own_prefix_from_agent_names
- test_root_namespace_none_keeps_all_prefixes
- test_print_wrapped_items_continuation_indent
- test_print_wrapped_items_no_wrap_when_short
- test_print_wrapped_items_empty_list_produces_no_output
Task 2: Apply escape_markup() to all user-derived strings in Rich markup f-strings. Prevents Rich from interpreting [ and ] in tool names, hook names, agent names, behavior names, module IDs, and source URIs as markup tags. Affected rendering methods: - _render_simple_section: escape name - _render_hooks_section_v2: escape name, event, attribution - _render_behaviors_section_v2: escape name - _render_items_with_behavior_attribution: escape name, behavior_str - _render_providers_section_v2: escape name, attribution, source_uri - _render_tools_section: escape name, module_id, behavior_str escape_markup() was already imported from .utils.error_format (which wraps rich.markup.escape). No new import needed.
Extract all /config dashboard rendering logic from CommandProcessor into a dedicated DashboardRenderer class in amplifier_app_cli/ui/dashboard_renderer.py: - _SENSITIVE_KEY_PATTERNS and _redact_value() as module-level functions - DashboardRenderer(console) with: render_header, format_status, build_attribution, render_config_tree, print_wrapped_items, render_simple_section, render_tools_section, render_hooks_section, render_providers_section, render_attributed_section, render_behaviors_section CommandProcessor updated: - _render_config_dashboard() creates DashboardRenderer and delegates all section rendering to it (single renderer instance per dashboard render) - All rendering methods become thin one-liner delegates to DashboardRenderer - _redact_value stays as a @staticmethod delegate for backward compatibility - _SENSITIVE_KEY_PATTERNS kept as class attribute for backward compatibility All existing tests continue to work because the rendering methods remain accessible on CommandProcessor (as delegates), and the public API is unchanged.
This was referenced Apr 20, 2026
Closed
Closed
bkrabach
added a commit
that referenced
this pull request
Apr 20, 2026
… PR #158 PR #158 (merge commit ca9362d, with earlier commit 8944aec) accidentally committed a full copy of the repo at amplifier-app-cli/ inside the repo root — TWO levels of self-nesting, 340 stale files. This is the mirror of the amplifier-foundation cleanup (PR #174). Root cause: sub-agents used relative paths prefixed with the submodule name (e.g., 'amplifier-app-cli/amplifier_app_cli/main.py') while cwd was already inside the submodule, creating the nested tree. Verified no legit content at risk: - pyproject.toml IDENTICAL between root and both nested copies - uv.lock IDENTICAL between root and both nested copies - Root source has refactored ui/dashboard_renderer.py which does NOT exist in nested copies — nested snapshots are older, superseded state - Root main.py is the current refactored version Also adds /amplifier-app-cli/ to .gitignore as a recurrence guard. 4 stale Dependabot PRs (#159, #160, #161, #162 — all targeting nested /amplifier-app-cli paths) will be closed as no longer applicable.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reworked /config command as a full live session configuration dashboard with real-time toggle capabilities. Users can now disable/enable tools, contexts, agents, providers, and entire behaviors mid-session and see the changes reflected immediately. Depends on: microsoft/amplifier-foundation#160 (SessionConfigurator library). Includes 113 tests, rich-formatted dashboard with green/red status, dim sub-lines, config trees, behavior provenance, namespace stripping. All 113 tests passing.