Context
We already have auto-compaction working in src/agent/auto-compaction.ts (header comment: "Inspired by Claude Code's auto-compaction"). Today the knobs are process env vars:
MAESTRO_AUTOCOMPACT_PCT (default 85)
MAESTRO_AUTOCOMPACT_ENABLED (default true)
MAESTRO_AUTOCOMPACT_MIN_MESSAGES (default 10)
Sourcegraph Amp's "Neo" rebuild ships the same threshold as a typed user setting (internal.compactionThresholdPercent) validated by zod, alongside internal.model, internal.oracleReasoningEffort, openai.speed, etc. The settings schema itself becomes an audit-able artifact: "what knobs even exist." See ampcode.com/news/neo.
We have the storage already — db/schema.ts has users.settings: jsonb<UserSettings> and organizations.settings: jsonb<OrganizationSettings> columns sitting empty for this. We just don't have a typed catalog to go in them.
Scope
- Add a
MaestroSettingsSchema (TypeBox, alongside the existing packages/contracts/src/schemas.ts) covering at minimum:
internal.compactionThresholdPercent (number, 50–100)
internal.compactionEnabled (boolean)
internal.compactionMinMessages (number, ≥0)
internal.compactionKeepRecentTokens (number, ≥0) — the existing token-based cut point in src/agent/compaction.ts
- Resolution order at runtime: org settings → user settings → env var (legacy fallback) → built-in default.
- Wire resolution into
getAutoCompactionConfig() so callers don't change shape.
- Surface the schema through
amp plugins show-docs-equivalent (we don't have one yet — could reuse the headless control plane handshake's ClientCapabilities field to advertise settings keys instead).
- Audit hook: emit a
settings_changed event with the (org, user, key, old, new, by) tuple when settings flip — mirrors SERVER_REQUEST_RESOLVED_BY_* attribution model.
Non-goals
- Not migrating all env vars — only auto-compaction in this slice. Other
MAESTRO_* env vars become candidates in follow-up issues.
- Not building a settings UI. Settings are edited via API/CLI for now.
Acceptance criteria
- Setting
internal.compactionThresholdPercent on an org JSON column changes behavior for new sessions of users in that org without restarting maestro.
- Env var still works for users who don't have org/user settings (back-compat).
- Schema is exported from
packages/contracts and consumed by both the runtime and the platform's audit pipeline.
- One settings change emits exactly one audit event.
Why now
We already have the implementation, the proto event (CompactionMessage in proto/maestro/v1/headless.proto:458), and the DB columns. This is a wiring task, not a build task — the cost is low and the audit-grade payoff is real.
Context
We already have auto-compaction working in
src/agent/auto-compaction.ts(header comment: "Inspired by Claude Code's auto-compaction"). Today the knobs are process env vars:MAESTRO_AUTOCOMPACT_PCT(default 85)MAESTRO_AUTOCOMPACT_ENABLED(default true)MAESTRO_AUTOCOMPACT_MIN_MESSAGES(default 10)Sourcegraph Amp's "Neo" rebuild ships the same threshold as a typed user setting (
internal.compactionThresholdPercent) validated by zod, alongsideinternal.model,internal.oracleReasoningEffort,openai.speed, etc. The settings schema itself becomes an audit-able artifact: "what knobs even exist." See ampcode.com/news/neo.We have the storage already —
db/schema.tshasusers.settings: jsonb<UserSettings>andorganizations.settings: jsonb<OrganizationSettings>columns sitting empty for this. We just don't have a typed catalog to go in them.Scope
MaestroSettingsSchema(TypeBox, alongside the existingpackages/contracts/src/schemas.ts) covering at minimum:internal.compactionThresholdPercent(number, 50–100)internal.compactionEnabled(boolean)internal.compactionMinMessages(number, ≥0)internal.compactionKeepRecentTokens(number, ≥0) — the existing token-based cut point insrc/agent/compaction.tsgetAutoCompactionConfig()so callers don't change shape.amp plugins show-docs-equivalent (we don't have one yet — could reuse the headless control plane handshake'sClientCapabilitiesfield to advertise settings keys instead).settings_changedevent with the(org, user, key, old, new, by)tuple when settings flip — mirrorsSERVER_REQUEST_RESOLVED_BY_*attribution model.Non-goals
MAESTRO_*env vars become candidates in follow-up issues.Acceptance criteria
internal.compactionThresholdPercenton an org JSON column changes behavior for new sessions of users in that org without restarting maestro.packages/contractsand consumed by both the runtime and the platform's audit pipeline.Why now
We already have the implementation, the proto event (
CompactionMessageinproto/maestro/v1/headless.proto:458), and the DB columns. This is a wiring task, not a build task — the cost is low and the audit-grade payoff is real.