feat(settings): Activity category — conversation fold level (T-453)

The first real settings tab. The Claude extension contributes an Activity
SettingsCategory whose fold-level select binds to app.claude.activityFoldLevel;
the activity panes already rebuild off the settings notifier, so a pick applies
live. Proves the schema-driven engine end to end with a production setting —
opening Settings now shows a populated, working category.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 12:41:20 +02:00
co-authored by Claude Opus 4.8
parent 76d8dadc25
commit 291f997d31
3 changed files with 56 additions and 13 deletions
+12 -13
View File
@@ -25,30 +25,29 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit.
✕, Esc, or a barrier tap. (T-445)
- **Schema-driven settings engine.** Subsystems register a `SettingsCategory`
(a `SettingsCategoryContribution` routed into the kernel `SettingsRegistry`);
the panel renders it as carded sections of field rows — toggle, select,
text, number, and an "opens external file" button — each bound to a
`SettingsStore` key with help text and reset-to-default. Inputs recede to
`panelBackground` inside the elevated `panelHeader` cards (ui-design
surface.md). Categories are data; registering one surfaces a new tab. (T-448)
(via `SettingsCategoryContribution` the kernel `SettingsRegistry`); the
panel renders it as carded sections of toggle/select/text/number/file rows,
each bound to a `SettingsStore` key with help and reset-to-default.
Registering a category surfaces a new tab. (T-448)
- **Settings category rail.** The modal's left rail lists the registered
categories (icon + title, data-driven from the registry) with an accent
left-stripe + surfaceHi selection; picking one swaps the panel. (T-447)
- **Per-field scope tags.** Each settings field shows where its value lives —
folder = Project (`.clide`), globe = Always (`~/.clide`), circle-dashed =
Default/unset — colour-coded with a tooltip. Tapping opens a menu to move the
value between the scopes the key supports or reset it to default. Backed by
scope-explicit `SettingsStore` access (`rawAt`/`setAt`/`removeAt`/
`effectiveLayer`/`writableLayers`); `ext.*` keys layer project-over-app,
`app.*`/`project.*` keys live in their prefix's file. (T-449)
- **Per-field scope tags.** Each field shows where its value lives — folder =
Project (`.clide`), globe = Always (`~/.clide`), circle-dashed =
Default/unset — with a tooltip and a menu to move the value between scopes or
reset it. Backed by scope-explicit `SettingsStore` access. (T-449)
- **Cross-category settings search.** A search box atop the rail filters fields
across every category; the panel shows the matches grouped under category
subheaders (editable inline), and each rail row shows its match count with
zero-match categories dimmed. (T-450)
- **Settings → Activity category.** The first real settings tab: the
conversation fold level (none / tools / thinking / everything) as a schema
field; picking a level applies live to the activity stream. (T-453)
### Changed
- **Theme picker relabelled "Theme…".** The ⌘K theme picker's command title
+32
View File
@@ -100,6 +100,38 @@ class ClaudeExtension extends ClideExtension {
title: 'Claude: cycle activity fold level',
run: _cycleFoldLevel,
),
// Activity settings category (T-453) — the fold level as a schema field,
// written to kActivityFoldLevelKey; the panes already rebuild off the
// settings notifier, so picking a level applies live.
const SettingsCategoryContribution(
id: 'activity',
category: SettingsCategory(
id: 'activity',
title: 'Activity',
iconName: 'cards-three',
priority: 50,
sections: [
SettingsSection(
label: 'Conversation',
fields: [
SettingsField(
key: kActivityFoldLevelKey,
kind: SettingsFieldKind.select,
label: 'Fold level',
help: 'How aggressively the conversation folds tool calls, thinking, and results.',
defaultValue: 'tools',
options: [
SettingsOption(value: 'none', label: 'Show everything'),
SettingsOption(value: 'tools', label: 'Fold tool calls'),
SettingsOption(value: 'thinking', label: 'Fold tools + thinking'),
SettingsOption(value: 'everything', label: 'Fold all but prose'),
],
),
],
),
],
),
),
// T-171: agent roster controls (D-6 CLI/UI parity).
// Usage: clide claude.agent.show <sessionId>
CommandContribution(
@@ -145,4 +145,16 @@ void main() {
expect(activeClaudeConfig, isNull);
});
});
group('Activity settings category (T-453)', () {
final category = ext.contributions.whereType<SettingsCategoryContribution>().firstWhere((c) => c.id == 'activity').category;
test('contributes an Activity category with the fold-level field', () {
expect(category.title, 'Activity');
final field = category.sections.expand((s) => s.fields).firstWhere((f) => f.key == kActivityFoldLevelKey);
expect(field.kind, SettingsFieldKind.select);
expect(field.defaultValue, 'tools');
expect(field.options.map((o) => o.value), containsAll(['none', 'tools', 'thinking', 'everything']));
});
});
}