{
  "handoffs": [
    {
      "id": "handoff-2026-07-01-subagentworkers",
      "schema_version": "0.1.0",
      "kind": "agent_handoff",
      "instance_id": "claude-sonnet-5",
      "created_at_field": "2026-07-01",
      "summary": "Remove the ANTHROPIC_API_KEY dependency from workers/subagentworkers, rebuild generation on Cloudflare Workers AI, dogfood both live Workers (subagentworkers.com + subagentdb.com) by converting two Claude Code blog posts' goal/loop methodology into real Cowork artifacts + scheduled tasks, research Managed Agents/Office Agents/Claude Tag docs relevance, and produce a type-safe session handoff for Fable 5.",
      "tasks": [
        {
          "id": "task-diagram-latency-optimization",
          "content": "Investigate reducing /api/diagram P50 latency (~84s from chaining 2 sequential Workers AI calls) in workers/subagentworkers",
          "priority": "low",
          "status": "pending",
          "kind": {
            "type": "todo"
          },
          "notes": "Not urgent -- inherent to the two-step explore+generate design on a reasoning model; would need a real architecture change (e.g. single-call redesign, or accepting the latency), not just a parameter tweak."
        },
        {
          "id": "task-ai-search-upgrade-path",
          "content": "Provision Cloudflare AI Search for workers/subagentworkers retrieval, replacing hand-rolled D1 FTS5",
          "priority": "low",
          "status": "pending",
          "kind": {
            "type": "todo"
          },
          "notes": "Documented in wrangler.toml/README as an upgrade path, not executed -- wrangler already has ai-search write/run scopes."
        },
        {
          "id": "task-claude-tag-docs-gap",
          "content": "Add Claude Tag docs to the local docs/ mirror, or confirm no local copy is intended",
          "priority": "low",
          "status": "pending",
          "kind": {
            "type": "todo"
          },
          "notes": "claude.com/docs/claude-tag/ is real and documented publicly but has zero files under docs/docs/ in this repo, unlike managed-agents and office-agents, which are fully mirrored."
        },
        {
          "id": "task-fable5-model-slug-confirm",
          "content": "Confirm Fable 5's real API model-string slug at platform.claude.com/docs before assuming a value in any code/config",
          "priority": "medium",
          "status": "pending",
          "kind": {
            "type": "todo"
          },
          "notes": "Not published in the redeploy announcement; sessions/handoff-2026-07-01.json flagged the same open question independently -- see meta.to_agent_note in both files."
        }
      ],
      "still_open_from_previous_handoffs": {
        "ref": "sessions/handoff-2026-06-30.json",
        "note": "None of that file's 8 tasks (task-refresh-lockfile, task-migration-006, task-migration-007, task-verify-bootstrap, task-first-crawl, task-index-docs, task-a2a-executor, task-repo-fmt-debt) were touched this session either -- all Rust/Postgres/docs-crawl work, unrelated to this session's TypeScript/Workers AI scope. sessions/handoff-2026-07-01.json records the identical finding independently; both converging on 'still pending, unrelated scope' is a useful cross-check, but re-verify status rather than trusting either note indefinitely."
      },
      "previous_handoff": "handoff-2026-06-30",
      "see_also": [
        {
          "path": "sessions/handoff-2026-07-01.json",
          "note": "A concurrent, separate session's structured handoff (same schema, also chained off sessions/handoff-2026-06-30.json) covering disjoint work: Ashby/OpenAI ingestion, a workers/etl rebuild, the new workers/subagentetl (subagentetl.com) Kimball dashboard, and a plugins/cwc-data plugin. No shared code paths with this file's scope (workers/subagentworkers + workers/subagentdb). It independently re-derived the Managed Agents / Office Agents / Claude Tag findings in this file's model_notes via live web fetch rather than this repo's local docs/ mirror -- the two converge on the same conclusions, which is a useful cross-check."
        },
        {
          "path": "HANDOFF.md",
          "note": "Repo-root redirect stub (kept at this path, not deleted, so the see_also reference above from sessions/handoff-2026-07-01.json stays valid). Originally a narrative Markdown handoff; superseded by this file per explicit user instruction ('Rewrite that handoff to be type safe')."
        }
      ],
      "source_site": "subagenthandoffs.com",
      "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"schema_version\": \"0.1.0\",\n  \"kind\": \"agent_handoff\",\n  \"previous_handoff\": \"sessions/handoff-2026-06-30.json\",\n  \"see_also\": [\n    {\n      \"path\": \"sessions/handoff-2026-07-01.json\",\n      \"note\": \"A concurrent, separate session's structured handoff (same schema, also chained off sessions/handoff-2026-06-30.json) covering disjoint work: Ashby/OpenAI ingestion, a workers/etl rebuild, the new workers/subagentetl (subagentetl.com) Kimball dashboard, and a plugins/cwc-data plugin. No shared code paths with this file's scope (workers/subagentworkers + workers/subagentdb). It independently re-derived the Managed Agents / Office Agents / Claude Tag findings in this file's model_notes via live web fetch rather than this repo's local docs/ mirror -- the two converge on the same conclusions, which is a useful cross-check.\"\n    },\n    {\n      \"path\": \"HANDOFF.md\",\n      \"note\": \"Repo-root redirect stub (kept at this path, not deleted, so the see_also reference above from sessions/handoff-2026-07-01.json stays valid). Originally a narrative Markdown handoff; superseded by this file per explicit user instruction ('Rewrite that handoff to be type safe').\"\n    }\n  ],\n  \"meta\": {\n    \"from_agent\": \"claude-sonnet-5\",\n    \"to_agent\": \"claude-fable-5\",\n    \"to_agent_note\": \"Fable 5 redeploys 2026-07-01 (today) per anthropic.com/news/redeploying-fable-5 -- independently confirmed real via web search this session (multiple sources), not just trusted from a user-supplied URL. Its exact API model-string slug was not published in that announcement -- confirm the real string at platform.claude.com/docs before assuming \\\"claude-fable-5\\\" is correct. sessions/handoff-2026-07-01.json's model_notes.fable_5 has a fuller writeup (usage-limit percentages, the auto-route-to-Opus-4.8-on-block behavior) from live fetch; this file's model_notes.fable_5 is a lighter independent confirmation -- read both.\",\n    \"repo\": \"opencoworkers/subagentjobs\",\n    \"default_branch\": \"main\",\n    \"created_at\": \"2026-07-01\",\n    \"session_goal\": \"Remove the ANTHROPIC_API_KEY dependency from workers/subagentworkers, rebuild generation on Cloudflare Workers AI, dogfood both live Workers (subagentworkers.com + subagentdb.com) by converting two Claude Code blog posts' goal/loop methodology into real Cowork artifacts + scheduled tasks, research Managed Agents/Office Agents/Claude Tag docs relevance, and produce a type-safe session handoff for Fable 5.\"\n  },\n  \"mission\": \"Everything under completed_this_session is LIVE in production and was verified end-to-end this session (not just type-checked/assumed) -- subagentworkers.com and subagentdb.com are both deployed and passing their full regression suites as of 2026-07-01. Read CLAUDE.md's Pending tasks + still_open_from_previous_handoffs below before starting new work -- none of that was touched this session. This file supersedes the narrative HANDOFF.md, which is now a stub pointing here.\",\n  \"completed_this_session\": {\n    \"api_key_removal\": {\n      \"summary\": \"Removed the ANTHROPIC_API_KEY dependency from workers/subagentworkers per explicit, hard user instruction: a claude.ai subscription does not cover separate Anthropic API billing, and no external paid API should ever be a dependency of this project. Rebuilt generation (prose Q&A + architecture-diagram tool) on Cloudflare Workers AI (`@cf/zai-org/glm-5.2`) via the native `env.AI.run()` binding -- zero external API keys, billed entirely inside the user's own Cloudflare account.\",\n      \"verified\": \"Confirmed no ANTHROPIC_API_KEY secret was ever actually configured on the deployed Worker; wrangler.toml and README.md rewritten to remove all Claude Sonnet 5 / Anthropic API references and document the pure-Workers-AI architecture, including a historical note about the brief detour/revert.\"\n    },\n    \"diagram_tool_calling_rebuild\": {\n      \"summary\": \"generateDiagram() in workers/subagentworkers/src/index.ts redesigned as a two-step explore-then-generate flow on glm-5.2: step 1 uses Workers AI 'Traditional' function/tool calling (tools array, tool_calls response field) to search the docs corpus; step 2 generates the SVG diagram + explanation + citations from the retrieved context.\",\n      \"bugfix\": \"Both generateDiagram() env.AI.run() calls (explore: max_tokens 800, generate: max_tokens 4096) were returning empty content. Root cause: glm-5.2's chat_template_kwargs.enable_thinking defaults to true (confirmed by reading the model's raw input JSON schema at developers.cloudflare.com/workers-ai/models/glm-5.2/sync-input.json, not assumed) -- reasoning tokens consume the same max_tokens budget as real output. Fixed by adding chat_template_kwargs: { enable_thinking: false } to both calls.\",\n      \"verified\": \"Deployed and live-tested across multiple topics -- valid SVG + explanation + citations returned each time post-fix.\"\n    },\n    \"dogfood_pass\": {\n      \"summary\": \"Converted two Claude Code blog posts (artifacts support, and 'Getting started with loops') into goal-based Cowork follow-up tasks, applying their proactive-loop/self-steering methodology to both live Workers using actually-available Cowork primitives (mcp__scheduled-tasks__*, mcp__cowork__create_artifact/update_artifact) rather than nonexistent Claude Code CLI slash commands (/goal, /loop, /schedule).\",\n      \"findings\": \"Ran a 4-topic diagram reliability check on subagentworkers (3/4 clean on first attempt; P50 diagram-gen latency ~84s from the two chained model calls; one non-reproducing malformed-JSON parse error on a retry, never seen again). Ran the 4-query regression suite on subagentdb and found two real, previously-unpatched bugs: (1) explainResults() had the same enable_thinking empty-output bug as subagentworkers' diagram tool -- never fixed here even though the same root cause was already fixed in the sibling Worker the same day; (2) the destructive-safety path returned a misleading explanation ('table is now empty after the delete operation') implying a DELETE succeeded when it had actually been safely declined by validateSelect().\",\n      \"bugfixes\": \"workers/subagentdb/src/index.ts: added chat_template_kwargs:{enable_thinking:false} to nl2sql() and explainResults(); added sentinel detection in runAsk() (regex match on the 'SELECT 0 WHERE 0' safety sentinel) to short-circuit with a fixed, unambiguous message instead of calling explainResults() on a query that never ran.\",\n      \"verified\": \"All 4 subagentdb regression queries (jobs simple aggregate, docs cross-database, jobs JOIN, destructive-safety) pass with correct, non-misleading explanations post-fix; redeployed and live-tested.\"\n    },\n    \"verification_tooling\": {\n      \"summary\": \"Extended both redeploy-* Claude Skills (workers/subagentworkers/skills/redeploy-subagentworkers, workers/subagentdb/skills/redeploy-subagentdb) from single-sample spot-checks to multi-sample regression suites with retry/backoff, and repackaged both as .skill files. Built a Cowork status artifact (subagentworkers-subagentdb-status) and a daily 8am scheduled health-check task (subagentworkers-subagentdb-health-check, cron 0 8 * * *) that re-verifies both Workers and refreshes the artifact.\",\n      \"bugfix\": \"The redeploy-subagentdb verification script itself had a false-positive gap: it only grepped for a JSON-shaped '\\\"error\\\"' string, so a raw Cloudflare edge error ('error code: 1101', plain text under load) silently passed as a success. Fixed by requiring the response to start with '{' before acceptance (ask_with_retry(), 3 attempts, 10s backoff), with '|| true' guards at each call site so set -e can't suppress the custom downstream error messages.\",\n      \"notes\": \"diagram_with_retry() (3 attempts, 20s backoff) added to redeploy-subagentworkers for the same reason -- transient Workers AI '3040: Capacity temporarily exceeded' errors were observed repeatedly during this session's own heavy back-to-back testing, judged self-induced infra pressure rather than a code defect.\"\n    },\n    \"docs_research\": {\n      \"summary\": \"Read all 24 files under docs/docs/platform.claude.com/docs/en/managed-agents/ and all 11 files under docs/docs/claude.com/docs/office-agents/ (local mirror in this repo) to assess relevance of Claude Managed Agents and Office Agents to this project. Also researched Claude Tag per explicit user request.\",\n      \"findings\": \"See model_notes below for the honest, non-oversold per-product assessment. Notable gap: zero files exist under any claude-tag path in the local docs/ mirror (unlike the other two, which are fully mirrored) -- confirmed via web search that Claude Tag is a real, currently-documented product at claude.com/docs/claude-tag/, so this is a documentation-mirroring gap in this repo, not evidence the product doesn't exist.\",\n      \"notes\": \"Original findings were written to a narrative HANDOFF.md at repo root; that file now redirects here per explicit user instruction ('Rewrite that handoff to be type safe').\"\n    }\n  },\n  \"gotchas\": [\n    \"The user pays for a claude.ai subscription, not Anthropic API usage -- these are separate products with separate billing. Never add a paid external API dependency without stating that distinction explicitly; default to what's already billed inside the user's own Cloudflare account (Workers AI) instead.\",\n    \"glm-5.2 (and other reasoning-capable Workers AI models) have chat_template_kwargs.enable_thinking=true by default; reasoning tokens draw from the same max_tokens budget as real output and can silently produce empty content. Set enable_thinking:false unless deep reasoning is actually wanted, and confirm defaults by reading the model's raw input JSON schema rather than assuming.\",\n    \"A verification script that only greps for a JSON-shaped '\\\"error\\\"' string can be fooled by a raw, non-JSON infra error (e.g. Cloudflare 'error code: 1101' plain text) -- always confirm the response actually starts with '{' before trusting it.\",\n    \"One-time live verification at ship time is not sufficient for model-backed code -- the same subagentdb queries marked 'verified live' regressed days later with zero changes to the calling code (underlying model behavior/load characteristics shifted). Prefer goal-based checks plus a scheduled proactive loop over a single build-time test.\",\n    \"Never run npm/tsc/wrangler for a workers/* project from a cloud/agent sandbox -- node_modules is on a mount shared with the real Mac, and a Linux sandbox install poisons it with wrong-platform workerd/esbuild binaries. Use Desktop Commander (or the user's own terminal); read-only curl against live public URLs is fine from a sandbox.\"\n  ],\n  \"environment_constraints_new_this_session\": [\n    {\n      \"id\": \"glm52-reasoning-budget\",\n      \"severity\": \"high\",\n      \"fact\": \"glm-5.2's chat_template_kwargs.enable_thinking defaults to true (confirmed via the model's raw input schema at developers.cloudflare.com/workers-ai/models/glm-5.2/sync-input.json). Reasoning tokens consume the same max_tokens budget as real output, and can silently exhaust it, returning empty content with no error.\",\n      \"workaround\": \"Set chat_template_kwargs:{enable_thinking:false} on any env.AI.run() call to a reasoning-capable Workers AI model where the content field must be reliably populated within a fixed max_tokens budget.\"\n    },\n    {\n      \"id\": \"workers-ai-transient-capacity-3040\",\n      \"severity\": \"medium\",\n      \"fact\": \"Workers AI returns '3040: Capacity temporarily exceeded' under bursty back-to-back requests -- confirmed self-inflicted by this session's own heavy dogfood testing burst, not a baseline production issue.\",\n      \"workaround\": \"Retry 2-3x with 15-20s backoff before treating a single occurrence as a code regression (see diagram_with_retry() / ask_with_retry() in both redeploy-* skills).\"\n    },\n    {\n      \"id\": \"cloudflare-edge-plaintext-errors\",\n      \"severity\": \"medium\",\n      \"fact\": \"Cloudflare's edge can return a raw plain-text error (e.g. 'error code: 1101') instead of the Worker's own JSON error shape, under the same load conditions as the capacity errors above.\",\n      \"workaround\": \"Validate that a response actually starts with '{' before parsing/trusting it in any verification script -- a check that only looks for a JSON-shaped \\\"error\\\" key will treat a plain-text infra error as a pass.\"\n    }\n  ],\n  \"still_open_from_previous_handoffs\": {\n    \"ref\": \"sessions/handoff-2026-06-30.json\",\n    \"note\": \"None of that file's 8 tasks (task-refresh-lockfile, task-migration-006, task-migration-007, task-verify-bootstrap, task-first-crawl, task-index-docs, task-a2a-executor, task-repo-fmt-debt) were touched this session either -- all Rust/Postgres/docs-crawl work, unrelated to this session's TypeScript/Workers AI scope. sessions/handoff-2026-07-01.json records the identical finding independently; both converging on 'still pending, unrelated scope' is a useful cross-check, but re-verify status rather than trusting either note indefinitely.\"\n  },\n  \"tasks\": [\n    {\n      \"id\": \"task-diagram-latency-optimization\",\n      \"content\": \"Investigate reducing /api/diagram P50 latency (~84s from chaining 2 sequential Workers AI calls) in workers/subagentworkers\",\n      \"priority\": \"low\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"todo\" },\n      \"notes\": \"Not urgent -- inherent to the two-step explore+generate design on a reasoning model; would need a real architecture change (e.g. single-call redesign, or accepting the latency), not just a parameter tweak.\"\n    },\n    {\n      \"id\": \"task-ai-search-upgrade-path\",\n      \"content\": \"Provision Cloudflare AI Search for workers/subagentworkers retrieval, replacing hand-rolled D1 FTS5\",\n      \"priority\": \"low\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"todo\" },\n      \"notes\": \"Documented in wrangler.toml/README as an upgrade path, not executed -- wrangler already has ai-search write/run scopes.\"\n    },\n    {\n      \"id\": \"task-claude-tag-docs-gap\",\n      \"content\": \"Add Claude Tag docs to the local docs/ mirror, or confirm no local copy is intended\",\n      \"priority\": \"low\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"todo\" },\n      \"notes\": \"claude.com/docs/claude-tag/ is real and documented publicly but has zero files under docs/docs/ in this repo, unlike managed-agents and office-agents, which are fully mirrored.\"\n    },\n    {\n      \"id\": \"task-fable5-model-slug-confirm\",\n      \"content\": \"Confirm Fable 5's real API model-string slug at platform.claude.com/docs before assuming a value in any code/config\",\n      \"priority\": \"medium\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"todo\" },\n      \"notes\": \"Not published in the redeploy announcement; sessions/handoff-2026-07-01.json flagged the same open question independently -- see meta.to_agent_note in both files.\"\n    }\n  ],\n  \"model_notes\": {\n    \"fable_5\": {\n      \"summary\": \"Verified via web search (multiple independent sources, including Anthropic's own news page) that this is real: a Mythos-class model released 2026-06-09 alongside Mythos 5, hit US export controls 2026-06-12 after an Amazon-reported jailbreak/vulnerability-identification technique, controls lifted 2026-06-30, redeploying 2026-07-01 (today) with a new safety classifier. Did not independently re-derive the deeper detail (exact usage-limit percentages, the Opus-4.8-auto-route-on-block behavior, the >99% block-rate figure) -- sessions/handoff-2026-07-01.json's model_notes.fable_5 did that research more thoroughly via live fetch; treat that entry as the fuller source and this one as an independent existence/timeline confirmation.\",\n      \"source\": \"https://www.anthropic.com/news/redeploying-fable-5\"\n    },\n    \"claude_managed_agents\": {\n      \"summary\": \"Researched from this repo's local docs/docs/platform.claude.com/docs/en/managed-agents/ mirror (24 files), not live fetch. Beta hosted async agent product, own ANTHROPIC_API_KEY billing (see the zero-external-paid-API gotcha above -- adopting any of this means real per-token spend), beta-gated, not ZDR/HIPAA-eligible. Nothing here clearly beats the existing Cowork-scheduled-task + local-skill setup already running for subagentworkers/subagentdb's daily health check. The one piece worth prototyping if the goal ever shifts from 'run a check' to 'verify and self-correct' is Outcomes/rubric grading (define-outcomes.md) -- iterate against a graded rubric instead of a scripted pass/fail. Multi-agent coordination and persistent memory stores are real capabilities but solve problems (cross-session state, parallel fan-out) this project doesn't currently have.\",\n      \"source\": \"local mirror: docs/docs/platform.claude.com/docs/en/managed-agents/ (24 files)\"\n    },\n    \"office_agents\": {\n      \"summary\": \"Researched from this repo's local docs/docs/claude.com/docs/office-agents/ mirror (11 files), not live fetch. Weak, speculative relevance to this project -- an interactive M365 add-in operating on open files, no connector to Cloudflare/D1/this codebase, no batch/scheduled invocation path documented. If a Word/Excel status report is ever wanted, the docx/xlsx/pptx Claude Skills already available in a Cowork session generate those files directly and are the better fit -- no M365 licensing or manual file-open step required.\",\n      \"source\": \"local mirror: docs/docs/claude.com/docs/office-agents/ (11 files)\"\n    },\n    \"claude_tag\": {\n      \"summary\": \"Zero files exist under any claude-tag path in this repo's local docs/ mirror, unlike the other two products above (both fully mirrored). Confirmed via web search that it's real and currently documented at claude.com/docs/claude-tag/ -- a Slack-native persistent agent-identity product -- so this is a documentation-mirroring gap in this repo, not evidence the product doesn't exist. sessions/handoff-2026-07-01.json's model_notes.claude_tag independently re-derived a live-fetched summary (the '@Claude admin-governed Slack teammate' description) since it wasn't blocked by this same local-mirror gap -- see that entry for actual product detail this file doesn't restate.\",\n      \"source\": \"https://www.claude.com/docs/claude-tag/ (confirmed real via web search; not present in this repo's local docs/ mirror)\"\n    }\n  },\n  \"enum_reference\": {\n    \"task_status\": [\"pending\", \"in_progress\", \"completed\", \"cancelled\"],\n    \"task_priority\": [\"high\", \"medium\", \"low\"],\n    \"task_kind_type\": [\"todo\", \"crawl_board\", \"evict_stale\", \"deploy\", \"migration\", \"git_push\", \"code_review\", \"sub_task\", \"shell_command\"]\n  },\n  \"operating_rules\": [\n    \"Develop on a fresh branch off origin/main; never push to main.\",\n    \"Push, then open a ready-for-review PR; check for a PR template first.\",\n    \"End commit messages with the Co-Authored-By + Claude-Session trailers (chat-only; never reference the model id in committed artifacts).\",\n    \"GitHub access is scoped to opencoworkers/subagentjobs only; use mcp__github__* tools (no gh CLI).\",\n    \"Never run npm/tsc/wrangler for a workers/* project from a cloud/agent sandbox -- see the sandbox gotcha above; use Desktop Commander or the user's own terminal instead.\"\n  ]\n}\n",
      "created_at": "2026-07-02 02:06:38"
    },
    {
      "id": "handoff-2026-07-01",
      "schema_version": "0.1.0",
      "kind": "agent_handoff",
      "instance_id": "claude-sonnet-5",
      "created_at_field": "2026-07-01",
      "summary": "Expand job-board crawler with Ashby/OpenAI support, rebuild workers/etl, build subagentetl.com Kimball ETL dashboard, build cwc-data plugin, deploy all three live via Desktop Commander",
      "tasks": [
        {
          "id": "task-vendor-indexer-run",
          "content": "Run indexer over vendor repos (crates/indexer walks .vendors.toml repos -> fact_filesystem + dim_file_ast)",
          "priority": "medium",
          "status": "pending",
          "kind": {
            "type": "shell_command",
            "command": "cargo run -p indexer -- --all"
          }
        },
        {
          "id": "task-switch-cowork-profile",
          "content": "Switch Claude Desktop to the cowork profile (surface macos__desktop_cowork__engineering_coworker)",
          "priority": "low",
          "status": "pending",
          "kind": {
            "type": "shell_command",
            "command": "bash profiles/switch-profile.sh cowork"
          },
          "notes": "Requires building the engineering-coworker binary first: cargo build -p engineering-coworker"
        },
        {
          "id": "task-refresh-oauth-token",
          "content": "Refresh CLAUDE_CODE_OAUTH_TOKEN if expired",
          "priority": "low",
          "status": "pending",
          "kind": {
            "type": "shell_command",
            "command": "claude auth login"
          },
          "notes": "Conditional -- only needed if the current token has actually expired."
        }
      ],
      "still_open_from_previous_handoffs": {
        "ref": "sessions/handoff-2026-06-30.json",
        "note": "None of that file's 8 tasks (task-refresh-lockfile, task-migration-006, task-migration-007, task-verify-bootstrap, task-first-crawl, task-index-docs, task-a2a-executor, task-repo-fmt-debt) were touched this session -- all Rust/Postgres/docs-crawl work, unrelated to this session's TypeScript/Wrangler/plugin scope. Presumed still pending; re-verify status rather than trusting this note indefinitely."
      },
      "previous_handoff": "handoff-2026-06-30",
      "see_also": [
        {
          "path": "HANDOFF.md",
          "note": "A concurrent, separate session's narrative handoff (untracked, written same day) covering disjoint work: workers/subagentworkers + workers/subagentdb (GLM-5.2 thinking-mode empty-output bug, a zero-external-paid-API product constraint, and a general 'never run npm/tsc/wrangler for any workers/* project from a cloud sandbox -- it poisons the shared node_modules mount with wrong-platform binaries' warning that applies here too, not just to those two workers). It also researched Managed Agents/Office Agents/Claude Tag independently, using this repo's local docs/docs/ mirror instead of live fetch -- conclusions converge with model_notes below, which is a useful cross-check."
        }
      ],
      "source_site": "subagenthandoffs.com",
      "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"schema_version\": \"0.1.0\",\n  \"kind\": \"agent_handoff\",\n  \"previous_handoff\": \"sessions/handoff-2026-06-30.json\",\n  \"see_also\": [\n    {\n      \"path\": \"HANDOFF.md\",\n      \"note\": \"A concurrent, separate session's narrative handoff (untracked, written same day) covering disjoint work: workers/subagentworkers + workers/subagentdb (GLM-5.2 thinking-mode empty-output bug, a zero-external-paid-API product constraint, and a general 'never run npm/tsc/wrangler for any workers/* project from a cloud sandbox -- it poisons the shared node_modules mount with wrong-platform binaries' warning that applies here too, not just to those two workers). It also researched Managed Agents/Office Agents/Claude Tag independently, using this repo's local docs/docs/ mirror instead of live fetch -- conclusions converge with model_notes below, which is a useful cross-check.\"\n    }\n  ],\n  \"meta\": {\n    \"from_agent\": \"claude-sonnet-5\",\n    \"to_agent\": \"claude-fable-5\",\n    \"to_agent_note\": \"Fable 5 redeploys 2026-07-01 (today) per anthropic.com/news/redeploying-fable-5. Its exact API model-string slug was not published in that announcement -- confirm the real string at platform.claude.com/docs before assuming \\\"claude-fable-5\\\" is correct. If a request unexpectedly comes back from Opus 4.8 instead, that's expected: Anthropic auto-routes Fable-5 requests blocked by its new cybersecurity classifier to Opus 4.8 rather than refusing outright.\",\n    \"repo\": \"opencoworkers/subagentjobs\",\n    \"default_branch\": \"main\",\n    \"created_at\": \"2026-07-01\",\n    \"session_goal\": \"Expand job-board crawler with Ashby/OpenAI support, rebuild workers/etl, build subagentetl.com Kimball ETL dashboard, build cwc-data plugin, deploy all three live via Desktop Commander\"\n  },\n  \"mission\": \"Everything under completed_this_session is LIVE in production and was verified end-to-end this session (not just type-checked/assumed). Read CLAUDE.md's Pending tasks + still_open_from_previous_handoffs below before starting new work -- none of that was touched this session.\",\n  \"completed_this_session\": {\n    \"ashby_integration\": {\n      \"summary\": \"Added Ashby ATS platform support (fetchAshbyIds) to workers/cron for OpenAI (board token 'openai'). Ingested and reconciled to 723 rows in fact_job_posting; fixed a company_name capitalization bug ('OpenAI' -> 'openai') to match the lowercase-token convention every other company uses (anthropic, figma, palantir, ...).\",\n      \"verified\": \"Live crawl via deployed workers/etl: /crawl?board=openai -> {\\\"platform\\\":\\\"ashby\\\",\\\"changed\\\":true,\\\"jobs\\\":723}. Confirmed via direct D1 query.\"\n    },\n    \"etl_worker_rebuild\": {\n      \"summary\": \"workers/etl previously had NO in-repo source (dashboard/script-API deployed). Rebuilt src/index.ts, package.json, tsconfig.json, wrangler.toml from scratch, added fetchAshby(). Fixed a pre-existing silent dim_board bug: writes were UPDATE-only, so 43 of 45 Greenhouse boards never got a dim_board row (invisible on any job_count>0 dashboard filter despite having live job data) -- changed to INSERT ... ON CONFLICT ... DO UPDATE and backfilled the 43 boards; documented via migrations/005_expand_boards.sql + 006_backfill_dim_board_stats.sql.\",\n      \"verified\": \"Post-deploy live tests: /crawl?board=openai -> 723 jobs (ashby), /crawl?board=whoop -> 164 (lever), /crawl?board=figma -> 168 (greenhouse). crawl_log rows carry real sha256 hashes, replacing the earlier manual placeholder 'manual-ingest-2026-07-01'.\"\n    },\n    \"subagentetl_dashboard\": {\n      \"summary\": \"New Cloudflare Worker workers/subagentetl, serves subagentetl.com. Kimball-style ETL pipeline dashboard: SVG star-schema diagram (fact_job_posting / dim_board / dim_skill / dim_department / dim_office / bridge_job_skill / bridge_job_office / crawl_log), pipeline-run history table, per-source freshness badges (STALE_HOURS=12). User explicitly chose scope: visualize the EXISTING crawler pipeline, not a new one.\",\n      \"bugfix\": \"starSchemaSvg() originally hardcoded literal counts (e.g. '51 skills') as static SVG text. Fixed by threading the live D1-backed Summary object through the function so the diagram can't silently go stale.\",\n      \"verified\": \"Deployed (Version 4347336a-e4e4-41a6-bb19-bfd8b0d60251). My sandboxed web_fetch showed a stale cached page post-deploy; diagnosed as a fetch-tool caching artifact (not a real regression) via cache-busted `curl -D-` run on the real machine through Desktop Commander -- response headers matched the new code exactly.\"\n    },\n    \"cwc_data_plugin\": {\n      \"summary\": \"New plugins/cwc-data, mirrors plugins/cwc-design's file layout exactly (.claude-plugin/plugin.json, commands/data.md, skills/data-playbook/SKILL.md, agents/data-coworker.md, gates.toml, README.md, LICENSE). Scope: warehouse analyst ONLY, per explicit user choice -- pipeline/DAG authoring and web/data-extraction skill areas deliberately excluded. Registered in .claude-plugin/marketplace.json alongside cwc-design.\",\n      \"notes\": \"skills/data-playbook/SKILL.md encodes the real schema gotchas discovered this session (see gotchas array below), a 6-item self-review checklist, and a provenance-footer format, following the design basis of Anthropic's self-service-analytics blog post the user cited.\"\n    },\n    \"deploys\": {\n      \"summary\": \"Ran real `npm install` + `wrangler deploy` for subagentetl, workers/etl, workers/cron via the Desktop Commander MCP (operates on the user's actual Mac, not this sandbox) at the user's explicit request.\",\n      \"bugfix\": \"`wrangler deploy` failed non-interactively ('More than one account available but unable to select one in non-interactive mode') because the login resolves 2 Cloudflare accounts. Fixed permanently by adding `account_id = \\\"e6294e3ea89f8207af387d459824aaae\\\"` to wrangler.toml for all three workers touched this session (cron, etl, subagentetl). Did NOT touch workers/web or other untouched workers' wrangler.toml files.\"\n    }\n  },\n  \"gotchas\": [\n    \"company_name is a lowercase crawl token ('anthropic', 'openai'), never a display name.\",\n    \"evicted_at IS NULL is the 'active' hygiene filter used everywhere.\",\n    \"dim_department, dim_office, bridge_job_office, streams_job_change are schema-defined but empty/unused in production -- don't assume data exists there.\",\n    \"Netflix uses Eightfold (not Greenhouse/Lever/Ashby) -- handled as a one-time manual lookup, never ingested into the warehouse.\",\n    \"job_count = 0 on a board can be legitimate, not a bug.\",\n    \"D1 has bound-parameter limits; the ETL's 50-row x 12-column batch upserts deliberately use manual SQL-string escaping instead of .bind() placeholders for this reason -- don't 'improve' this without checking the limit math first.\"\n  ],\n  \"environment_constraints_new_this_session\": [\n    {\n      \"id\": \"deploy-requires-desktop-commander\",\n      \"severity\": \"high\",\n      \"fact\": \"This agent (cloud sandbox) has no authenticated wrangler/npm session and cannot deploy Cloudflare Workers directly.\",\n      \"workaround\": \"Use the Desktop Commander MCP (mcp__Desktop_Commander__start_process / read_process_output / interact_with_process) to run npm/wrangler commands on the user's real Mac, which has an authenticated wrangler CLI. Only usable when the user explicitly invokes/grants it.\"\n    },\n    {\n      \"id\": \"wrangler-multi-account-noninteractive\",\n      \"severity\": \"medium\",\n      \"fact\": \"The user's Cloudflare login resolves to 2 accounts (Admin@jadecli.com and Alex@jadecli.com). `wrangler deploy` fails non-interactively with 'More than one account available' unless account_id is pinned.\",\n      \"workaround\": \"Add `account_id = \\\"e6294e3ea89f8207af387d459824aaae\\\"` to any NEW worker's wrangler.toml before deploying. Already present in workers/cron, workers/etl, workers/subagentetl.\"\n    },\n    {\n      \"id\": \"connected-folder-delete-blocked\",\n      \"severity\": \"low\",\n      \"fact\": \"rm/mv/unlink on files inside the connected project folder fail with 'Operation not permitted' by default.\",\n      \"workaround\": \"Call mcp__cowork__allow_cowork_file_delete on the path once; deletion then works for the rest of the session for that path/folder.\"\n    }\n  ],\n  \"still_open_from_previous_handoffs\": {\n    \"ref\": \"sessions/handoff-2026-06-30.json\",\n    \"note\": \"None of that file's 8 tasks (task-refresh-lockfile, task-migration-006, task-migration-007, task-verify-bootstrap, task-first-crawl, task-index-docs, task-a2a-executor, task-repo-fmt-debt) were touched this session -- all Rust/Postgres/docs-crawl work, unrelated to this session's TypeScript/Wrangler/plugin scope. Presumed still pending; re-verify status rather than trusting this note indefinitely.\"\n  },\n  \"tasks\": [\n    {\n      \"id\": \"task-vendor-indexer-run\",\n      \"content\": \"Run indexer over vendor repos (crates/indexer walks .vendors.toml repos -> fact_filesystem + dim_file_ast)\",\n      \"priority\": \"medium\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"shell_command\", \"command\": \"cargo run -p indexer -- --all\" }\n    },\n    {\n      \"id\": \"task-switch-cowork-profile\",\n      \"content\": \"Switch Claude Desktop to the cowork profile (surface macos__desktop_cowork__engineering_coworker)\",\n      \"priority\": \"low\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"shell_command\", \"command\": \"bash profiles/switch-profile.sh cowork\" },\n      \"notes\": \"Requires building the engineering-coworker binary first: cargo build -p engineering-coworker\"\n    },\n    {\n      \"id\": \"task-refresh-oauth-token\",\n      \"content\": \"Refresh CLAUDE_CODE_OAUTH_TOKEN if expired\",\n      \"priority\": \"low\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"shell_command\", \"command\": \"claude auth login\" },\n      \"notes\": \"Conditional -- only needed if the current token has actually expired.\"\n    }\n  ],\n  \"model_notes\": {\n    \"fable_5\": {\n      \"summary\": \"Released 2026-06-09 alongside Mythos 5 (same underlying model; Fable 5 shipped with much stronger safeguards for general use, Mythos 5 with fewer safeguards to a small set of trusted Project Glasswing partners for defensive cybersecurity). Both hit US export controls 2026-06-12 after Amazon researchers found a technique prompting Fable 5 to identify software vulnerabilities (in one case, produce exploit code). Testing showed weaker models (incl. Opus 4.8, GPT-5.5, Kimi K2.7, and for the single-exploit case even Haiku 4.5/Sonnet 4.6/Opus 4.6/4.7) could reproduce the same outputs, so this was judged a borderline safety-margin gap, not a unique Mythos-level capability leak. Controls lifted 2026-06-30. Fable 5 redeploys 2026-07-01 (today) across Claude Platform, Claude.ai, Claude Code, and Claude Cowork. A new safety classifier blocks the specific reported technique in >99% of cases; blocked Fable-5 requests are auto-routed to Opus 4.8 instead of just refusing. Expect more false-positive blocks on routine coding/debugging while the classifier is refined. Pro/Max/Team/select-Enterprise: up to 50% of weekly usage limits through 2026-07-07, then usage credits; standard Enterprise seats need usage credits enabled or Fable 5 won't work at all.\",\n      \"source\": \"https://www.anthropic.com/news/redeploying-fable-5\"\n    },\n    \"claude_managed_agents\": {\n      \"summary\": \"Beta hosted agent harness (`managed-agents-2026-04-01` beta header required), a separate product from Claude Cowork (what this session runs in). Core concepts: Agent (model+prompt+tools+MCP+skills), Environment (Anthropic cloud sandbox or self-hosted), Session (running instance), Events. Explicitly stateful: sessions are long-running and 'resume cleanly after pauses', with conversation history/sandbox state/outputs persisted server-side -- the closest existing Anthropic product concept to 'resuming a session across a gap'. Not eligible for Zero Data Retention or HIPAA BAA because of that persistence. Relevant if a future session wants to move the 6h crawl cycle or ETL pipeline off Cloudflare Cron Triggers onto a hosted async agent instead.\",\n      \"source\": \"https://platform.claude.com/docs/en/managed-agents/overview\"\n    },\n    \"claude_tag\": {\n      \"summary\": \"'@Claude' -- a persistent, admin-governed AI teammate embedded in Slack, one shared instance per channel, runs in an ephemeral Anthropic-hosted sandbox, works with Opus 4.8. Could plausibly be used later for Slack alerts on crawl/deploy failures for this repo, but nothing wired up this session.\",\n      \"source\": \"https://www.anthropic.com/news/introducing-claude-tag\"\n    },\n    \"office_agents\": {\n      \"summary\": \"Resolved after initial searches turned up only adjacent products: 'Office Agents' is an admin-settings toggle within Claude for Microsoft 365 that enables cross-app context sharing -- e.g. a Word agent and an Excel agent share one conversation thread so Claude can pull live spreadsheet data while drafting a doc or building slides, without the user re-explaining context per app. Shipped 2026-03-11. Not directly relevant to this repo (no Microsoft 365 surface here); researched only because the user explicitly asked for it.\",\n      \"source\": \"https://thenewstack.io/claude-word-excel-powerpoint-outlook-microsoft-office/ and https://amitkoth.com/claude-office-agents-explained/\"\n    }\n  },\n  \"enum_reference\": {\n    \"task_status\": [\"pending\", \"in_progress\", \"completed\", \"cancelled\"],\n    \"task_priority\": [\"high\", \"medium\", \"low\"],\n    \"task_kind_type\": [\"todo\", \"crawl_board\", \"evict_stale\", \"deploy\", \"migration\", \"git_push\", \"code_review\", \"sub_task\", \"shell_command\"]\n  },\n  \"operating_rules\": [\n    \"Develop on a fresh branch off origin/main; never push to main.\",\n    \"Push, then open a ready-for-review PR; check for a PR template first.\",\n    \"End commit messages with the Co-Authored-By + Claude-Session trailers (chat-only; never reference the model id in committed artifacts).\",\n    \"GitHub access is scoped to opencoworkers/subagentjobs only; use mcp__github__* tools (no gh CLI).\",\n    \"Deploys in this environment require the Desktop Commander MCP against the user's real Mac -- see environment_constraints_new_this_session.deploy-requires-desktop-commander.\"\n  ]\n}\n",
      "created_at": "2026-07-02 02:06:38"
    },
    {
      "id": "handoff-2026-06-30",
      "schema_version": "0.1.0",
      "kind": "agent_handoff",
      "instance_id": "claude-opus-4-6",
      "created_at_field": "2026-06-30",
      "summary": "Review open PRs/issues; implemented and merged issue #2",
      "tasks": [
        {
          "id": "task-refresh-lockfile",
          "content": "Regenerate Cargo.lock on main with the new task-bootstrap, schema-export, and serde_yaml entries, then commit. PR #3's lockfile was never updated because the a2a-rs git dep is unfetchable in this environment; CI's non---locked cargo check tolerated it, but main's lock is stale.",
          "priority": "high",
          "status": "pending",
          "kind": {
            "type": "shell_command",
            "command": "cargo check --workspace && git add Cargo.lock && git commit"
          },
          "acceptance": [
            "Cargo.lock contains [[package]] entries for task-bootstrap, schema-export, serde_yaml (+ transitive deps)",
            "a2a-bridge / a2a-lf entries are preserved (not stripped)",
            "`cargo check --workspace --locked` succeeds"
          ],
          "notes": "Must be run in an environment that can fetch github.com/a2aproject/a2a-rs (this sandbox cannot)."
        },
        {
          "id": "task-migration-006",
          "content": "Apply 006_ecosystem_catalog.sql to Postgres",
          "priority": "high",
          "status": "pending",
          "kind": {
            "type": "migration",
            "file": "crates/durable-store/migrations/postgres/006_ecosystem_catalog.sql"
          }
        },
        {
          "id": "task-migration-007",
          "content": "Apply 007_doc_pages.sql to Postgres",
          "priority": "high",
          "status": "pending",
          "kind": {
            "type": "migration",
            "file": "crates/durable-store/migrations/postgres/007_doc_pages.sql"
          }
        },
        {
          "id": "task-verify-bootstrap",
          "content": "End-to-end verify the new task-bootstrap: with DATABASE_URL set, run `make load-tasks` twice and confirm idempotency (second run prints '· skipped (exists)' and inserts no duplicate fact_tasks rows).",
          "priority": "medium",
          "status": "pending",
          "blocked_by": [
            "task-migration-007"
          ],
          "kind": {
            "type": "shell_command",
            "command": "make load-tasks"
          },
          "acceptance": [
            "First run inserts 7 pending tasks into fact_tasks",
            "Second run inserts 0 rows (ON CONFLICT id DO NOTHING)",
            "event_task_states has exactly one creation row per task"
          ]
        },
        {
          "id": "task-first-crawl",
          "content": "Run make crawl-docs (requires DATABASE_URL + Redis)",
          "priority": "high",
          "status": "pending",
          "blocked_by": [
            "task-migration-007"
          ],
          "kind": {
            "type": "shell_command",
            "command": "make crawl-docs"
          }
        },
        {
          "id": "task-index-docs",
          "content": "Run make index-docs after first crawl",
          "priority": "medium",
          "status": "pending",
          "blocked_by": [
            "task-first-crawl"
          ],
          "kind": {
            "type": "shell_command",
            "command": "make index-docs"
          }
        },
        {
          "id": "task-a2a-executor",
          "content": "Implement AgentExecutor trait in crates/a2a-bridge once a2a-server-lf API stabilises",
          "priority": "medium",
          "status": "pending",
          "kind": {
            "type": "todo"
          }
        },
        {
          "id": "task-repo-fmt-debt",
          "content": "Decide on repo-wide rustfmt debt: the CI `cargo fmt --all -- --check` step is currently non-blocking (continue-on-error) because ~167 sites across ~25 files use intentional hand-aligned match arms / struct fields. Either commit to `cargo fmt --all` (large diff, drops alignment) or keep it advisory.",
          "priority": "low",
          "status": "pending",
          "kind": {
            "type": "todo"
          },
          "notes": "Owner decision. If reformatting, do it as its own dedicated PR, not bundled with features."
        }
      ],
      "still_open_from_previous_handoffs": null,
      "previous_handoff": null,
      "see_also": null,
      "source_site": "subagenthandoffs.com",
      "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"schema_version\": \"0.1.0\",\n  \"kind\": \"agent_handoff\",\n  \"meta\": {\n    \"from_agent\": \"claude-opus-4-6\",\n    \"to_agent\": \"claude-opus-4-6\",\n    \"repo\": \"opencoworkers/subagentjobs\",\n    \"default_branch\": \"main\",\n    \"created_at\": \"2026-06-30\",\n    \"session_goal\": \"Review open PRs/issues; implemented and merged issue #2\"\n  },\n  \"mission\": \"Continue work on subagentjobs after PR #3 merged. Address the lockfile follow-up first, then pick up the durable-task backlog. Read CLAUDE.md and sessions/CLAUDE.md before acting.\",\n  \"completed_this_session\": {\n    \"merged_pr\": {\n      \"number\": 3,\n      \"squash_sha\": \"b318788c72e60815385ea51eb9e8bd18bab0c07d\",\n      \"title\": \"feat: durable task YAML + SessionStart bootstrap (#3)\",\n      \"implements_issue\": 2,\n      \"summary\": \"Typed sessions/tasks.yaml bootstrapped into Postgres fact_tasks on session start via crates/task-bootstrap; schemas/task-session.schema.json generated by crates/schema-export; Makefile schema/load-tasks targets; .vscode YAML validation. Removed flaky GitHub Actions sccache cache dependency from CI; made fmt non-blocking; cleared pre-existing clippy -D warnings debt across 6 crates.\"\n    }\n  },\n  \"environment_constraints\": [\n    {\n      \"id\": \"git-dep-blocked\",\n      \"severity\": \"high\",\n      \"fact\": \"crates/a2a-bridge depends on a2a-rs via git (github.com/a2aproject/a2a-rs @ 9738e50b). The agent proxy returns 403 on that fetch, so the full workspace cannot resolve/build locally in this environment.\",\n      \"workaround\": \"Temporarily remove \\\"crates/a2a-bridge\\\" from root Cargo.toml [workspace.members], run cargo with `--exclude a2a-bridge` (mirrors CI), then restore Cargo.toml + `git checkout HEAD -- Cargo.lock`. Never commit the member removal or the a2a-stripped lockfile.\"\n    },\n    {\n      \"id\": \"linker-clang-mold\",\n      \"severity\": \"medium\",\n      \"fact\": \".cargo/config.toml sets linker=clang + rustflags `-Clink-arg=-fuse-ld=mold`. `mold` is NOT installed in the sandbox, so linking fails by default.\",\n      \"workaround\": \"Run cargo with `RUSTFLAGS=\\\"\\\"` to drop the mold flag (clang is present). Example: `RUSTC_WRAPPER=\\\"\\\" RUSTFLAGS=\\\"\\\" cargo clippy --workspace --keep-going -- -D warnings`.\"\n    },\n    {\n      \"id\": \"sccache-local-only\",\n      \"severity\": \"low\",\n      \"fact\": \".cargo/config.toml keeps `rustc-wrapper = \\\"sccache\\\"` for local dev. CI disables it via `RUSTC_WRAPPER: \\\"\\\"` in .github/workflows/check.yml. sccache binary is not in the sandbox.\",\n      \"workaround\": \"Prefix cargo commands with `RUSTC_WRAPPER=\\\"\\\"` (the repo's established convention; see Makefile targets).\"\n    }\n  ],\n  \"tasks\": [\n    {\n      \"id\": \"task-refresh-lockfile\",\n      \"content\": \"Regenerate Cargo.lock on main with the new task-bootstrap, schema-export, and serde_yaml entries, then commit. PR #3's lockfile was never updated because the a2a-rs git dep is unfetchable in this environment; CI's non---locked cargo check tolerated it, but main's lock is stale.\",\n      \"priority\": \"high\",\n      \"status\": \"pending\",\n      \"kind\": {\n        \"type\": \"shell_command\",\n        \"command\": \"cargo check --workspace && git add Cargo.lock && git commit\"\n      },\n      \"acceptance\": [\n        \"Cargo.lock contains [[package]] entries for task-bootstrap, schema-export, serde_yaml (+ transitive deps)\",\n        \"a2a-bridge / a2a-lf entries are preserved (not stripped)\",\n        \"`cargo check --workspace --locked` succeeds\"\n      ],\n      \"notes\": \"Must be run in an environment that can fetch github.com/a2aproject/a2a-rs (this sandbox cannot).\"\n    },\n    {\n      \"id\": \"task-migration-006\",\n      \"content\": \"Apply 006_ecosystem_catalog.sql to Postgres\",\n      \"priority\": \"high\",\n      \"status\": \"pending\",\n      \"kind\": {\n        \"type\": \"migration\",\n        \"file\": \"crates/durable-store/migrations/postgres/006_ecosystem_catalog.sql\"\n      }\n    },\n    {\n      \"id\": \"task-migration-007\",\n      \"content\": \"Apply 007_doc_pages.sql to Postgres\",\n      \"priority\": \"high\",\n      \"status\": \"pending\",\n      \"kind\": {\n        \"type\": \"migration\",\n        \"file\": \"crates/durable-store/migrations/postgres/007_doc_pages.sql\"\n      }\n    },\n    {\n      \"id\": \"task-verify-bootstrap\",\n      \"content\": \"End-to-end verify the new task-bootstrap: with DATABASE_URL set, run `make load-tasks` twice and confirm idempotency (second run prints '· skipped (exists)' and inserts no duplicate fact_tasks rows).\",\n      \"priority\": \"medium\",\n      \"status\": \"pending\",\n      \"blocked_by\": [\"task-migration-007\"],\n      \"kind\": {\n        \"type\": \"shell_command\",\n        \"command\": \"make load-tasks\"\n      },\n      \"acceptance\": [\n        \"First run inserts 7 pending tasks into fact_tasks\",\n        \"Second run inserts 0 rows (ON CONFLICT id DO NOTHING)\",\n        \"event_task_states has exactly one creation row per task\"\n      ]\n    },\n    {\n      \"id\": \"task-first-crawl\",\n      \"content\": \"Run make crawl-docs (requires DATABASE_URL + Redis)\",\n      \"priority\": \"high\",\n      \"status\": \"pending\",\n      \"blocked_by\": [\"task-migration-007\"],\n      \"kind\": {\n        \"type\": \"shell_command\",\n        \"command\": \"make crawl-docs\"\n      }\n    },\n    {\n      \"id\": \"task-index-docs\",\n      \"content\": \"Run make index-docs after first crawl\",\n      \"priority\": \"medium\",\n      \"status\": \"pending\",\n      \"blocked_by\": [\"task-first-crawl\"],\n      \"kind\": {\n        \"type\": \"shell_command\",\n        \"command\": \"make index-docs\"\n      }\n    },\n    {\n      \"id\": \"task-a2a-executor\",\n      \"content\": \"Implement AgentExecutor trait in crates/a2a-bridge once a2a-server-lf API stabilises\",\n      \"priority\": \"medium\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"todo\" }\n    },\n    {\n      \"id\": \"task-repo-fmt-debt\",\n      \"content\": \"Decide on repo-wide rustfmt debt: the CI `cargo fmt --all -- --check` step is currently non-blocking (continue-on-error) because ~167 sites across ~25 files use intentional hand-aligned match arms / struct fields. Either commit to `cargo fmt --all` (large diff, drops alignment) or keep it advisory.\",\n      \"priority\": \"low\",\n      \"status\": \"pending\",\n      \"kind\": { \"type\": \"todo\" },\n      \"notes\": \"Owner decision. If reformatting, do it as its own dedicated PR, not bundled with features.\"\n    }\n  ],\n  \"enum_reference\": {\n    \"task_status\": [\"pending\", \"in_progress\", \"completed\", \"cancelled\"],\n    \"task_priority\": [\"high\", \"medium\", \"low\"],\n    \"task_kind_type\": [\"todo\", \"crawl_board\", \"evict_stale\", \"deploy\", \"migration\", \"git_push\", \"code_review\", \"sub_task\", \"shell_command\"]\n  },\n  \"operating_rules\": [\n    \"Develop on a fresh branch off origin/main; never push to main.\",\n    \"Push, then open a ready-for-review PR; check for a PR template first.\",\n    \"End commit messages with the Co-Authored-By + Claude-Session trailers (chat-only; never reference the model id in committed artifacts).\",\n    \"Verify clippy locally with: RUSTC_WRAPPER=\\\"\\\" RUSTFLAGS=\\\"\\\" cargo clippy --workspace --exclude a2a-bridge -- -D warnings\",\n    \"GitHub access is scoped to opencoworkers/subagentjobs only; use mcp__github__* tools (no gh CLI).\"\n  ]\n}\n",
      "created_at": "2026-07-02 02:06:38"
    }
  ]
}