feat(session): persist model tier overrides per session

Store per-session config in SQLite and route /model and /reset through command fast-paths so channel sessions keep independent model selection across reconnects and restarts.
This commit is contained in:
William Valentin
2026-02-13 01:04:26 -08:00
parent 3472a0b926
commit 9f81c01603
35 changed files with 1438 additions and 144 deletions
+29
View File
@@ -150,6 +150,35 @@ describe('configSchema — skills watcher', () => {
const result = configSchema.parse(minimalConfig);
expect(result.skills.load.watch).toBe(false);
expect(result.skills.load.watch_debounce_ms).toBe(250);
expect(result.skills.installation_execution).toBe('disabled');
expect(result.skills.allow_shell_runner).toBe(false);
expect(result.skills.shell_runner_allowlist).toEqual([]);
expect(result.skills.shell_runner_governance.owner).toBeUndefined();
expect(result.skills.shell_runner_governance.review_cadence_days).toBe(7);
expect(result.skills.shell_runner_governance.promotion_min_success_rate).toBe(0.9);
});
it('accepts explicit installation execution policy', () => {
const enabled = configSchema.parse({
...minimalConfig,
skills: {
installation_execution: 'enabled',
allow_shell_runner: true,
shell_runner_allowlist: ['npm install*'],
shell_runner_governance: {
owner: 'skills-team',
review_cadence_days: 14,
promotion_min_success_rate: 0.95,
},
},
});
expect(enabled.skills.installation_execution).toBe('enabled');
expect(enabled.skills.allow_shell_runner).toBe(true);
expect(enabled.skills.shell_runner_allowlist).toEqual(['npm install*']);
expect(enabled.skills.shell_runner_governance.owner).toBe('skills-team');
expect(enabled.skills.shell_runner_governance.review_cadence_days).toBe(14);
expect(enabled.skills.shell_runner_governance.promotion_min_success_rate).toBe(0.95);
});
it('accepts explicit watcher settings', () => {
+17
View File
@@ -108,6 +108,15 @@ const skillsLoadSchema = z.object({
watch_debounce_ms: z.number().min(10).max(10_000).default(250),
}).default({});
const skillsShellRunnerGovernanceSchema = z.object({
/** Responsible owner for shell-runner allowlist decisions. */
owner: z.string().min(1).optional(),
/** Review cadence for allowlist + rollout status checks. */
review_cadence_days: z.number().min(1).max(90).default(7),
/** Minimum success rate required before broader rollout. */
promotion_min_success_rate: z.number().min(0).max(1).default(0.9),
}).default({});
const skillsSchema = z.object({
/** Directory for user-created workspace skills. */
workspace_dir: z.string().optional(),
@@ -115,6 +124,14 @@ const skillsSchema = z.object({
managed_dir: z.string().optional(),
/** Directory for bundled skills shipped with Flynn. */
bundled_dir: z.string().optional(),
/** Global policy gate for installer command execution. */
installation_execution: z.enum(['disabled', 'enabled']).default('disabled'),
/** Allow use of the shell runner for installer commands. */
allow_shell_runner: z.boolean().default(false),
/** Allowlist patterns for shell runner commands (supports '*' wildcard). */
shell_runner_allowlist: z.array(z.string()).default([]),
/** Governance controls for shell-runner rollout decisions. */
shell_runner_governance: skillsShellRunnerGovernanceSchema,
/** Skills watcher settings. */
load: skillsLoadSchema,
}).default({});