@posthog/wizard 2.62.0 → 2.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +48 -6
  2. package/dist/{add-mcp-server-to-clients-Bzl7_wB3.js → add-mcp-server-to-clients-D9l1dyw9.js} +4 -4
  3. package/dist/{add-mcp-server-to-clients-Bzl7_wB3.js.map → add-mcp-server-to-clients-D9l1dyw9.js.map} +1 -1
  4. package/dist/{agent-interface-C90hyvs1.js → agent-interface-BQfwaSe-.js} +24 -16
  5. package/dist/agent-interface-BQfwaSe-.js.map +1 -0
  6. package/dist/{agent-prompt-loader-CBj2DWAJ.js → agent-prompt-loader-BRKe3VE6.js} +15 -7
  7. package/dist/agent-prompt-loader-BRKe3VE6.js.map +1 -0
  8. package/dist/{agent-runner-DA5YfjOD.js → agent-runner-B4ZdNkj4.js} +215 -42
  9. package/dist/agent-runner-B4ZdNkj4.js.map +1 -0
  10. package/dist/analytics-BlE8Yjoh.js +2 -0
  11. package/dist/{analytics-BdKBzz4M.js → analytics-Duy9Vfk-.js} +2 -2
  12. package/dist/{analytics-BdKBzz4M.js.map → analytics-Duy9Vfk-.js.map} +1 -1
  13. package/dist/{api-aTkzJ9vG.js → api-DEb25KDf.js} +3 -3
  14. package/dist/{api-aTkzJ9vG.js.map → api-DEb25KDf.js.map} +1 -1
  15. package/dist/bin.js +256 -43
  16. package/dist/bin.js.map +1 -1
  17. package/dist/{bounded-fs-BU2L5mjO.js → bounded-fs-CvYIzQbg.js} +3 -3
  18. package/dist/{bounded-fs-BU2L5mjO.js.map → bounded-fs-CvYIzQbg.js.map} +1 -1
  19. package/dist/check-screens.tsx +15 -0
  20. package/dist/{ci-install-BnTAUOz8.js → ci-install-k2HWuLQ3.js} +4 -4
  21. package/dist/{ci-install-BnTAUOz8.js.map → ci-install-k2HWuLQ3.js.map} +1 -1
  22. package/dist/{debug-BTPYy9p7.js → debug-3FJsmlmC.js} +15 -8
  23. package/dist/debug-3FJsmlmC.js.map +1 -0
  24. package/dist/{debug-D2L-fM_I.js → debug-D7eikh3K.js} +1 -1
  25. package/dist/{env-api-key-cjD4yfGT.js → env-api-key-uk6HInaB.js} +4 -7
  26. package/dist/env-api-key-uk6HInaB.js.map +1 -0
  27. package/dist/{environment-lV2X1gS-.js → environment-Cyq61jKV.js} +4 -4
  28. package/dist/{environment-lV2X1gS-.js.map → environment-Cyq61jKV.js.map} +1 -1
  29. package/dist/{file-watcher-qqQBl5Em.js → file-watcher-DZDDYHrv.js} +2 -2
  30. package/dist/{file-watcher-qqQBl5Em.js.map → file-watcher-DZDDYHrv.js.map} +1 -1
  31. package/dist/{headless-ui-TSoOsa3j.js → headless-ui-MpPKNNH9.js} +2 -2
  32. package/dist/{headless-ui-TSoOsa3j.js.map → headless-ui-MpPKNNH9.js.map} +1 -1
  33. package/dist/{interactive-DMoXEiKo.js → interactive-BDCUPSmr.js} +2 -2
  34. package/dist/{interactive-DMoXEiKo.js.map → interactive-BDCUPSmr.js.map} +1 -1
  35. package/dist/{mcp-Dqu0_QzN.js → mcp-DOH54TGI.js} +2 -2
  36. package/dist/{mcp-Dqu0_QzN.js.map → mcp-DOH54TGI.js.map} +1 -1
  37. package/dist/{mcp-prompt-streaming-B4cYVDVP.js → mcp-prompt-streaming-BKY-srkT.js} +3 -3
  38. package/dist/{mcp-prompt-streaming-B4cYVDVP.js.map → mcp-prompt-streaming-BKY-srkT.js.map} +1 -1
  39. package/dist/{non-interactive-EG_lII4R.js → non-interactive-DOG-p4ku.js} +2 -2
  40. package/dist/{non-interactive-EG_lII4R.js.map → non-interactive-DOG-p4ku.js.map} +1 -1
  41. package/dist/{orchestrator-tools-DrhpNOKK.js → orchestrator-tools-CfaYl_W4.js} +13 -10
  42. package/dist/orchestrator-tools-CfaYl_W4.js.map +1 -0
  43. package/dist/{package-manager-z33XHEWO.js → package-manager-62MxCa1Y.js} +2 -2
  44. package/dist/{package-manager-z33XHEWO.js.map → package-manager-62MxCa1Y.js.map} +1 -1
  45. package/dist/{pi-CVJB0Ban.js → pi-DohBskuT.js} +11 -11
  46. package/dist/{pi-CVJB0Ban.js.map → pi-DohBskuT.js.map} +1 -1
  47. package/dist/{playground-BjWqoWhf.js → playground-DaTeK9-L.js} +6 -6
  48. package/dist/{playground-BjWqoWhf.js.map → playground-DaTeK9-L.js.map} +1 -1
  49. package/dist/{posthog-3ijs_66W.js → posthog-DvM4V-to.js} +2 -2
  50. package/dist/{posthog-3ijs_66W.js.map → posthog-DvM4V-to.js.map} +1 -1
  51. package/dist/{posthog-integration-C3wuB5B1.js → posthog-integration-BHqFQd4U.js} +54 -24
  52. package/dist/{posthog-integration-C3wuB5B1.js.map → posthog-integration-BHqFQd4U.js.map} +1 -1
  53. package/dist/{provisioning-IKacrvWB.js → provisioning-B41dKvno.js} +3 -3
  54. package/dist/{provisioning-IKacrvWB.js.map → provisioning-B41dKvno.js.map} +1 -1
  55. package/dist/{queue-tools-zM8_mxx6.js → queue-tools-DED9kPuc.js} +117 -19
  56. package/dist/queue-tools-DED9kPuc.js.map +1 -0
  57. package/dist/{registry-DF_aKyS0.js → registry-Dh9aqVC6.js} +5 -5
  58. package/dist/{registry-DF_aKyS0.js.map → registry-Dh9aqVC6.js.map} +1 -1
  59. package/dist/{security-CVFKNYBn.js → security-HZDvt7uh.js} +5 -5
  60. package/dist/{security-CVFKNYBn.js.map → security-HZDvt7uh.js.map} +1 -1
  61. package/dist/{setup-utils-iINkc0xu.js → setup-utils-DJF-LjYE.js} +101 -19
  62. package/dist/setup-utils-DJF-LjYE.js.map +1 -0
  63. package/dist/{start-tui-CjtL-ls7.js → start-tui-0p-Ybwxe.js} +40 -18
  64. package/dist/start-tui-0p-Ybwxe.js.map +1 -0
  65. package/dist/{steps-DzUGHdfY.js → steps-BSp0kHUG.js} +7 -7
  66. package/dist/{steps-DzUGHdfY.js.map → steps-BSp0kHUG.js.map} +1 -1
  67. package/dist/{store-DtckpbSC.js → store-BgOhG49V.js} +5 -4
  68. package/dist/store-BgOhG49V.js.map +1 -0
  69. package/dist/{subagent-cD_bF490.js → subagent-DDsAb9we.js} +2 -2
  70. package/dist/{subagent-cD_bF490.js.map → subagent-DDsAb9we.js.map} +1 -1
  71. package/dist/{task-eIt2iATF.js → task-CCZAWF2U.js} +12 -12
  72. package/dist/{task-eIt2iATF.js.map → task-CCZAWF2U.js.map} +1 -1
  73. package/dist/{task-stream-DGBUveUD.js → task-stream-B0Eo4KX1.js} +4 -4
  74. package/dist/{task-stream-DGBUveUD.js.map → task-stream-B0Eo4KX1.js.map} +1 -1
  75. package/dist/{tasks-wQ3V6Ft6.js → tasks-DRqU9G95.js} +2 -2
  76. package/dist/{tasks-wQ3V6Ft6.js.map → tasks-DRqU9G95.js.map} +1 -1
  77. package/dist/{telemetry-BWYDFAwf.js → telemetry-4VTeK1h9.js} +3 -3
  78. package/dist/{telemetry-BWYDFAwf.js.map → telemetry-4VTeK1h9.js.map} +1 -1
  79. package/dist/{terminal-yKJZx1UC.js → terminal-CDqEDXWF.js} +16 -13
  80. package/dist/terminal-CDqEDXWF.js.map +1 -0
  81. package/dist/{tools-CDlaJb_e.js → tools-CjNt0TUI.js} +6 -6
  82. package/dist/{tools-CDlaJb_e.js.map → tools-CjNt0TUI.js.map} +1 -1
  83. package/dist/{wizard-abort-CztG5WTv.js → wizard-abort-BeuIRy5a.js} +3 -3
  84. package/dist/{wizard-abort-CztG5WTv.js.map → wizard-abort-BeuIRy5a.js.map} +1 -1
  85. package/dist/{wizard-abort-Cjk5z73h.js → wizard-abort-DNHeIZ8N.js} +1 -1
  86. package/dist/wizard-session-BUhlJ1b8.js.map +1 -1
  87. package/dist/yara-hooks-BE3OXk2V.js +2 -0
  88. package/dist/{yara-hooks-DeLjTIiJ.js → yara-hooks-CCGjiVA2.js} +4 -4
  89. package/dist/{yara-hooks-DeLjTIiJ.js.map → yara-hooks-CCGjiVA2.js.map} +1 -1
  90. package/package.json +1 -1
  91. package/dist/agent-interface-C90hyvs1.js.map +0 -1
  92. package/dist/agent-prompt-loader-CBj2DWAJ.js.map +0 -1
  93. package/dist/agent-runner-DA5YfjOD.js.map +0 -1
  94. package/dist/analytics-CijpxQFN.js +0 -2
  95. package/dist/debug-BTPYy9p7.js.map +0 -1
  96. package/dist/env-api-key-cjD4yfGT.js.map +0 -1
  97. package/dist/orchestrator-tools-DrhpNOKK.js.map +0 -1
  98. package/dist/queue-tools-zM8_mxx6.js.map +0 -1
  99. package/dist/setup-utils-iINkc0xu.js.map +0 -1
  100. package/dist/start-tui-CjtL-ls7.js.map +0 -1
  101. package/dist/store-DtckpbSC.js.map +0 -1
  102. package/dist/terminal-yKJZx1UC.js.map +0 -1
  103. package/dist/yara-hooks-DVGKhwaz.js +0 -2
@@ -1,7 +1,7 @@
1
- import { s as logToFile } from "./debug-BTPYy9p7.js";
2
- import { n as analytics } from "./analytics-BdKBzz4M.js";
3
- import { f as isThinkingLevel } from "./queue-tools-zM8_mxx6.js";
4
- import { M as fetchWithRetry, S as WIZARD_TOOL_NAMES } from "./agent-interface-C90hyvs1.js";
1
+ import { s as logToFile } from "./debug-3FJsmlmC.js";
2
+ import { n as analytics } from "./analytics-Duy9Vfk-.js";
3
+ import { m as isThinkingLevel } from "./queue-tools-DED9kPuc.js";
4
+ import { M as fetchWithRetry, S as WIZARD_TOOL_NAMES } from "./agent-interface-BQfwaSe-.js";
5
5
  //#region src/lib/agent/agent-prompt-loader.ts
6
6
  function projectContext(ctx) {
7
7
  return `You have access to the PostHog MCP server and the wizard tools.
@@ -9,7 +9,8 @@ function projectContext(ctx) {
9
9
  Project context:
10
10
  - PostHog Project ID: ${ctx.projectId}
11
11
  - PostHog public token: ${ctx.projectApiKey}
12
- - PostHog Host: ${ctx.host.apiHost}`;
12
+ - PostHog Host: ${ctx.host.apiHost}
13
+ - PostHog app URL (base for any link you show the user in a browser): ${ctx.host.appHost}`;
13
14
  }
14
15
  /** Points the agent at the framework's reference integration to learn patterns from. */
15
16
  function exampleReference(ctx) {
@@ -39,10 +40,17 @@ const SEED_BASICS = `You are the orchestrator. Plan the work and seed the queue
39
40
  * Tasks the wizard queued before the planner ran. It has to see them: they are
40
41
  * part of the run it is planning around, and the task that reports last has to
41
42
  * depend on them. Their ids are real, so it can wire the edge directly.
43
+ *
44
+ * The one-way rule matters as much as the sink edge. These tasks are deferred to
45
+ * the end of the drain after planning (`seeded-deps.ts`) and may block on a
46
+ * person, so a task the planner hangs off one would wait on the user too — which
47
+ * is the interruption deferring them removed. The resolver drops such a task
48
+ * from the seeded task's own dependencies to stay acyclic, so the damage is
49
+ * silent; saying so here is what prevents it.
42
50
  */
43
51
  function preQueuedTasks(tasks) {
44
52
  if (tasks.length === 0) return null;
45
- return `The queue already holds these tasks, placed by the wizard from what it found in this project. Do not queue them again — plan around them, and make sure the reporting task ends up depending on each one:\n${tasks.map((t) => `- ${t.type} (id: ${t.id})`).join("\n")}`;
53
+ return `The queue already holds these tasks, placed by the wizard from what it found in this project. Do not queue them again. They run late — after every task you queue — and one may stop to ask the user for input, so make the reporting task depend on each one and hang nothing else off them: any other task you made depend on one would end up waiting on a person.\n${tasks.map((t) => `- ${t.type} (id: ${t.id})`).join("\n")}`;
46
54
  }
47
55
  /**
48
56
  * Points the agent at its installed task instructions (the HOW). They live under
@@ -299,4 +307,4 @@ const EMPTY_PROMPT = {};
299
307
  //#endregion
300
308
  export { assembleTaskPrompt as a, queueTools as c, taskModelSpec as d, assembleSeedPrompt as i, renderToolInventory as l, agentRunTools as n, loadAgentRegistry as o, allowsPostHogMcp as r, promptModelFor as s, ASK_TOOL as t, resolveTask as u };
301
309
 
302
- //# sourceMappingURL=agent-prompt-loader-CBj2DWAJ.js.map
310
+ //# sourceMappingURL=agent-prompt-loader-BRKe3VE6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-prompt-loader-BRKe3VE6.js","names":[],"sources":["../src/lib/agent/agent-prompt-loader.ts"],"sourcesContent":["/**\n * Agent-prompt loader + registry.\n *\n * Agent prompts are the WHAT of a task: a markdown file per type, served from\n * context-mill as the `agents` content type (parallel to skills). The frontmatter\n * carries the artifacts the executor needs — model, the mini-skills to load (the\n * HOW), the tools the task may use, and its dependencies — and the body is the\n * instruction the agent reads.\n *\n * The registry is fetched once at startup and scoped to one flow — agents\n * declare `flow` and (for the planner) `seed: true` in frontmatter, so each\n * program (integration, audit, migration, ...) ships its own agent set and the\n * loader stays generic. Every prompt is downloaded and parsed up front, so\n * resolving a task to its run config is synchronous and adds no mid-drain\n * network latency. The registry's type list also drives `enqueue_task`\n * validation.\n */\nimport type {\n QueueStore,\n QueuedTask,\n} from './runner/sequence/orchestrator/queue';\nimport type { ResolvedTask } from './runner/sequence/orchestrator/executor';\nimport type { HostResolution } from '@lib/host-resolution';\nimport {\n isThinkingLevel,\n type ThinkingLevel,\n} from './runner/switchboard/models';\nimport { logToFile } from '@utils/debug';\nimport { analytics } from '@utils/analytics';\nimport { fetchWithRetry } from '@lib/fetch-retry';\nimport { WIZARD_TOOL_NAMES } from '@lib/wizard-tools/tools';\n\n/**\n * The basics the client injects around every agent-prompt body. The `/agents/`\n * files carry intent only (goal, success criteria); the wizard owns the I/O\n * contract — who the agent is, how it reports, how it surfaces progress — so the\n * authored prompts never restate it.\n */\nexport interface OrchestratorPromptContext {\n projectId: number;\n projectApiKey: string;\n host: HostResolution;\n /** Path to the framework's reference implementation (EXAMPLE.md), if available. */\n examplePath?: string;\n /** Path to the framework's rules (COMMANDMENTS.md), if available. */\n commandmentsPath?: string;\n}\n\nfunction projectContext(ctx: OrchestratorPromptContext): string {\n // Both hosts, distinctly labelled: `apiHost` is the ingestion/API origin the\n // SDK talks to, `appHost` the user-facing web app. A task that hands the user\n // a link (e.g. the data-warehouse new-source fallback) must build it from the\n // app host — the ingestion host does not serve those pages.\n return `You have access to the PostHog MCP server and the wizard tools.\n\nProject context:\n- PostHog Project ID: ${ctx.projectId}\n- PostHog public token: ${ctx.projectApiKey}\n- PostHog Host: ${ctx.host.apiHost}\n- PostHog app URL (base for any link you show the user in a browser): ${ctx.host.appHost}`;\n}\n\n/** Points the agent at the framework's reference integration to learn patterns from. */\nfunction exampleReference(ctx: OrchestratorPromptContext): string | null {\n if (!ctx.examplePath) return null;\n return `A reference PostHog integration for this framework is at \\`${ctx.examplePath}\\`. It shows the target implementation pattern. Reference its patterns and conventions, adapting them to this codebase.`;\n}\n\n/** The framework's rules ship with the reference skill; every task follows them. */\nfunction commandmentsReference(ctx: OrchestratorPromptContext): string | null {\n if (!ctx.commandmentsPath) return null;\n return `Framework rules for this integration are at \\`${ctx.commandmentsPath}\\`. Read them before you edit and follow them.`;\n}\n\n/**\n * The task's own tool list, injected so an agent never has to discover a tool's\n * absence by trying it — and never reports that absence as a finding. Later\n * tasks hold tools this one does not, so work it cannot do is handed on rather\n * than attempted.\n */\n/** Renders the inventory from the tool names a harness actually registered for\n * the run — the one complete list, in the vocabulary the agent will call. */\nexport function renderToolInventory(toolNames: readonly string[]): string {\n if (toolNames.length === 0) return '';\n return `Your tools for this task: ${toolNames.join(\n ', ',\n )}. Do not look for a tool that is not listed or treat its absence as a problem to report. Later tasks in this run hold tools you do not: when your task needs one, hand that work off in your handoff for the task that can do it, or note it for the final report.`;\n}\n\nconst TASK_BASICS = `You are one step in a larger PostHog workflow made of several tasks, run as a fresh agent with no memory of the other tasks beyond the context you are given. Other tasks — before and after you — own the rest of the work, so stay strictly on your own task: do not do a neighbouring step's job, redo what an upstream handoff already did, or reach beyond what you were asked. Do only your task, then report exactly once by calling complete_task with a structured handoff: what your goal was, what you did, and what the next agent should know. When you are given context from previous steps, trust it — those agents already did their work, so do not re-verify or re-read what their handoffs tell you. Build on it and move fast. Read a file before you edit it, so your own changes do not duplicate what is already there. Work only inside this project's own directory: never read, list, or search (find, ls, grep, glob) outside it — not the OS, not other projects, not global package caches. If your task seems to need something outside this directory, it does not — skip that part and say so in your handoff rather than hunting across the filesystem. If your task does not apply to this project — there is genuinely nothing for it to do — report it with status \\`not needed\\` and say why, rather than marking it done.`;\n\nconst SEED_BASICS = `You are the orchestrator. Plan the work and seed the queue with enqueue_task — each call returns an id you can pass as a dependency to a later task. Give each task a short label for the UI — the action in a few words, not file names, class names, or other specifics. The last task you queue, the one that reports on the run, must depend on every other task in the queue — directly, or through a task it already depends on. You are not a task yourself: do not call complete_task and do not edit the project.`;\n\n/**\n * Tasks the wizard queued before the planner ran. It has to see them: they are\n * part of the run it is planning around, and the task that reports last has to\n * depend on them. Their ids are real, so it can wire the edge directly.\n *\n * The one-way rule matters as much as the sink edge. These tasks are deferred to\n * the end of the drain after planning (`seeded-deps.ts`) and may block on a\n * person, so a task the planner hangs off one would wait on the user too — which\n * is the interruption deferring them removed. The resolver drops such a task\n * from the seeded task's own dependencies to stay acyclic, so the damage is\n * silent; saying so here is what prevents it.\n */\nfunction preQueuedTasks(\n tasks: readonly { id: string; type: string }[],\n): string | null {\n if (tasks.length === 0) return null;\n const lines = tasks.map((t) => `- ${t.type} (id: ${t.id})`);\n return `The queue already holds these tasks, placed by the wizard from what it found in this project. Do not queue them again. They run late — after every task you queue — and one may stop to ask the user for input, so make the reporting task depend on each one and hang nothing else off them: any other task you made depend on one would end up waiting on a person.\\n${lines.join(\n '\\n',\n )}`;\n}\n\n/**\n * Points the agent at its installed task instructions (the HOW). They live under\n * the wizard's run dir, not `.claude/skills/`, so the SDK does not auto-load\n * them — the prompt has to name them.\n */\nfunction skillReference(paths: readonly string[]): string | null {\n if (paths.length === 0) return null;\n const list = paths.map((p) => `\\`${p}\\``).join(', ');\n return `Your task instructions are at ${list}. Read them before you start and follow them. They are wizard scaffolding, not part of the project.`;\n}\n\n/** A task agent's full prompt: injected basics, then the authored intent. */\nexport function assembleTaskPrompt(\n ctx: OrchestratorPromptContext,\n body: string,\n skillPaths: readonly string[] = [],\n): string {\n return [\n projectContext(ctx),\n exampleReference(ctx),\n commandmentsReference(ctx),\n skillReference(skillPaths),\n TASK_BASICS,\n body,\n ]\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/** The seed agent's full prompt: injected basics, then the authored intent. */\nexport function assembleSeedPrompt(\n ctx: OrchestratorPromptContext,\n body: string,\n preQueued: readonly { id: string; type: string }[] = [],\n): string {\n return [projectContext(ctx), SEED_BASICS, preQueuedTasks(preQueued), body]\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/** Orchestrator tools are MCP tools under the `posthog-wizard` server. Frontmatter\n * names them short (e.g. `enqueue_task`); the SDK gates on the full name. */\nconst ORCHESTRATOR_TOOL_PREFIX = 'mcp__posthog-wizard__';\nconst ORCHESTRATOR_TOOLS = new Set([\n 'enqueue_task',\n 'complete_task',\n 'read_handoffs',\n]);\n\n/** The one tool that stops a task until a person answers. Named short in frontmatter. */\nexport const ASK_TOOL = 'wizard_ask';\n\n/**\n * The PostHog MCP, as an agent asks for it in frontmatter. Every tool a task\n * gets is granted by its own prompt, this one included: a task that never names\n * it never has the server wired in, and one that does gets it under this name\n * on both harnesses.\n */\nexport const POSTHOG_MCP_TOOL = 'posthog_exec';\n/** The same tool as the anthropic SDK names it, on the hosted PostHog server. */\nconst POSTHOG_MCP_SDK_TOOL = 'mcp__posthog-wizard__exec';\n\n/** Whether a task asked for the PostHog MCP — accepts either spelling. */\nexport function allowsPostHogMcp(\n allowedTools: readonly string[] | undefined,\n): boolean {\n return (allowedTools ?? []).some(\n (name) => name === POSTHOG_MCP_TOOL || name === POSTHOG_MCP_SDK_TOOL,\n );\n}\n\n/** The queue tools a task holds — all of them minus its disallows. Short names.\n * Single source for both the injected inventory and the harness's tool grant. */\nexport function queueTools(disallowedTools: readonly string[]): string[] {\n const disallowed = new Set(\n disallowedTools.map((n) => n.replace(ORCHESTRATOR_TOOL_PREFIX, '')),\n );\n return [...ORCHESTRATOR_TOOLS].filter((t) => !disallowed.has(t));\n}\n\n/** A parsed agent prompt. The frontmatter fields plus the markdown body. */\nexport interface AgentPrompt {\n type: string;\n /** Human-readable title for the TUI; falls back to `type` when absent. */\n label?: string;\n /** The flow this agent belongs to (the program id, e.g. \\`posthog-integration\\`). */\n flow?: string;\n /** Marks the flow's planner: it seeds the queue and is not an enqueueable task. */\n seed: boolean;\n /** Marks a task that runs last: it must depend on every other task in the queue. */\n sink: boolean;\n /**\n * Marks a task only the wizard may queue. The planner never sees the type, so\n * whether it runs is a decision the client makes from what it detected, not\n * one an agent can reach — it can neither invent the task nor forget it.\n */\n runnerSeeded: boolean;\n /** Per-profile model + effort. `pi` = the gpt/pi harness, `sdk` = the anthropic\n * harness. The mapping is not 1:1 across providers, so each agent names both. */\n modelPi?: string;\n effortPi?: ThinkingLevel;\n modelSdk?: string;\n effortSdk?: ThinkingLevel;\n skills: string[];\n allowedTools: string[];\n disallowedTools: string[];\n /**\n * Task types this one runs after. Read differently by the two kinds of task:\n *\n * - **Enqueueable types**: advisory. The planner authors the real graph with\n * `enqueue_task`, passing ids, and its seed prompt describes the shape it\n * should build. Nothing resolves this field for them.\n * - **`runnerSeeded` types**: authoritative. Such a task is queued before the\n * planner runs, so it cannot name ids; the runner resolves these types to\n * the ids the planner produced and applies them (see `seeded-deps.ts`).\n * Empty means \"after everything that is not the sink\".\n */\n dependsOn: string[];\n body: string;\n}\n\n/** The model + effort an agent runs on for a given harness — `pi` picks the gpt\n * column, anything else the sdk (anthropic) column. */\nexport function promptModelFor(\n prompt: AgentPrompt,\n harness: string,\n): { model?: string; effort?: ThinkingLevel } {\n const pi = harness === 'pi';\n return {\n model: pi ? prompt.modelPi : prompt.modelSdk,\n effort: pi ? prompt.effortPi : prompt.effortSdk,\n };\n}\n\nexport interface AgentRegistry {\n /** The flow's task types — every prompt except the seed. */\n readonly types: string[];\n /** The types an agent may enqueue: `types` minus the runner-seeded ones. */\n readonly enqueueableTypes: string[];\n /** The types that run last and must depend on the whole queue. */\n readonly sinkTypes: string[];\n /** The types only the wizard queues, from what it detected before the run. */\n readonly runnerSeededTypes: string[];\n /** The flow's planner, the one prompt marked `seed: true` in its frontmatter. */\n readonly seed?: AgentPrompt;\n get(type: string): AgentPrompt | undefined;\n}\n\n/** The registry for one flow's prompts. Pure; the loader feeds it the fetched set. */\nexport function buildRegistry(\n prompts: readonly AgentPrompt[],\n flow: string,\n opts?: {\n exclude?: readonly string[];\n /** Per-stage pi model/effort overlays, keyed by task type ('seed' for the planner). Applied here — the one place prompts enter the wizard — so every downstream read sees the effective spec. */\n overrides?: Record<\n string,\n { model?: string; effort?: ThinkingLevel } | undefined\n >;\n },\n): AgentRegistry {\n // The harness can exclude task types (CI excludes dashboards). An excluded\n // type does not exist for the run: the seed cannot enqueue it and no agent\n // is ever spun up for it.\n const excluded = new Set(opts?.exclude ?? []);\n const inFlow = prompts\n .filter((p) => p.flow === flow && !excluded.has(p.type))\n .map((p) => {\n const o = opts?.overrides?.[p.seed ? 'seed' : p.type];\n if (!o) return p;\n return {\n ...p,\n modelPi: o.model ?? p.modelPi,\n effortPi: o.effort ?? p.effortPi,\n };\n });\n const byType = new Map(inFlow.map((p) => [p.type, p]));\n const tasks = inFlow.filter((p) => !p.seed);\n return {\n types: tasks.map((p) => p.type),\n enqueueableTypes: tasks.filter((p) => !p.runnerSeeded).map((p) => p.type),\n sinkTypes: tasks.filter((p) => p.sink).map((p) => p.type),\n runnerSeededTypes: tasks.filter((p) => p.runnerSeeded).map((p) => p.type),\n seed: inFlow.find((p) => p.seed),\n get: (type) => byType.get(type),\n };\n}\n\ninterface AgentMenu {\n /** `flow` arrived with context-mill's flow-scoped agents folder; older menus omit it. */\n agents: { id: string; flow?: string; downloadUrl: string }[];\n}\n\n/** A native tool passes through; an MCP tool gets its fully-qualified name. */\nfunction expandToolName(name: string): string {\n if (name === ASK_TOOL) return WIZARD_TOOL_NAMES.wizardAsk;\n if (name === POSTHOG_MCP_TOOL) return POSTHOG_MCP_SDK_TOOL;\n return ORCHESTRATOR_TOOLS.has(name)\n ? `${ORCHESTRATOR_TOOL_PREFIX}${name}`\n : name;\n}\n\n/** A prompt's allow/disallow lists with orchestrator tool names MCP-qualified. */\nexport function agentRunTools(prompt: AgentPrompt): {\n allowedTools: string[];\n disallowedTools: string[];\n} {\n return {\n allowedTools: prompt.allowedTools.map(expandToolName),\n disallowedTools: prompt.disallowedTools.map(expandToolName),\n };\n}\n\nfunction toStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((v): v is string => typeof v === 'string');\n}\n\n/**\n * Parse the leading `---` frontmatter block and the markdown body. The\n * frontmatter is a small, known schema (scalars and inline `[a, b]` arrays), so\n * a tiny parser covers it without a YAML dependency. Inline `# comments` after a\n * value are stripped. `fallbackType` (the menu id) and `fallbackFlow` (the\n * menu entry's flow) apply when the frontmatter omits `type:`/`flow:`.\n */\nexport function parseAgentPrompt(\n text: string,\n fallbackType: string,\n fallbackFlow?: string,\n): AgentPrompt {\n const match = text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n const frontmatter = match ? match[1] : '';\n const body = (match ? match[2] : text).trim();\n\n const fields: Record<string, unknown> = {};\n for (const rawLine of frontmatter.split(/\\r?\\n/)) {\n const line = rawLine.replace(/\\s+#.*$/, '').trim();\n if (!line || line.startsWith('#')) continue;\n const kv = line.match(/^([\\w-]+):\\s*(.*)$/);\n if (!kv) continue;\n const [, key, raw] = kv;\n if (raw.startsWith('[') && raw.endsWith(']')) {\n fields[key] = raw\n .slice(1, -1)\n .split(',')\n .map((s) => s.trim().replace(/^['\"]|['\"]$/g, ''))\n .filter(Boolean);\n } else {\n fields[key] = raw.replace(/^['\"]|['\"]$/g, '');\n }\n }\n\n const str = (v: unknown) => (typeof v === 'string' ? v : undefined);\n // Effort is remote data — reject typos here so downstream carries ThinkingLevel.\n const effort = (v: unknown, key: string): ThinkingLevel | undefined => {\n if (v === undefined) return undefined;\n if (isThinkingLevel(v)) return v;\n logToFile(\n `[agent-prompt] ${fallbackType}: ignoring invalid ${key} \"${String(v)}\"`,\n );\n analytics.wizardCapture('agent prompt invalid effort', {\n task_type: fallbackType,\n key,\n value: String(v),\n });\n return undefined;\n };\n return {\n type: typeof fields.type === 'string' ? fields.type : fallbackType,\n label: typeof fields.label === 'string' ? fields.label : undefined,\n flow: typeof fields.flow === 'string' ? fields.flow : fallbackFlow,\n seed: fields.seed === 'true',\n sink: fields.sink === 'true',\n runnerSeeded: fields.runnerSeeded === 'true',\n modelPi: str(fields.model_pi),\n effortPi: effort(fields.effort_pi, 'effort_pi'),\n modelSdk: str(fields.model_sdk),\n effortSdk: effort(fields.effort_sdk, 'effort_sdk'),\n skills: toStringArray(fields.skills),\n allowedTools: toStringArray(fields.allowedTools),\n disallowedTools: toStringArray(fields.disallowedTools),\n dependsOn: toStringArray(fields.dependsOn),\n body,\n };\n}\n\nasync function fetchText(url: string): Promise<string> {\n const res = await fetchWithRetry(url);\n return res.text();\n}\n\n/**\n * Fetch the agent menu and every agent prompt it lists, parse them, and build\n * the registry for one flow. Throws if the menu cannot be fetched — the\n * orchestrator cannot run without its prompts.\n */\nexport async function loadAgentRegistry(\n skillsBaseUrl: string,\n flow: string,\n opts?: Parameters<typeof buildRegistry>[2],\n): Promise<AgentRegistry> {\n const menuRaw = await fetchText(`${skillsBaseUrl}/agent-menu.json`);\n const menu = JSON.parse(menuRaw) as AgentMenu;\n\n // Menus that carry a flow per entry let us skip other flows' prompts before\n // fetching them; entries without one are fetched and filtered by their\n // frontmatter in buildRegistry, as before.\n const entries = (menu.agents ?? []).filter(\n (entry) => !entry.flow || entry.flow === flow,\n );\n const prompts = await Promise.all(\n entries.map(async (entry) => {\n const text = await fetchText(entry.downloadUrl);\n return parseAgentPrompt(text, entry.id, entry.flow);\n }),\n );\n\n return buildRegistry(prompts, flow, opts);\n}\n\n/**\n * Render a task's own inputs into a section, so a fanned-out task (e.g. one\n * `capture` per event) sees the specific thing it owns. Empty when there are none.\n */\nfunction renderInputs(task: QueuedTask): string {\n const entries = Object.entries(task.inputs ?? {});\n if (entries.length === 0) return '';\n const lines = entries.map(([k, v]) => `- ${k}: ${formatInputValue(v)}`);\n return `## Your task input\\n\\n${lines.join('\\n')}`;\n}\n\nfunction formatInputValue(value: unknown): string {\n if (typeof value === 'string') return value;\n return JSON.stringify(value);\n}\n\n/**\n * The ids of every task `task` transitively depends on — the full upstream\n * chain, not just direct dependencies — ordered roots-first, each once. A `seen`\n * set dedupes diamonds and guards against cycles.\n */\nfunction ancestorIds(task: QueuedTask, store: QueueStore): string[] {\n const seen = new Set<string>();\n const ordered: string[] = [];\n const visit = (id: string): void => {\n if (seen.has(id)) return;\n seen.add(id);\n const t = store.get(id);\n if (!t) return;\n for (const dep of t.dependsOn) visit(dep); // ancestors before dependents\n ordered.push(id);\n };\n for (const dep of task.dependsOn) visit(dep);\n return ordered;\n}\n\n/**\n * Render the handoffs of every step `task` transitively depends on into a context\n * section, so a fresh agent sees the whole upstream chain — not just its direct\n * dependencies. Reliability over token economy: a step must never have to\n * re-discover what any ancestor already established just because an intermediate\n * handoff happened to omit it. Empty when there are no completed ancestors.\n */\nfunction renderHandoffContext(task: QueuedTask, store: QueueStore): string {\n const lines: string[] = [];\n for (const id of ancestorIds(task, store)) {\n const dep = store.get(id);\n const handoff = store.readHandoff(id);\n if (!dep || !handoff) continue;\n lines.push(`### ${dep.type}`);\n lines.push(`- did: ${handoff.did}`);\n lines.push(`- for you: ${handoff.forNextAgent}`);\n if (handoff.filesTouched?.length) {\n lines.push(`- files: ${handoff.filesTouched.join(', ')}`);\n }\n if (handoff.evidence) {\n lines.push(`- evidence: ${handoff.evidence}`);\n }\n if (handoff.assumptions) {\n lines.push(`- assumed: ${handoff.assumptions}`);\n }\n if (handoff.reportSection) {\n lines.push(`- report section:\\n${handoff.reportSection}`);\n }\n lines.push('');\n }\n if (lines.length === 0) return '';\n return `## Context from previous steps\\n\\n${lines.join('\\n')}`.trim();\n}\n\n/**\n * Resolve a queued task to its run config: the prompt body (with upstream\n * handoffs appended), the model, and the tool lists with orchestrator tool names\n * MCP-qualified. The model precedence is enqueue override, then prompt, then\n * default. Throws if no prompt is registered for the task's type.\n */\nexport function resolveTask(\n registry: AgentRegistry,\n task: QueuedTask,\n store: QueueStore,\n): ResolvedTask {\n const prompt = registry.get(task.type);\n if (!prompt) {\n throw new Error(`No agent prompt registered for task type \"${task.type}\"`);\n }\n\n const body = [\n renderInputs(task),\n prompt.body,\n renderHandoffContext(task, store),\n ]\n .filter(Boolean)\n .join('\\n\\n');\n\n return {\n ...agentRunTools(prompt),\n prompt: body,\n skills: prompt.skills,\n };\n}\n\n/** The model + effort a task runs on for a harness: enqueue override, then the\n * prompt's per-profile frontmatter; the caller's switchboard pick is the fallback. */\nexport function taskModelSpec(\n registry: AgentRegistry,\n task: QueuedTask,\n harness: string,\n): { model?: string; effort?: ThinkingLevel } {\n const picked = promptModelFor(\n registry.get(task.type) ?? EMPTY_PROMPT,\n harness,\n );\n return {\n model: task.model ?? picked.model,\n effort: picked.effort,\n };\n}\n\nconst EMPTY_PROMPT = {} as AgentPrompt;\n"],"mappings":"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"}
@@ -1,17 +1,17 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
2
- import { A as GPT5_6_LUNA_MODEL, D as DEFAULT_AGENT_MODEL, F as Harness, M as GPT5_6_TERRA_MODEL, _ as evaluateWizardReadiness, a as getLogFilePath, c as WIZARD_BENCHMARK_FILE, ct as WIZARD_ORCHESTRATOR_OVERRIDE_FLAG_KEY, et as SONNET_5_MODEL, f as getUI, ft as WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY, g as SIGNUP_WIZARD_READINESS_CONFIG, h as SERVICE_LABELS, i as enableDebugLogs, j as GPT5_6_SOL_MODEL, l as WIZARD_LOG_FILE, lt as WIZARD_ORCHESTRATOR_SEEDED_TASKS_FLAG_KEY, mt as getSkillsBaseUrl, o as initLogFile, rt as WIZARD_CONTACT_EMAIL, s as logToFile, st as WIZARD_ORCHESTRATOR_FLAG_KEY, t as configureLogFile, tt as Sequence, v as getBlockingServiceKeys, vt as RUN_SURFACE, xt as runtimeEnv } from "./debug-BTPYy9p7.js";
3
- import { a as ciExcludedTaskTypes, n as analytics, r as groupsFromUser } from "./analytics-BdKBzz4M.js";
4
- import { t as getOrAskForProjectData } from "./setup-utils-iINkc0xu.js";
2
+ import { A as GPT5_6_LUNA_MODEL, D as DEFAULT_AGENT_MODEL, F as Harness, M as GPT5_6_TERRA_MODEL, _ as evaluateWizardReadiness, a as getLogFilePath, c as WIZARD_BENCHMARK_FILE, ct as WIZARD_ORCHESTRATOR_OVERRIDE_FLAG_KEY, et as SONNET_5_MODEL, f as getUI, ft as WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY, g as SIGNUP_WIZARD_READINESS_CONFIG, h as SERVICE_LABELS, i as enableDebugLogs, j as GPT5_6_SOL_MODEL, l as WIZARD_LOG_FILE, lt as WIZARD_ORCHESTRATOR_SEEDED_TASKS_FLAG_KEY, mt as getSkillsBaseUrl, o as initLogFile, rt as WIZARD_CONTACT_EMAIL, s as logToFile, st as WIZARD_ORCHESTRATOR_FLAG_KEY, t as configureLogFile, tt as Sequence, v as getBlockingServiceKeys, vt as RUN_SURFACE, xt as runtimeEnv } from "./debug-3FJsmlmC.js";
3
+ import { a as ciExcludedTaskTypes, n as analytics, r as groupsFromUser } from "./analytics-Duy9Vfk-.js";
4
+ import { t as getOrAskForProjectData } from "./setup-utils-DJF-LjYE.js";
5
5
  import "./wizard-session-BUhlJ1b8.js";
6
- import { i as wizardAbort, n as registerCleanup, t as WizardError } from "./wizard-abort-CztG5WTv.js";
7
- import { n as isNonInteractiveEnvironment } from "./environment-lV2X1gS-.js";
8
- import { c as QueueStore, h as requireKnownModel, l as TaskStatus, o as uncoveredBySink, p as isValidModel, s as QUEUE_DIR_NAME } from "./queue-tools-zM8_mxx6.js";
9
- import { E as installSkillById, F as createTriageLLMProvider, N as createWizardAskBridge, T as fetchSkillMenu, c as classifySettingsConflicts, i as runAgent$1, n as buildRunTags, o as backupAndFixClaudeSettings, p as AgentSignals, r as initializeAgent, s as checkAllSettingsConflicts, u as restoreClaudeSettings } from "./agent-interface-C90hyvs1.js";
10
- import { a as flushScanReport, m as writeScanReport, o as formatScanReport, s as formatYaraAbortMessage } from "./yara-hooks-DeLjTIiJ.js";
11
- import { a as piBackend, s as createAioCapture } from "./pi-CVJB0Ban.js";
12
- import { r as detectNodePackageManagers } from "./package-manager-z33XHEWO.js";
13
- import { t as FRAMEWORK_REGISTRY } from "./registry-DF_aKyS0.js";
14
- import { a as assembleTaskPrompt, d as taskModelSpec, i as assembleSeedPrompt, n as agentRunTools, o as loadAgentRegistry, s as promptModelFor, t as ASK_TOOL, u as resolveTask } from "./agent-prompt-loader-CBj2DWAJ.js";
6
+ import { i as wizardAbort, n as registerCleanup, t as WizardError } from "./wizard-abort-BeuIRy5a.js";
7
+ import { n as isNonInteractiveEnvironment } from "./environment-Cyq61jKV.js";
8
+ import { _ as requireKnownModel, c as uncoveredBySink, d as TaskStatus, h as isValidModel, l as QUEUE_DIR_NAME, s as dependencyClosure, u as QueueStore } from "./queue-tools-DED9kPuc.js";
9
+ import { E as installSkillById, F as createTriageLLMProvider, N as createWizardAskBridge, T as fetchSkillMenu, c as classifySettingsConflicts, i as runAgent$1, n as buildRunTags, o as backupAndFixClaudeSettings, p as AgentSignals, r as initializeAgent, s as checkAllSettingsConflicts, u as restoreClaudeSettings } from "./agent-interface-BQfwaSe-.js";
10
+ import { a as flushScanReport, m as writeScanReport, o as formatScanReport, s as formatYaraAbortMessage } from "./yara-hooks-CCGjiVA2.js";
11
+ import { a as piBackend, s as createAioCapture } from "./pi-DohBskuT.js";
12
+ import { r as detectNodePackageManagers } from "./package-manager-62MxCa1Y.js";
13
+ import { t as FRAMEWORK_REGISTRY } from "./registry-Dh9aqVC6.js";
14
+ import { a as assembleTaskPrompt, d as taskModelSpec, i as assembleSeedPrompt, n as agentRunTools, o as loadAgentRegistry, s as promptModelFor, t as ASK_TOOL, u as resolveTask } from "./agent-prompt-loader-BRKe3VE6.js";
15
15
  import fs, { cpSync, existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from "fs";
16
16
  import * as path$1 from "path";
17
17
  import path from "path";
@@ -21,7 +21,7 @@ import { randomUUID } from "crypto";
21
21
  async function authenticate(session, programId) {
22
22
  if (session.credentials) return;
23
23
  logToFile("[agent-runner] starting OAuth");
24
- const { projectApiKey, host, accessToken, projectId, roleAtOrganization, user, project } = await getOrAskForProjectData({
24
+ const { projectApiKey, host, accessToken, projectId, roleAtOrganization, user, project, missingScopes } = await getOrAskForProjectData({
25
25
  signup: session.signup,
26
26
  ci: session.ci,
27
27
  apiKey: session.apiKey,
@@ -36,7 +36,8 @@ async function authenticate(session, programId) {
36
36
  accessToken,
37
37
  projectApiKey,
38
38
  host,
39
- projectId
39
+ projectId,
40
+ missingScopes
40
41
  };
41
42
  session.apiProject = project;
42
43
  session.roleAtOrganization = roleAtOrganization;
@@ -105,6 +106,7 @@ const anthropicBackend = {
105
106
  additionalFeatureQueue: config.additionalFeatureQueue ?? [],
106
107
  abortCases: config.abortCases,
107
108
  emitStepEvents: config.trackStepProgress ?? false,
109
+ resolveStepKey: config.resolveStepKey,
108
110
  triageProvider: boot.triageProvider
109
111
  }, middleware);
110
112
  },
@@ -1614,6 +1616,7 @@ var RunMetrics = class {
1614
1616
  firstStartMs;
1615
1617
  lastStartMs;
1616
1618
  firstCompleteMs;
1619
+ firstAskMs;
1617
1620
  lastVisibleMs;
1618
1621
  maxGapMs = 0;
1619
1622
  constructor(runStartMs) {
@@ -1640,6 +1643,14 @@ var RunMetrics = class {
1640
1643
  this.markVisible(nowMs);
1641
1644
  }
1642
1645
  /**
1646
+ * A question was put to the user. Only the first matters here, and it is not a
1647
+ * queue transition — waiting on a person is not the silence `max_gap_ms`
1648
+ * measures, so this deliberately does not mark visible progress.
1649
+ */
1650
+ recordAsk(nowMs) {
1651
+ this.firstAskMs ??= nowMs;
1652
+ }
1653
+ /**
1643
1654
  * The run-level responsiveness summary. Timings are `undefined` when the
1644
1655
  * relevant transition never happened (e.g. a run that started no task), so a
1645
1656
  * no-task run stays distinguishable from a genuine zero.
@@ -1648,7 +1659,8 @@ var RunMetrics = class {
1648
1659
  return {
1649
1660
  time_to_first_task_ms: this.firstStartMs === void 0 ? void 0 : this.firstStartMs - this.runStartMs,
1650
1661
  time_to_first_completion_ms: this.firstCompleteMs === void 0 ? void 0 : this.firstCompleteMs - this.runStartMs,
1651
- max_gap_ms: this.lastVisibleMs === void 0 ? void 0 : this.maxGapMs
1662
+ max_gap_ms: this.lastVisibleMs === void 0 ? void 0 : this.maxGapMs,
1663
+ time_to_first_ask_ms: this.firstAskMs === void 0 ? void 0 : this.firstAskMs - this.runStartMs
1652
1664
  };
1653
1665
  }
1654
1666
  /** requeue is not user-visible, so a retry stall counts as silence here. */
@@ -1658,6 +1670,72 @@ var RunMetrics = class {
1658
1670
  }
1659
1671
  };
1660
1672
  //#endregion
1673
+ //#region src/lib/agent/runner/sequence/orchestrator/seeded-deps.ts
1674
+ /**
1675
+ * Resolve a runner-seeded task's dependencies against the planned queue.
1676
+ *
1677
+ * Two exclusions apply to both the declared and the default path:
1678
+ *
1679
+ * - **Sinks are never dependencies.** A sink runs last and must depend on the
1680
+ * whole queue, this task included. Depending on it back would invert the edge
1681
+ * and cost the report this task's `reportSection`. Leaving sinks out means a
1682
+ * planner that forgot the sink→seeded edge is still caught by the sink
1683
+ * invariant check rather than silently papered over here.
1684
+ * - **Anything already downstream of this task is never a dependency**, which is
1685
+ * what makes the result cycle-free by construction rather than by the queue's
1686
+ * per-edge refusal.
1687
+ */
1688
+ function seededDependencies(store, seededTaskId, declaredTypes, sinkTypes) {
1689
+ const eligible = store.list().filter((task) => {
1690
+ if (task.id === seededTaskId) return false;
1691
+ if (sinkTypes.includes(task.type)) return false;
1692
+ return !dependencyClosure(store, [task.id]).has(seededTaskId);
1693
+ });
1694
+ if (declaredTypes.length === 0) return {
1695
+ depIds: eligible.map((t) => t.id),
1696
+ unresolvedTypes: [],
1697
+ declared: false
1698
+ };
1699
+ const depIds = [];
1700
+ const unresolvedTypes = [];
1701
+ for (const type of declaredTypes) {
1702
+ if (!store.list().some((t) => t.type === type)) {
1703
+ unresolvedTypes.push(type);
1704
+ continue;
1705
+ }
1706
+ for (const task of eligible) if (task.type === type && !depIds.includes(task.id)) depIds.push(task.id);
1707
+ }
1708
+ return {
1709
+ depIds,
1710
+ unresolvedTypes,
1711
+ declared: true
1712
+ };
1713
+ }
1714
+ /**
1715
+ * Give every runner-seeded task the dependencies it could not name at enqueue,
1716
+ * and report what happened per task.
1717
+ *
1718
+ * The runner calls this once, after the planner has seeded the queue and before
1719
+ * the sink invariant is checked. Kept here rather than inline in the runner so
1720
+ * the wiring — which prompt's types feed which task — is testable without
1721
+ * standing up a whole run.
1722
+ */
1723
+ function deferSeededTasks(store, seededTasks, declaredTypesFor, sinkTypes) {
1724
+ return seededTasks.map((seeded) => {
1725
+ const declaredTypes = [...declaredTypesFor(seeded.type)];
1726
+ const resolved = seededDependencies(store, seeded.id, declaredTypes, sinkTypes);
1727
+ const { added, refused } = store.addDependencies(seeded.id, resolved.depIds);
1728
+ return {
1729
+ type: seeded.type,
1730
+ declaredTypes,
1731
+ declared: resolved.declared,
1732
+ added,
1733
+ refused,
1734
+ unresolvedTypes: resolved.unresolvedTypes
1735
+ };
1736
+ });
1737
+ }
1738
+ //#endregion
1661
1739
  //#region src/lib/agent/runner/sequence/orchestrator/orchestrator-runner.ts
1662
1740
  /**
1663
1741
  * Experimental task-queue orchestrator runner.
@@ -1747,6 +1825,43 @@ function resolveReferenceSkillId(entries, framework) {
1747
1825
  * — the executor holds the task's promise — so the only real limit is this one.
1748
1826
  */
1749
1827
  const TASK_ASK_TIMEOUT_MS = 1200 * 1e3;
1828
+ /**
1829
+ * How long an optional step's notice waits for an answer.
1830
+ *
1831
+ * Much shorter than the ask timeout above, because it is asking for something
1832
+ * much smaller: one keypress to accept or decline, not "go mint a restricted
1833
+ * Stripe key". The notice is also the only interactive screen sitting in front
1834
+ * of the run's final steps, so an unanswered one holds the report — and with it
1835
+ * the notebook and the outro — behind a modal nobody is looking at.
1836
+ */
1837
+ const TASK_NOTICE_TIMEOUT_MS = 300 * 1e3;
1838
+ /**
1839
+ * Offer an optional step, defaulting to declining it if nobody answers.
1840
+ *
1841
+ * Skip is the right default on a timeout: continuing would send the step on to
1842
+ * ask for credentials that the same absent user cannot supply either, burning
1843
+ * {@link TASK_ASK_TIMEOUT_MS} per question before falling back to the same
1844
+ * links declining gives immediately.
1845
+ */
1846
+ async function offerSeededTask(notice, timeoutMs = TASK_NOTICE_TIMEOUT_MS) {
1847
+ let timer;
1848
+ let timedOut = false;
1849
+ const timeout = new Promise((resolve) => {
1850
+ timer = setTimeout(() => {
1851
+ timedOut = true;
1852
+ getUI().cancelTaskNotice();
1853
+ resolve(false);
1854
+ }, timeoutMs);
1855
+ });
1856
+ try {
1857
+ return {
1858
+ keep: await Promise.race([getUI().showTaskNotice(notice), timeout]),
1859
+ timedOut
1860
+ };
1861
+ } finally {
1862
+ if (timer) clearTimeout(timer);
1863
+ }
1864
+ }
1750
1865
  /** Whether a task's prompt lets it ask the user, and so needs the ask bridge. */
1751
1866
  function canAsk(prompt) {
1752
1867
  return (prompt?.allowedTools ?? []).includes(ASK_TOOL);
@@ -1789,7 +1904,7 @@ function displayOrder(tasks, isOptional) {
1789
1904
  index
1790
1905
  })).sort((a, b) => a.depth - b.depth || a.optional - b.optional || a.index - b.index).map((entry) => entry.task);
1791
1906
  }
1792
- async function runOrchestrator(session, programConfig, boot) {
1907
+ async function runOrchestrator(session, config, programConfig, boot) {
1793
1908
  const runId = randomUUID();
1794
1909
  const switchboardCtx = {
1795
1910
  program: programConfig.id,
@@ -1869,7 +1984,8 @@ async function runOrchestrator(session, programConfig, boot) {
1869
1984
  let commandmentsPath;
1870
1985
  let referenceInstallPath;
1871
1986
  const menuSkillEntries = await fetchSkillMenuEntries(boot.skillsBaseUrl);
1872
- const referenceSkillId = session.skillId ? resolveReferenceSkillId(menuSkillEntries, session.skillId) : void 0;
1987
+ const framework = session.integration ?? session.skillId ?? void 0;
1988
+ const referenceSkillId = framework ? resolveReferenceSkillId(menuSkillEntries, framework) : void 0;
1873
1989
  if (referenceSkillId) {
1874
1990
  const ref = await installSkillById(referenceSkillId, session.installDir, boot.skillsBaseUrl, {
1875
1991
  skillsRoot: path$1.join(QUEUE_DIR_NAME, "reference"),
@@ -1882,16 +1998,16 @@ async function runOrchestrator(session, programConfig, boot) {
1882
1998
  const commandments = path$1.join(ref.path, "references", "COMMANDMENTS.md");
1883
1999
  if (existsSync(path$1.join(session.installDir, commandments))) commandmentsPath = commandments;
1884
2000
  } else logToFile(`[orchestrator] reference unavailable: ${ref.kind} (${referenceSkillId})`);
1885
- } else if (session.skillId) logToFile(`[orchestrator] no integration skill for framework "${session.skillId}"`);
2001
+ } else if (framework) logToFile(`[orchestrator] no integration skill for framework "${framework}"`);
1886
2002
  const missingVariants = [];
1887
2003
  for (const type of registry.types) for (const skillId of registry.get(type)?.skills ?? []) {
1888
- if (resolveSkillVariantId(menuSkillEntries, skillId, session.skillId)) continue;
2004
+ if (resolveSkillVariantId(menuSkillEntries, skillId, framework)) continue;
1889
2005
  missingVariants.push(`${type}/${skillId}`);
1890
- logToFile(`[orchestrator] no skill variant type=${type} skill=${skillId} framework=${session.skillId ?? "none"}`);
2006
+ logToFile(`[orchestrator] no skill variant type=${type} skill=${skillId} framework=${framework ?? "none"}`);
1891
2007
  analytics.wizardCapture("orchestrator skill variant missing", {
1892
2008
  task_type: type,
1893
2009
  skill: skillId,
1894
- framework: session.skillId
2010
+ framework
1895
2011
  });
1896
2012
  }
1897
2013
  if (missingVariants.length > 0) await wizardAbort({
@@ -1901,10 +2017,10 @@ Please try again, or contact wizard@posthog.com.
1901
2017
  You can also set up with your agent by downloading the skills here:
1902
2018
  https://github.com/PostHog/context-mill/releases
1903
2019
  or integrate manually here:
1904
- ${(session.skillId ? FRAMEWORK_REGISTRY[session.skillId]?.docsUrl : void 0) ?? "https://posthog.com/docs"}`,
2020
+ ${(framework ? FRAMEWORK_REGISTRY[framework]?.docsUrl : void 0) ?? "https://posthog.com/docs"}`,
1905
2021
  error: new WizardError("Orchestrator preflight: skill variant missing", {
1906
2022
  missing: missingVariants.join(", "),
1907
- framework: session.skillId
2023
+ framework
1908
2024
  })
1909
2025
  });
1910
2026
  const promptContext = {
@@ -1927,27 +2043,19 @@ or integrate manually here:
1927
2043
  store,
1928
2044
  validTypes: registry.enqueueableTypes,
1929
2045
  sinkTypes: registry.sinkTypes,
2046
+ runnerSeededTypes: registry.runnerSeededTypes,
1930
2047
  currentTaskId
1931
2048
  });
1932
2049
  const seedEntries = areSeededTasksEnabled(boot.wizardFlags) ? programConfig.seedTasks?.(session) ?? [] : [];
1933
2050
  const seededTypes = [];
2051
+ const seededTasks = [];
2052
+ const seededNotices = /* @__PURE__ */ new Map();
1934
2053
  for (const seeded of seedEntries) {
1935
2054
  if (!registry.runnerSeededTypes.includes(seeded.type)) {
1936
2055
  logToFile(`[orchestrator] skipping runner-seeded task "${seeded.type}": not a runner-seeded type in this flow`);
1937
2056
  continue;
1938
2057
  }
1939
- if (seeded.notice) {
1940
- const keep = await getUI().showTaskNotice(seeded.notice);
1941
- analytics.wizardCapture("orchestrator task notice answered", {
1942
- type: seeded.type,
1943
- kept: keep
1944
- });
1945
- if (!keep) {
1946
- logToFile(`[orchestrator] user declined runner-seeded ${seeded.type}`);
1947
- continue;
1948
- }
1949
- }
1950
- store.enqueue({
2058
+ const task = store.enqueue({
1951
2059
  type: seeded.type,
1952
2060
  label: seeded.label,
1953
2061
  inputs: seeded.inputs,
@@ -1955,6 +2063,8 @@ or integrate manually here:
1955
2063
  optional: true
1956
2064
  });
1957
2065
  seededTypes.push(seeded.type);
2066
+ seededTasks.push(task);
2067
+ if (seeded.notice) seededNotices.set(task.id, seeded.notice);
1958
2068
  logToFile(`[orchestrator] runner-seeded task ${seeded.type}`);
1959
2069
  }
1960
2070
  const askingTypes = seededTypes.filter((type) => canAsk(registry.get(type)));
@@ -1966,9 +2076,12 @@ or integrate manually here:
1966
2076
  });
1967
2077
  const askBridge = shouldDisableAsk(session) ? void 0 : createWizardAskBridge({
1968
2078
  getSource: () => session.skillId ?? programConfig.id,
1969
- showQuestion: (q) => getUI().requestQuestion(q),
2079
+ showQuestion: (q) => {
2080
+ metrics.recordAsk(Date.now());
2081
+ return getUI().requestQuestion(q);
2082
+ },
1970
2083
  cancelQuestion: () => getUI().cancelPendingQuestion(),
1971
- richLinks: false,
2084
+ richLinks: config.richLinks ?? false,
1972
2085
  timeoutMs: TASK_ASK_TIMEOUT_MS
1973
2086
  });
1974
2087
  const spinner = getUI().spinner();
@@ -1999,6 +2112,28 @@ or integrate manually here:
1999
2112
  types: store.list().map((t) => t.type)
2000
2113
  });
2001
2114
  renderQueue();
2115
+ const deferred = deferSeededTasks(store, seededTasks, (type) => registry.get(type)?.dependsOn ?? [], registry.sinkTypes);
2116
+ for (const entry of deferred) {
2117
+ logToFile(`[orchestrator] deferred runner-seeded ${entry.type}: ${entry.added.length} deps (${entry.declared ? `declared: ${entry.declaredTypes.join(", ")}` : "default"})${entry.refused.length > 0 ? `, ${entry.refused.length} refused` : ""}${entry.unresolvedTypes.length > 0 ? `, unresolved: ${entry.unresolvedTypes.join(", ")}` : ""}`);
2118
+ analytics.wizardCapture("orchestrator seeded task deferred", {
2119
+ type: entry.type,
2120
+ dep_count: entry.added.length,
2121
+ declared: entry.declared,
2122
+ declared_types: entry.declaredTypes,
2123
+ unresolved_types: entry.unresolvedTypes,
2124
+ refused_count: entry.refused.length
2125
+ });
2126
+ }
2127
+ if (deferred.length > 0) renderQueue();
2128
+ for (const seeded of seededTasks) {
2129
+ const dependants = store.list().filter((t) => !registry.sinkTypes.includes(t.type) && t.id !== seeded.id && dependencyClosure(store, [t.id]).has(seeded.id));
2130
+ if (dependants.length === 0) continue;
2131
+ logToFile(`[orchestrator] one-way rule broken: ${dependants.map((t) => t.type).join(", ")} depend on runner-seeded ${seeded.type}`);
2132
+ analytics.wizardCapture("orchestrator seeded task depended on", {
2133
+ type: seeded.type,
2134
+ dependant_types: dependants.map((t) => t.type)
2135
+ });
2136
+ }
2002
2137
  const unwaited = store.list().filter((t) => registry.sinkTypes.includes(t.type)).flatMap((sink) => uncoveredBySink({
2003
2138
  store,
2004
2139
  validTypes: registry.types,
@@ -2020,15 +2155,45 @@ or integrate manually here:
2020
2155
  const taskSkillsRoot = path$1.join(QUEUE_DIR_NAME, "skills");
2021
2156
  const claudeSkillsDir = path$1.join(session.installDir, ".claude", "skills");
2022
2157
  const preexistingSkills = new Set(existsSync(claudeSkillsDir) ? readdirSync(claudeSkillsDir) : []);
2158
+ let noticeGate = Promise.resolve();
2023
2159
  const runTask = async (task) => {
2024
2160
  renderQueue();
2161
+ const notice = seededNotices.get(task.id);
2162
+ if (notice) {
2163
+ seededNotices.delete(task.id);
2164
+ const offer = noticeGate.then(() => offerSeededTask(notice));
2165
+ noticeGate = offer.catch(() => void 0);
2166
+ const { keep, timedOut } = await offer.catch((err) => {
2167
+ logToFile(`[orchestrator] notice failed for ${task.type}, declining: ${String(err)}`);
2168
+ analytics.captureException(err instanceof Error ? err : new Error(String(err)), { step: "orchestrator_task_notice" });
2169
+ return {
2170
+ keep: false,
2171
+ timedOut: false
2172
+ };
2173
+ });
2174
+ analytics.wizardCapture("orchestrator task notice answered", {
2175
+ type: task.type,
2176
+ kept: keep,
2177
+ timed_out: timedOut
2178
+ });
2179
+ if (!keep) {
2180
+ logToFile(`[orchestrator] runner-seeded ${task.type} declined (${timedOut ? "timed out" : "by the user"})`);
2181
+ store.skip(task.id, {
2182
+ goals: notice.title,
2183
+ did: timedOut ? "Nothing — the step was offered and the offer timed out with no answer." : "Nothing — the user chose to skip this step when offered it.",
2184
+ forNextAgent: timedOut ? "This step was offered and nobody answered, so it did no work. Report it as not set up, and point the user at how to do it later." : "This step was offered and declined, so it did no work. Report it as skipped at the user’s request, not as failed."
2185
+ });
2186
+ renderQueue();
2187
+ return;
2188
+ }
2189
+ }
2025
2190
  try {
2026
2191
  const resolved = resolveTask(registry, task, store);
2027
2192
  const skillPaths = [];
2028
2193
  for (const skillId of resolved.skills) {
2029
- const variantId = resolveSkillVariantId(menuSkillEntries, skillId, session.skillId);
2194
+ const variantId = resolveSkillVariantId(menuSkillEntries, skillId, framework);
2030
2195
  if (!variantId) {
2031
- logToFile(`[orchestrator] no skill variant type=${task.type} skill=${skillId} framework=${session.skillId ?? "none"}`);
2196
+ logToFile(`[orchestrator] no skill variant type=${task.type} skill=${skillId} framework=${framework ?? "none"}`);
2032
2197
  continue;
2033
2198
  }
2034
2199
  const result = await installSkillById(variantId, session.installDir, boot.skillsBaseUrl, {
@@ -2116,12 +2281,15 @@ or integrate manually here:
2116
2281
  const blocked = verdict.blocked;
2117
2282
  if (verdict.requiredFailedTypes.length > 0 || blocked > 0) {
2118
2283
  const failedTypes = verdict.requiredFailedTypes.join(", ");
2284
+ const whatFailed = failedTypes ? `the ${failedTypes} step failed` : `${blocked} steps never ran`;
2285
+ const missingScopes = boot.credentials.missingScopes ?? [];
2119
2286
  await wizardAbort({
2120
- message: `The wizard was unable to set up PostHog: ${failedTypes ? `the ${failedTypes} step failed` : `${blocked} steps never ran`}.\n\nPlease report this to: ${WIZARD_CONTACT_EMAIL}`,
2287
+ message: missingScopes.length > 0 ? `The wizard could not finish setup: ${whatFailed}, and this run was authorized without the following permission${missingScopes.length === 1 ? "" : "s"}: ${missingScopes.join(", ")}.\n\nPlease try again, approving all permissions on the PostHog authorization screen. If it still fails, report it to: ${WIZARD_CONTACT_EMAIL}` : `The wizard was unable to set up PostHog: ${whatFailed}.\n\nPlease report this to: ${WIZARD_CONTACT_EMAIL}`,
2121
2288
  error: new WizardError("orchestrator drain ended with failed tasks", {
2122
2289
  tasks_failed: summary.failed,
2123
2290
  tasks_blocked: blocked,
2124
2291
  failed_types: failedTypes,
2292
+ missing_oauth_scopes: missingScopes.join(" "),
2125
2293
  queue_state: JSON.stringify(store.list())
2126
2294
  })
2127
2295
  });
@@ -2151,7 +2319,7 @@ const SEQUENCE_OPTIONS = {
2151
2319
  },
2152
2320
  ["orchestrator"]: {
2153
2321
  name: "orchestrator",
2154
- run: (session, _config, programConfig, boot, _composed) => runOrchestrator(session, programConfig, boot)
2322
+ run: (session, config, programConfig, boot, _composed) => runOrchestrator(session, config, programConfig, boot)
2155
2323
  }
2156
2324
  };
2157
2325
  function getSequence(name) {
@@ -2272,6 +2440,11 @@ const PROGRAM_BINDINGS = {
2272
2440
  "mcp-remove": DEFAULT_BINDING,
2273
2441
  "mcp-tutorial": DEFAULT_BINDING,
2274
2442
  "mcp-analytics": DEFAULT_BINDING,
2443
+ "replay-vision": {
2444
+ sequence: "orchestrator",
2445
+ harness: "anthropic",
2446
+ model: DEFAULT_AGENT_MODEL
2447
+ },
2275
2448
  "ai-observability": {
2276
2449
  sequence: "linear",
2277
2450
  harness: "anthropic",
@@ -2521,4 +2694,4 @@ var agent_runner_exports = /* @__PURE__ */ __exportAll({ runAgent: () => runAgen
2521
2694
  //#endregion
2522
2695
  export { formatCostUsd as a, computeTokenCostUsd as i, runAgent as n, formatTokenCount as o, shouldDisableAsk as r, authenticate as s, agent_runner_exports as t };
2523
2696
 
2524
- //# sourceMappingURL=agent-runner-DA5YfjOD.js.map
2697
+ //# sourceMappingURL=agent-runner-B4ZdNkj4.js.map