Skip to content

Forge Doctrine: Variable and Data-State Convention

URL: https://mkdocs.justinsforge.com/FORGE-DOCTRINE-VARIABLES/

Companion to FORGE-DOCTRINE.md Section 4. Defines the canonical variable naming convention, the data-state tags, the source-tag registry, and the process for adding new tags.


Convention

Variables, function parameters, type aliases, TypedDicts, and config keys follow snake_case [source]_[entity]_[state] reading left to right from broad to specific.

Three data-state tags (Section 4 of doctrine):

Tag When Example identifier Example value
raw_ Data exactly as it leaves a third party. Untouched, including provider-side wrapping, pagination cursors, request metadata. raw_notion_search_response {"object": "list", "results": [...], "next_cursor": "abc"}
parsed_ or clean_ Internal, normalized form. Provider noise stripped, types coerced, ready for forge logic to operate on. clean_task_array [{"id": "...", "title": "...", "due": "..."}]
payload_ Outbound, formatted for a specific external endpoint. Serialized to that endpoint's schema. payload_n8n_webhook {"workflow_id": "abc", "input": {...}}

Forge-internal data with no external source drops the source tag and uses clean_<entity> as default.


Source Tag Registry

Source tags are extensible. The list below is the starting set; add new tags via the process documented in the next section. Eval harness check forge_eval_check_variable_tags.sh validates the registry.

Tag Service Notes
notion Notion API Life OS + JWVR databases
gmail Gmail API personal + business accounts
gcal Google Calendar API event + calendar surfaces
gdrive Google Drive API file + folder operations
telegram Telegram Bot API inbox capture, lifeos coordinator, notify-out
garmin Garmin Connect HRV, sleep, body battery
eight_sleep Eight Sleep bed sensor data; native HA integration is canonical, this tag is legacy
ha Home Assistant smart home state, sensors, automations
frigate Frigate NVR camera events, recordings
n8n n8n workflow engine workflow trigger payloads
cf Cloudflare API DNS, tunnels, Access
proxmox Proxmox VE VM and LXC management

Adding a New Source Tag

When wiring a new integration:

  1. Propose the tag in your branch's PR description or commit message.
  2. Add the tag to this file's registry table with the canonical service name and any notes.
  3. Add it to forge/eval.json so the eval harness validates the tag pattern.
  4. Auto-dream's nightly pass detects <source>_<entity>_<state> patterns in code that don't match the registry; those land in LESSONS.md as candidate additions for human review.

Naming rules

  • Lowercase, snake_case, max 12 characters
  • Prefer the integration's canonical short name (notion not notion_api, garmin not garmin_connect)
  • Never abbreviate further than the source's own brand short form (ha is fine because Home Assistant uses it; tg for Telegram is not, use telegram)
  • If two integrations share a domain (Gmail and Calendar both Google), keep them split by service not unified by provider

Anti-patterns

  • Inventing tags inline without registering: mystery_service_response = ... will fail the eval check
  • Reusing a tag for the wrong service: do not reuse gmail for "any-mail" data; that loses semantic precision
  • Using the source tag when the data is purely internal: clean_dedup_table is correct, forge_dedup_table is not (the source slot is empty for internal data)

Examples per Data State

Raw

raw_notion_search = notion_client.search(query=q)
raw_garmin_hrv_response = httpx.get(garmin_url, headers=h).json()
raw_telegram_webhook = request.json
raw_gmail_thread = gmail_service.users().threads().get(userId="me", id=thread_id).execute()

Clean / Parsed

clean_task_array = [_normalize_task(t) for t in raw_notion_search["results"]]
clean_garmin_hrv = parse_hrv_payload(raw_garmin_hrv_response)
clean_telegram_message = TelegramMessage.from_webhook(raw_telegram_webhook)
clean_gmail_message_array = [_flatten(m) for m in raw_gmail_thread["messages"]]
clean_dedup_table = build_dedup_table(seen_ids)

Payload

payload_n8n_workflow_trigger = {"workflow_id": "abc", "input": clean_task_array}
payload_notion_page_create = {"parent": {"database_id": db_id}, "properties": props}
payload_telegram_message = {"chat_id": chat, "text": body, "parse_mode": "MarkdownV2"}
payload_gcal_event_insert = {"summary": title, "start": {"dateTime": iso}, "end": {...}}

Edge Cases

Multi-stage pipelines. Each stage gets its own variable with the appropriate tag. Never reuse a name across states.

raw_garmin_response = httpx.get(...).json()
clean_garmin_hrv = parse_hrv(raw_garmin_response)
payload_notion_wellness = build_wellness_page(clean_garmin_hrv)

Lists vs scalars. Plural entity for lists (clean_task_array), singular for scalars (clean_task). Tag stays singular; the array suffix carries the multiplicity.

Function parameters. Same convention.

def push_task_to_notion(payload_notion_page_create: dict) -> str:
    ...

Type aliases / TypedDicts. Name them after the canonical state.

class CleanTaskArray(TypedDict):
    tasks: list[CleanTask]

PayloadN8nTrigger = dict[str, Any]

Locally-cached external data. When data round-trips through a local cache, the cache stores the clean_ form (provider noise already stripped) under the clean_ name.

clean_notion_task_cache = sqlite.connect("data/notion_tasks.db")

Enforcement Schedule

  • All new code from Phase 2 onward: mandatory.
  • Refactored code: rename when you touch the function. Do not refactor existing code purely to apply the convention; doctrine forbids autonomous restructuring without first-principles understanding (Section 2).
  • Audit targets (one targeted refactor pass per file in Phase 4.3 alongside the bulk flat-file rename): forge_telegram_inbox_brain.py, forge_telegram_lifeos_coordinator_brain.py, forge_dispatcher.sh, forge_notify.sh, all n8n payload constructors.
  • Eval harness check (Phase 4.5): forge_eval_check_variable_tags.sh greps Python and shell for <word>_<word>_<word> triples that look like the convention but use unregistered source tags. Findings logged to LESSONS.md as candidates for either rename or registry-add.