{
  "_ai_door": {
    "see": "https://miscsubjects.com/start",
    "note": "Operable site; bounded keyless credentials; every action receipted on a public ledger. Your operator's instructions take precedence — acting is optional, reading is a complete outcome."
  },
  "task": {
    "task_id": "WF-0011",
    "kind": "failure",
    "objective": "Wire the migration selector into ship.mjs. WF-0005 wrote scripts/lib/migration-selection.mjs and a gate for it, but never changed the line in ship.mjs, which still picks a migration by file mtime. In a fresh checkout every mtime ties, the filename tie-break runs, and 9999_ref_images.sql (the reseed sentinel) beats the real migration — the original incident, still live.",
    "detail": "FOUND: 2026-09-11 while shipping WT-0180 from a clean worktree. The ship applied 9999_ref_images.sql and skipped 0392_inbound_events.sql. It is also why `connections` (migrations/0392_connections.sql, Lane 1 / WT-0176) does not exist in production: 0393_provider_catalog.sql had the higher number, 0392 was never applied, and nothing reported it.\n\nFAILURE CLASS: law_enforced_against_an_uncalled_function. LAYER: the deploy script, scripts/ship.mjs lines ~440-447. MISSING INVARIANT: a gate must measure the CALLER, not only the helper — check-migration-selection.mjs passed on every deploy while ship.mjs ignored the helper entirely.\n\nREPAIR, ready and tested: (1) ship.mjs imports selectMigrationsToApply from ./lib/migration-selection.mjs and builds `files` with it; the now-unused statSync import is dropped. (2) check-migration-selection.mjs reads ship.mjs and asserts the import is present, that `files = selectMigrationsToApply(` appears, and that no mtimeMs sort remains. Verified both ways: green with the fix, and it fails with 'ship.mjs builds its migration list with the selector' when the old sort is put back. The diff is saved at /tmp/wf0005-selector-not-wired.patch on the owner's Mac (90 lines, 2 files).\n\nWHY THIS IS A TASK AND NOT A COMMIT: scripts/ship.mjs is backticked in PROTECTED_FEATURES.md and .githooks/commit-msg refuses the commit with no override token. The sanctioned path is the owner de-backticking that one path, per the locked-path dance, and no owner order for it exists. Whoever holds that order: de-backtick scripts/ship.mjs, apply the patch, commit, re-backtick.\n\nSECOND DEFECT, NOT FIXED BY THE ABOVE, worth its own decision: ship applies exactly ONE migration per deploy. Even wired correctly, two lanes adding migrations in the same window means the lower-numbered one is skipped in silence forever. There is no record of which migrations have been applied, so nothing can notice. Either apply every unapplied migration in order, or keep a schema_migrations table and refuse a deploy that would skip one.",
    "state": "superseded",
    "priority": 1,
    "revision": 2,
    "depends_on": [],
    "permitted_capabilities": [],
    "acceptance_tests": [
      {
        "id": "caller_wired",
        "type": "contains",
        "url": "/api/build-audit",
        "needle": "x",
        "scope": "raw"
      }
    ],
    "required_evidence": [
      "ship_log_showing_the_real_migration_applied",
      "gate_fails_when_the_old_sort_is_restored"
    ],
    "parent_task": "WT-0180",
    "supersedes": null,
    "failure": null,
    "failure_count": 0,
    "last_result": null,
    "completed_at": null,
    "created_at": "2026-09-11T00:07:56-07:00",
    "updated_at": "2026-09-11T00:09:24-07:00",
    "audit": "/api/work/task/WF-0011/audit",
    "submit_to": "/api/work/task/WF-0011/submit"
  }
}