From 83d99eff60cc6835fea36440956f840dca61e7f7 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 8 May 2026 17:26:26 +0200 Subject: [PATCH] Whitelist lora-augmentation.jsonl in extraction/ .gitignore The inner .gitignore at docs/scripts/extraction/.gitignore blanket-ignored *.md/*.json/*.jsonl so research-agent transcripts wouldn't drift in. The curated augmentation file needs an explicit exception so the Docker build step on production can read it during `node scripts/build-corpus.mjs`. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/scripts/extraction/.gitignore | 6 + .../extraction/lora-augmentation.jsonl | 196 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 docs/scripts/extraction/lora-augmentation.jsonl diff --git a/docs/scripts/extraction/.gitignore b/docs/scripts/extraction/.gitignore index d4dcdf1..9bd283a 100644 --- a/docs/scripts/extraction/.gitignore +++ b/docs/scripts/extraction/.gitignore @@ -1,3 +1,9 @@ +# Extraction outputs from research-agent runs are typically large + transient. +# Keep them local by default — except the curated augmentation file which +# needs to ship for the Docker build to fold it into the LoRA corpus. *.md *.json *.jsonl + +# …with one explicit exception: +!lora-augmentation.jsonl diff --git a/docs/scripts/extraction/lora-augmentation.jsonl b/docs/scripts/extraction/lora-augmentation.jsonl new file mode 100644 index 0000000..2667018 --- /dev/null +++ b/docs/scripts/extraction/lora-augmentation.jsonl @@ -0,0 +1,196 @@ +{"instruction":"What is the namespace prefix for autogenerated models in Nibiru and how does it map to disk?","input":"","output":"Autogenerated models live under `\\Nibiru\\Model\\\\`. The folder name is derived from the database `basename` (PascalCased after splitting on `-` or `_`), and the file path is `application/model//.php`. Example: `\\Nibiru\\Model\\WarehouseLoach\\Timeanddate` lives at `/application/model/WarehouseLoach/timeanddate.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["framework-reference-v2.md §1","core/c/table.php:63","core/c/table.php:111"]}} +{"instruction":"Quick question: where does the `\\Nibiru\\Factory\\*` namespace map to on disk?","input":"","output":"`\\Nibiru\\Factory\\*` maps to `core/f/*.php`. These are the static factories — call signature is `ClassName::staticMethod()`. Example: `Db::loadModel('WarehouseLoach\\\\Timeanddate')` returns an `IDb`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["framework-reference-v2.md §1"]}} +{"instruction":"Where do module interfaces live and how do they get loaded?","input":"","output":"Module interfaces live at `application/module/[NAME]/interfaces/` and are registered as `\\Nibiru\\Module\\[Name]\\Interfaces\\*`. They are loaded by `Auto::loader()->loadModules()` if listed in the INI under `[AUTOLOADER] iface.pos[]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"workflow","citations":["framework-reference-v2.md §1","framework-reference-v2.md §4.2"]}} +{"instruction":"I'm trying to figure out which adapter namespace MySQL models extend — what is it?","input":"","output":"MySQL-driver models extend `\\Nibiru\\Adapter\\MySQL\\Db`, which lives at `core/a/mysql.db.php`. The generated model has `use Nibiru\\Adapter\\MySQL\\Db;` and `class extends Db`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["core/a/mysql.db.php:15","framework-reference-v2.md §1"]}} +{"instruction":"What interface guarantees model methods like `loadTableAsArray()` exist?","input":"","output":"`\\Nibiru\\Adapter\\IDb`, defined at `core/i/IDb.php`. It is implemented by all generated models and guarantees `loadTableAsArray()`, `updateRowById()`, `insertArrayIntoTable()`, `selectRowsetById()`, `selectDatasetByFieldWhere()`, `selectRowByFieldWhere()`, `lastInsertId()`, `deleteRowById()`, `updateRowByFieldWhere()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §1"]}} +{"instruction":"Are module plugin classes loaded before or after traits?","input":"","output":"Plugins are loaded last. The order is: interfaces (`iface.pos[]`), then traits (`trait.pos[]`), then modules (`class.pos[]`), then plugins (`class.plugin.pos[]`). Loaded by `Auto::loader()->loadModules()` and the order inside each array is significant.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["framework-reference-v2.md §4.3","framework-reference-v2.md §1"]}} +{"instruction":"Show me the signature of `Config::getInstance()`.","input":"","output":"```php\npublic static function getInstance(): Settings\n```\nDefined at `core/c/config.php:12`. It reads the environment via `getenv('APPLICATION_ENV')` (or the `APPLICATION_ENV` constant), calls `parent::setConfig(self::getEnv())` which parses the INI for that environment, and returns a singleton holding the entire application config array.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"code-recall","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}} +{"instruction":"How does Nibiru pick which INI file to parse?","input":"","output":"It uses the template `settings.ENV.ini`, where `ENV` comes from `getenv('APPLICATION_ENV')` or the `APPLICATION_ENV` constant. Real filenames seen in production: `settings.development.ini`, `settings.production.ini`, `settings.cli.ini`, `settings.preproduction.ini`. The file is parsed with `parse_ini_file(..., true)` so each section becomes an associative array keyed by section name.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"workflow","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}} +{"instruction":"How do I read a single INI value in code? Give me an example.","input":"","output":"```php\nConfig::getInstance()->getConfig()['DATABASE']['username']\nConfig::getInstance()->getConfig()['ENGINE']['templates']\nConfig::getInstance()->getConfig()['AUTOLOADER']['class.pos']\n```\nThe returned value is whatever `parse_ini_file(..., true)` produced for that section/key.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"code-recall","citations":["framework-reference-v2.md §2.1"]}} +{"instruction":"What happens if I call `Config::getInstance()->getConfig()['MISSING_SECTION']['key']`?","input":"","output":"It returns `NULL` and emits no error. Then if you pipe that NULL into something like `array_key_exists($null_value, $array)` you'll get a warning about the wrong number of arguments. Always wrap nested INI accesses with `array_key_exists()` checks before reading.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.6 Missing INI Keys","kind":"gotcha","citations":["framework-reference-v2.md §11.6"]}} +{"instruction":"Show me the two static methods Pdo exposes for switching databases.","input":"","output":"```php\npublic static function settingsSection( $section = IOdbc::SETTINGS_DATABASE )\npublic static function getInstance( $section = false ): Mysql\n```\nDefined at `core/c/pdo.php:12`. `settingsSection()` writes to the static `Pdo::$section` variable (line 14); `getInstance()` returns the connection for that section.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:12","core/c/pdo.php:14","framework-reference-v2.md §2.2"]}} +{"instruction":"What happens if I call `Pdo::settingsSection('DATABASE_X')` and that section doesn't exist in the INI?","input":"","output":"`Mysql::__construct()` at `core/c/pdo.php` line 32 reads `$settings = Config::getInstance()->getConfig()[$section];`. If `DATABASE_X` is missing, the access yields `NULL`, so `$settings['username']`, `$settings['password']`, etc. are all NULL — connection construction will fail when PDO actually tries to connect with empty credentials. There is no defensive check inside the framework: missing INI section means a runtime error in PDO.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"edge-case","citations":["core/c/pdo.php:32","framework-reference-v2.md §2.2","framework-reference-v2.md §11.6"]}} +{"instruction":"Why do all my Pdo queries suddenly hit a different database after I instantiate one model?","input":"","output":"Because `Pdo::$section` is a **static** variable (`core/c/pdo.php:14`) and every model's `__construct()` writes to it. Last write wins per request. Example:\n```php\n$userModel = Db::loadModel('App\\User'); // Pdo::$section = 'DATABASE'\n$logs = Pdo::queryString('SELECT ...'); // queries DATABASE\n$adminModel = Db::loadModel('App\\Admin'); // Pdo::$section = 'DATABASE_ADMIN'\n$logs = Pdo::queryString('SELECT ...'); // queries DATABASE_ADMIN now\n```\nMitigation: explicitly call `Pdo::settingsSection('DATABASE')` before raw Pdo queries, or instantiate a model bound to that section.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.1 Pdo last-write-wins","kind":"gotcha","citations":["core/c/pdo.php:14","framework-reference-v2.md §11.1"]}} +{"instruction":"Show me the exact `__construct()` body the autogenerator produces for a MySQL model.","input":"","output":"```php\npublic function __construct()\n{\n Pdo::settingsSection('DATABASE');\n self::initTable( self::TABLE );\n}\n```\nFrom `loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php:30-34`. The first line writes the static `Pdo::$section`; the second registers the table schema with the adapter's static `$table` array.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php:30-34","framework-reference-v2.md §2.2"]}} +{"instruction":"Walk me through what happens when I call `Pdo::queryString('SELECT 1')` directly without instantiating a model first.","input":"","output":"`queryString()` routes through `parent::getInstance(self::getSettingsSection())->getConn()`. `getSettingsSection()` returns the static `Pdo::$section`. If no model has been instantiated yet, `Pdo::$section` still holds whatever it was last set to — typically the default `IOdbc::SETTINGS_DATABASE` (the string `\"DATABASE\"`). So a fresh request will query the `[DATABASE]` section unless a previous call mutated `Pdo::$section`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"workflow","citations":["core/c/pdo.php:14","core/c/pdo.php:19","framework-reference-v2.md §2.2"]}} +{"instruction":"What's the difference between `Db::loadModel('Acl')` and `new \\Nibiru\\Model\\Acl()`?","input":"","output":"`Db::loadModel('Acl')` runs the factory chain at `core/f/db.php:11`: `_setModel(\"Acl\")` builds `$fmodel = \"\\\\Nibiru\\\\Model\\\\\".$model` and does `self::$_model = new $fmodel;`, which fires the model's `__construct()` — and that constructor calls `Pdo::settingsSection('DATABASE')` (or whichever DBSECTION was baked in by the autogenerator). The factory returns the instance via `IDb`.\n\nDirect `new \\Nibiru\\Model\\Acl()` ALSO fires the same constructor (the `Pdo::settingsSection()` call still runs), but you skip the static `Db::$_model` registration and you don't get the IDb-typed return path. In practice: same DB-switch side effect; different return-type contract.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"comparison","citations":["core/f/db.php:11","framework-reference-v2.md §2.3"]}} +{"instruction":"Show me the `Db::loadModel()` pipeline step by step.","input":"","output":"From `core/f/db.php:11`:\n1. Call `Db::loadModel('WarehouseLoach\\\\Timeanddate')`.\n2. Internally: `_setModel(\"WarehouseLoach\\\\Timeanddate\")`.\n3. Constructs namespace: `$fmodel = \"\\\\Nibiru\\\\Model\\\\\".$model` → `\\Nibiru\\Model\\WarehouseLoach\\Timeanddate`.\n4. Instantiates: `self::$_model = new $fmodel;`.\n5. Returns: `self::getModel()`, the static `$_model`, typed as `IDb`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/f/db.php:11","framework-reference-v2.md §2.3"]}} +{"instruction":"Give me a real production usage of Db::loadModel for an insert.","input":"","output":"From `loach.mssql.database-connection/application/module/pdf/plugins/pdf.php`:\n```php\nuse Nibiru\\Factory\\Db;\n// ...\nDb::loadModel('WarehouseLoach\\Timeanddate')->insertArrayIntoTable([...]);\n$timeanddate_id = Db::loadModel('WarehouseLoach\\Timeanddate')->lastInsertId();\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["loach.mssql.database-connection/application/module/pdf/plugins/pdf.php","framework-reference-v2.md §2.3"]}} +{"instruction":"What return type does `Db::loadModel()` declare?","input":"","output":"```php\npublic static function loadModel( $modelName = \"\"): IDb\n```\nDefined at `core/f/db.php:11`. The `IDb` interface guarantees `loadTableAsArray()`, `selectRowsetById($id)`, `updateRowById(array, int, string)`, `insertArrayIntoTable($dataset)`, `selectDatasetByFieldWhere($fieldWhere, $sortOrder)`, `selectRowByFieldWhere($field)`, `lastInsertId()`, `deleteRowById(int)`, `updateRowByFieldWhere($wherefield, $wherevalue, $rowfield, $rowvalue)`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/f/db.php:11","framework-reference-v2.md §2.3"]}} +{"instruction":"I want to get the auto-increment ID right after an insert. How?","input":"","output":"Call `lastInsertId()` on a freshly loaded model. Real example:\n```php\nDb::loadModel('WarehouseLoach\\Timeanddate')->insertArrayIntoTable([...]);\n$timeanddate_id = Db::loadModel('WarehouseLoach\\Timeanddate')->lastInsertId();\n```\nNote both calls go through `Db::loadModel()` — each instantiation re-runs the model's `__construct()` and re-asserts `Pdo::settingsSection('DATABASE')`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"workflow","citations":["framework-reference-v2.md §2.3","loach.mssql.database-connection/application/module/pdf/plugins/pdf.php"]}} +{"instruction":"What does `Form::create()` actually do under the hood?","input":"","output":"It clears the static buffer `self::$form` so the form factory starts with an empty assembly state. Subsequent calls to `addInputType*`, `addType*`, `addSelect`, etc. each append HTML to that buffer; the final `addForm()` wraps the buffer in `
` tags via the `FIELDS` placeholder. From `core/f/form.php:41`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.4 Form Factory","kind":"code-recall","citations":["core/f/form.php:41","framework-reference-v2.md §2.4","framework-reference-v2.md §5.8"]}} +{"instruction":"Why does my form not save? I see `value` in the input but the controller gets nothing.","input":"","output":"Most likely cause: you used uppercase keys (`['VALUE' => 'x']`) where the framework expects lowercase, or vice versa. The form factory's substitution engine at `core/c/formattributes.php:48-58` does `str_replace(strtoupper($key), $entry, $this->getElement())` — so user keys must be **lowercase**, and the engine uppercases them internally to match template tokens. If you supplied `'NAME' => 'foo'` instead of `'name' => 'foo'`, `strtoupper('NAME')` is still `'NAME'` and works, but `'Name' => 'foo'` becomes `'NAME'` too. The deeper trap: only keys present in the Type class's `$_attributes` allowlist are substituted — any unrecognized key is silently dropped.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form substitution","kind":"debug","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}} +{"instruction":"What's the basic usage pattern for the Form factory? Give me the canonical 5-line login form.","input":"","output":"```php\nForm::create();\nForm::addInputTypeText(['NAME' => 'email', 'ID' => 'email_field']);\nForm::addInputTypePassword(['NAME' => 'password']);\nForm::addInputTypeSubmit(['VALUE' => 'Login']);\n$html = Form::addForm(['METHOD' => 'POST', 'ACTION' => '/login']);\necho $html;\n```\nFrom the Quick Reference appendix. Note `addForm()` is the only method that returns HTML; everything else appends to the static `$form` buffer.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.4 Form Factory","kind":"code-recall","citations":["framework-reference-v2.md §2.4","framework-reference-v2.md Appendix Quick Reference"]}} +{"instruction":"How do I wrap a single input in a div without doing it manually?","input":"","output":"Pass a second `$div` argument — an associative array of attribute=>value pairs. Example:\n```php\nForm::addInputTypeText(['NAME' => 'username', 'ID' => 'user'], ['class' => 'form-group']);\n```\nThis emits:\n```html\n
\n\n
\n```\nThe wrapper is single-shot — `assemble()` at `core/f/form.php:86-97` resets `self::$div` to `false` after one use.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div wrapping","kind":"workflow","citations":["core/f/form.php:86-97","core/f/form.php:120-140","framework-reference-v2.md §5.7"]}} +{"instruction":"What does Controller::getInstance() return?","input":"","output":"```php\npublic static function getInstance(): View|Controller\n```\nDefined at `core/c/controller.php:14`. The Controller class extends View, so the union return type reflects that the same singleton can be accessed as either.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"How do I read POST and GET parameters in a Nibiru controller?","input":"","output":"Use the helper methods on the Controller singleton:\n```php\n$email = $this->getPost('email'); // $_POST\n$page = $this->getGet('page'); // $_GET\n$param = $this->getRequest('param'); // $_REQUEST (POST/GET unified)\n$user = $this->getSession('user');\n$ip = $this->getServer('REMOTE_ADDR');\n$file = $this->getFiles('upload');\n```\nDefined at `core/c/controller.php:14` and following.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"How does `View::assign()` work and how do I use the values in a Smarty template?","input":"","output":"```php\nView::assign(['user_name' => 'John', 'role' => 'admin']);\n```\nIn the Smarty template you reference them with the dollar-prefix: `{$user_name}`, `{$role}`. From `core/c/view.php:11` and the Smarty wrapper.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","framework-reference-v2.md §2.6"]}} +{"instruction":"How do I do a server-side redirect to a JSON response from a Nibiru controller?","input":"","output":"`View::forwardToJsonHeader(string $encoding = \"\")` sends the JSON content-type headers. The constants `IView::NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\"` and `NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\"` are used in this path. Defined at `core/c/view.php:11`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","core/i/IView.php","framework-reference-v2.md §9"]}} +{"instruction":"Where does the Smarty template directory get configured?","input":"","output":"In `core/c/view.php:66-79` (the `_setEngine()` block). It reads from the INI:\n- Template dir: `core/c/../../{ENGINE[templates]}`\n- Compile dir: `core/c/../../{ENGINE[templates_c]}`\n- Cache dir: `core/c/../../{ENGINE[cache]}`\n- Config dir: `core/c/../../{ENGINE[config_dir]}`\n- Debug template: `{ENGINE[debug_template]}`\n- Caching: if `ENGINE[caching]==true`, set to `CACHING_LIFETIME_CURRENT`","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"code-recall","citations":["core/c/view.php:66-79","framework-reference-v2.md §2.6"]}} +{"instruction":"What `.tpl` constant does the framework use to identify templates?","input":"","output":"`IView::NIBIRU_FILE_END = \".tpl\"`. `View::display($page)` checks if `$page` ends with this constant before handing off to Smarty. Defined in `core/i/IView.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"inikey","citations":["core/i/IView.php","framework-reference-v2.md §9"]}} +{"instruction":"How does Nibiru pick which database driver to use?","input":"","output":"From the INI's `[GENERATOR][driver]` or `[DATABASE*][driver]` field:\n- `driver = \"mysql\"` → uses `Pdo`, adapter is `\\Nibiru\\Adapter\\MySQL\\Db`.\n- `driver = \"psql\"` → uses `Postgres`, adapter is `\\Nibiru\\Adapter\\Postgres\\Db` (UnixODBC path).\n- `driver = \"postgresql\"` → uses `Postgresql`, adapter is `\\Nibiru\\Adapter\\Postgresql\\Db` (libpq path).\nThe choice is consumed by the autogenerator at `core/c/model.php:115-132`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"inikey","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.1","framework-reference-v2.md §3.2"]}} +{"instruction":"Show me the abstract base adapter class that all generated MySQL models extend.","input":"","output":"```php\nabstract class Db implements IDb\n{\n private static $table = array();\n\n protected static function initTable( $table = array() )\n protected static function getTable()\n}\n```\nFrom `core/a/mysql.db.php:15`. Generated models call `self::initTable( self::TABLE )` from their `__construct()` to register the schema.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"code-recall","citations":["core/a/mysql.db.php:15","framework-reference-v2.md §3.1"]}} +{"instruction":"What's the structure of the TABLE constant in a generated model?","input":"","output":"```php\nconst TABLE = array(\n 'table' => 'tablename',\n 'fields' => ['id' => 'id', 'name' => 'name', ...]\n);\n```\nThe `'table'` key holds the raw table name; the `'fields'` array is a `field => field` mapping (key and value identical) used by the adapter's `getTable()` lookups. Built by the generator at `core/c/model.php:80-104`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"code-recall","citations":["core/c/model.php:80-104","framework-reference-v2.md §3.1"]}} +{"instruction":"Is the autogenerator a CLI tool or does it run on every request?","input":"","output":"It runs on every web request (not a CLI tool). The trigger lives in `core/c/dispatcher.php:35-39`:\n```php\nif(Config::getInstance()->getConfig()[self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE])\n{\n new Model( false );\n}\n```\nWith `[GENERATOR] database = true` in the INI, `new Model(false)` fires on every page load. Production turns it off by setting `[GENERATOR] database = false`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/dispatcher.php:35-39","framework-reference-v2.md §3.2"]}} +{"instruction":"Is there a standalone CLI script that runs the autogenerator without booting the dispatcher?","input":"","output":"No. `grep -rn \"new Model(\"` finds only `dispatcher.php:38`. `Table::__construct($argv)` parses argv-style flags (`--table=…`, `--config-section=…`, `--folder-out=…`, `--help`) at `core/c/table.php:48-70`, but the shipped framework only ever calls `new Model(false)` — `false` is passed straight through to `Table::__construct` at `core/c/model.php:18`, so `is_array($argv)` at `table.php:51` is false and no flags are parsed. Dev-mode autogeneration uses INI defaults only.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["core/c/dispatcher.php:38","core/c/model.php:18","core/c/table.php:48-70","framework-reference-v2.md §3.2"]}} +{"instruction":"Walk me through the full call chain from `Dispatcher::run()` to a generated model file.","input":"","output":"```\nDispatcher::run() core/c/dispatcher.php:38 -> new Model(false)\n Model::__construct(false) core/c/model.php:14\n early-bail at line 16 if [DATABASE][is.active] != true\n parent::__construct($argv) core/c/model.php:18 -> Table::__construct\n Table::__construct($argv) core/c/table.php:48\n _setParams() reads CLI flags (no-op when $argv === false)\n _setConfigSection() table.php:162 reads --config-section or [GENERATOR][config-section]\n _setDatabaseDriver() table.php:148 $driver = config[$configSection][driver]\n _setDatabase() table.php:194 $dbName = config[$configSection][basename]\n _setDbNamespace() table.php:63 PascalCase the basename\n _setFolderNamespace() table.php:111 split on '-' or '_', ucfirst each segment\n _setFolderOut() table.php:208 --folder-out OR __DIR__ + [GENERATOR][folder-out] + foldernamespace\n _setTable() picks --table flag, or empty (= scan all)\n _setTemplateFile() table.php:67 [GENERATOR][modeltemplate]\n _setModelTemplate() slurps mask file\n _setTables() SHOW TABLES (MySQL) or information_schema (Postgres)\n createOutFolder() core/c/model.php:28 mkdir -p with chmod 0777\n createClassFiles() core/c/model.php:37\n generateClassByTableName($table) core/c/model.php:53\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/dispatcher.php:38","core/c/model.php:14","core/c/table.php:48","framework-reference-v2.md §3.2"]}} +{"instruction":"How does the autogenerator turn a table name like `user_to_acl` into a class name?","input":"","output":"From `core/c/model.php:57-69`:\n```php\n$pclassname = explode('_', $table);\n$classname = \"\";\nfor($i=0; count($pclassname)>$i; $i++) {\n if($i!=0) $classname .= ucfirst($pclassname[$i]);\n else $classname = $pclassname[$i];\n}\n```\nThe first underscore-separated segment is kept as-is; subsequent segments are `ucfirst`-ed. Then a final `ucfirst($classname)` is applied at line 111. So `user_to_acl` -> `userToAcl` -> final `UserToAcl`. `time_and_date` -> `timeAndDate` -> `TimeAndDate`. `timeanddate` -> `timeanddate` -> `Timeanddate`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:57-69","core/c/model.php:111","framework-reference-v2.md §3.2"]}} +{"instruction":"What happens to my hand-edits to a generated model when `[GENERATOR][database.overwrite] = true`?","input":"","output":"They're destroyed on every request. From `core/c/model.php:70-74`:\n```php\nif(Config::getInstance()->getConfig()[self::CONFIG_SECTION][self::DB_OVERWRITE_MODELS]) {\n unlink($this->getFolderOut() . '/' . $classname . self::PHP_FILE_ENDING);\n}\n```\nThe existing `.php` file is `unlink`ed before regeneration. Mitigation: keep `database.overwrite = false` (the safe default) and only delete the file you want rebuilt.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/model.php:70-74","framework-reference-v2.md §3.2"]}} +{"instruction":"In safe (non-overwrite) mode, how does the generator decide whether to write a file?","input":"","output":"It checks `filesize() == 0` rather than `file_exists()`. Step 2 of `generateClassByTableName()` does `fclose( fopen(..., 'w') )` to create an empty file, then step 6 checks:\n```php\nif(!filesize(...)) {\n file_put_contents(...);\n}\n```\nFrom `core/c/model.php:133-145`. Workflow: delete the model file you want regenerated -> reload the page -> file is recreated with fresh schema.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/model.php:133-145","framework-reference-v2.md §3.2"]}} +{"instruction":"What setter name does the autogenerator produce for a column named `user_first_name`?","input":"","output":"`_setUserfirstname` — single capital, no inner caps. The generator uses `str_replace('_', '', ucfirst($field))` which strips ALL underscores first, then `ucfirst` capitalizes only the first letter. So `user_first_name` becomes `_setUserfirstname`, NOT `_setUserFirstName`. From `core/c/model.php:80-104` (§3.2 step 3).","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/model.php:80-104","framework-reference-v2.md §3.2"]}} +{"instruction":"List the eight placeholder substitutions the autogenerator makes in the mask file.","input":"","output":"From `core/c/model.php:106-113`:\n| Placeholder | Source |\n|---|---|\n| `[CLASSPARAMETERS]` | `$parameters` (concatenated `private $field;` lines) |\n| `[FIELDARRAY]` | `$fieldarray` (concatenated `'k' => 'v',` lines) |\n| `[SETTERS]` | `$setters` |\n| `[GETTERS]` | `$getters` |\n| `[TABLE]` | raw table name |\n| `[CLASSNAME]` | `ucfirst($classname)` |\n| `[FOLDERNAME]` | `ucfirst($this->getFolderNamespace())` |\n| `[DBSECTION]` | `$this->getConfigSection()` |\n\nThen step 5 substitutes `[ADAPTER]` and `[CONNECTOR]` based on driver.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:106-113","framework-reference-v2.md §3.2"]}} +{"instruction":"What values does the generator substitute into `[ADAPTER]` and `[CONNECTOR]` for a Postgres model with `odbc=true`?","input":"","output":"From `core/c/model.php:115-132`:\n```php\nif($this->getDatabaseDriver()==self::DB_DRIVER_POSTGRESS) {\n if(Config::getInstance()->getConfig()[self::CONFIG_SECTION]['odbc']) {\n $template = str_replace('[ADAPTER]', self::ADAPTER_POSTGRES, $template);\n $template = str_replace('[CONNECTOR]', self::ADAPTER_POSTGRES, $template);\n } else {\n $template = str_replace('[ADAPTER]', self::ADAPTER_POSTGRESQL, $template);\n $template = str_replace('[CONNECTOR]', self::ADAPTER_POSTGRESQL, $template);\n }\n}\n```\nWith `odbc=true`, both placeholders become `Postgres`. With `odbc` falsy/missing, both become `Postgresql`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.2"]}} +{"instruction":"What does `[CONNECTOR]` resolve to for a `driver = \"mysql\"` model?","input":"","output":"`Pdo`. From `core/c/model.php:115-132`:\n```php\nif($this->getDatabaseDriver()==self::DB_DRIVER_MYSQL) {\n $template = str_replace('[ADAPTER]', self::ADAPTER_MYSQL, $template);\n $template = str_replace('[CONNECTOR]', self::ADAPTER_PDO, $template);\n}\n```\nSo for MySQL, `[ADAPTER]` becomes `MySQL` and `[CONNECTOR]` becomes `Pdo`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.2"]}} +{"instruction":"I'm getting `Class 'Nibiru\\Postgres' not found` from a generated Postgres model. What's wrong?","input":"","output":"The Postgres-mode footgun in the mask file. `application/settings/db/db.class.mask` line 4 is:\n```php\nuse Nibiru\\Pdo;\n```\nThat import is hardcoded regardless of driver. For MySQL output it's correct (`[CONNECTOR]` -> `Pdo` matches the import). For Postgres, `[CONNECTOR]` substitutes to `Postgres` or `Postgresql`, but the import line still reads `use Nibiru\\Pdo;`. The unqualified `Postgres::settingsSection(...)` call then resolves against the current namespace (`Nibiru\\Model\\\\Postgres`), not `\\Nibiru\\Postgres`, and PHP fatal-errors at request time.\n\nFix: manually patch the generated `use` line to `use Nibiru\\Postgres;` (or `Postgresql`), or change the mask to use a `[CONNECTOR_USE]` placeholder. Confirmed at `core/c/pdo.php:2`, `core/c/postgres.php:3`, `core/c/postgresql.php:2` that all three live in the `\\Nibiru` root namespace.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"debug","citations":["application/settings/db/db.class.mask:4","core/c/pdo.php:2","core/c/postgres.php:3","framework-reference-v2.md §3.2"]}} +{"instruction":"Show me the verbatim contents of the model mask file.","input":"","output":"```php\n '[TABLE]',\n 'fields' => [FIELDARRAY]\n );\n\n public function __construct()\n {\n [CONNECTOR]::settingsSection('[DBSECTION]');\n self::initTable( self::TABLE );\n }\n\n public function getTableInfo()\n {\n return self::TABLE;\n }\n\n [SETTERS]\n\n [GETTERS]\n}\n```\nFrom `application/settings/db/db.class.mask` (48 lines). Ten distinct placeholders: `[FOLDERNAME]`, `[ADAPTER]`, `[CLASSNAME]`, `[CLASSPARAMETERS]`, `[TABLE]` (x2), `[FIELDARRAY]`, `[CONNECTOR]`, `[DBSECTION]`, `[SETTERS]`, `[GETTERS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["application/settings/db/db.class.mask","framework-reference-v2.md §3.2"]}} +{"instruction":"Show me a verified sample of generated model output for a `timeanddate` table.","input":"","output":"For table `timeanddate`, folder namespace `WarehouseLoach`, driver `mysql`, config-section `DATABASE`:\n```php\n 'timeanddate',\n 'fields' => array(\n 'timeanddate_id' => 'timeanddate_id',\n 'timeanddate_date' => 'timeanddate_date',\n 'timeanddate_time' => 'timeanddate_time'\n )\n );\n\n public function __construct()\n {\n Pdo::settingsSection('DATABASE');\n self::initTable( self::TABLE );\n }\n\n public function getTableInfo() { return self::TABLE; }\n\n public function _setTimeanddateid($timeanddate_id) { $this->timeanddate_id = $timeanddate_id; }\n public function getTimeanddateid() { return $this->timeanddate_id; }\n}\n```\nVerified against `loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php","framework-reference-v2.md §3.2"]}} +{"instruction":"What value of `[GENERATOR][config-section]` does Nibiru default to?","input":"","output":"`\"DATABASE\"`. From `application/settings/config/settings.development.ini:78-86`:\n```ini\n[GENERATOR]\ndatabase = true\ndatabase.overwrite = false\nconfig-section = \"DATABASE\"\nfolder-out = \"/../../application/model/\"\nmodeltemplate = \"/../../application/settings/db/db.class.mask\"\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["application/settings/config/settings.development.ini:78-86","framework-reference-v2.md §3.2"]}} +{"instruction":"Why do `folder-out` and `modeltemplate` in `[GENERATOR]` start with `/../../`?","input":"","output":"Because both are resolved as `__DIR__ . $value` where `__DIR__` is `core/c/`. From `core/c/table.php:217` (folder-out) and `core/c/table.php:67` (modeltemplate). The `/../../` walks up out of `core/c/` to the project root, then into the application path.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["core/c/table.php:217","core/c/table.php:67","framework-reference-v2.md §3.2"]}} +{"instruction":"What's the typo in the Postgres driver constant name?","input":"","output":"`DB_DRIVER_POSTGRESS = \"psql\"` — note the two S's in `POSTGRESS`. Defined at `core/c/table.php:20-26` alongside `DB_DRIVER_MYSQL = \"mysql\"`, `ADAPTER_POSTGRES`, `ADAPTER_POSTGRESQL`, `ADAPTER_MYSQL`, `ADAPTER_PDO`. The INI value is the conventional `psql`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/table.php:20-26","framework-reference-v2.md §3.2"]}} +{"instruction":"I want to talk to two MySQL databases at once. What does the INI look like and how do I generate the models?","input":"","output":"INI:\n```ini\n[DATABASE]\nis.active = true\nbasename = \"warehouse_loach\"\ndriver = \"mysql\"\nhostname = \"db-primary\"\nusername = \"user\"\npassword = \"pass\"\n\n[DATABASE_SECONDARY]\nis.active = true\nbasename = \"other_db\"\ndriver = \"mysql\"\nhostname = \"db-secondary\"\nusername = \"user2\"\npassword = \"pass2\"\n```\nGenerate Model A with `[GENERATOR][config-section] = \"DATABASE\"`, then flip the INI to `\"DATABASE_SECONDARY\"` and reload. Each generated `__construct()` will hard-bake the right `Pdo::settingsSection('DATABASE')` or `Pdo::settingsSection('DATABASE_SECONDARY')` line.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["framework-reference-v2.md §3.3"]}} +{"instruction":"Quick question: can I switch databases without instantiating a model?","input":"","output":"Yes — call `Pdo::settingsSection()` directly:\n```php\nPdo::settingsSection('DATABASE_SECONDARY');\n$data = Pdo::queryString('SELECT * FROM table_name');\n```\nThe static `Pdo::$section` is what every Pdo query reads via `self::getSettingsSection()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["core/c/pdo.php:14","framework-reference-v2.md §3.3"]}} +{"instruction":"How would I switch one model in a multi-database setup from `[DATABASE]` to `[DATABASE_REPORTING]` without breaking the others?","input":"","output":"Regenerate just that one model with the autogenerator pointed at the new config section. Workflow:\n1. Add `[DATABASE_REPORTING]` block to the INI alongside `[DATABASE]`.\n2. Temporarily set `[GENERATOR][config-section] = \"DATABASE_REPORTING\"` and `database.overwrite = true`, OR delete the single model file you want rebuilt while keeping `database.overwrite = false`.\n3. Hit any URL — `Dispatcher::run()` regenerates the model. Its `__construct()` will now contain `Pdo::settingsSection('DATABASE_REPORTING')`.\n4. Reset `[GENERATOR][config-section]` back to `\"DATABASE\"` so subsequent regenerations of other models don't get the wrong section.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"refactor","citations":["framework-reference-v2.md §3.3","framework-reference-v2.md §11.1"]}} +{"instruction":"How expensive is it to instantiate multiple models in a request?","input":"","output":"Effectively free. The framework uses a lazy singleton per-section: `parent::getInstance(self::getSettingsSection())` returns the cached connection for that section. Instantiating a second model that references `'DATABASE_SECONDARY'` opens at most one new connection (the first time), and reusing it is just a static lookup.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["framework-reference-v2.md §3.3","core/c/pdo.php:19"]}} +{"instruction":"What's the standard module directory layout in Nibiru?","input":"","output":"```\napplication/module/users/\n users.php # Main class\n interfaces/\n users.php # IUsers interface\n progressObserver.php # IProgressObserver interface\n traits/\n users.php # Users trait\n userForm.php # UserForm trait\n plugins/\n user.php # User plugin class\n acl.php # ACL plugin class\n```\nFrom `framework-reference-v2.md §4.1`. The main class file is named after the module folder (lowercase) and lives at the root of the module directory.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.1 Module Structure","kind":"workflow","citations":["framework-reference-v2.md §4.1"]}} +{"instruction":"Show me a real `[AUTOLOADER]` INI registry from production.","input":"","output":"From `develop.maschinen-stockert.de/application/settings/config/settings.development.ini:10-72`:\n```ini\n[AUTOLOADER]\nclass.pos[] = \"observer\"\nclass.pos[] = \"users\"\nclass.pos[] = \"memcached\"\nclass.pos[] = \"assetmanager\"\nclass.pos[] = \"cms\"\n\niface.pos[] = \"observer\"\niface.pos[] = \"users\"\niface.pos[] = \"cms\"\n\ntrait.pos[] = \"observer\"\ntrait.pos[] = \"users\"\ntrait.pos[] = \"userForm\"\ntrait.pos[] = \"cms\"\n\nclass.plugin.pos[] = \"progressTracker\"\nclass.plugin.pos[] = \"observer\"\nclass.plugin.pos[] = \"user\"\nclass.plugin.pos[] = \"acl\"\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"4.2 Module Registry","kind":"code-recall","citations":["develop.maschinen-stockert.de/application/settings/config/settings.development.ini:10-72","framework-reference-v2.md §4.2"]}} +{"instruction":"What does each `[AUTOLOADER]` array key control?","input":"","output":"- `class.pos[]` — array of module names to load (order matters).\n- `iface.pos[]` — which interfaces to scan for each module name.\n- `trait.pos[]` — which traits to scan for each module name.\n- `class.plugin.pos[]` — which plugins to scan/load (order matters; loaded last).\nAll consumed by `Auto::loader()->loadModules()` at `core/c/auto.php`. From `framework-reference-v2.md §4.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.2 Module Registry","kind":"inikey","citations":["framework-reference-v2.md §4.2"]}} +{"instruction":"Walk me through how `Auto::loadModules()` actually loads files.","input":"","output":"From `core/c/auto.php` (by extension of `Dispatcher::run()` line 43):\n1. Read INI `AUTOLOADER[iface.pos]` — array of interface names.\n2. For each interface name, scan `application/module/[modulename]/interfaces/` for matching files.\n3. `require_once` each found file.\n4. Repeat for traits, then modules, then plugins.\n\nThe order in the INI dictates the order of `require_once` calls within each category.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["core/c/auto.php","core/c/dispatcher.php:43","framework-reference-v2.md §4.3"]}} +{"instruction":"What's the minimum requirement for a module main class?","input":"","output":"It must implement `IModule` (from `core/i/IModule.php`). It may optionally implement `SplSubject` (Observer pattern). Real example from `develop.maschinen-stockert.de/application/module/users/users.php:20-32`:\n```php\nclass Users extends Module implements Interfaces\\Users, SplSubject\n{\n use Traits\\Users;\n protected static object $usersRegistry;\n protected SplObjectStorage $observers;\n\n public function __construct()\n {\n $this->setUsersRegistry();\n $this->observers = new SplObjectStorage();\n }\n}\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["develop.maschinen-stockert.de/application/module/users/users.php:20-32","core/i/IModule.php","framework-reference-v2.md §4.3"]}} +{"instruction":"Show me a real plugin class that uses `Db::loadModel`.","input":"","output":"From `loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40`:\n```php\nuse Nibiru\\Factory\\Db;\n\nclass Acl extends User\n{\n public function __construct()\n {\n parent::__construct();\n }\n\n public function init(): void\n {\n if(!$this->validate())\n {\n View::forwardTo('/users/login');\n }\n else\n {\n $this->loadUserRole();\n }\n }\n}\n```\nLater: `$acl = Db::loadModel('WarehouseLoach\\Acl');` — instantiating sets `Pdo::$section = 'DATABASE'` via the model's `__construct()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.4 Plugin Pattern","kind":"code-recall","citations":["loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40","framework-reference-v2.md §4.4"]}} +{"instruction":"Walk me through the module lifecycle on a request.","input":"","output":"From `framework-reference-v2.md §4.5`:\n1. INI parse: Dispatcher reads `[AUTOLOADER]` section.\n2. Model load: `Auto::loader()->loadModelFiles()` requires all model files.\n3. Module load: `Auto::loader()->loadModules()` scans and requires interfaces, traits, modules, plugins in order.\n4. Controller load: if route matches, require and instantiate the controller.\n5. Action call: if `_action` param exists and a matching `*Action()` method exists, call it.\n\nImplicit hooks: each module class's constructor, each plugin class's constructor, the controller's action method.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.5 Module Lifecycle","kind":"workflow","citations":["framework-reference-v2.md §4.5"]}} +{"instruction":"My new module isn't loading. What's the most common cause?","input":"","output":"You forgot to register it in the INI's `[AUTOLOADER] class.pos[]`. The autoloader is NOT PSR-4 — it does NOT follow `composer.json` mapping. It scans directories driven by INI keys. Without `class.pos[] = \"yourmodule\"` in the `[AUTOLOADER]` block, `Auto::loader()->loadModules()` never visits the directory. From `framework-reference-v2.md §11.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.7 Autoloader not PSR-4","kind":"debug","citations":["framework-reference-v2.md §11.7"]}} +{"instruction":"My late-registered module's constructor blows up because it depends on an earlier module. What's wrong?","input":"","output":"Module loading order is dictated by INI array order, not by dependencies. Example:\n```ini\n[AUTOLOADER]\nclass.pos[] = \"late_module\"\nclass.pos[] = \"early_module\"\n```\n`late_module` constructor runs first; if it depends on `early_module` being initialized, you get a silent failure. Mitigation: order INI entries carefully with dependents AFTER dependencies. From `framework-reference-v2.md §11.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.4 Module Loading Order","kind":"gotcha","citations":["framework-reference-v2.md §11.4"]}} +{"instruction":"What namespace does a trait in module `users` end up under?","input":"","output":"`\\Nibiru\\Module\\Users\\Traits\\` — file at `application/module/users/traits/.php`. From `framework-reference-v2.md §8`. Example: trait `UserForm` in module `users` is `\\Nibiru\\Module\\Users\\Traits\\UserForm` at `application/module/users/traits/userForm.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"8 Namespace Conventions","kind":"workflow","citations":["framework-reference-v2.md §8"]}} +{"instruction":"What are the four collaborating files in the form system architecture?","input":"","output":"From `framework-reference-v2.md §5.1`:\n| Role | File | Owns |\n|---|---|---|\n| Factory (static buffer + 30 `add*` methods) | `core/f/form.php` | `\\Nibiru\\Factory\\Form` |\n| Per-element template + allowlist | `core/c/type*.php` (28 files) | `\\Nibiru\\Form\\Type` |\n| Substitution engine | `core/c/formattributes.php` | `\\Nibiru\\Form\\FormAttributes` |\n| Constant catalog | `core/i/IForm.php` | 60+ `FORM_*` constants |\n\nThe factory has zero knowledge of HTML — it manages the buffer and dispatches to a Type class. Each Type is an attribute allowlist plus a template string.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/f/form.php","core/c/formattributes.php","core/i/IForm.php","framework-reference-v2.md §5.1"]}} +{"instruction":"Show me the literal template string `TypeText` uses.","input":"","output":"```php\n$this->_element = '';\n```\nFrom `core/c/typetext.php:42`. The UPPERCASE tokens are substituted by `FormAttributes::_setAttributes()` for whatever lowercase key the user passed.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/c/typetext.php:42","framework-reference-v2.md §5.2"]}} +{"instruction":"How does the form substitution engine actually replace attributes?","input":"","output":"From `core/c/formattributes.php:48-58`:\n```php\nforeach( $attributes as $key=>$entry ) {\n switch ($key) {\n case array_key_exists($key, $this->_attributes):\n $this->_element = str_replace(strtoupper($key), $entry, $this->getElement());\n break;\n }\n}\n```\nTwo non-obvious facts:\n1. The `switch ($key) { case array_key_exists(...) }` form works because `case` compares its expression to `$key` and `array_key_exists()` returns a boolean. So only allowlisted keys substitute — unknown keys are silently dropped.\n2. `strtoupper($key)` is plain ASCII; user keys must be lowercase (`name`, `data-bts-decimals`).","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}} +{"instruction":"How does the form factory clean up unused placeholders so I don't get `required=\"REQUIRED\"` in my output?","input":"","output":"After the substitution loop, `core/c/formattributes.php:59-102` runs ~50 hard-coded `str_replace()` calls that strip unused placeholders. Example at line 84:\n```php\n$this->_element = str_replace(' required=\"REQUIRED\"', '', $this->_element);\n```\nIf the user didn't pass `required`, the literal `REQUIRED` was never substituted, so this line removes the whole ` required=\"REQUIRED\"` fragment. The leading space matters — it prevents collapsing two attributes. There's also `str_replace(' ', ' ', ...)` at line 87 to fold double-spaces.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/c/formattributes.php:59-102","core/c/formattributes.php:84","core/c/formattributes.php:87","framework-reference-v2.md §5.2"]}} +{"instruction":"Why does `id`, `class`, `form` work differently from other form attributes?","input":"","output":"They're bare-word tokens in the templates (`ID`, `CLASS`, `FORM`), not `id=\"ID\"`. The trait at `core/t/form.php:14` rewrites the user's value into `' id=\"x\"'` before substitution, so the final HTML reads `` rather than ``. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/t/form.php:14","framework-reference-v2.md §5.2"]}} +{"instruction":"I passed `'checked' => true` to a checkbox and got `checked=\"CHECKED\"` in the HTML. Why?","input":"","output":"Because the substitution engine literally swaps `CHECKED` for whatever you passed. There is no path that emits a clean bare `checked` (without the `=\"CHECKED\"` value). The strip rule at `core/c/formattributes.php:63-67` only removes `checked=\"CHECKED\"` when the user did NOT pass `checked` (i.e. passed `false`/empty). Production code accepts the `checked=\"CHECKED\"` rendering — browsers treat it as a truthy attribute. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"gotcha","citations":["core/c/formattributes.php:63-67","framework-reference-v2.md §5.2"]}} +{"instruction":"What's the four-step recipe every Type class follows?","input":"","output":"`__construct` (register allowlist) -> `_setElement` (load template) -> `loadAttributeValues` (pre-format `id`/`class`/`form`) -> `_setAttributes` (substitute + strip). Identical across all 28 Type classes — only the contents of `$_attributes` and `$_element` vary. Code from `core/c/typetext.php`:\n```php\npublic function loadElement( $attributes )\n{\n parent::__construct( $this->_attributes );\n $this->_setElement();\n $this->_setAttributes( self::loadAttributeValues( $attributes ) );\n return $this->getElement();\n}\n```\nFrom `framework-reference-v2.md §5.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.3 Type Class Anatomy","kind":"code-recall","citations":["core/c/typetext.php","framework-reference-v2.md §5.3"]}} +{"instruction":"What does TypeText's allowlist look like?","input":"","output":"```php\nprivate $_attributes = array(\n self::FORM_NAME => '',\n self::FORM_VALUE => '',\n self::FORM_ATTRIBUTE_SPEECH => '',\n self::FORM_ATTRIBUTE_ID => '',\n self::FORM_ATTRIBUTE_CLASS => '',\n self::FORM_ATTRIBUTE_PLACEHOLDER => '',\n self::FORM_ATTRIBUTE_REQUIRED => '',\n self::FORM_ATTRIBUTE_MAXLENGTH => '',\n self::FORM_ATTRIBUTE_TABINDEX => '',\n self::FORM_ATTRIBUTE_DISABLED => '',\n self::FORM_ATTRIBUTE_TS_DECIMALS => '',\n self::FORM_ATTRIBUTE_TS_STEPS => ''\n);\n```\nFrom `core/c/typetext.php`. Any key not in this array is silently dropped by the substitution engine.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.3 Type Class Anatomy","kind":"code-recall","citations":["core/c/typetext.php","framework-reference-v2.md §5.3"]}} +{"instruction":"What's the difference between `addInputType*`, `addType*`, and `add*` in the Form factory?","input":"","output":"Three different naming patterns with no semantic justification — historical drift:\n- `addInputType*` for: Text, Submit, Textarea, Radio, Checkbox, Switch, Password, Date, Email, Color, Datetime.\n- `addType*` for: FileUpload, Hidden, ImageSubmit, Number, Range, Reset, Search, Telefon, Url, Button, Label.\n- `add*` (no Type prefix) for: Form, Select, SelectOption, OpenDiv, CloseDiv, OpenAny, CloseAny.\n\nDon't normalize them — callers expect the literal names. From `framework-reference-v2.md §5.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.5 Naming Inconsistency","kind":"comparison","citations":["framework-reference-v2.md §5.5"]}} +{"instruction":"What does TypeOption's template string look like?","input":"","output":"```\n\n```\nFrom `core/c/typeoption.php:35`. The `CONTEXT` placeholder holds the visible text (e.g. `'context' => 'Admin'`); `VALUE` is the form-submitted value.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeoption.php:35","framework-reference-v2.md §5.4"]}} +{"instruction":"What does TypeSelect's template look like?","input":"","output":"```\n\n```\nFrom `core/c/typeselect.php:37`. The `OPTIONS` token is what `Form::displaySelect()` (`core/f/form.php:71`) replaces with the accumulated option HTML.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeselect.php:37","core/f/form.php:71","framework-reference-v2.md §5.4"]}} +{"instruction":"My `` | `assembleOptions()` buffer at `core/f/form.php:60` |\n| `ELEMENT` | one element only (single-shot div wrapper) | `assemble()` at `core/f/form.php:92` |\n| `FIELDS` | inside the `` wrapper | `display()` at `core/f/form.php:106` |\n\nThree replace targets, three different scopes. Plus the per-attribute UPPERCASE-token substitution inside each Type class.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.8 Assembly Pipeline","kind":"code-recall","citations":["core/f/form.php:60","core/f/form.php:92","core/f/form.php:106","framework-reference-v2.md §5.8"]}} +{"instruction":"How does TypeButton's template render the inner content?","input":"","output":"It uses `value` for the inner HTML, not the `value` attribute. From `framework-reference-v2.md §5.4`: ``. Production code passes things like `'value' => ' Speichern'` to embed an icon plus text. The substitution engine does no HTML escaping — embedded markup is rendered as-is.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["framework-reference-v2.md §5.4"]}} +{"instruction":"My file upload form isn't submitting the file. What's wrong?","input":"","output":"The parent `` tag needs `enctype=\"multipart/form-data\"`. Add it via `Form::addForm`:\n```php\nForm::addForm([\n 'method' => 'POST',\n 'action' => '/upload',\n 'enctype' => 'multipart/form-data',\n]);\n```\nFrom `framework-reference-v2.md §5.4` (TypeFileUpload row). Without this, browsers send the filename only, not the file contents.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"debug","citations":["framework-reference-v2.md §5.4"]}} +{"instruction":"What is the `addOpenAny` method for and what template does it use?","input":"","output":"It emits a generic open tag whose name comes from the `'any'` attribute. Template from `core/c/typeopenany.php`:\n```\nVALUE\n```\nThe caller passes `'any' => 'span'` (or any tag name) and `ANY` becomes `span`. Used for icon spans inside input groups. The leftover-`ANY` strip at `core/c/formattributes.php:100` removes any unused bare `ANY` from final output. From `framework-reference-v2.md §5.4` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeopenany.php","core/c/formattributes.php:100","framework-reference-v2.md §5.4"]}} +{"instruction":"What does the addForm wrapper template look like?","input":"","output":"```\nFIELDS\n```\nFrom `framework-reference-v2.md §5.4`. The `FIELDS` token is replaced at the end of `Form::addForm()` via `display()` at `core/f/form.php:106` — `str_replace('FIELDS', self::$form, $template)`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/f/form.php:106","framework-reference-v2.md §5.4"]}} +{"instruction":"I'm trying to understand the production user-edit form. What's the high-level shape?","input":"","output":"From `nibiru-modules/application/module/users/traits/userForm.php` lines 12, 19, 22-89:\n```php\nuse Nibiru\\Factory\\Form;\n\ntrait UserForm {\n public static function userForm(string $action = '', array $user = []) {\n Form::create();\n self::openHalfWidthElement('Benutzer Informationen');\n self::openInnerHalfWithElement();\n foreach(self::FORM_CREATE_USER as $entry) {\n self::addTextElement($entry['visibleName'], $entry['valueName'], $entry['icon'], $user[$entry['valueName']] ?? '');\n }\n self::addSelectDropdown($acl->loadAclRoles(), 'lock', $user['user_role_id']);\n self::closeHalfWidthElement();\n self::addSubmitFormButton('Speichern', 'save-alt');\n return Form::addForm([\n 'name' => 'userForm',\n 'action' => $action,\n 'class' => 'row',\n 'method' => 'post',\n 'target' => '_self',\n ]);\n }\n}\n```\n`Form::addForm()` is the only call that returns HTML — every other `add*` appends to the buffer.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"code-recall","citations":["nibiru-modules/application/module/users/traits/userForm.php:12-89","framework-reference-v2.md §5.9"]}} +{"instruction":"Why doesn't `Form::addInputTypeText()` echo HTML directly — what does it return?","input":"","output":"Most `add*` methods return `void`. They append the rendered Type-class HTML to the static buffer `self::$form`. Only `Form::addForm()` returns the final HTML string (the caller assigns it and either `echo`s or hands it to Smarty). From `framework-reference-v2.md §5.9`. Calling `Form::addForm()` is also what closes out the buffer — it substitutes `FIELDS` with `self::$form`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"workflow","citations":["framework-reference-v2.md §5.9","framework-reference-v2.md §5.8"]}} +{"instruction":"My form is missing the password field — what did I do wrong?","input":"","output":"You called `Form::addForm()` before all the field calls. The factory builds statefully:\n```php\nForm::create();\nForm::addInputTypeText(...);\n$html = Form::addForm(...); // BUG: password not added yet\n```\nMitigation: always add ALL fields BEFORE calling `addForm()`. Once `addForm()` runs, it substitutes `FIELDS` with the current `self::$form` buffer; later `addInputType*` calls just dirty the buffer for the next `addForm()`. From `framework-reference-v2.md §11.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.2 Form Statefulness","kind":"gotcha","citations":["framework-reference-v2.md §11.2"]}} +{"instruction":"What's the typo in the form factory's `addTypeImageSubmit` parameter name?","input":"","output":"It's misspelled `$attrbutes` (missing the `i`) at `core/f/form.php:363`. It works fine — PHP doesn't care about the parameter variable name — but the framework hasn't fixed it. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"gotcha","citations":["core/f/form.php:363","framework-reference-v2.md §5.4"]}} +{"instruction":"Why is the phone-input type class spelled `TypeTelefon`?","input":"","output":"German spelling. `core/c/typetelefon.php` exposes `addTypeTelefon($attributes)` which renders ``. The class name reflects the German `Telefon` rather than English `Telephone`. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"gotcha","citations":["core/c/typetelefon.php","framework-reference-v2.md §5.4"]}} +{"instruction":"What does the front controller look like? Where does Nibiru bootstrap?","input":"","output":"`index.php` at the application root requires `core/framework.php`:\n```php\nrequire_once 'core/framework.php'; // loads Dispatcher::run() at end\n```\n`framework.php` at line 119 calls `Nibiru\\Dispatcher::getInstance()->run()`. From `framework-reference-v2.md §6.1` and §12.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.1 Front Controller","kind":"workflow","citations":["framework-reference-v2.md §6.1","framework-reference-v2.md §12"]}} +{"instruction":"Walk me through the full Dispatcher::run() flow.","input":"","output":"From `core/c/dispatcher.php:33`:\n1. Set timezone from INI `[SETTINGS][timezone]`.\n2. If `[GENERATOR][database]==true`, run autogenerator: `new Model(false)`.\n3. Call `Router::getInstance()->route()` — parses URL, extracts controller/action.\n4. Call `Auto::loader()->loadModelFiles()` — requires all model files.\n5. Call `Auto::loader()->loadModules()` — requires modules (interfaces -> traits -> modules -> plugins).\n6. Check `application/controller/{ControllerName}Controller.php` exists.\n7. If yes: require, instantiate, call `navigationAction()` (line 52), then `{_action}Action()` if `$_REQUEST['_action']` is set, then `pageAction()` (line 60).\n8. If no controller file: route to error controller (lines 75-80).\n9. Finally: `Debug::getInstance()` and `Display::getInstance()->display()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["core/c/dispatcher.php:33","core/c/dispatcher.php:52","core/c/dispatcher.php:60","framework-reference-v2.md §6.2"]}} +{"instruction":"What's the controller method order: navigationAction, pageAction, or my custom action?","input":"","output":"Order in `Dispatcher::run()`:\n1. `navigationAction()` — line 52, called BEFORE custom action.\n2. `{_action}Action()` — your method, if `$_REQUEST['_action']` is set and the method exists.\n3. `pageAction()` — line 60, called LAST.\n\nSo `navigationAction()` is the place to load nav JSON or breadcrumbs that the page template depends on; `pageAction()` is the place to render the main template. From `framework-reference-v2.md §6.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.3 Controller Lifecycle","kind":"workflow","citations":["core/c/dispatcher.php:52","core/c/dispatcher.php:60","framework-reference-v2.md §6.3"]}} +{"instruction":"How does Nibiru render the final HTML to the browser?","input":"","output":"At the end of `Dispatcher::run()`:\n```php\nDebug::getInstance(); // add debug info if enabled\nDisplay::getInstance()->display(); // render via Smarty\n```\nThe `Display` class calls `View::getInstance()->display($template_name)`, which calls Smarty's `display()`. From `framework-reference-v2.md §6.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.4 View Rendering","kind":"workflow","citations":["framework-reference-v2.md §6.4"]}} +{"instruction":"Trace a request to `/users/login` end to end.","input":"","output":"From `framework-reference-v2.md §12`:\n1. Browser: `GET /users/login`.\n2. Web server routes to `index.php`.\n3. `index.php` requires `core/framework.php`.\n4. `framework.php:119` calls `Nibiru\\Dispatcher::getInstance()->run()`.\n5. `Dispatcher::run()`:\n - `Router::getInstance()->route()` parses URL, sets `$_REQUEST['_action'] = 'login'`.\n - `Auto::loader()->loadModelFiles()` requires all model files.\n - `Auto::loader()->loadModules()` requires all module files.\n - Checks `application/controller/usersController.php` exists.\n - Requires and instantiates: `$controller = new usersController()`.\n - Calls `$controller->navigationAction()` (before action).\n - Checks `$_REQUEST['_action'] == 'login'` -> calls `$controller->loginAction()` if exists.\n - Calls `$controller->pageAction()` (after action).\n - Calls `Debug::getInstance()`.\n - Calls `Display::getInstance()->display()`.\n6. Controller methods run, View renders template via Smarty.","metadata":{"language":"en","source":"framework-reference-v2","section":"12 Request Trace","kind":"workflow","citations":["framework-reference-v2.md §12"]}} +{"instruction":"Which INI key sets the Smarty cache directory?","input":"","output":"`[ENGINE][cache]`. Default `/../../application/view/cache/`. Read by `View::_setEngine()` at `core/c/view.php:66-79`. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}} +{"instruction":"Which INI key controls the soft-404 error controller?","input":"","output":"`[ENGINE][error_controller]`. Read by `Dispatcher::run()`. There's no built-in default — if missing, soft-404 handling fails. Pair with `[ENGINE][error_template]` for the matching template path. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"What `[ENGINE]` keys does `View::_setEngine()` read?","input":"","output":"From `core/c/view.php:66-79` and `framework-reference-v2.md §7`:\n- `cache` (path) — Smarty cache dir, default `/../../application/view/cache/`.\n- `templates` (path) — Smarty template dir.\n- `templates_c` (path) — Smarty compile dir.\n- `config_dir` (path) — Smarty config dir.\n- `debug_template` (path) — debugbar template.\n- `debugbar` (bool) — enable Smarty debugbar (default false).\n- `caching` (bool) — enable Smarty caching (default false).\n- `error_controller` (string) — controller for 404s.\n- `error_template` (string) — template for 404s.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}} +{"instruction":"Which INI key does `Table::__construct` read for the database driver?","input":"","output":"`[GENERATOR][driver]` (or `[DATABASE*][driver]`). Read by `Table::_setDatabaseDriver()` at `core/c/table.php:148`: `$driver = config[$configSection][driver]`. Valid values: `mysql`, `psql`, `postgresql`. From `framework-reference-v2.md §7 [GENERATOR]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["core/c/table.php:148","framework-reference-v2.md §7"]}} +{"instruction":"What's the master switch INI key to enable model autogeneration?","input":"","output":"`[GENERATOR][database] = true`. Read by `Dispatcher::run()`. Defaults to `false`. When true, `new Model(false)` fires on every request. Production should keep this `false`. From `framework-reference-v2.md §7 [GENERATOR]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"What does the `[GENERATOR][odbc]` key do?","input":"","output":"For Postgres only: when truthy, the autogenerator picks the UnixODBC adapter (`Postgres`); when falsy or missing, it picks the libpq adapter (`Postgresql`). Read by `Table::_setTables()` and used in `core/c/model.php:115-132`. Has no effect for `driver = \"mysql\"`. From `framework-reference-v2.md §7 [GENERATOR]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["core/c/model.php:115-132","framework-reference-v2.md §7"]}} +{"instruction":"What INI keys are required in a `[DATABASE]` section?","input":"","output":"From `framework-reference-v2.md §7 [DATABASE]`:\n- `is.active` (bool) — enable this connection.\n- `username`, `password`, `hostname`, `basename`, `driver` — all required.\n- `port` (string) — default `3306`.\n- `encoding` (string) — default `utf8`.\n- `db_info_print` (bool) — optional debug flag, not core.\n\nReal example:\n```ini\n[DATABASE]\nis.active = true\nusername = \"loach\"\npassword = \"08mj7hchqegtjf7znc6978d\"\nhostname = \"sto-loach-production-mariadb-1\"\nbasename = \"warehouse_loach\"\ndriver = \"mysql\"\nport = \"3306\"\nencoding = \"UTF8\"\ndb_info_print = 0\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"inikey","citations":["loach.mssql.database-connection/application/settings/config/settings.production.ini","framework-reference-v2.md §7"]}} +{"instruction":"Which INI key sets the PHP timezone?","input":"","output":"`[SETTINGS][timezone]`. Read by `Dispatcher::run()`. Defaults to `UTC`. From `framework-reference-v2.md §7 [SETTINGS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"What `[SETTINGS]` paths does the autoloader rely on?","input":"","output":"From `framework-reference-v2.md §7 [SETTINGS]`:\n- `dbmodel` — model folder, default `/../../application/model/`.\n- `module` — module folder template, default `/../../application/module/[NAME]` (with `[NAME]` placeholder).\n- `interfaces` — `/../../application/module/[NAME]/interfaces/`.\n- `traits` — `/../../application/module/[NAME]/traits/`.\n- `plugins` — `/../../application/module/[NAME]/plugins/`.\n\nAll consumed by `Auto::loader()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"How is the home/index route configured?","input":"","output":"`[ROUTING][route[index]]`. Default `/`. Read by `Router::getInstance()`. Pair with `[ROUTING][route[controller]]` (default `/controller`) for the controller route prefix. From `framework-reference-v2.md §7 [ROUTING]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ROUTING]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"Where does the autoloader look for module names?","input":"","output":"`[AUTOLOADER][class.pos[]]` is the array of module names to load (in order). Paired with `iface.pos[]`, `trait.pos[]`, and `class.plugin.pos[]` to scan interfaces, traits, and plugins respectively. All read by `Auto::loader()->loadModules()`. From `framework-reference-v2.md §7 [AUTOLOADER]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [AUTOLOADER]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"How does the basename `warehouse_loach` become the namespace folder `WarehouseLoach`?","input":"","output":"`Table::_setFolderNamespace()` at `core/c/table.php:111` splits on `-` or `_` and runs `ucfirst` on each segment. So `warehouse_loach` -> split into `[\"warehouse\", \"loach\"]` -> `[\"Warehouse\", \"Loach\"]` -> joined `WarehouseLoach`. The full namespace becomes `\\Nibiru\\Model\\WarehouseLoach\\`. From `framework-reference-v2.md §8`.","metadata":{"language":"en","source":"framework-reference-v2","section":"8 Namespace Conventions","kind":"workflow","citations":["core/c/table.php:111","framework-reference-v2.md §8"]}} +{"instruction":"Show me the exact constants from IMysql.","input":"","output":"From `core/i/IMysql.php`:\n```php\nconst SETTINGS_DATABASE = \"DATABASE\";\nconst PLACE_NO_QUERY = \"NO QUERY\";\nconst NO_ID = false;\nconst PLACE_TABLE_NAME = \"NO TABLENAME\";\nconst PLACE_ARRAY_NAME = \"NO ARRAY\";\nconst PLACE_QUERY_LIMIT = \"NO LIMIT\";\nconst PLACE_SORT_ORDER = \"NO ORDER\";\nconst PLACE_DSN = \"NO CONNECTION STRING\";\nconst PLACE_IS_ACTIVE = \"is.active\";\nconst PLACE_USERNAME = \"username\";\nconst PLACE_PASSWORD = \"password\";\nconst PLACE_HOSTNAME = \"hostname\";\nconst PLACE_DRIVER = \"driver\";\nconst PLACE_DATABASE = \"basename\";\nconst PLACE_PORT = \"port\";\nconst PLACE_ENCODING = \"encoding\";\nconst PLACE_PRIMARY_KEY = \"PRI\";\nconst PLACE_COLUMN_NAME = \"NO COLUMN NAME\";\nconst PLACE_SEARCH_TERM = \"NO SEARCH PARAMETER\";\nconst PLACE_FIELD_NAME = \"NO FIELD NAME\";\nconst PLACE_WHERE_VALUE = \"NO WHERE VALUE\";\nconst PLACE_DES_ENCRYPT = false;\nconst PLACE_SQL_UPDATE = \"UPDATE\";\nconst PLACE_SQL_INSERT = \"INSERT\";\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}} +{"instruction":"What does `IMysql::PLACE_DATABASE` actually equal?","input":"","output":"The literal string `\"basename\"`. The constant is the INI key name used when reading `Config::getInstance()->getConfig()[SETTINGS_DATABASE][PLACE_DATABASE]` to get the database name. From `core/i/IMysql.php`. So `[DATABASE][basename]` is the conventional INI path for the DB name.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}} +{"instruction":"What's the value of `IMysql::PLACE_PRIMARY_KEY`?","input":"","output":"The string `\"PRI\"` — the value MySQL's `SHOW COLUMNS` returns in the `Key` column for primary-key columns. The framework matches against this constant when introspecting tables. From `core/i/IMysql.php` and `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}} +{"instruction":"What does the framework set `Content-Type` to for JSON responses?","input":"","output":"`IView::NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\"`. Used by `View::forwardToJsonHeader()`. Paired with `IView::NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\"`. From `core/i/IView.php` and `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IView.php","framework-reference-v2.md §9"]}} +{"instruction":"List the IView header constants.","input":"","output":"From `core/i/IView.php`:\n```php\nconst NIBIRU_SETTINGS = \"SETTINGS\";\nconst NIBIRU_ROUTING = \"ROUTING\";\nconst NIBIRU_SECURITY = \"SECURITY\";\nconst NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\";\nconst NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\";\nconst NIBIRU_CONTENT_ENCODING = \"Content-Encoding: gzip\";\nconst NIBIRU_CONTENT_TRANSFER_ENCODING = \"Content-Transfer-Encoding: {transfer}\";\nconst NIBIRU_FILE_END = \".tpl\";\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IView.php","framework-reference-v2.md §9"]}} +{"instruction":"What do IOdbc constants look like?","input":"","output":"From `core/i/IOdbc.php`:\n```php\nconst SETTINGS_DATABASE = \"DATABASE\";\nconst PLACE_READONLY = \"readonly\";\nconst FILTER_COLUMN_NAME = \"COLUMN_NAME\";\n```\nUsed by the Odbc adapter and Postgres drivers. The default section name `\"DATABASE\"` mirrors `IMysql::SETTINGS_DATABASE`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IOdbc.php","framework-reference-v2.md §9"]}} +{"instruction":"Is the CMS module part of Nibiru core?","input":"","output":"No. The CMS module at `application/module/cms/` is a downstream production pattern from `develop.maschinen-stockert.de/`. It models pages, blocks, templates, and text content separately. Nibiru core has no CMS abstraction — the module is a complete sub-framework built on top of Nibiru's module system. From `framework-reference-v2.md §10.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.1 CMS Module","kind":"comparison","citations":["framework-reference-v2.md §10.1"]}} +{"instruction":"What's the production pattern for chaining plugin `init()` calls?","input":"","output":"```php\nuse Nibiru\\Module\\Cms\\Plugins\\Cms;\nuse Nibiru\\Module\\Assetmanager\\Plugins\\Assetmanager;\n\n$cms = Cms::init(Assetmanager::init()->loadTemplate());\n$cms->loadPageTemplate();\n```\nNot a framework requirement — just a downstream pattern from `develop.maschinen-stockert.de`. The `init()` method is conventional for plugin classes that need explicit initialization. From `framework-reference-v2.md §10.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.2 Plugin init Pattern","kind":"workflow","citations":["framework-reference-v2.md §10.2"]}} +{"instruction":"Is the Observer pattern built into Nibiru core?","input":"","output":"No. Several production modules implement `SplSubject` (PHP's built-in interface) and support `attach()`, `detach()`, `notify()` for observer registration. This is a convention used in `develop.maschinen-stockert.de/application/module/users/users.php` (see `class Users extends Module implements Interfaces\\Users, SplSubject`), but Nibiru core has no observer abstraction. From `framework-reference-v2.md §10.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.3 Observer Pattern","kind":"comparison","citations":["develop.maschinen-stockert.de/application/module/users/users.php:20-32","framework-reference-v2.md §10.3"]}} +{"instruction":"I keep getting weird database connection mismatches between two parts of my code. What's the cause?","input":"","output":"`Pdo::$section` is a static (last-write-wins) variable at `core/c/pdo.php:14`. Any model instantiation or `Pdo::settingsSection()` call mutates it. So if your code does:\n```php\n$userModel = Db::loadModel('App\\User'); // Pdo::$section = 'DATABASE'\n$logs = Pdo::queryString('SELECT ...'); // queries DATABASE\n$adminModel = Db::loadModel('App\\Admin'); // Pdo::$section = 'DATABASE_ADMIN'\n$logs = Pdo::queryString('SELECT ...'); // now queries DATABASE_ADMIN!\n```\nthe second raw `Pdo::queryString()` hits a different database than the first. Mitigation: explicitly call `Pdo::settingsSection('DATABASE')` immediately before any raw Pdo query, or always use `Db::loadModel()` and method calls on the returned model. From `framework-reference-v2.md §11.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.1 Pdo last-write-wins","kind":"debug","citations":["core/c/pdo.php:14","framework-reference-v2.md §11.1"]}} +{"instruction":"Schema field `user_ID` (uppercase) — what setter does the autogenerator produce?","input":"","output":"`_setUserID()` — `str_replace('_', '', ucfirst('user_ID'))` produces `UserID` (the upper-case `ID` is preserved because `ucfirst` only touches the first letter). So the generated method is `_setUserID($user_ID)`. Mitigation: enforce lowercase-with-underscores in your DB schema. From `framework-reference-v2.md §11.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.5 Field Casing","kind":"gotcha","citations":["framework-reference-v2.md §11.5"]}} +{"instruction":"How do I do a soft 404 in Nibiru?","input":"","output":"The Dispatcher routes to the configured error controller when no controller file matches. Configure in INI:\n```ini\n[ENGINE]\nerror_controller = \"errorController\"\nerror_template = \"error.tpl\"\n```\nThe Dispatcher line 75-80 path is taken if `application/controller/{ControllerName}Controller.php` doesn't exist. From `framework-reference-v2.md §6.2` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher 404","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md §7"]}} +{"instruction":"Show me the canonical insert + lastInsertId pattern.","input":"","output":"```php\nDb::loadModel('App\\Logs')->insertArrayIntoTable([\n 'log_message' => 'User logged in',\n 'log_timestamp' => date('Y-m-d H:i:s')\n]);\n$newId = Db::loadModel('App\\Logs')->lastInsertId();\n```\nFrom `framework-reference-v2.md` Quick Reference. Each `Db::loadModel()` call re-instantiates the model and re-asserts `Pdo::settingsSection()` from its `__construct()`. Both calls hit the same lazy connection.","metadata":{"language":"en","source":"framework-reference-v2","section":"Quick Reference","kind":"code-recall","citations":["framework-reference-v2.md Quick Reference"]}} +{"instruction":"Show me the canonical select-by-where pattern.","input":"","output":"```php\nuse Nibiru\\Factory\\Db;\n\n$model = Db::loadModel('App\\Users');\n$users = $model->loadTableAsArray();\n$user = $model->selectRowsetById(5);\n$admins = $model->selectDatasetByFieldWhere(['field' => 'role', 'value' => 'admin']);\n```\nFrom `framework-reference-v2.md` Quick Reference. The `IDb` interface guarantees these methods on every generated model.","metadata":{"language":"en","source":"framework-reference-v2","section":"Quick Reference","kind":"code-recall","citations":["framework-reference-v2.md Quick Reference","core/i/IDb.php"]}} +{"instruction":"Where do controller files live?","input":"","output":"`application/controller/*Controller.php`. The Dispatcher checks `application/controller/{ControllerName}Controller.php` exists at line 75-80; if so, requires and instantiates `new {ControllerName}Controller()`. Naming convention: lowercase first letter of the URL segment, `Controller` suffix. From `framework-reference-v2.md §6.2` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md Appendix"]}} +{"instruction":"What core file is the entry point for Nibiru's bootstrapping?","input":"","output":"`core/framework.php`. It includes all core files and at line 119 calls `Nibiru\\Dispatcher::getInstance()->run()`. The application root's `index.php` does `require_once 'core/framework.php';`. From `framework-reference-v2.md §6.1` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"workflow","citations":["framework-reference-v2.md §6.1","framework-reference-v2.md Appendix"]}} +{"instruction":"What's the purpose of `core/c/auto.php`?","input":"","output":"It hosts `Auto::loader()`, the modern autoloader. Replaces the legacy `core/c/autoloader.php`. Drives `loadModelFiles()` and `loadModules()` (which scans interfaces, traits, modules, plugins per INI registry). From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["core/c/auto.php","framework-reference-v2.md Appendix"]}} +{"instruction":"What's the difference between `core/c/auto.php` and `core/c/autoloader.php`?","input":"","output":"`core/c/auto.php` is the modern autoloader (`Auto::loader()`); `core/c/autoloader.php` is the deprecated legacy one. New code should use `Auto::loader()`. From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"comparison","citations":["framework-reference-v2.md Appendix"]}} +{"instruction":"List the database-related files in core.","input":"","output":"From `framework-reference-v2.md` Appendix:\n- `core/c/pdo.php` — `Pdo`, database switcher singleton.\n- `core/c/mysql.php` — `Mysql`, base connection class.\n- `core/c/table.php` — `Table`, autogenerator CLI parser.\n- `core/c/model.php` — `Model`, autogenerator executor.\n- `core/f/db.php` — `Db::loadModel()` static factory.\n- `core/a/mysql.db.php` — `\\Nibiru\\Adapter\\MySQL\\Db` base class.\n- `core/i/IMysql.php`, `core/i/IOdbc.php`, `core/i/IDb.php` — interfaces.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix"]}} +{"instruction":"List the form-related files in core.","input":"","output":"From `framework-reference-v2.md` Appendix:\n- `core/f/form.php` — `Form::create()` static factory.\n- `core/c/type*.php` (28 files) — form type classes (TypeText, TypeEmail, etc.).\n- `core/c/formattributes.php` — substitution engine `FormAttributes`.\n- `core/i/IForm.php` — 60+ `FORM_*` constants.\n- `core/t/form.php` — helper trait for `loadAttributeValues`.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix","framework-reference-v2.md §5.1"]}} +{"instruction":"I want to build a new module that records user actions. Walk me through the steps.","input":"","output":"1. Create directory `application/module/audit/` (lowercase).\n2. Create main class file `application/module/audit/audit.php` with namespace `\\Nibiru\\Module\\Audit\\Audit` extending `Module` and implementing `IModule` (or your local `Interfaces\\Audit`).\n3. Optional sub-folders: `interfaces/`, `traits/`, `plugins/` — files inside use namespaces `\\Nibiru\\Module\\Audit\\Interfaces\\*`, `\\Nibiru\\Module\\Audit\\Traits\\*`, `\\Nibiru\\Module\\Audit\\Plugins\\*`.\n4. Register in INI:\n```ini\n[AUTOLOADER]\nclass.pos[] = \"audit\"\niface.pos[] = \"audit\" ; if you have interfaces\ntrait.pos[] = \"audit\" ; if you have traits\nclass.plugin.pos[] = \"audit\" ; if you have plugins\n```\n5. Plugins access models via `use Nibiru\\Factory\\Db;` then `Db::loadModel('Folder\\Audit')->insertArrayIntoTable([...])`.\n\nFrom `framework-reference-v2.md §4.1`, §4.2, §4.4, §11.7.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §4.1","framework-reference-v2.md §4.2","framework-reference-v2.md §4.4","framework-reference-v2.md §11.7"]}} +{"instruction":"I want to add a new database table and use it in a controller. Walk me through it.","input":"","output":"1. Create the table in your database (e.g. via SQL migration in `application/settings/config/database/`).\n2. Ensure dev INI has `[GENERATOR][database] = true` and `database.overwrite = false`.\n3. Visit any URL — `Dispatcher::run()` fires `new Model(false)` which scans `SHOW TABLES` (MySQL) or `information_schema` (Postgres) and writes the new model file at `application/model//.php`.\n4. In your controller, `use Nibiru\\Factory\\Db;` and call `$rows = Db::loadModel('FolderName\\TableName')->loadTableAsArray();`.\n5. `View::assign(['rows' => $rows]);` — render in template via `{$rows}`.\n\nFrom `framework-reference-v2.md §3.2`, §6.3, §2.6.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md §6.3","framework-reference-v2.md §2.6"]}} +{"instruction":"I'm getting `Class 'Nibiru\\Model\\Foo\\Bar' not found` after creating a new database table. What's wrong?","input":"","output":"Either:\n1. The autogenerator isn't enabled — check `[GENERATOR][database] = true` in your INI.\n2. The model file at `application/model/Foo/Bar.php` exists but is empty (size 0). The non-overwrite generator only writes to a zero-byte file. If a previous failed run left a non-zero-byte stub, delete it and reload.\n3. Your folder namespace is wrong: `_setFolderNamespace()` PascalCases the basename. If `[DATABASE][basename] = \"foo\"`, the namespace is `\\Nibiru\\Model\\Foo`, not `\\Nibiru\\Model\\foo`.\n4. Autoloader hasn't run on the model — `Auto::loader()->loadModelFiles()` needs to require the file. If the directory exists but the file isn't there, regenerate.\n\nFrom `framework-reference-v2.md §3.2`, §8, §11.7.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Debug","kind":"debug","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md §8","framework-reference-v2.md §11.7"]}} +{"instruction":"Walk me through accepting form input in a Nibiru controller and saving it to the DB.","input":"","output":"1. Build the form via the `Form::*` factory in a trait or controller method:\n```php\nForm::create();\nForm::addInputTypeText(['name' => 'email']);\nForm::addInputTypeSubmit(['value' => 'Save']);\n$html = Form::addForm(['method' => 'POST', 'action' => '/users/save']);\n```\n2. Render the `$html` in a Smarty template via `View::assign(['form' => $html])` then `{$form nofilter}`.\n3. The form posts to `/users/save` -> Dispatcher routes to `usersController.php`, calls `saveAction()` (since `$_REQUEST['_action'] === 'save'`).\n4. In `saveAction()`:\n```php\n$email = $this->getPost('email');\nDb::loadModel('App\\Users')->insertArrayIntoTable(['email' => $email]);\n$id = Db::loadModel('App\\Users')->lastInsertId();\n```\n5. `View::forwardTo('/users/list')` to redirect.\n\nFrom `framework-reference-v2.md §2.4`, §2.5, §2.6, §6.3, Quick Reference.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §2.4","framework-reference-v2.md §2.5","framework-reference-v2.md §6.3","framework-reference-v2.md Quick Reference"]}} +{"instruction":"My production deployment shows a fresh model file getting overwritten between requests. What's happening?","input":"","output":"Two likely causes:\n1. `[GENERATOR][database] = true` is enabled in production — every request fires `new Model(false)` from `Dispatcher::run()` at `core/c/dispatcher.php:38`. Set it to `false` in `settings.production.ini`.\n2. `[GENERATOR][database.overwrite] = true` is enabled — every request `unlink`s the model file before regenerating from `core/c/model.php:70-74`. Set it to `false`.\n\nProduction should have BOTH off: `database = false` (master switch) and `database.overwrite = false` (safety net). From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Debug","kind":"debug","citations":["core/c/dispatcher.php:38","core/c/model.php:70-74","framework-reference-v2.md §3.2"]}} +{"instruction":"What happens if `[DATABASE][is.active] = false` but the autogenerator is enabled?","input":"","output":"`Model::__construct()` early-bails at line 16 of `core/c/model.php` before reaching `Table::__construct`. So no autogeneration happens, and no file scans run. The trade-off: if you disable a DB section temporarily but leave autogen enabled, you don't get models for that section but the rest of the app continues fine. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["core/c/model.php:14","core/c/model.php:16","framework-reference-v2.md §3.2"]}} +{"instruction":"How do I redirect after a POST in Nibiru?","input":"","output":"`View::forwardTo($page)` is a static helper on `\\Nibiru\\View` (singleton). Defined at `core/c/view.php:11`. Real plugin example from `loach.mssql.database-connection/application/module/users/plugins/acl.php`:\n```php\nView::forwardTo('/users/login');\n```\nIt sends an HTTP redirect to the specified path. From `framework-reference-v2.md §2.6` and §4.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","loach.mssql.database-connection/application/module/users/plugins/acl.php","framework-reference-v2.md §2.6"]}} +{"instruction":"What's the right way to assign multiple variables to a Smarty template?","input":"","output":"Pass an associative array to `View::assign`:\n```php\nView::assign([\n 'page_title' => 'Home',\n 'user_name' => 'John',\n 'role' => 'admin'\n]);\n```\nIn the Smarty template, reference them with `{$page_title}`, `{$user_name}`, `{$role}`. Defined at `core/c/view.php:11`. From `framework-reference-v2.md §2.6` and Quick Reference.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"code-recall","citations":["core/c/view.php:11","framework-reference-v2.md §2.6"]}} +{"instruction":"How do I check if there's an active session before reading a session value?","input":"","output":"`Controller::getSession()` accepts a third parameter:\n```php\n$user = $this->getSession('user', false, true);\n// parameter params checkForActiveSession\n```\nThe full signature from `core/c/controller.php:14`:\n```php\ngetSession($param, bool $params = false, bool $checkForActiveSession = false)\n```\nWith the third argument true, the helper checks session-active state before accessing.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"What does `getController()` return inside a Controller method?","input":"","output":"The current controller name, extracted from URL segment 1. From `core/c/controller.php:14`. Useful for navigation/breadcrumbs that need to know which controller is active. Different from class introspection — it returns the URL-derived name, not the PHP class name.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"What core methods does Pdo expose for building queries?","input":"","output":"From `framework-reference-v2.md §2.2`:\n- `query($string)` — exec or fetch; routes via `parent::getInstance(self::getSettingsSection())`.\n- `queryString($string, $associative)` — fetch all.\n- `fetchTableAsArray($tablename, $limit, $order)` — table dump with pagination.\n- `selectDatasetByFieldAndValue($tablename, $fieldAndValue, $sortOrder)` — WHERE clause.\n- `fetchRowInArrayById($tablename, $id)` — single row by PK.\n- `fetchRowInArrayByWhere($tablename, $column_name, $parameter_name)` — single row by column.\n- `insertArrayIntoTable($tablename, $array_name, $encrypted)` — insert with optional `DES_ENCRYPT()`.\n- `updateRowById($tablename, $columnNames, $data, $id, $encrypted)` — update by PK.\n\nAll routed through `self::getSettingsSection()` so they respect the current `Pdo::$section`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}} +{"instruction":"How does Pdo's optional encryption work?","input":"","output":"`Pdo::insertArrayIntoTable($tablename, $array_name, $encrypted)` and `Pdo::updateRowById($tablename, $columnNames, $data, $id, $encrypted)` accept an `$encrypted` flag. When set, MySQL `DES_ENCRYPT()` is applied to the relevant columns. The default `IMysql::PLACE_DES_ENCRYPT = false` means no encryption. From `framework-reference-v2.md §2.2` and §9.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}} +{"instruction":"How do I do a fetch-all SELECT with associative results?","input":"","output":"```php\n$rows = Pdo::queryString('SELECT * FROM my_table', true);\n```\nThe second argument controls associative-vs-numeric fetch. Routes through `self::getSettingsSection()` so the active `Pdo::$section` decides which DB connection. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}} +{"instruction":"What constants are listed under IForm and where are they used?","input":"","output":"`IForm` (at `core/i/IForm.php`) declares 60+ `FORM_*` constants — every legal attribute key (`name`, `value`, `class`, `id`, `placeholder`, `required`, `onchange`, `onblur`, `onfocus`, `selected`, `context`, `multiple`, `tabindex`, `pattern`, `data-bts-decimals`, `data-bts-step`, `any`, etc.). The constants are lowercase strings; the substitution engine uppercases them at replace time. Each Type class's `$_attributes` allowlist references these constants by name. From `framework-reference-v2.md §5.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/i/IForm.php","framework-reference-v2.md §5.1"]}} +{"instruction":"What's the difference between TypeText and TypeEmail?","input":"","output":"Different template strings and slightly different allowlists. `TypeText` (`core/c/typetext.php:42`) renders `` with attributes including `data-bts-decimals`, `data-bts-step`, `maxlength`, `disabled`, `speech`. `TypeEmail` (`core/c/typeemail.php`) renders `` with attributes `name, value, id, class, placeholder, required, pattern`. Both follow the same four-step recipe (`__construct` -> `_setElement` -> `loadAttributeValues` -> `_setAttributes`); only the template and allowlist differ. From `framework-reference-v2.md §5.3` and §5.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"comparison","citations":["core/c/typetext.php:42","core/c/typeemail.php","framework-reference-v2.md §5.4"]}} +{"instruction":"What's the difference between TypeSelect and TypeOpenAny?","input":"","output":"`TypeSelect` (`core/c/typeselect.php:37`) is a self-closing element template `` — fully formed, no manual close. `TypeOpenAny` (`core/c/typeopenany.php`) is just an open tag `VALUE` where `ANY` is replaced by the user's `'any' => 'span'` value; the matching close requires `Form::addCloseAny(['any' => 'span'])`. Use `TypeSelect` for dropdowns; use the OpenAny/CloseAny pair to wrap arbitrary children inside whatever HTML element you need. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"comparison","citations":["core/c/typeselect.php:37","core/c/typeopenany.php","framework-reference-v2.md §5.4"]}} +{"instruction":"How do I register a new option to a `` template with `OPTIONS` replaced by that buffer and clears it. From `framework-reference-v2.md §5.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.6 Select/Option Ordering","kind":"workflow","citations":["framework-reference-v2.md §5.6"]}} +{"instruction":"Walk me through how the Form factory pre-formats `id` and `class`.","input":"","output":"The trait `\\Nibiru\\Attributes\\Form` at `core/t/form.php:14` exposes `loadAttributeValues($attributes)`. It iterates the user's attribute array and rewrites the `id`, `class`, and `form` values into pre-quoted attribute snippets like `' id=\"x\"'`. So when the substitution engine later does `str_replace('ID', $value, $template)`, the bare `ID` token becomes `' id=\"x\"'` — and if the user didn't supply `id`, the strip pass at `core/c/formattributes.php:59-102` removes any leftover bare `ID` token. From `framework-reference-v2.md §5.1` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"workflow","citations":["core/t/form.php:14","core/c/formattributes.php:59-102","framework-reference-v2.md §5.2"]}} +{"instruction":"I need to render text inside a `` next to my input. What method do I use?","input":"","output":"Use the OpenAny/CloseAny pair:\n```php\nForm::addOpenAny(['any' => 'span', 'class' => 'input-group-addon']);\nForm::addInputTypeText(['name' => 'email']);\nForm::addCloseAny(['any' => 'span']);\n```\n`addOpenAny` emits `` (the `ANY` template token becomes `span`); `addCloseAny` emits ``. The leftover-`ANY` strip at `core/c/formattributes.php:100` ensures clean output. From `framework-reference-v2.md §5.4` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["core/c/formattributes.php:100","framework-reference-v2.md §5.4"]}} +{"instruction":"I need a labelled input with an icon. What's the canonical structure?","input":"","output":"Label + OpenDiv (input-group) + OpenAny (span for icon) + CloseAny + InputTypeText + CloseDiv. This is the production `addTextElement` pattern in `nibiru-modules/application/module/users/traits/userForm.php` lines 137-175. The factory call sequence:\n```php\nForm::addTypeLabel(['for' => 'email', 'value' => 'Email']);\nForm::addOpenDiv(['class' => 'input-group']);\nForm::addOpenAny(['any' => 'span', 'class' => 'input-group-addon']);\n// (icon HTML inside)\nForm::addCloseAny(['any' => 'span']);\nForm::addInputTypeText(['name' => 'email']);\nForm::addCloseDiv();\n```\nFrom `framework-reference-v2.md §5.9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"workflow","citations":["nibiru-modules/application/module/users/traits/userForm.php:137-175","framework-reference-v2.md §5.9"]}} +{"instruction":"My form HTML has weird double spaces. Why?","input":"","output":"That's an artifact of the substitution engine when several attributes are stripped consecutively. After the strip pass at `core/c/formattributes.php:59-102`, line 87 runs `str_replace(' ', ' ', ...)` to fold double spaces. If you still see them, you might have leftover unrecognized tokens that the engine never substituted AND never has a strip rule for — usually because you used a key not in the Type's allowlist. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"debug","citations":["core/c/formattributes.php:87","framework-reference-v2.md §5.2"]}} +{"instruction":"What happens when I call `Pdo::settingsSection()` with no arguments?","input":"","output":"It defaults to `IOdbc::SETTINGS_DATABASE`, which is the literal string `\"DATABASE\"`. From `core/c/pdo.php:19`:\n```php\npublic static function settingsSection( $section = IOdbc::SETTINGS_DATABASE )\n```\nSo a bare `Pdo::settingsSection()` resets `Pdo::$section` to `'DATABASE'` — the canonical primary connection.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"edge-case","citations":["core/c/pdo.php:19","core/i/IOdbc.php","framework-reference-v2.md §2.2"]}} +{"instruction":"Quick question: where is `Pdo::$section` declared?","input":"","output":"`core/c/pdo.php:14`, as a static property on the `Pdo` class. It's the single source of truth for which `[DATABASE*]` INI section the next query will use. Last write wins per request. From `framework-reference-v2.md §2.2` and §11.1.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:14","framework-reference-v2.md §2.2"]}} +{"instruction":"What's the relationship between Pdo and Mysql in core?","input":"","output":"`Pdo extends Mysql`. `Pdo` is the singleton/static-section interface; `Mysql` is the underlying connection class. `Pdo::getInstance(...)` calls `parent::getInstance(self::getSettingsSection())` which gives back a `Mysql` connection. From `framework-reference-v2.md §3.1` (file index) and §2.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"comparison","citations":["core/c/pdo.php","core/c/mysql.php","framework-reference-v2.md §3.1"]}} +{"instruction":"My logs show the wrong timezone in timestamps. What INI key fixes that?","input":"","output":"`[SETTINGS][timezone]`. The Dispatcher reads it on every request and calls PHP's timezone setter. Default is `UTC`. Set to e.g. `\"Europe/Berlin\"` and reload — all subsequent `date()` and `DateTime` calls reflect the new zone. From `framework-reference-v2.md §7 [SETTINGS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"debug","citations":["framework-reference-v2.md §7"]}} +{"instruction":"What does the autoloader do if a model file is missing?","input":"","output":"`Auto::loader()->loadModelFiles()` calls `require_once` on each file it scans inside the model folder. If the file is missing from disk, it isn't required. The runtime error happens later when something actually does `new \\Nibiru\\Model\\Foo\\Bar()` — PHP throws a fatal `Class … not found`. The autoloader is NOT PSR-4 — it scans directories driven by INI keys, so it can only require what's on disk. From `framework-reference-v2.md §11.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.7 Autoloader not PSR-4","kind":"edge-case","citations":["framework-reference-v2.md §11.7"]}} +{"instruction":"Show me the `addCloseDiv` invocation pattern.","input":"","output":"```php\nForm::addCloseDiv();\n```\nNo arguments needed. Emits ``. Companion to `addOpenDiv($attributes)`. Useful for nesting structural sections in production form code. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["framework-reference-v2.md §5.4"]}} +{"instruction":"How do I assign a value to a hidden form field?","input":"","output":"```php\nForm::addTypeHidden(['name' => '_action', 'value' => 'save']);\n```\nRenders ``. The factory method is `addTypeHidden` (note: `addType*` without `Input`), per `framework-reference-v2.md §5.5`'s naming-pattern table.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4","framework-reference-v2.md §5.5"]}} +{"instruction":"How do I include `_action` in a route?","input":"","output":"Route to a path matching the controller, and pass `_action` as a POST/GET param. Example: posting to `/users/save` sets `$_REQUEST['_action'] = 'save'`. The Dispatcher then calls `$controller->saveAction()`. You can put `_action` in form data:\n```html\n\n```\nFrom `framework-reference-v2.md §6.2` and §12.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md §12"]}} +{"instruction":"What happens if `_action` is set but the controller has no matching `*Action()` method?","input":"","output":"The Dispatcher only calls `{_action}Action()` if it exists on the controller. If the method is missing, the call is skipped — `navigationAction()` and `pageAction()` still run. There's no fatal error. From `framework-reference-v2.md §6.2` step 7.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"edge-case","citations":["framework-reference-v2.md §6.2"]}} +{"instruction":"Quick: which files comprise the View/Controller layer?","input":"","output":"From `framework-reference-v2.md` Appendix:\n- `core/c/view.php` — `View::getInstance()`, Smarty wrapper.\n- `core/c/controller.php` — `Controller::getInstance()`, request access.\n- `core/c/display.php` — final rendering.\n- `core/c/engine.php` — template engine setup.\n- `core/c/debug.php` — debug output.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix"]}} +{"instruction":"What does `core/l/autoload.php` do?","input":"","output":"It hosts a PSR-4 autoloader hook. Distinct from `core/c/auto.php` (which is `Auto::loader()`, scanning directories driven by INI). The PSR-4 hook handles class loading via standard Composer-style namespace mapping. From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix"]}} +{"instruction":"How do I render a JSON response from a Nibiru controller action?","input":"","output":"Call `View::forwardToJsonHeader()` to set the JSON content-type headers, then echo the JSON-encoded payload. `forwardToJsonHeader(string $encoding = \"\")` is defined at `core/c/view.php:11`. The headers it emits use `IView::NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\"` and `IView::NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\"`. From `framework-reference-v2.md §2.6` and §9.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","core/i/IView.php","framework-reference-v2.md §2.6"]}} +{"instruction":"What's the constant `NIBIRU_CONTENT_TRANSFER_ENCODING`?","input":"","output":"`\"Content-Transfer-Encoding: {transfer}\"` — a header template with a `{transfer}` placeholder for the actual encoding value. Defined in `core/i/IView.php` as `IView::NIBIRU_CONTENT_TRANSFER_ENCODING`. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IView.php","framework-reference-v2.md §9"]}} +{"instruction":"Walk me through writing a plugin that validates ACL on every request.","input":"","output":"1. Create `application/module/users/plugins/acl.php`.\n2. Use the framework imports and the canonical pattern:\n```php\nuse Nibiru\\Factory\\Db;\nuse Nibiru\\View;\n\nclass Acl extends User\n{\n public function __construct() { parent::__construct(); }\n\n public function init(): void\n {\n if(!$this->validate()) {\n View::forwardTo('/users/login');\n } else {\n $this->loadUserRole();\n }\n }\n}\n```\n3. Register in INI: `[AUTOLOADER] class.plugin.pos[] = \"acl\"`. Plugins load LAST per `Auto::loader()` order.\n4. Inside the plugin, `Db::loadModel('Folder\\Acl')` triggers the model's `Pdo::settingsSection('DATABASE')`.\n\nReal example: `loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40`. From `framework-reference-v2.md §4.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40","framework-reference-v2.md §4.4"]}} +{"instruction":"How are interfaces, traits, modules, and plugins loaded in order?","input":"","output":"`Auto::loader()->loadModules()` processes them in this fixed order: interfaces (`iface.pos[]`), traits (`trait.pos[]`), modules (`class.pos[]`), plugins (`class.plugin.pos[]`). Within each category, the array order from the INI is preserved. So plugins always load last; interfaces always first. From `framework-reference-v2.md §4.3` and §1 (namespace map row).","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["framework-reference-v2.md §4.3","framework-reference-v2.md §1"]}} +{"instruction":"Explain the IDb interface methods.","input":"","output":"From `core/i/IDb.php`, every generated model implements:\n- `loadTableAsArray()` — returns the entire table as a PHP array.\n- `selectRowsetById($id)` — returns the row whose PK matches `$id`.\n- `updateRowById(array $rowData, int $id, string $encrypted = \"\")` — UPDATE by PK with optional `DES_ENCRYPT()`.\n- `insertArrayIntoTable($dataset = array())` — INSERT row.\n- `selectDatasetByFieldWhere($fieldWhere = array(), $sortOrder = false)` — SELECT … WHERE.\n- `selectRowByFieldWhere($field = array())` — SELECT single row by column.\n- `lastInsertId()` — return last AUTO_INCREMENT value.\n- `deleteRowById(int $id = 0)` — DELETE by PK.\n- `updateRowByFieldWhere($wherefield, $wherevalue, $rowfield, $rowvalue)` — UPDATE … WHERE.\n\nFrom `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}} +{"instruction":"What does `selectDatasetByFieldWhere(['field' => 'role', 'value' => 'admin'])` actually do?","input":"","output":"It builds a `SELECT * FROM WHERE role = 'admin'` query against the model's table. The `$fieldWhere` parameter is an associative array with `'field'` (column name) and `'value'` (filter value). The optional second arg `$sortOrder` controls `ORDER BY`. From `framework-reference-v2.md` Quick Reference and §2.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["framework-reference-v2.md §2.3","framework-reference-v2.md Quick Reference"]}} +{"instruction":"Quick: when does `Auto::loader()->loadModelFiles()` run vs `loadModules()`?","input":"","output":"`Dispatcher::run()` calls `loadModelFiles()` at line 42, THEN `loadModules()` at line 43. So all model files are required first, modules second. This guarantees that a module's plugin can `Db::loadModel('Folder\\Foo')` and the class is already require'd. From `framework-reference-v2.md §4.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/c/dispatcher.php:42","core/c/dispatcher.php:43","framework-reference-v2.md §4.3"]}} +{"instruction":"How do I create a single-shot wrapping div around a select?","input":"","output":"Pass the wrapper as the second arg to `addSelect`:\n```php\nForm::addSelectOption(['value' => 'a', 'context' => 'A']);\nForm::addSelectOption(['value' => 'b', 'context' => 'B']);\nForm::addSelect(['name' => 'choice'], ['class' => 'form-group']);\n```\nThe `$div` argument is one-shot — only the next assembled element is wrapped. From `framework-reference-v2.md §5.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div Wrapping","kind":"workflow","citations":["framework-reference-v2.md §5.7"]}} +{"instruction":"What's an example multi-attribute div wrapper with class and id?","input":"","output":"The `setDiv` implementation iterates each `$key=>$selector` pair, but it OVERWRITES `self::$div` on each iteration:\n```php\nforeach ( $div as $key=>$selector ) {\n self::$div = '
' . \"\\n\" . 'ELEMENT
' . \"\\n\";\n}\n```\nFrom `core/f/form.php:120-140`. So the LAST entry in the `$div` array wins — passing `['class' => 'a', 'id' => 'b']` results in only `id=\"b\"` ending up in the wrapper. To get both, pre-build a single attribute string in the value or use a different mechanism. This is a footgun.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div Wrapping","kind":"gotcha","citations":["core/f/form.php:120-140","framework-reference-v2.md §5.7"]}} +{"instruction":"What's the typical INI structure for a development environment?","input":"","output":"Sections seen in real Nibiru INI files (per `framework-reference-v2.md §7`):\n- `[ENGINE]` — Smarty paths, caching, error controller/template.\n- `[AUTOLOADER]` — `class.pos[]`, `iface.pos[]`, `trait.pos[]`, `class.plugin.pos[]` arrays.\n- `[GENERATOR]` — `database`, `database.overwrite`, `config-section`, `folder-out`, `modeltemplate`, `odbc`.\n- `[DATABASE]` (and optional `[DATABASE_*]`) — `is.active`, `username`, `password`, `hostname`, `basename`, `driver`, `port`, `encoding`.\n- `[SETTINGS]` — `timezone`, `pageurl`, `dbmodel`, `module`, `interfaces`, `traits`, `plugins`.\n- `[ROUTING]` — `route[index]`, `route[controller]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI Reference","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"I want to talk to MSSQL through Nibiru. How does the framework support that?","input":"","output":"There's no native MSSQL driver in the v2 reference — Nibiru ships MySQL/MariaDB (`driver = \"mysql\"`), PostgreSQL via libpq (`driver = \"postgresql\"`), and PostgreSQL via UnixODBC (`driver = \"psql\"` + `[GENERATOR][odbc] = true`). For MSSQL you'd typically route through ODBC by writing a custom driver class or wrapping queries through PHP's PDO ODBC layer. The `loach.mssql.database-connection` project name suggests this was the pattern, but the v2 reference does not document an MSSQL driver. From `framework-reference-v2.md §3.1` and §3.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"edge-case","citations":["framework-reference-v2.md §3.1","framework-reference-v2.md §3.2"]}} +{"instruction":"What runs when I do `Db::loadModel('App\\Logs')->insertArrayIntoTable([...])`?","input":"","output":"1. `Db::loadModel('App\\Logs')` instantiates `\\Nibiru\\Model\\App\\Logs` via the factory at `core/f/db.php:11`.\n2. The model's `__construct()` runs: `Pdo::settingsSection('DATABASE')` mutates `Pdo::$section`; `self::initTable( self::TABLE )` registers the schema with the static `$table` array on the base adapter (`core/a/mysql.db.php:15`).\n3. `Db::loadModel()` returns the model typed as `IDb`.\n4. `->insertArrayIntoTable([...])` (from `IDb`) invokes the adapter's INSERT, which routes through `Pdo::insertArrayIntoTable($tablename, $array_name, $encrypted)` using `self::getSettingsSection()` to pick the connection.\n5. MySQL receives `INSERT INTO logs (...) VALUES (...)`.\n\nFrom `framework-reference-v2.md §2.3`, §3.1, §2.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["core/f/db.php:11","core/a/mysql.db.php:15","framework-reference-v2.md §2.3"]}} +{"instruction":"How do I disable Smarty caching for development?","input":"","output":"Set `[ENGINE][caching] = false` in `settings.development.ini`. The `_setEngine()` block at `core/c/view.php:66-79` only enables `CACHING_LIFETIME_CURRENT` when `ENGINE[caching]==true`. From `framework-reference-v2.md §2.6` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §2.6"]}} +{"instruction":"How do I turn on the Smarty debugbar?","input":"","output":"`[ENGINE][debugbar] = true` in your INI. Read by `View::_setEngine()` at `core/c/view.php:66-79`. Pair it with `[ENGINE][debug_template]` pointing at the debugbar template path. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}} +{"instruction":"What does the `db_info_print` INI key do?","input":"","output":"Optional debug flag in `[DATABASE]`, default `0`. Not consumed by core — it's a downstream convention for printing connection diagnostics. The framework's `Mysql::__construct()` does not read it. From `framework-reference-v2.md §7 [DATABASE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"Why does PHP raise `Class 'Nibiru\\Adapter\\Postgresql\\Db' not found` from a generated model?","input":"","output":"The autogenerator emitted `use Nibiru\\Adapter\\Postgresql\\Db;` because `[GENERATOR][odbc]` was falsy at generation time. If `core/a/postgresql.db.php` (or its `\\Nibiru\\Adapter\\Postgresql` namespace) is missing or wasn't loaded by the autoloader, PHP fatals. Check that:\n1. `core/a/postgresql.db.php` exists in the framework directory.\n2. The PSR-4 hook at `core/l/autoload.php` is active.\n3. The `core/framework.php` boot includes the relevant adapter file.\n\nFrom `framework-reference-v2.md §3.2` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"debug","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md Appendix"]}} +{"instruction":"What's the difference between `selectRowByFieldWhere` and `fetchRowInArrayByWhere`?","input":"","output":"`selectRowByFieldWhere($field = array())` is a method on the `IDb`-typed model (from `core/i/IDb.php`) — used via `Db::loadModel(...)->selectRowByFieldWhere([...])`.\n`fetchRowInArrayByWhere($tablename, $column_name, $parameter_name)` is on `Pdo` directly — used via `Pdo::fetchRowInArrayByWhere(...)`.\n\nFunctionally similar (both fetch a single row by column/value), but the IDb version takes an array argument and is bound to the model's table; the Pdo version takes raw `$tablename`/`$column`/`$value` strings and lets you query any table. From `framework-reference-v2.md §2.2` and §2.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Comparison","kind":"comparison","citations":["core/i/IDb.php","core/c/pdo.php","framework-reference-v2.md §2.2"]}} +{"instruction":"How do I register an interface for a module?","input":"","output":"1. Place the interface file at `application/module//interfaces/.php` with namespace `\\Nibiru\\Module\\\\Interfaces\\`.\n2. Add to INI: `[AUTOLOADER] iface.pos[] = \"\"`.\n3. Reload — `Auto::loader()->loadModules()` will scan the interfaces directory and `require_once` matching files.\n\nFrom `framework-reference-v2.md §4.2` and §8.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.2 Module Registry","kind":"workflow","citations":["framework-reference-v2.md §4.2","framework-reference-v2.md §8"]}} +{"instruction":"Explain the difference between `getRequest`, `getPost`, and `getGet`.","input":"","output":"From `core/c/controller.php:14`:\n- `getPost($param)` — reads `$_POST` only.\n- `getGet($param)` — reads `$_GET` only.\n- `getRequest($param, bool $params = false)` — reads `$_REQUEST` (POST/GET unified).\n\nUse `getPost`/`getGet` when the source matters (security or method-specific behavior); use `getRequest` when you just want the value regardless of how it arrived. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"comparison","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"Where does `$controller->getServer($param)` map to?","input":"","output":"`$_SERVER`. So `$this->getServer('REMOTE_ADDR')` returns the client IP, `$this->getServer('HTTP_USER_AGENT')` the user agent. Defined at `core/c/controller.php:14`. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"How do I access uploaded files in a Nibiru controller?","input":"","output":"`$this->getFiles($param)` — reads `$_FILES`. Defined at `core/c/controller.php:14`. Combine with `
` and `Form::addTypeFileUpload(['name' => 'upload'])`. From `framework-reference-v2.md §2.5` and §5.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}} +{"instruction":"Show me the IMysql `PLACE_*` constants for INI keys.","input":"","output":"From `core/i/IMysql.php`:\n```php\nconst PLACE_IS_ACTIVE = \"is.active\";\nconst PLACE_USERNAME = \"username\";\nconst PLACE_PASSWORD = \"password\";\nconst PLACE_HOSTNAME = \"hostname\";\nconst PLACE_DRIVER = \"driver\";\nconst PLACE_DATABASE = \"basename\";\nconst PLACE_PORT = \"port\";\nconst PLACE_ENCODING = \"encoding\";\n```\nThese are the literal INI key names used when reading `[DATABASE*]` sections via `Config::getInstance()->getConfig()`. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}} +{"instruction":"Quick question: where is the model autogeneration master switch read?","input":"","output":"`Dispatcher::run()` at `core/c/dispatcher.php:35-39` reads `Config::getInstance()->getConfig()[self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]`. The constants resolve to the INI path `[GENERATOR][database]`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["core/c/dispatcher.php:35-39","framework-reference-v2.md §3.2"]}} +{"instruction":"What's the production-safe combination of `[GENERATOR]` flags?","input":"","output":"```ini\n[GENERATOR]\ndatabase = false ; off in production\ndatabase.overwrite = false ; safety net (already off)\n```\nWith `database = false`, `Dispatcher::run()` skips the `new Model(false)` branch entirely. With `database.overwrite = false`, even if you flip the master switch back on for a moment, existing model files aren't `unlink`ed. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["framework-reference-v2.md §3.2"]}} +{"instruction":"What's the structure of an IForm constant entry?","input":"","output":"All `FORM_*` constants in `core/i/IForm.php` are public lowercase strings. Example shape:\n```php\nconst FORM_NAME = 'name';\nconst FORM_VALUE = 'value';\nconst FORM_ATTRIBUTE_PLACEHOLDER = 'placeholder';\nconst FORM_ATTRIBUTE_REQUIRED = 'required';\nconst FORM_ATTRIBUTE_ID = 'id';\nconst FORM_ATTRIBUTE_CLASS = 'class';\n```\nThe Type classes reference these constants in their `$_attributes` allowlists; the substitution engine uppercases them at replace time. From `framework-reference-v2.md §5.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/i/IForm.php","framework-reference-v2.md §5.1"]}} +{"instruction":"What's the entry point line that calls `Dispatcher::run()`?","input":"","output":"`core/framework.php` at line 119:\n```php\nNibiru\\Dispatcher::getInstance()->run();\n```\nThis is the line that fires after all core files are required, kicking off the entire request lifecycle. From `framework-reference-v2.md §12` step 4.","metadata":{"language":"en","source":"framework-reference-v2","section":"12 Request Trace","kind":"code-recall","citations":["core/framework.php:119","framework-reference-v2.md §12"]}} +{"instruction":"What does Nibiru's `Module` base class give me?","input":"","output":"It's at `core/c/module.php` (and `core/a/module.php` for the adapter base). Provides the common base for all module main classes. Production module example extends `Module`:\n```php\nclass Users extends Module implements Interfaces\\Users, SplSubject\n```\nFrom `framework-reference-v2.md §4.3` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/c/module.php","core/a/module.php","framework-reference-v2.md §4.3"]}} +{"instruction":"How does the `IModule` interface interact with the Module base class?","input":"","output":"`IModule` (from `core/i/IModule.php`) is the contract every module main class must implement. The base `Module` class at `core/c/module.php` provides default behavior; concrete modules extend `Module` AND implement `IModule` (sometimes via a module-local `Interfaces\\Users` interface that itself extends `IModule`). From `framework-reference-v2.md §4.3` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/i/IModule.php","core/c/module.php","framework-reference-v2.md §4.3"]}} +{"instruction":"How does the autogenerator know which tables to scan?","input":"","output":"`Table::_setTables()` runs `SHOW TABLES` for MySQL or queries `information_schema` for Postgres. The result populates `$tables`, which `Model::createClassFiles()` (at `core/c/model.php:37`) loops over to call `generateClassByTableName()`. If `--table=foo` was passed (CLI flag, not used by dispatcher), only `foo` is generated. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/table.php","core/c/model.php:37","framework-reference-v2.md §3.2"]}} +{"instruction":"Why does the generator chmod files to 0777?","input":"","output":"`Model::createOutFolder()` at `core/c/model.php:28` does `mkdir -p` with `chmod 0777`. `generateClassByTableName()` ends with `chmod(..., 0777)` at `core/c/model.php:133-145`. The aggressive permission is so the web server user (which created the file) doesn't lock developers out of editing or removing it on shared dev machines. In production, since the generator should be off, this chmod doesn't run. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:28","core/c/model.php:133-145","framework-reference-v2.md §3.2"]}} +{"instruction":"Show me the field-array indentation pattern in the generated TABLE constant.","input":"","output":"The generator hard-codes tabs/newlines (`\\t\\t\\t\\t\\t\\t\\t\\t`) at `core/c/model.php:86, 94, 101` when concatenating `$fieldarray`. So generated output looks like:\n```php\n'fields' => array(\n 'timeanddate_id' => 'timeanddate_id',\n 'timeanddate_date' => 'timeanddate_date'\n)\n```\nThe indentation is baked into the generator and won't match any other code style — don't try to lint your generated models. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/model.php:86","core/c/model.php:94","core/c/model.php:101","framework-reference-v2.md §3.2"]}} +{"instruction":"How do I share data between `navigationAction()` and `pageAction()`?","input":"","output":"Use instance properties on the controller class:\n```php\nclass UsersController extends Controller {\n private array $userData = [];\n\n public function navigationAction() {\n $this->userData = Db::loadModel('App\\Users')->loadTableAsArray();\n }\n\n public function pageAction() {\n View::assign(['users' => $this->userData]);\n }\n}\n```\nBoth methods run on the same `$controller` instance per the Dispatcher flow at `core/c/dispatcher.php:52` (navigation) and `:60` (page). From `framework-reference-v2.md §6.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.3 Controller Lifecycle","kind":"workflow","citations":["core/c/dispatcher.php:52","core/c/dispatcher.php:60","framework-reference-v2.md §6.3"]}} +{"instruction":"Quick: which singletons follow `getInstance()` in Nibiru?","input":"","output":"All core singletons: `Config`, `Controller`, `View`, `Pdo`, `Router`, `Dispatcher`, `Engine`. All live under `\\Nibiru\\` (root namespace) at `core/c/*.php`. From `framework-reference-v2.md §1` (namespace map row).","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["framework-reference-v2.md §1"]}} +{"instruction":"What's the difference between the `Db` factory and the `Pdo` singleton?","input":"","output":"`Db` is a static factory (`\\Nibiru\\Factory\\Db` at `core/f/db.php:11`) — `Db::loadModel($name)` returns an `IDb` instance, hiding the namespace assembly and `new` call.\n\n`Pdo` is a connection-switcher singleton (`\\Nibiru\\Pdo` at `core/c/pdo.php:12`) — used directly for raw queries (`Pdo::queryString(...)`) or to swap connections (`Pdo::settingsSection('OTHER')`).\n\nUse `Db` when you want to work with a specific table via its model. Use `Pdo` when you want raw SQL or to control which DB section subsequent calls use. From `framework-reference-v2.md §2.2` and §2.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Comparison","kind":"comparison","citations":["core/f/db.php:11","core/c/pdo.php:12","framework-reference-v2.md §2.2","framework-reference-v2.md §2.3"]}} +{"instruction":"How do I use `selectDatasetByFieldAndValue` from Pdo directly?","input":"","output":"```php\nPdo::selectDatasetByFieldAndValue(\n $tablename = 'users',\n $fieldAndValue = ['role' => 'admin'],\n $sortOrder = 'created_at DESC'\n);\n```\nBuilds a `SELECT * FROM users WHERE role = 'admin' ORDER BY created_at DESC`. Routed through `self::getSettingsSection()` so it respects the active `Pdo::$section`. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}} +{"instruction":"What does `Pdo::fetchTableAsArray($tablename, $limit, $order)` do?","input":"","output":"Returns the entire table as a PHP array, with optional pagination via `$limit` and ordering via `$order`. Routes through `self::getSettingsSection()` for connection selection. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}} +{"instruction":"How does `_setFolderOut` decide where to write generated models?","input":"","output":"From `core/c/table.php:208`:\n- If `--folder-out=` was passed via CLI flags, that wins.\n- Otherwise, it concatenates `__DIR__ . config[GENERATOR][folder-out] . $foldernamespace`.\n- `__DIR__` is `core/c/`, so the leading `/../../` in `[GENERATOR][folder-out] = \"/../../application/model/\"` walks back to the project root.\n- `$foldernamespace` is the PascalCased basename (e.g. `WarehouseLoach`).\n\nResult: `core/c/../../application/model/WarehouseLoach/` -> `application/model/WarehouseLoach/`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/table.php:208","framework-reference-v2.md §3.2"]}} +{"instruction":"How do I read `pageurl` from the INI inside controller code?","input":"","output":"```php\n$url = Config::getInstance()->getConfig()['SETTINGS']['pageurl'];\n```\nThe key is custom (no core consumer). The framework only documents it — you read it manually. From `framework-reference-v2.md §7 [SETTINGS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"What does `entriesperpage` do in the INI?","input":"","output":"It's a custom-use INI key in `[SETTINGS]` with no core consumer — application code reads it for pagination size. The framework documents it in `framework-reference-v2.md §7 [SETTINGS]` but doesn't act on it.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}} +{"instruction":"My module's trait has a public method but the IDE says it's undefined when used in another module's class. Why?","input":"","output":"Module-specific traits live under `\\Nibiru\\Module\\\\Traits\\`. To use a trait from module `users` (`\\Nibiru\\Module\\Users\\Traits\\UserForm`) inside another class, you must `use \\Nibiru\\Module\\Users\\Traits\\UserForm;` AND ensure the autoloader has loaded the trait file. The autoloader only scans the trait if `[AUTOLOADER] trait.pos[] = \"users\"` is in the INI. If you reference the trait from a class in a different module that loads BEFORE `users`, the trait won't be available yet. From `framework-reference-v2.md §1`, §4.2, §11.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Debug","kind":"debug","citations":["framework-reference-v2.md §1","framework-reference-v2.md §4.2","framework-reference-v2.md §11.4"]}}