DEV Community

Casey Sun
Casey Sun

Posted on

Uncited Runtime Does Not Belong on a Free Host

Scene: a staging bot opens a pull request at 09:12. The plan JSON names a working directory and a retry ceiling. None of those keys live in the repository.

The model wrote them because the prompt stayed quiet. The job still looked cheap to the reviewer. The reviewer almost scheduled it on a shared free host.

Cheap inference hides expensive assumptions inside ordinary plan files. Silent fields become invented runtime on the next host. A free host then executes those guesses next to other tenants.

This field guide lists when that path should fail. It also lists better homes for the same work.

Uncited runtime, in plain terms

Uncited runtime is a concrete value the agent emitted. No repo file supplied that value. No secret store and no checklist approved it.

The value often looks boring in review. Boring values still steer process, disk, and network. Shared hosts then amplify a quiet guess.

Common inventions that pass a weak schema

  • /tmp/agent-work as a working directory
  • UTC as a timezone nobody pinned
  • retries: 30 with no budget owner
  • localhost:6379 as a cache the app lacks
  • chmod 777 on a scratch path
  • curl to an undocumented health URL

Each line can satisfy a loose JSON schema. Each line can still be false. False runtime on a free host travels farther than a laptop scratch folder.

Where free model access fits this gate

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

MonkeyCode offers free model access and a free server option. Those two availability facts matter for scheduling. They do not weaken the allowlist.

Cheap planning invites another pass over silent fields. A free server invites another retry of the same guess. Silence starts to look like consent.

The checks below still stand if that product is absent. Any team with a plan file can run them. The product is only one place the brake can sit.

Red flags before the job is scheduled

Refuse the free host when any flag below is true.

  1. The plan fills paths the repository never named.
  2. The plan sets locale, timezone, or umask without a manifest.
  3. The plan invents hostnames, ports, or health URLs.
  4. The plan sets retries above the checked-in budget file.
  5. The plan requests egress the network allowlist omits.
  6. The plan writes credentials into argv, env, or log format.
  7. The plan claims a container user the image never defined.
  8. The job class is incident, prod-adjacent, or secret-adjacent.

One flag is enough to stop the schedule. Two flags mean the plan is fiction.

Decision table

Job class Uncited runtime present Allowed on free host Better home
Docs lint No Yes Free host or laptop
Unit tests with fixtures No Yes CI runner with cache
Agent plan with filled paths Yes No Local fixture VM
Secret rotation dry run Either No Isolated paid runner
Incident replay Either No Locked debug box
Load probe with egress Either No Named staging cluster
Eval of recorded traces No, traces redacted Maybe Ephemeral runner

Maybe still needs a human owner. The table is a brake, not a waiver.

Artifact: an assumption gate for plan files

The gate reads a plan file and an allowlist. It fails CI when the plan cites nothing. Treat the code as an unexecuted example. Teams must adapt paths and policy.

Allowlist file

# agent-runtime.allow.yaml
working_directory:
  - "."
  - "./tmp/ci"
timezone:
  - "UTC"
max_retries: 3
allowed_hosts:
  - "api.internal.example"
forbidden_keys:
  - "password"
  - "api_key"
  - "token"
  - "secret"
job_classes_blocked_on_free_host:
  - "incident"
  - "secret-adjacent"
  - "prod-replay"
Enter fullscreen mode Exit fullscreen mode

Plan file the agent must emit

{
  "job_class": "docs-lint",
  "working_directory": "./tmp/ci",
  "timezone": "UTC",
  "retries": 2,
  "egress_hosts": [],
  "env": {},
  "argv": ["python", "-m", "ruff", "check", "."]
}
Enter fullscreen mode Exit fullscreen mode

Gate script

#!/usr/bin/env python3
"""Fail CI when an agent plan emits uncited runtime."""

from __future__ import annotations

import json
import sys
from pathlib import Path

import yaml  # install pyyaml in CI; do not assume a global copy

FALLBACK_NEEDLES = ("password", "api_key", "token", "secret")


def load_yaml(path: Path) -> dict:
    with path.open("r", encoding="utf-8") as handle:
        data = yaml.safe_load(handle)
    if not isinstance(data, dict):
        raise ValueError(f"allowlist must be a mapping: {path}")
    return data


def flatten_strings(value: object) -> list[str]:
    if value is None:
        return []
    if isinstance(value, str):
        return [value]
    if isinstance(value, (int, float, bool)):
        return [str(value)]
    if isinstance(value, list):
        out: list[str] = []
        for item in value:
            out.extend(flatten_strings(item))
        return out
    if isinstance(value, dict):
        out: list[str] = []
        for key, item in value.items():
            out.append(str(key))
            out.extend(flatten_strings(item))
        return out
    return [str(value)]


def main(plan_path: str, allow_path: str) -> int:
    plan = json.loads(Path(plan_path).read_text(encoding="utf-8"))
    allow = load_yaml(Path(allow_path))
    failures: list[str] = []

    job_class = plan.get("job_class")
    blocked = set(allow.get("job_classes_blocked_on_free_host", []))
    if job_class in blocked:
        failures.append(f"job_class {job_class} is banned on the free host")

    cwd = plan.get("working_directory")
    if cwd not in allow.get("working_directory", []):
        failures.append(f"working_directory uncited or denied: {cwd}")

    tz = plan.get("timezone")
    if tz not in allow.get("timezone", []):
        failures.append(f"timezone uncited or denied: {tz}")

    retries = plan.get("retries", 0)
    max_retries = allow.get("max_retries", 0)
    if retries > max_retries:
        failures.append(f"retries {retries} exceed budget {max_retries}")

    allowed_hosts = set(allow.get("allowed_hosts", []))
    for host in plan.get("egress_hosts", []):
        if host not in allowed_hosts:
            failures.append(f"egress host uncited or denied: {host}")

    blob = " ".join(flatten_strings(plan)).lower()
    needles = allow.get("forbidden_keys", FALLBACK_NEEDLES)
    for needle in needles:
        if str(needle).lower() in blob:
            failures.append(f"secret-adjacent key leaked into plan: {needle}")

    required = ("job_class", "working_directory", "timezone", "retries")
    for key in required:
        if key not in plan:
            failures.append(f"missing required key {key}; refuse inferred fill")

    if failures:
        print("assumption gate failed:")
        for item in failures:
            print(f"- {item}")
        return 1

    print("assumption gate passed")
    return 0


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("usage: assumption_gate.py PLAN.json ALLOW.yaml", file=sys.stderr)
        raise SystemExit(2)
    raise SystemExit(main(sys.argv[1], sys.argv[2]))
Enter fullscreen mode Exit fullscreen mode

CI step

# .github/workflows/agent-assumption-gate.yml
name: agent-assumption-gate
on:
  pull_request:
    paths:
      - "agent/plans/**"
      - "agent-runtime.allow.yaml"
jobs:
  gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install pyyaml
      - run: python tools/assumption_gate.py agent/plans/current.json agent-runtime.allow.yaml
Enter fullscreen mode Exit fullscreen mode

Run the same command on a laptop before review.

python tools/assumption_gate.py agent/plans/current.json agent-runtime.allow.yaml
echo $?
Enter fullscreen mode Exit fullscreen mode

A non-zero exit is the entire control. The free host never receives the plan.

Better alternatives when the gate fails

Move the work. Do not loosen the allowlist in a hurry.

  • Replay the plan on a laptop with recorded fixtures.
  • Use an ephemeral CI runner that dies with the job.
  • Pin timezone and paths in a checked-in manifest.
  • Strip egress and rerun as a pure file function.
  • Hand the incident box to a human operator.

Free model access can still draft the next plan. The execution host stays on a different side of the brake. That split is the actual control.

Exit criteria

Leave the free host, and stay off it, when any line holds.

  • The plan needed a default the allowlist does not name.
  • Prior logs showed inferred paths or inferred hosts.
  • Retries grew without a budget change in git.
  • The job class moved into incident or secret-adjacent work.
  • A reviewer cannot point to the file behind each value.

Return only after every runtime field has a cited source. A citation is a repo path, a secret name, or a ticket. Model habit is not a source.

Who should not use this approach

Skip this gate in a few honest cases.

  • Throwaway scripts with no network and no secrets.
  • Workshops that run on paper plans, not hosts.
  • Teams with no plan file and no will to add one.
  • Workloads already locked in a single-tenant box.

The gate adds friction on purpose. Friction is wasted when the blast radius is a scratch folder.

Limitations

The script does not prove the plan is correct. It only proves the plan stayed inside a list. Homographs can still sneak through an allowlist. A host alias can match and still be wrong.

YAML comments are not policy. The CI example does not pin action SHAs. Teams should pin those SHAs before relying on the workflow.

This article does not claim quotas, model names, hardware, or uptime. Those figures go stale fast. Operators should read current product docs at publish time.

Closing

Uncited runtime is not a style issue. It is unreviewed process, disk, and network. A free host multiplies that guess.

The cheap path is the one that should fail first. Keep banned job classes on isolated compute after the gate fires.

Top comments (0)