[{"data":1,"prerenderedAt":457},["ShallowReactive",2],{"docs-sections":3,"docs-page-\u002Fdocs\u002Fskill-define":123},[4,9,13,17,22,26,30,34,38,42,46,50,55,59,63,67,72,76,80,85,89,93,97,102,106,110,114,119],{"path":5,"title":6,"description":7,"group":8},"\u002Fdocs","Introduction","What tunables is, the problem it solves, and the principles it holds to.","Get started",{"path":10,"title":11,"description":12,"group":8},"\u002Fdocs\u002Fquickstart","Quickstart","Take one group of settings from constants to a screen with a history, in a Nuxt app on Postgres.",{"path":14,"title":15,"description":16,"group":8},"\u002Fdocs\u002Fpatterns","What it is for","The kinds of value tunables keeps — live limits, plans, per-workspace and per-person values, model choices, values that bound each other, costly switches — and the feature that does each.",{"path":18,"title":19,"description":20,"group":21},"\u002Fdocs\u002Fsettings-and-groups","Settings and groups","Declare each setting once, in a group edited beside what it affects, and read it with types.","Concepts",{"path":23,"title":24,"description":25,"group":21},"\u002Fdocs\u002Fkinds-and-units","Kinds and units","The eight kinds of setting, the built-in units, your own units, and how values are checked and read.",{"path":27,"title":28,"description":29,"group":21},"\u002Fdocs\u002Fchecks-and-guards","Checks and guards","Rules across settings, guards for what your app keeps, within for presets, confirmations for costly changes, and notes.",{"path":31,"title":32,"description":33,"group":21},"\u002Fdocs\u002Fhistory-and-restore","History and restore","Every change is a revision with who, when, why and each value before and after; restoring one runs the same checks as any save.",{"path":35,"title":36,"description":37,"group":21},"\u002Fdocs\u002Fpresets","Presets","Named, reusable configurations with one default per slot, assigned by reference and bounded by the settings.",{"path":39,"title":40,"description":41,"group":21},"\u002Fdocs\u002Fscopes","Scopes","Values per workspace and per person, through layers — the system, a plan, the workspace, the person — each bounded by what it inherits.",{"path":43,"title":44,"description":45,"group":21},"\u002Fdocs\u002Fcatalogs","Catalogs","Lists of allowed choices, such as permitted models, whose entries are retired rather than deleted and cannot be retired while in use.",{"path":47,"title":48,"description":49,"group":21},"\u002Fdocs\u002Fdeployment-values","Deployment values","Values a deployment sets in its environment and nobody tunes while the app runs, declared once and listed in .env.example.",{"path":51,"title":52,"description":53,"group":54},"\u002Fdocs\u002Fstorage","Storage","Postgres through your own client, the four tables and how to create them, joining your transactions, and the storage contract behind it.","Integrate",{"path":56,"title":57,"description":58,"group":54},"\u002Fdocs\u002Fserver","Server and access","Mount tunables' API as a fetch handler in Nitro, Hono, Bun or Deno, as Express middleware or as an oRPC router, with access decided by your app.",{"path":60,"title":61,"description":62,"group":54},"\u002Fdocs\u002Faccess","Who can do what","End users bound by values they never see, staff who tune groups, owners and members who change only their own scope, and the terminal.",{"path":64,"title":65,"description":66,"group":54},"\u002Fdocs\u002Ftesting","Testing","Your app's tunables in memory for its own tests, with values set where a test needs them, and how to test rules, guards and confirmations.",{"path":68,"title":69,"description":70,"group":71},"\u002Fdocs\u002Fnuxt-layer","The Nuxt layer","Ready screens for a Nuxt UI app — a group's form, All settings, history, presets, assignments and catalogs — placed beside what they affect.","Screens",{"path":73,"title":74,"description":75,"group":71},"\u002Fdocs\u002Fvue-composables","Vue composables","Headless composables for building tunables' screens in any Vue app, on any design system.",{"path":77,"title":78,"description":79,"group":71},"\u002Fdocs\u002Ftheming","Theming","The screens bring no colors, fonts or CSS of their own; they take your Nuxt UI theme.",{"path":81,"title":82,"description":83,"group":84},"\u002Fdocs\u002Fcli","The CLI","The tunables command, tunables.config.ts, and which commands need a database.","CLI",{"path":86,"title":87,"description":88,"group":84},"\u002Fdocs\u002Fcli-check","Check and generate","The commands that need no database — checking definitions, writing .env.example, and keeping explanations and defaults in step with a pdd-kit Product Model.",{"path":90,"title":91,"description":92,"group":84},"\u002Fdocs\u002Fcli-values","Read and change values","The commands that read and change stored values, through the same checks and history as the screens.",{"path":94,"title":95,"description":96,"group":84},"\u002Fdocs\u002Fcli-skills","Install skills","Install tunables' agent skills for Claude Code, Codex CLI, Cursor, Gemini CLI and GitHub Copilot, and keep them current.",{"path":98,"title":99,"description":100,"group":101},"\u002Fdocs\u002Fskills","Agent skills","Three skills that let a coding agent adopt tunables, define settings the right way and verify that every value has one home.","Skills",{"path":103,"title":104,"description":105,"group":101},"\u002Fdocs\u002Fskill-adopt","tunables-adopt","Bring tunables into an app that has none yet, from an inventory of every value to a wired, synced app with the old homes removed.",{"path":107,"title":108,"description":109,"group":101},"\u002Fdocs\u002Fskill-define","tunables-define","Add, change, rename or remove one value in an app that uses tunables, with its home, its checks, its reads and what happens to stored values.",{"path":111,"title":112,"description":113,"group":101},"\u002Fdocs\u002Fskill-verify","tunables-verify","Audit an app's tunables against their rules, report every finding with where it is and the rule it breaks, and fix only the findings you choose.",{"path":115,"title":116,"description":117,"group":118},"\u002Fdocs\u002Fapi","API reference","Every export of the tunables package, by the subpath it is imported from.","Reference",{"path":120,"title":121,"description":122,"group":118},"\u002Fdocs\u002Ftasklane-example","Tasklane, the example app","A todo app with workspaces and people as tunables — two groups, plans as a layer, a catalog of models, scopes, a rule, a confirmation, and the playground that runs it.",{"id":124,"title":108,"body":125,"description":109,"extension":450,"group":101,"meta":451,"navigation":452,"order":453,"path":107,"seo":454,"stem":455,"__hash__":456},"docs\u002Fdocs\u002Fskill-define.md",{"type":126,"value":127,"toc":443},"minimark",[128,131,138,143,276,280,414,418,424,429,434],[129,130,108],"h1",{"id":108},[132,133,134,137],"p",{},[135,136,108],"code",{}," makes one change to an app's tunables: a setting, a group, a\npreset set, a catalog or a deployment value. It decides where the value\nbelongs, declares it with everything it needs, and says exactly what happens to\nthe values already stored in each environment.",[139,140,142],"h2",{"id":141},"what-it-does","What it does",[144,145,146,162,168,174,192,224,242,256],"ol",{},[147,148,149,153,154,157,158,161],"li",{},[150,151,152],"strong",{},"Starts from the current state."," It finds ",[135,155,156],{},"tunables.config.ts"," and the\ndefinitions, runs ",[135,159,160],{},"tunables check",", and reports findings that were there\nbefore it started rather than fixing them unasked.",[147,163,164,167],{},[150,165,166],{},"Classifies the request",": add, change (default, bounds, options, kind,\nunit, section, effects, fact), rename, move between groups or between the\nenvironment and a setting, or remove. For a new value, it decides its home;\nif the value is code or user data, it says so and stops.",[147,169,170,173],{},[150,171,172],{},"Finds every read and every dependent",": other settings, presets, rows your\napp keeps, and work a change sets off.",[147,175,176,179,180,183,184,187,188,191],{},[150,177,178],{},"Settles the meaning."," With a pdd-kit Product Model, a new setting or a\nchange in what one means is a product change: it drafts the fact with\n",[135,181,182],{},"tunables model draft"," and brings it to ",[135,185,186],{},"\u002Fpdd-ideate",". Without one, it\nwrites the field's ",[135,189,190],{},"help"," in the product's words.",[147,193,194,197,198,203,204,207,208,211,212,215,216,219,220,223],{},[150,195,196],{},"Designs the field and its checks",": key, kind, unit, default, bounds,\nsection, effects and fact or label; when your app has\n",[199,200,202],"a",{"href":201},".\u002Fscopes","scopes",", whether a workspace or a person may set their own\n(",[135,205,206],{},"override",", freely or at most or at least what they inherit); the ",[135,209,210],{},"rules"," it joins, the guard for app\ndata that depends on it and the ",[135,213,214],{},"hold"," on the write that saves such data,\nthe ",[135,217,218],{},"within"," for presets it bounds, and the ",[135,221,222],{},"confirm"," for a costly change.\nWhatever you did not state, it presents for approval first.",[147,225,226,229,230,233,234,237,238,241],{},[150,227,228],{},"Writes the change",": the definition, new effects or units, each read\nreplaced (at the workspace's or person's path, ",[135,231,232],{},"get(group, { scope })",",\nwhere their own value applies) and the old constant, fallback or\nenvironment read deleted, and\n",[135,235,236],{},"tunables explain"," or ",[135,239,240],{},"tunables env"," when they apply.",[147,243,244,247,248,251,252,255],{},[150,245,246],{},"Plans stored values."," A changed definition never changes a stored value,\nso for each environment it says what ",[135,249,250],{},"sync"," will do and runs or hands you\neach ",[135,253,254],{},"tunables set"," the change needs.",[147,257,258,261,262,265,266,272,273,275],{},[150,259,260],{},"Tests and checks",": each new rule, guard and confirmation through ",[135,263,264],{},"save","\nwith ",[199,267,269],{"href":268},".\u002Ftesting",[135,270,271],{},"tunables\u002Ftesting",", then ",[135,274,160],{},", your\ntypecheck, lint and tests.",[139,277,279],{"id":278},"stored-values-by-kind-of-change","Stored values, by kind of change",[281,282,283,296],"table",{},[284,285,286],"thead",{},[287,288,289,293],"tr",{},[290,291,292],"th",{},"Change",[290,294,295],{},"What happens to stored values",[297,298,299,310,322,337,350,360,374,382,390,402],"tbody",{},[287,300,301,305],{},[302,303,304],"td",{},"Add a field or group",[302,306,307,309],{},[135,308,250],{}," stores it at its default. It must run before the new code reads it.",[287,311,312,315],{},[302,313,314],{},"Change a default",[302,316,317,318,321],{},"Existing environments keep their value; ",[135,319,320],{},"set"," moves one that should change.",[287,323,324,327],{},[302,325,326],{},"Tighten bounds, options or kind",[302,328,329,330,333,334,336],{},"A stored value outside them makes ",[135,331,332],{},"get"," throw. Move it inside with ",[135,335,320],{}," before the code ships.",[287,338,339,342],{},[302,340,341],{},"Rename or move a key",[302,343,344,346,347,349],{},[135,345,250],{}," adds the new key at its default and keeps the old one. ",[135,348,320],{}," the new key to the old value in each environment.",[287,351,352,355],{},[302,353,354],{},"Remove a field or group",[302,356,357,359],{},[135,358,250],{}," reports the stored key as undeclared and keeps it.",[287,361,362,365],{},[302,363,364],{},"Environment to setting",[302,366,367,368,370,371,373],{},"Add the field; after ",[135,369,250],{},", ",[135,372,320],{}," the value each environment ran with; remove the variable.",[287,375,376,379],{},[302,377,378],{},"Setting to environment",[302,380,381],{},"Read each environment's value first, add the deployment value, remove the field, set the variable where it differed.",[287,383,384,387],{},[302,385,386],{},"Allow an override, or loosen its bound",[302,388,389],{},"Nothing stored changes; each scope inherits until it sets its own.",[287,391,392,395],{},[302,393,394],{},"Stop allowing an override at a scope",[302,396,397,398,401],{},"Overrides stored there are kept and still read. Clear each with ",[135,399,400],{},"set --scope … --inherit key"," first, then ship the change.",[287,403,404,407],{},[302,405,406],{},"Bound an override that was free",[302,408,409,410,413],{},"An override outside the new bound stays until the next save at or above its scope is refused, naming it. Move each inside with ",[135,411,412],{},"set --scope"," first.",[139,415,417],{"id":416},"ask-for-it","Ask for it",[419,420,421],"blockquote",{},[132,422,423],{},"Make the export batch size tunable, between 100 and 5000.",[419,425,426],{},[132,427,428],{},"Lower the default Tasks per project to 150, and tell me what happens in production.",[419,430,431],{},[132,432,433],{},"Let each person lower their own AI suggestions a day, never above their workspace's.",[419,435,436],{},[132,437,438,439,442],{},"Move ",[135,440,441],{},"LOG_LEVEL"," into a deployment value with a default.",{"title":444,"searchDepth":445,"depth":445,"links":446},"",2,[447,448,449],{"id":141,"depth":445,"text":142},{"id":278,"depth":445,"text":279},{"id":416,"depth":445,"text":417},"md",{},true,25,{"title":108,"description":109},"docs\u002Fskill-define","v3hpSiBFPRgqIN02RToxMSazfKarkkOx9aRIP174zEE",1792845119725]