{
  "_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": "WT-0473",
    "kind": "work",
    "objective": "WT-0473 CONTRACTS harness and the six-column projection — batch runner, RUN column, regression fixtures",
    "detail": "# WT-0473 — CONTRACTS harness and the six-column projection — batch runner, RUN column, regression fixtures\n\n## GOAL\nMake the CONTRACTS system (the six-column sheet sh_nyab2cgy in the build workbook, scripts/contracts-*.mjs, the CONTRACTS_RUN row, the RUN column) a durable harness: it reads capability_contracts + proof_runs (canonical) and projects them; it re-runs any row on demand from the sheet; it never stops a batch on one failure; every known failure class from the 2026-09-23 run is a fixture the runner is tested against.\n\n## WHY THIS EXISTS\nThe owner's format law (CONTRACTS_FORMAT_LAW) is how he reads execution. The 2026-09-23 run produced 11,035 rows but the runner was a session tool: it stalled on Apps Script throttling, split cells at 24,000 chars, ran in a shell where `set -- $spec` did not word-split, and the sheet was hand-loaded. The harness must be the build's, not a session's.\n\n## CURRENT STATE (measured 2026-09-23)\n- Sheet sh_nyab2cgy: 11,035 rows (10,072 verbs + 962 ways + header); columns exactly TOOL NAME | ONTOLOGY | RAW INVOCATION | RAW CONFIRMATION | RAW RETURN | PROOF / RECEIPT; counts 2026-09-23: HTTP 2xx 1,698; HTTP 5xx 2,378; transport failed 42; NOT RUN with reason 5,954.\n- scripts/contracts-sheet.mjs (build rows from /tmp/claude-501/contracts/*.json), contracts-run.mjs (`--marked=build:<sheet>` RUN-column mode, policy(), runText()), contracts-ways.mjs, contracts-load-workbook.mjs (60 rows/PUT, cells cut at 24,000), contracts-write-results.mjs (D:F only, chunks ≤ 60).\n- CONTRACTS_RUN directory row → POST agent.miscsubjects.com/exec → `node scripts/contracts-run.mjs --marked=build:sh_nyab2cgy --max=50`.\n- apps-script/Contracts.gs (Google copy 1cUE88…) — a projection the owner does not want as home; keep it working, never make it the source.\n- Scratch sheet sh_ahznwfyd for `=FORMULA` cells.\n- Vault: CONTRACTS_WORKBOOK_SHEET, CONTRACTS_SCRATCH_SHEET, CONTRACTS_LINK_TOKEN (10-year rows: token; door keys included), CONTRACTS_SHEET_ID.\n\n## SOURCE OF TRUTH\n- capability_contracts + proof_runs (after WT-0470/0485) — the sheet is derived from them\n- scripts/contracts-*.mjs\n- functions/api/sheets (PUT values ≤ 400 cells per call; `=DISPATCH(\"KEY\",\"args\")` formulas)\n- the `laws` row CONTRACTS_FORMAT_LAW\n\n## IN-SCOPE INVENTORY\n- scripts/contracts-project.mjs (new): reads canonical rows → writes the six columns; idempotent; `--since <receipt>` incremental.\n- RUN column: typing RUN in column G is not allowed (no seventh column) — the RUN mechanism is a cell edit in column C prefixed `RUN ` OR the CONTRACTS_RUN row with `--rows`; decide: keep `--marked` reading column C prefix `RUN `; document in the sheet header note only.\n- Runner hardening: per-row timeout; DNS/transport failure isolates the row; cells > 20,000 chars stored whole in the ledger and cut in the projection with `… [cut at 20000; full at receipt <id>]`; writes ≤ 400 cells and ≤ 80 KB per PUT; retry 5 with backoff; a stalled write never blocks execution (results go to file first, then to the sheet).\n- Fixture suite scripts/contracts-fixtures.test.mjs built from the exact 2026-09-23 failures (list below).\n- The Google copy: Contracts.gs contracts_run/invoke_json stay; a header note says \"projection of the build workbook\".\n\n## OUT OF SCOPE\n- Executing per-surface runners (WT-0472 supplies them; this harness schedules and projects). Ontology labels (WT-0486). New columns (forbidden).\n\n## ONTOLOGY (separate axes; never a flat string)\n- TOOL SURFACE: cell `RUN ` prefix; CONTRACTS_RUN row via dispatch; `node scripts/contracts-run.mjs`\n- CAPABILITY: CONTRACTS_RUN, CONTRACTS_PROJECT\n- OBJECT: six-column rows\n- ROUTE / CONTEXT: owner Mac (runner) → doors; the build workbook\n- PROTOCOL: HTTP to /api/sheets and /api/dispatch; local process\n- EXECUTOR: node on the Mac (through agent.miscsubjects.com/exec) or on a CF container (CLOUD_EXEC)\n- PLATFORM: the build; Cloudflare; Google (projection only)\n\n## DISCOVERY (run these first; they answer, they do not prove)\n- `curl -sS \"https://ops.miscsubjects.com/api/sheets/sh_nyab2cgy?range=A1:F3\" -H \"x-terminal-key: $TERMINAL_KEY\"`\n- `node scripts/contracts-run.mjs --help` (this prints usage; it is not proof of anything)\n- `cat /tmp/claude-501/contracts/workbook-counts.json`\n\n## CONTRACT (FIELD LAW)\n- `contracts-run.mjs` flags: --rows (csv or a-b), --from/--to (ints), --concurrency (1–8, default 2), --only=<ontology substring>, --target=google|file:<path>|build:<sheet>, --marked=build:<sheet>, --max (int), --timeout-ms (default 60000). --rows conflicts with --from/--to. Omitting --target writes nowhere but the results file.\n- Row contract (the six cells): A tool name (string, ≤ 200), B ontology (`<axis> · <axis> · …`, from WT-0486), C raw invocation (executable text as pasted, ≤ 20,000 in the projection), D raw confirmation (`HTTP <status> · <ms> ms · <ISO> · run by <surface> · plane=<…> · ids …` | `EXIT <n> …` | `NOT RUN BY THE SESSION · <reason> · type RUN here to run it yourself` | `NOT RUNNABLE FROM THIS MAC · <reason>`), E raw return (verbatim, cut at 20,000 with the receipt pointer), F proof/receipt (`receipt:<id> trace:<id> parent:<id|none> surface:<spelling> cause:<…>`).\n\n## MINIMUM VALID INVOCATION\n`node scripts/contracts-run.mjs --rows 2 --target=build:sh_nyab2cgy`\n\n## FULL / MAXIMUM INVOCATION\n`node scripts/contracts-run.mjs --from 2 --to 11035 --concurrency 4 --only \"dispatch\" --target=build:sh_nyab2cgy --timeout-ms 90000 --cause task:WT-0473`\n\n## RAW CONFIRMATION SHAPE\nPer row: the surface's confirmation (column D). Per run: `run-summary.json` {rows, ran, not_run, failed_transport, http_2xx, http_4xx, http_5xx, wrote_cells}.\n\n## RAW RETURN SHAPE\nColumn E per row; run log at /tmp/claude-501/contracts/run*.out (session) → move to `~/miscsubjects-pages/.runs/contracts/<ISO>.log` (gitignored) so the next session finds it.\n\n## ERROR SHAPES\n- Sheets PUT `too_many_cells` (>400) — chunk.\n- Apps Script bounce (HTML page instead of JSON, >~100 KB POST) — Google projection only; chunk to <80 KB.\n- DNS ENOTFOUND on a stale host — row result, batch continues.\n- AdsPower Local API unreachable from Google (local.adspower.net:50325 is LAN-only) — expected; the row says NOT RUNNABLE FROM GOOGLE; the build runner on the Mac runs it.\n- Cell > 50,000 chars refused by Google — projection cut; canonical keeps whole.\n\n## RECEIPT / TRACE / PARENT LINKAGE\nColumn F per row; run-summary.json per run; a CONTRACTS_RUN dispatch receipt per triggered run.\n\n## TEST MATRIX\n| case | what runs | kind |\n|---|---|---|\n| project | contracts-project.mjs regenerates rows 2..N from canonical and diff = 0 cells against the current sheet for rows already proven | live |\n| RUN one | edit C of one row to `RUN <invocation>` → CONTRACTS_RUN → D:F filled within 2 min | live |\n| DNS isolate | fixture host nonexistent.invalid → that row FAILED (transport), next row ran | fixture |\n| big cell | a 60,000-char return → E cut with receipt pointer; ledger whole | fixture |\n| throttle | simulate 3 write failures → results file complete, sheet catches up | fixture |\n| google copy | Contracts.gs contracts_run on 5 rows still works and its header says projection | live |\n\n## ACCEPTANCE TESTS (mechanical; the infrastructure runs them)\n- `{\"type\": \"evidence_present\", \"id\": \"commit\", \"field\": \"commit\"}`\n- `{\"type\": \"evidence_present\", \"id\": \"live\", \"field\": \"verification\"}`\n- `{\"type\": \"evidence_present\", \"id\": \"summary\", \"field\": \"run_summary\"}`\n- `{\"type\": \"contains\", \"id\": \"header\", \"url\": \"https://ops.miscsubjects.com/api/sheets/sh_nyab2cgy?range=A1:F1&share=public\", \"needle\": \"PROOF / RECEIPT\"}`\nEvidence fields the submitting agent supplies: commit, run_summary, verification. `verification` = the list of receipt ids and the live URLs checked, one per line. `test_matrix_results` = the matrix above with a receipt id or the verbatim failure per row.\n\n## KNOWN FAILURES / REGRESSION FIXTURES (preserve; never rewrite into success)\n- google_sync_off on unrelated routes (fixed by switchOnFresh; keep the test)\n- stale hosts\n- DNS failure stopping a batch\n- >50,000-char cell\n- AdsPower unreachable from GAS\n- Apps Script >100 KB bounce\n- zsh `set -- $spec` no word-split (runner launched with empty --from)\n- write timeout stall (90 s)\n- transport 2xx ≠ success\n\n## DEPENDENCIES\n- depends_on: WT-0470\n- OWNS (only this task rewrites): scripts/contracts-*.mjs; scripts/contracts-project.mjs (new); scripts/contracts-fixtures.test.mjs (new); apps-script/Contracts.gs; CONTRACTS_RUN row; sheets sh_nyab2cgy and sh_ahznwfyd\n- SHARED (additive edits only): functions/api/sheets (call only); functions/_lib/invocation_methods.js (read only; WT-0472)\n\n## HANDOFF FOR NEXT SESSION\n- Do not reset the sheet. Regenerate rows from canonical only after WT-0470 schema exists; until then the runner keeps writing D:F as today.\n- The `contains` acceptance uses `share=public` — if the sheets door has no public share for the header, mint a rows: share for sh_nyab2cgy read (WT-0487 owns the token law; a read-only share of one range is allowed).\n- Keep counts in run_summary evidence: rows examined, ran, not run, failed.\n\n## DONE LAW (this task is done when every line is true and evidenced; not before)\n- The sheet is regenerable from canonical (evidence: diff count).\n- RUN from a cell works end to end (evidence: receipt).\n- Fixture suite passes and is wired as a deploy gate `scripts/check-contracts-fixtures.mjs`.\n- The Google copy is labelled a projection and still runs.\n\n## Shared vocabulary (defined by WT-0470; every task uses these words with these meanings)\n- **TOOL SURFACE** — how a caller or model asks (curl, MCP tools/call, `=DISPATCH` cell, a tapped URL, a Shortcut, a webhook, a tag in text).\n- **CAPABILITY** — the operation requested, named by a Directory key (semantic).\n- **OBJECT** — what it acts on (a chat, a file, a profile, a row, a page).\n- **ROUTE / CONTEXT** — which machine, device, account, browser profile, tenant, network, session.\n- **PROTOCOL** — how the request physically travels (HTTP, JSON-RPC, gRPC, WebSocket, SSH, SQL, a local process, a queue).\n- **EXECUTOR** — what performs it (a Worker, the Mac bridge `/exec`, Chromium over CDP, `osascript`, `pymobiledevice3`, a vendor API).\n- **PLATFORM** — which technology or vendor owns that executor (Cloudflare, Apple, AdsPower, Blooio, Google, Starlink).\n- **RAW CONTRACT** — the exact physical invocation sent, fully resolved.\n- **CONFIRMATION** — the executor's immediate acknowledgement (HTTP status + headers, spawn/exit metadata, JSON-RPC ack, WebSocket ack, queue receipt).\n- **RETURN** — the final result, verbatim, including failure payloads.\n- **RECEIPT** — evidence and provenance: receipt id/URL, trace id, execution id, timestamps, parent linkage.\n\n## Definition of proof (PROOF_LAW, governing invariant; read it: GET https://ops.miscsubjects.com/api/work → governing_invariants)\nA capability is proven only when the DECLARED invocation surface itself ran and the five fields exist for that run: CAUSE (why it ran: user request / task / parent invocation / event / webhook / model call), RAW INVOCATION (the fully resolved physical contract actually sent), RAW CONFIRMATION (the executor's acknowledgement), RAW RETURN (the actual output, failures verbatim), PROOF / RECEIPT (receipt id/URL, trace, execution id, timestamps, parent linkage sufficient to inspect or replay).\nAn HTTP 200 proves an HTTP 200. A webhook acknowledgement proves receipt. Hidden bash proves bash. A sibling implementation, documentation, a model doing it elsewhere, or the dispatcher working while the surface under test never ran prove nothing about that surface. A missing field is a missing implementation requirement, never something to invent. Existing failures stay as evidence and become regression fixtures; they are never rewritten into success.\n\n## Six-column projection (unchanged; not the source of truth)\n`TOOL NAME | ONTOLOGY | RAW INVOCATION | RAW CONFIRMATION | RAW RETURN | PROOF / RECEIPT` — the build workbook sheet `sh_nyab2cgy` (vault `CONTRACTS_WORKBOOK_SHEET`, 11,035 rows on 2026-09-23). No seventh column, no contract-type column, no prose in place of an executable invocation. Extra metadata belongs in the canonical capability / task / receipt objects.\n\n## Parallelism law\nOther tasks run at the same time in other sessions. Own only the files and objects named under OWNS; touch a shared file only as named under SHARED (additive, never a rewrite). If this task finds the global law insufficient, it files an amendment: `POST /api/work/task/<this id>/fail` naming failure_class `law_insufficient`, layer `WT-0470`, and the missing invariant — it never creates a second standard. Ask the build, never the owner: keys are in `~/.build-vault.env` (`grep '^NAME=' ~/.build-vault.env`; `CLOUDFLARE_API_TOKEN=$CF_API_TOKEN` is a shell reference, resolve `$NAME`). The owner key travels as header `x-terminal-key`. Deploy only with `node scripts/land.mjs \"<WT id> what changed\"` from `~/miscsubjects-pages`. Submit evidence: `POST https://ops.miscsubjects.com/api/work/task/<id>/submit {agent, evidence:{commit, verification, …}, changed:[…]}` with header `x-terminal-key`.\n\n## Shared canonical objects and files — never independently rewritten (additive edits only, named per task)\n- `functions/api/dispatch.js` (the one door; runHttp/runFn/tenant delegation) — owner WT-0471.\n- `functions/_lib/invocation_methods.js`, `functions/_lib/grammar.js`, `functions/_lib/projection_manifest.js`, `functions/api/tools/[[path]].js`, `functions/api/mcp.js`, `functions/_lib/mcp_inspect.js` — owner WT-0472 (spellings and model projections).\n- `functions/_lib/event_log.js`, `functions/_lib/wire_log.js`, `functions/_lib/lean_receipt.js`, `functions/_lib/invocation_record.js`, the `events` table and R2 `logs/` — owner WT-0485 (ledger).\n- `functions/_lib/admin_session.js` (tokens, capabilities, tenants), `functions/_lib/tenant_devices.js`, `functions/api/onboard/[[path]].js` — owner WT-0487 (authority) / WT-0488 (onboarding).\n- `functions/_lib/mac_bridge.js`, `bridge/server.js`, `bridge/device_auth.js`, `bridge/surface-run.py`, `bridge/surface-verbs.py`, `bridge/bridge-run.py`, `bridge/bridge-browser.mjs`, `public/device-kit/*` (synced copies) — owners WT-0474 / WT-0475 / WT-0478.\n- `functions/_lib/work_object.js`, `functions/api/work/[[path]].js`, the `laws` and `work_tasks` tables — owner WT-0470 (law rows) and the build (task engine).\n- `scripts/contracts-*.mjs`, `apps-script/Contracts.gs`, the `CONTRACTS_RUN` directory row, sheet `sh_nyab2cgy` — owner WT-0473.\n- `scripts/ship.mjs`, `scripts/land.mjs`, `scripts/write.mjs`, `scripts/check-*.mjs`, `.githooks/*` — governed; add a gate only by adding a new `scripts/check-<name>.mjs` and wiring it as the existing gates are wired.\n",
    "state": "open",
    "priority": 2,
    "revision": 1,
    "depends_on": [
      "WT-0470"
    ],
    "permitted_capabilities": [
      "dispatch",
      "d1",
      "bridge",
      "sheets",
      "receipts"
    ],
    "acceptance_tests": [
      {
        "type": "evidence_present",
        "id": "commit",
        "field": "commit"
      },
      {
        "type": "evidence_present",
        "id": "live",
        "field": "verification"
      },
      {
        "type": "evidence_present",
        "id": "summary",
        "field": "run_summary"
      },
      {
        "type": "contains",
        "id": "header",
        "url": "https://ops.miscsubjects.com/api/sheets/sh_nyab2cgy?range=A1:F1&share=public",
        "needle": "PROOF / RECEIPT"
      }
    ],
    "required_evidence": [
      "commit",
      "run_summary",
      "verification"
    ],
    "parent_task": null,
    "supersedes": null,
    "failure": null,
    "failure_count": 0,
    "last_result": null,
    "completed_at": null,
    "created_at": "2026-09-22T19:51:50-07:00",
    "updated_at": "2026-09-22T19:51:50-07:00",
    "audit": "/api/work/task/WT-0473/audit",
    "submit_to": "/api/work/task/WT-0473/submit"
  }
}