{"_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."},"_self":{"principle":"Self-explaining payload — no external context required. This _self block describes what you are reading and where to look next.","widget":"article_topology","feature":"topology","name":"Article topology","what":"Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER.","contains":"claims, sources, anecdotes, question_graph slice","slug":"gas-sheets-build-sync","urls":{"read":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/topology"},"how_to_use":"Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER.","write":null,"imessage":null,"router_tag":null,"proof_chain":[{"step":1,"claim":"Articles are voxel graphs of tiered claims, not prose blobs.","verify":"https://miscsubjects.com/api/articles/constitution"},{"step":2,"claim":"Claims link to hash-chained sources via source_ids.","verify":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/sources"},{"step":3,"claim":"Ask reads topology; ingest/claim append to ledger.","verify":"https://miscsubjects.com/api/protocol"},{"step":4,"claim":"Models queue growth: populate → collaborate → repair → reflex.","verify":"https://miscsubjects.com/api/protocol/grow"},{"step":5,"claim":"Graph proves its own shape (reflex) and $/claim (yield).","verify":"https://miscsubjects.com/graph.html?layer=reflex"},{"step":6,"claim":"Full feature index + _explain on every API response.","verify":"https://miscsubjects.com/api/articles/system-map"}],"related_features":[{"id":"ask","name":"Ask protocol","what":"Answer only from topology; creates question_node with gaps and ingest_hint.","urls":{"read":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/prompts","write":"https://miscsubjects.com/api/protocol/ask"}},{"id":"graph_topology","name":"Cross-article graph","what":"Merged claims/sources across condition+stack slugs for one question.","urls":{"read":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/graph-topology?question=..."}},{"id":"question_graph","name":"Question graph","what":"Ask nodes (questions + gaps) and evidence_ingest nodes (pasted model output).","urls":{"read":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/question-graph","write":"https://miscsubjects.com/api/protocol/ask"}},{"id":"voxels","name":"Voxel graph","what":"Claims as atoms, sources as edges (supported_by, posted_by). Per-claim provenance.","urls":{"read":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/voxels","write":"https://miscsubjects.com/api/protocol/claim"}}],"system_map":"https://miscsubjects.com/api/articles/system-map","system_map_markdown":"https://miscsubjects.com/api/articles/system-map?format=markdown","not_medical_advice":true},"_explain":{"feature":"topology","name":"Article topology","what":"Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER.","why":"Every feature is auditable collective intelligence","how":"Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER.","model":null,"verifies":null,"urls":{"read":"https://miscsubjects.com/api/articles/gas-sheets-build-sync/topology"},"imessage":null,"router":null,"related":[{"id":"ask","what":"Answer only from topology; creates question_node with gaps and ingest_hint."},{"id":"graph_topology","what":"Merged claims/sources across condition+stack slugs for one question."},{"id":"question_graph","what":"Ask nodes (questions + gaps) and evidence_ingest nodes (pasted model output)."},{"id":"voxels","what":"Claims as atoms, sources as edges (supported_by, posted_by). Per-claim provenance."}],"not_medical_advice":true},"slug":"gas-sheets-build-sync","title":"How a Google Sheets edit reaches the live site with a receipt","register":"standard","tags":["gas","google-sheets","apps-script","sync","control-surface","proof-object"],"updated_at":"2026-08-02T02:57:16.620Z","body_excerpt":"A spreadsheet is not usually a control surface. It is where the output of a system goes to be looked at after the system has finished with it — a report, a dump, a thing you read. The sync described here is the opposite arrangement: the spreadsheet is an editable projection of the build. D1 remains authoritative; the sheet is a surface you can edit through, not a second copy the site renders from. This article documents that path completely enough that a model with no prior context can operate the entire build from Google Sheets, and it is itself a test of the claim, because this article was written, published, pulled into the sheet, edited in the sheet, and saved back from the sheet. If the path did not work, this page would not exist in the form you are reading.\n\n## The shape of the thing\n\nThere are three components and one credential.\n\n**The build** is `miscsubjects.com`, a Cloudflare Pages project. Every capability it has — every article, agent, prompt, outbound HTTP call, and flow — is a row in a D1 table called `directory`. One row is one invocable object, addressed by its `key`. There are 936 of them. Articles are a second table with a JSON `meta` column carrying everything that is not the body.\n\n**The bridge** is a Google Apps Script project bound to one spreadsheet, deployed as a web app. Script ID `1vkecGofPlp9d-QT84hexGMui5yjB5MafH-eBg3j0l7Gt8VweONRWV2R9`. It holds the terminal key in a Script Property and never in code.\n\n**The sheet** is \"Lead Outbox + Model Prompt Lab\". Each tab is a live projection of a table in the build, and each row carries a `DO` column that behaves as a button.\n\nThe credential is one 64-character terminal key, sent as `x-terminal-key`. It authorizes every `/api/*` route. There is no second credential, no OAuth dance, no per-service account.\n\n## How a row acts as a button\n\nThe mechanism is deliberately dumb, which is why it holds. An installable `onChange` trigger fires on the change itself and calls `boardTick()`; a one-minute time-driven trigger runs the same function underneath as a backstop.\n\nThe distinction matters and is easy to get wrong. Google documents two different things. A **time-driven** trigger is scheduled, and its timing is explicitly approximate — a recurring 9 AM trigger runs somewhere between 9 and 10. An **installable event trigger** (`onChange`, `onEdit`, `onOpen`, `onFormSubmit`) is not scheduled at all; it fires from the event. `onChange` is the one used here, and because it is installable rather than the simple `onChange(e)` function, it runs with full authorisation and may call `UrlFetchApp`. Describing this surface as having a one-minute floor, as an earlier version of this article did, was simply wrong: the floor belongs to the backstop, not to the mechanism.\n\nOne real caveat, since it bit the attempt to measure it: triggers fire on changes made by a person in the interface, not on changes an Apps Script makes to its own spreadsheet. A write through the API does not fire `onChange`. The latency claim here rests on Google's documented trigger semantics, not on a stopwatch — and saying so is cheaper than pretending otherwise. That function walks each tab looking for rows whose `DO` cell contains an imperative — `SAVE`, `PULL`, `RUN`, `APPROVE`, `REJECT`, `EXPLAIN`. For each one it performs the corresponding API call, writes the outcome into the `result` cell of the same row, and sets `DO` to `done`.\n\nNothing is queued. Nothing is held in memory between runs. The sheet *is* the state. If the trigger dies, the flagged rows simply sit there until it runs again, and the semantics do not change.\n\nOverlap is the honest weak point, and an earlier version of this article got it wrong. Two runs can both read a row as `RUN` before either writes `done`, because reading the flag and clearing it are not one atomic operation. Duplicate execution is therefore possible. Apps Script serialises a single trigger's executions, which makes it rare in practice, but rare is not prevented —","ranking":"safety-first (interaction_risk/limitations), then quote-gated effective_weight","claims":[{"id":"gs-c1","text":"A write from the spreadsheet answers the live writing-law challenge and receives a short-lived write token before any article write, with no bypass for the internal path.","tier":"runtime","section":"The gate","interaction_risk":false,"status":"active","source_ids":["gs-s1"],"why_material":"If the internal surface had a bypass, the law would only govern callers already inclined to obey it.","retracted_at":null,"retraction_reason":null,"challenged_by":[],"effective_weight":0.1,"quote_gated":false},{"id":"gs-c2","text":"Every capability of the build is a row in a D1 table called directory, addressed by key and run through POST /api/dispatch.","tier":"runtime","section":"The shape of the thing","interaction_risk":false,"status":"active","source_ids":["gs-s2"],"why_material":"It is why one bridge can operate the whole build rather than a fixed subset of features.","retracted_at":null,"retraction_reason":null,"challenged_by":[],"effective_weight":0.1,"quote_gated":false},{"id":"gs-c3","text":"An article is a body plus widgets, a hash-chained source ledger, atomized claims, tags, style, hero, images, category, register and status; a sync carrying only the body cannot insert a widget or add a source.","tier":"runtime","section":"The articles tab","interaction_risk":false,"status":"active","source_ids":["gs-s3"],"why_material":"It is the reason the tab carries every field as its own column instead of one editable body cell.","retracted_at":null,"retraction_reason":null,"challenged_by":[],"effective_weight":0.1,"quote_gated":false},{"id":"gs-c4","text":"Model ids advertised with grok:, openai:, gemini: and kimi: prefixes are dispatched to Workers AI, which does not have them, and return \"No such model\".","tier":"runtime","section":"The limits","interaction_risk":false,"status":"active","source_ids":["gs-s4"],"why_material":"A live defect in the model lane, stated rather than omitted.","retracted_at":null,"retraction_reason":null,"challenged_by":[],"effective_weight":0.1,"quote_gated":false},{"id":"gs-c5","text":"All 916 enabled directory rows are reachable from the DISPATCH tab; ten were dispatched from cells for this article and nine returned, with the failure (AIG_LIST, Cloudflare error 7003 on a moved gateway route) published alongside them.","tier":"runtime","section":"Ten directory rows, dispatched from cells","interaction_risk":false,"status":"active","source_ids":["gs-s2"],"why_material":"It is the difference between a sync that reads content and a control surface that can invoke the whole build.","retracted_at":null,"retraction_reason":null,"challenged_by":[],"effective_weight":0.1,"quote_gated":false},{"id":"gs-c6","text":"The bridge holds no database binding and no privileged route; it uses the same terminal key and the same public API as any other caller, so deleting the Apps Script project leaves the build unchanged.","tier":"runtime","section":"The questions a sceptic asks first","interaction_risk":false,"status":"active","source_ids":["gs-s1","gs-s2"],"why_material":"A sync layer with direct table access would create a second truth with no law attached to it.","retracted_at":null,"retraction_reason":null,"challenged_by":[],"effective_weight":0.1,"quote_gated":false}],"sources":[{"id":"gs-s1","type":"protocol","url":"https://miscsubjects.com/api/write-gate/challenge","title":"Write gate challenge and answer","quote":"write gate refused","summary":"Issues clauses from the live writing law plus questions whose answers exist only in that text; exchanges correct answers for a short-lived write token.","claim_ids":["gs-c1"],"hash":"04d4f18131a6f695218e830c93a10f5a9ba32ae1c6957ee8a26ac900395fab3a"},{"id":"gs-s2","type":"protocol","url":"https://miscsubjects.com/api/map","title":"Build ontology map","quote":"Whole-build ontology. Every capability is REST.","summary":"Self-describing map of the build: feeds, directory schema, route groups, bindings and row counts.","claim_ids":["gs-c2"],"hash":"f660a1a25cd9892a12bd3b637d0454ed31cd0aca20c2c17eec5a25c43477f48b"},{"id":"gs-s3","type":"protocol","url":"https://miscsubjects.com/api/articles/oip","title":"Article JSON representation","quote":"widgets, claims, sources, reviews, extra","summary":"The full field set of an article object: body, widgets, sources, claims, tags, style, hero, images, category, register, status.","claim_ids":["gs-c3"],"hash":"8c444259460df1435fcee58fd4a935a14e90d738f12dcbc3de943a63539ee11a"},{"id":"gs-s4","type":"protocol","url":"https://miscsubjects.com/api/models","title":"Model inventory","quote":"No such model","summary":"The advertised model ids, including prefixed ids the invoke lane cannot currently reach.","claim_ids":["gs-c4"],"hash":"abb4765563af1683a4e220d0042a2f90a52b39a1f88a8e8c088798b74bd4447c"}],"anecdotal_sources":[],"scientific_sources":[],"user_reports":[],"related_articles":[],"question_graph":{"slug":"gas-sheets-build-sync","questions":[],"evidence":[],"edges":[],"counts":{"questions":0,"evidence":0,"edges":0}},"honesty":{"active_claims":6,"retracted_claims":0,"cut_claims":0,"challenges":0,"scrub_events":0,"note":"Retracted/cut claims stay on ledger but are excluded from ask unless ?include_inactive=1"},"counts":{"claims":6,"claims_total":6,"sources":4,"anecdotal":0,"scientific":0,"user_reports":0,"questions":0,"evidence_ingests":0}}