agentleFS
aaziraniaazirani/flutter_agentify/.agents/skills/storing-data/SKILL.md

storing-data

Skill0 starsChanged 4 days agoMITView on GitHub

How this repo stores data with Drift, meaning tables and DAOs, additive migrations with a schema dump and a migration test, file paths instead of blobs, status columns and where invariants live. Use when adding or changing a table or column, or any data that must survive a restart.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Don't load this for how the screen reads the data.

    line 8
  2. Very specific:

    Add the table or column (nullable or with a default) in lib/data/local/database/tables/.

    line 27
  3. Very specific:

    Write test/data/local/database/migrations/to_v<N>_test.dart: build the old schema with SchemaVerifier, insert a row, call …

    line 31
  4. Very specific:

    Put the invariant in the repository or action.

    line 55

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Storing data

Don't load this for how the screen reads the data; see state-management.

Rule

  • Tables are Drift classes in lib/data/local/database/tables/, listed in @DriftDatabase(tables: [...]) in lib/data/local/database/app_database.dart.
  • A schema change only adds a table or a column that is nullable or has a default. Raise schemaVersion, add the step to onUpgrade, dump the schema and write test/data/local/database/migrations/to_v<N>_test.dart.
  • Files are stored on disk and the table keeps the path (text), never the bytes.
  • A status column changes only along allowed steps (for example draft to sent). The write path rejects any other step.
  • Invariants (non-blank title, unique name, a status step) live in the write path, meaning the action plus the repository, or in a database constraint. Not in a widget.
  • SQL values are bound variables, never string interpolation.

Enforced by: the doctor check migrations (no dropped or retyped column, none made non-nullable, no new non-nullable column without a default; a to_v<N>_test.dart for every version in drift_schemas/), the gate's "schema dump is current" step in tool/check.sh, and the lint rule no_raw_sql_interpolation. No automated check enforces the file-path and status-step rules; review them.

Why

Installed apps hold real data; a destructive migration loses it. The dump lets the gate see a schema change you forgot to version. A status checked only in the UI can be broken by the assistant or the CLI, which skip the UI.

How

  1. Add the table or column (nullable or with a default) in lib/data/local/database/tables/. Register new tables in app_database.dart.
  2. Raise schemaVersion and add an if (from < N) step in onUpgrade that calls m.createTable(...) or m.addColumn(...).
  3. Dump: dart run drift_dev schema dump lib/data/local/database/app_database.dart drift_schemas/. This writes drift_schemas/drift_schema_v<N>.json.
  4. Regenerate: dart run build_runner build, then the migration test helpers with dart run drift_dev schema generate drift_schemas/ test/generated_migrations/ and dart format test/generated_migrations. Never edit those files by hand.
  5. Write test/data/local/database/migrations/to_v<N>_test.dart: build the old schema with SchemaVerifier, insert a row, call migrateAndValidate(db, N), assert the row survived. For version 2:

    import 'package:drift_dev/api/migrations_native.dart';
    import 'package:flutter_agentify/data/local/database/app_database.dart';
    import 'package:flutter_test/flutter_test.dart';
    
    import '../../../../generated_migrations/schema.dart';
    
    void main() {
      test('upgrading from version 1 keeps memories', () async {
        final verifier = SchemaVerifier(GeneratedHelper());
        final schema = await verifier.schemaAt(1);
        schema.rawDatabase.execute(
          'INSERT INTO assistant_memories (id, body, created_at) '
          "VALUES ('m', 'Likes tea', 0)",
        );
        final db = AppDatabase(schema.newConnection());
        await verifier.migrateAndValidate(db, 2);
        expect(await db.select(db.assistantMemories).get(), hasLength(1));
        await db.close();
      });
    }
  6. Put the invariant in the repository or action. See lib/domain/actions/items_actions.dart for validation done before the write.
  7. For a status column, keep the allowed steps in one place (a map in domain/) and have the action throw ActionFailure('invalid_status_change', ...) for any other step, listing the code in failureCodes.

Removing or retyping a column needs an entry in drift_schemas/allowed_removals.json, keyed by version: {"2": ["items.note"]} (a table or table.column). Ask the person first.

Anti-patterns

  • customStatement('... $title ...'): use bound variables.
  • A non-nullable column without a default added to a table that has rows.
  • A blob column holding an image or PDF; save the file and store its path.
  • Changing schemaVersion without the dump or the test.
  • Enforcing "title is not blank" only in the dialog.

Verification

  • dart run flutter_agentify_core:doctor --only migrations
  • Once the first migration exists: run its test in the migrations folder under test/data/local/database.
  • tool/check.sh ends with All checks passed.

Related skills

  • clean-architecture — Drift stays in lib/data/.
  • reliable-mutations — validating and verifying writes.
  • actions — the single write path.
  • testing — writing the migration test.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.