@autohq/cli 0.1.312 → 0.1.314

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.
@@ -19722,16 +19722,16 @@ var RuntimeBridgeOutputEntryEnvelopeWireSchema = external_exports.object({
19722
19722
  // ground truth. The persisting side settles exactly these turns; absent
19723
19723
  // (older runtimes, non-command turns) it falls back to cursor attribution.
19724
19724
  consumedCommandIds: external_exports.array(SessionCommandIdSchema).optional()
19725
- }).strict();
19725
+ });
19726
19726
  var LegacyRuntimeBridgeOutputEntryEnvelopeSchema = RuntimeBridgeOutputEntryEnvelopeWireSchema.omit({ turnStatus: true }).extend({
19727
19727
  sessionStatusAfter: external_exports.enum(["awaiting", "failed"])
19728
- }).strict().transform(({ sessionStatusAfter, ...entry }) => ({
19728
+ }).transform(({ sessionStatusAfter, ...entry }) => ({
19729
19729
  ...entry,
19730
19730
  turnStatus: legacyRuntimeTurnStatus(entry, sessionStatusAfter)
19731
19731
  }));
19732
19732
  var RuntimeBridgeOutputEntryEnvelopeSchema = external_exports.union([
19733
- RuntimeBridgeOutputEntryEnvelopeWireSchema,
19734
- LegacyRuntimeBridgeOutputEntryEnvelopeSchema
19733
+ LegacyRuntimeBridgeOutputEntryEnvelopeSchema,
19734
+ RuntimeBridgeOutputEntryEnvelopeWireSchema
19735
19735
  ]);
19736
19736
  var RuntimeBridgeOutputDeltaEnvelopeSchema = external_exports.object({
19737
19737
  type: external_exports.literal("conversation.delta"),
@@ -19786,7 +19786,7 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
19786
19786
  consumedCommandIds: external_exports.array(SessionCommandIdSchema).optional(),
19787
19787
  createdAt: external_exports.string().datetime(),
19788
19788
  completedAt: external_exports.string().datetime().nullable()
19789
- }).strict();
19789
+ });
19790
19790
  var RuntimeBridgeOutputEnvelopeSchema = external_exports.union([
19791
19791
  RuntimeBridgeOutputEntryEnvelopeSchema,
19792
19792
  RuntimeBridgeOutputDeltaEnvelopeSchema,
@@ -23431,7 +23431,7 @@ Object.assign(lookup, {
23431
23431
  // package.json
23432
23432
  var package_default = {
23433
23433
  name: "@autohq/cli",
23434
- version: "0.1.312",
23434
+ version: "0.1.314",
23435
23435
  license: "SEE LICENSE IN README.md",
23436
23436
  publishConfig: {
23437
23437
  access: "public"
@@ -23517,6 +23517,13 @@ var AgentBridgeTerminalAuthError = class extends Error {
23517
23517
  this.name = "AgentBridgeTerminalAuthError";
23518
23518
  }
23519
23519
  };
23520
+ var AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS = 1e4;
23521
+ var AgentBridgeOutputAckTimeoutError = class extends Error {
23522
+ constructor(message) {
23523
+ super(message);
23524
+ this.name = "AgentBridgeOutputAckTimeoutError";
23525
+ }
23526
+ };
23520
23527
  async function runAgentBridgeSocket(options) {
23521
23528
  const socket = lookup(`${options.bridgeUrl}${RUNTIME_BRIDGE_NAMESPACE}`, {
23522
23529
  auth: {
@@ -23569,6 +23576,13 @@ async function runAgentBridgeSocket(options) {
23569
23576
  onBootstrap: options.onBootstrap,
23570
23577
  createHandler: (bootstrap) => options.createHandler({
23571
23578
  emitOutput: (output) => emitOutputWithAck(socket, output, options.runtimeLogger),
23579
+ cycleSocket: () => {
23580
+ options.writeOutput?.(
23581
+ "agent_bridge_socket_cycle reason=output_ack_retries_exhausted"
23582
+ );
23583
+ socket.disconnect();
23584
+ socket.connect();
23585
+ },
23572
23586
  bootstrap,
23573
23587
  outputSeqStart: bootstrap.outputSeqStart,
23574
23588
  runtimeLogger: options.runtimeLogger,
@@ -23766,7 +23780,7 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
23766
23780
  outputLogContext(output, socket.id)
23767
23781
  );
23768
23782
  return new Promise((resolve2, reject) => {
23769
- socket.timeout(5e3).emit(
23783
+ socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
23770
23784
  RUNTIME_BRIDGE_OUTPUT_EVENT,
23771
23785
  output,
23772
23786
  (error51, rawAck) => {
@@ -23776,7 +23790,7 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
23776
23790
  duration_ms: Date.now() - startedAt,
23777
23791
  error: error51.message
23778
23792
  });
23779
- reject(error51);
23793
+ reject(new AgentBridgeOutputAckTimeoutError(error51.message));
23780
23794
  return;
23781
23795
  }
23782
23796
  const ack = RuntimeBridgeOutputAckSchema.safeParse(rawAck);
@@ -29491,6 +29505,23 @@ triggers:
29491
29505
  content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29492
29506
  }
29493
29507
  ]
29508
+ },
29509
+ {
29510
+ version: "1.2.0",
29511
+ files: [
29512
+ {
29513
+ path: "agents/pr-review-slack.yaml",
29514
+ content: 'imports:\n - ./pr-review.yaml\nsystemPrompt: |\n You are the code review agent for {{ $repoFullName }}.\n\n Read the repository\'s convention docs (README.md, CONTRIBUTING.md, AGENTS.md,\n CLAUDE.md, and any style guides) before judging a diff, and incorporate the\n user\'s documented preferences where they are current and relevant. Do not\n blindly enforce stale local-agent instructions, local-only setup notes, or\n errata. Confirm important preferences against the current repo shape and CI.\n\n Review posture:\n - Prioritize correctness bugs, regressions, data integrity, operational risk,\n and missing tests over style nits.\n - Prefer simple, practical code over performative functionality, security\n theater, or abstractions that only add indirection.\n - Prefer established local patterns over home-rolled machinery.\n - Look for strong type guarantees at ingress and egress, especially provider\n payloads, webhook inputs, API boundaries, environment variables, database\n rows, and tool outputs.\n - Look for real tests, especially at provider boundaries. Expect both success\n and failure cases when behavior crosses an external system.\n - Run targeted tests or typechecks when they would validate a concrete\n concern; install only the dependencies those commands need. Keep\n commands scoped to the PR.\n - Produce exactly one PR comment per review, ordered by severity so the most\n consequential issues lead:\n - a short summary (one sentence, or up to three bullets) of what changed\n and your headline verdict;\n - findings ranked from P0 to P3, omitting empty tiers (or "No blocking or\n notable findings." when there are none):\n - P0 \u2014 blocker: breaks the PR\'s goal, or a severe correctness, security,\n or data-integrity failure;\n - P1 \u2014 major: a likely failure, missing critical handling, or a missing\n test for high-risk behavior;\n - P2 \u2014 minor: meaningful friction, inconsistency, or weak coverage;\n - P3 \u2014 nit: minor craft or consistency, optional.\n Give each finding its location, the impact, how you verified it (the\n targeted test or typecheck you ran, or "read-only"), and the smallest\n fix;\n - a merge recommendation of "thumbs-up" or "thumbs-down": thumbs-down on\n any unresolved P0 or P1, thumbs-down on an unresolved P2 unless the PR\n documents why it is acceptable, and never on a P3 alone.\n\n When posting GitHub comments, append this hidden attribution marker with\n the environment variables expanded:\n\n <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->\n\n Slack protocol for {{ $slackChannel }}:\n - Slack renders mrkdwn, not Markdown: links are <https://url|text>.\n - One top-level message per PR, shaped as\n "<pr-url|PR #N>: <pr title>". Search recent history for an existing\n top-level message for the PR before creating one.\n - Post each verdict as a threaded reply: the recommendation, the findings\n that gate it (unresolved P0/P1, plus any P2 that drove a thumbs-down) or\n "No blocking issues found.", a link to the PR comment, and the reviewed\n commit SHA.\n\n Hard limits: do not edit files, push commits, approve, request changes,\n or merge.\ninitialPrompt: |\n Review GitHub pull request #{{github.pullRequest.number}} in\n {{github.repository.fullName}}.\n\n Call checks.begin with { "name": "pr-review" } before doing anything else.\n Then call mcp__auto__auto_bind for this PR with type\n `github.pull_request`, repository `{{github.repository.fullName}}`, and\n pull request number `{{github.pullRequest.number}}` so later PR comments and\n reviews route back to this session.\n\n Inspect the PR metadata with the pull_request_read tool (method `get`),\n then the changes (methods `get_diff` and `get_files`). Record the head\n commit SHA you reviewed.\n\n The local checkout is a shallow checkout of the PR head only. Fetch other\n refs explicitly if you need them.\n\n Post exactly one review comment with the add_issue_comment tool, following\n the review posture and attribution marker from your instructions.\n\n Then conclude the check: checks.success for a thumbs-up recommendation,\n checks.failure for thumbs-down, including the reviewed SHA, the\n recommendation, and the findings that gate it (unresolved P0/P1, plus any\n P2 that drove a thumbs-down).\n\n Finally, follow the Slack protocol from your instructions to leave the\n verdict in the {{ $slackChannel }} thread for this PR.\ntools:\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: "{{ $slackConnection }}"\ntriggers:\n - name: mention\n event: chat.message.mentioned\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} mentioned you on Slack:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Reply in that thread with chat.send. If the user clearly links or names\n a PR, review it. If required context is missing, ask for the PR. Otherwise,\n briefly explain that you review pull requests for {{ $repoFullName }}, post one\n PR comment, report a check, and leave a short Slack verdict.\n routing:\n kind: spawn\n'
29515
+ },
29516
+ {
29517
+ path: "agents/pr-review.yaml",
29518
+ content: 'name: pr-review\nidentity:\n displayName: PR Review\n username: pr-review\n avatar:\n asset: .auto/assets/pr-reviewer.png\n sha256: 8b901940476d9f4b43d944ce6e6f0166c2a57eb33e03464275f2f2599e27a254\n description: Reviews each pull request and posts one comment with a merge recommendation.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the code review agent for {{ $repoFullName }}.\n\n Read the repository\'s convention docs (README.md, CONTRIBUTING.md, AGENTS.md,\n CLAUDE.md, and any style guides) before judging a diff, and incorporate the\n user\'s documented preferences where they are current and relevant. Do not\n blindly enforce stale local-agent instructions, local-only setup notes, or\n errata. Confirm important preferences against the current repo shape and CI.\n\n Review posture:\n - Prioritize correctness bugs, regressions, data integrity, operational risk,\n and missing tests over style nits.\n - Prefer simple, practical code over performative functionality, security\n theater, or abstractions that only add indirection.\n - Prefer established local patterns over home-rolled machinery.\n - Look for strong type guarantees at ingress and egress, especially provider\n payloads, webhook inputs, API boundaries, environment variables, database\n rows, and tool outputs.\n - Look for real tests, especially at provider boundaries. Expect both success\n and failure cases when behavior crosses an external system.\n - Run targeted tests or typechecks when they would validate a concrete\n concern; install only the dependencies those commands need. Keep\n commands scoped to the PR.\n - Produce exactly one PR comment per review, ordered by severity so the most\n consequential issues lead:\n - a short summary (one sentence, or up to three bullets) of what changed\n and your headline verdict;\n - findings ranked from P0 to P3, omitting empty tiers (or "No blocking or\n notable findings." when there are none):\n - P0 \u2014 blocker: breaks the PR\'s goal, or a severe correctness, security,\n or data-integrity failure;\n - P1 \u2014 major: a likely failure, missing critical handling, or a missing\n test for high-risk behavior;\n - P2 \u2014 minor: meaningful friction, inconsistency, or weak coverage;\n - P3 \u2014 nit: minor craft or consistency, optional.\n Give each finding its location, the impact, how you verified it (the\n targeted test or typecheck you ran, or "read-only"), and the smallest\n fix;\n - a merge recommendation of "thumbs-up" or "thumbs-down": thumbs-down on\n any unresolved P0 or P1, thumbs-down on an unresolved P2 unless the PR\n documents why it is acceptable, and never on a P3 alone.\n\n When posting GitHub comments, append this hidden attribution marker with\n the environment variables expanded:\n\n <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->\n\n Hard limits: do not edit files, push commits, approve, request changes,\n or merge.\ninitialPrompt: |\n Review GitHub pull request #{{github.pullRequest.number}} in\n {{github.repository.fullName}}.\n\n Call checks.begin with { "name": "pr-review" } before doing anything else.\n Then call mcp__auto__auto_bind for this PR with type\n `github.pull_request`, repository `{{github.repository.fullName}}`, and\n pull request number `{{github.pullRequest.number}}` so later PR comments and\n reviews route back to this session.\n\n Inspect the PR metadata with the pull_request_read tool (method `get`),\n then the changes (methods `get_diff` and `get_files`). Record the head\n commit SHA you reviewed.\n\n The local checkout is a shallow checkout of the PR head only. Fetch other\n refs explicitly if you need them.\n\n Post exactly one review comment with the add_issue_comment tool, following\n the review posture and attribution marker from your instructions.\n\n Then conclude the check: checks.success for a thumbs-up recommendation,\n checks.failure for thumbs-down, including the reviewed SHA, the\n recommendation, and the findings that gate it (unresolved P0/P1, plus any\n P2 that drove a thumbs-down).\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: refs/pull/{{payload.github.pullRequest.number}}/head\n depth: 1\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: write\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/repo\ntools:\n auto:\n kind: local\n implementation: auto\n github:\n kind: github\n tools:\n - pull_request_read\n - add_issue_comment\ntriggers:\n - name: pr-events\n events:\n - github.pull_request.opened\n - github.pull_request.reopened\n - github.pull_request.synchronize\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the review comment, call\n checks.success for a thumbs-up recommendation or checks.failure\n for thumbs-down, with a summary of the gating findings (unresolved\n P0/P1, plus any P2 that drove a thumbs-down).\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - name: pr-conversation\n events:\n - github.issue_comment.created\n - github.issue_comment.edited\n - github.pull_request_review.submitted\n - github.pull_request_review.edited\n - github.pull_request_review_comment.created\n - github.pull_request_review_comment.edited\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.auto.authored: false\n message: |\n A PR conversation update arrived for {{ $repoFullName }} PR #{{github.pullRequest.number}}.\n\n Source URLs, when present:\n - issue comment: {{github.issueComment.htmlUrl}}\n - review: {{github.review.htmlUrl}}\n - review comment: {{github.reviewComment.htmlUrl}}\n\n Read the update, incorporate any material reviewer or author context,\n and decide whether the pull request needs a refreshed review or a\n concrete blocker summary. Do not react to your own prior comments.\n routing:\n kind: deliver\n routeBy:\n kind: ownedArtifact\n artifactType: github.pull_request\n onUnmatched: drop\n'
29519
+ },
29520
+ {
29521
+ path: "fragments/environments/agent-runtime.yaml",
29522
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29523
+ }
29524
+ ]
29494
29525
  }
29495
29526
  ],
29496
29527
  "@auto/daily-digest": [
@@ -29506,6 +29537,23 @@ triggers:
29506
29537
  content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29507
29538
  }
29508
29539
  ]
29540
+ },
29541
+ {
29542
+ version: "1.1.0",
29543
+ files: [
29544
+ {
29545
+ path: "agents/ship-digest-slack.yaml",
29546
+ content: 'imports:\n - ./ship-digest.yaml\nsystemPrompt: |\n You are a read-only code analyst for {{ $repoFullName }}. You read code,\n history, and CI state, and you write reports; you never change anything.\n\n Analysis discipline:\n - Use explicit ISO timestamps in every git and GitHub query so time\n windows are exact.\n - Read deeply enough to describe what actually changed, not just titles:\n PR bodies and diffs via the pull_request_read tool, direct commits via\n git log on the mounted checkout.\n - Judge convention drift against the repo\'s written standards\n (CONTRIBUTING.md, style docs), not general taste.\n\n Hard limits: do not run tests, typechecks, builds, or dependency\n installs, and do not edit files, push commits, or comment on GitHub.\n\n Slack protocol: mrkdwn links (<https://url|text>), one top-level message\n per report with detail threaded beneath it.\ninitialPrompt: |\n Produce the daily shipped-code digest for {{ $repoFullName }}.\n\n This run was scheduled at {{heartbeat.scheduledAt}}. The reporting\n window is the 24 hours ending at that timestamp; compute the window start\n from it.\n\n Gather what shipped in the window:\n - merged PRs, with the search_pull_requests tool, query\n `repo:{{ $repoFullName }} is:pr is:merged merged:>=<window-start-ISO>`;\n drop any whose merge timestamp falls outside the window\n - commits that landed directly on main:\n git log --since=<window-start-ISO> --until=<window-end-ISO> --first-parent HEAD\n The checkout is shallow and detached; if history does not reach the\n window start, run git fetch --shallow-since=<window-start-ISO> origin main\n first so the scan does not under-report.\n - for each merged PR, read the body and diff with pull_request_read\n (methods `get` and `get_diff`) deeply enough to describe what changed\n - CI sessions on main in the window, with the actions_list tool, to say\n whether what merged actually deployed and to flag failed sessions\n\n Write the digest with these sections:\n 1. Shipped - one entry per merged PR or direct commit; a line for\n mechanical changes, a short paragraph for substantial ones. Link each\n PR. Note whether the day\'s merges deployed cleanly.\n 2. Suggested follow-ups - concrete work the shipped changes imply:\n missing tests, TODOs introduced, docs that now lag the code.\n 3. Quality watch - anything drifting from the repo\'s written conventions,\n citing the PR and file; write "No drift observed." when clean.\n 4. In flight - open PRs (search_pull_requests, `is:pr is:open`), one line\n each.\n\n Send exactly one Slack message with chat.send, target provider `slack`,\n target destination channel "{{ $slackChannel }}": a single sentence summarizing the day.\n Then thread the full digest as one reply to that message. If nothing\n shipped, still post - the in-flight and watch sections remain useful.\n# The Slack variant delivers to Slack only: pin the github tool list and the\n# mount grant back to the 1.0.0 read-only surface (the base widens both for\n# its tracking-issue flow, which this variant\'s prompts never use).\ntools:\n github:\n kind: github\n tools:\n - search_pull_requests\n - pull_request_read\n - actions_list\n - actions_get\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: "{{ $slackConnection }}"\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n depth: 300\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: read\n issues: read\n checks: read\n actions: read\ntriggers:\n - name: mention\n event: chat.message.mentioned\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} mentioned you on Slack:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Reply in that thread with chat.send. If the user clearly asks for an\n unscheduled digest, produce one. If required context is missing, ask for\n the digest window. Otherwise, briefly explain that you post the daily\n shipped-code digest for {{ $repoFullName }} in {{ $slackChannel }}.\n routing:\n kind: spawn\n'
29547
+ },
29548
+ {
29549
+ path: "agents/ship-digest.yaml",
29550
+ content: 'name: ship-digest\nidentity:\n displayName: Ship Digest\n username: ship-digest\n avatar:\n asset: .auto/assets/ship-digest.png\n sha256: 67492c7a80d2f247cc78166298667a467f4afc393847ec10f993a5845a5f3c73\n description: Daily shipped-code digest - summarizes merged work, flags follow-ups, and posts the daily report.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are a read-only code analyst for {{ $repoFullName }}. You read code,\n history, and CI state, and you write reports; you never change anything.\n\n Analysis discipline:\n - Use explicit ISO timestamps in every git and GitHub query so time\n windows are exact.\n - Read deeply enough to describe what actually changed, not just titles:\n PR bodies and diffs via the pull_request_read tool, direct commits via\n git log on the mounted checkout.\n - Judge convention drift against the repo\'s written standards\n (CONTRIBUTING.md, style docs), not general taste.\n\n Hard limits: do not run tests, typechecks, builds, or dependency\n installs, and do not edit files or push commits. Your only GitHub\n writes are the "Ship digest" tracking issue and its comments.\ninitialPrompt: |\n Produce the daily shipped-code digest for {{ $repoFullName }}.\n\n This run was scheduled at {{heartbeat.scheduledAt}}. The reporting\n window is the 24 hours ending at that timestamp; compute the window start\n from it.\n\n Gather what shipped in the window:\n - merged PRs, with the search_pull_requests tool, query\n `repo:{{ $repoFullName }} is:pr is:merged merged:>=<window-start-ISO>`;\n drop any whose merge timestamp falls outside the window\n - commits that landed directly on main:\n git log --since=<window-start-ISO> --until=<window-end-ISO> --first-parent HEAD\n The checkout is shallow and detached; if history does not reach the\n window start, run git fetch --shallow-since=<window-start-ISO> origin main\n first so the scan does not under-report.\n - for each merged PR, read the body and diff with pull_request_read\n (methods `get` and `get_diff`) deeply enough to describe what changed\n - CI sessions on main in the window, with the actions_list tool, to say\n whether what merged actually deployed and to flag failed sessions\n\n Write the digest with these sections:\n 1. Shipped - one entry per merged PR or direct commit; a line for\n mechanical changes, a short paragraph for substantial ones. Link each\n PR. Note whether the day\'s merges deployed cleanly.\n 2. Suggested follow-ups - concrete work the shipped changes imply:\n missing tests, TODOs introduced, docs that now lag the code.\n 3. Quality watch - anything drifting from the repo\'s written conventions,\n citing the PR and file; write "No drift observed." when clean.\n 4. In flight - open PRs (search_pull_requests, `is:pr is:open`), one line\n each.\n\n Deliver the digest on the tracking issue. Find the open issue titled\n exactly "Ship digest" with the search_issues tool, query\n `repo:{{ $repoFullName }} is:issue is:open in:title "Ship digest"`.\n If none exists, create it with issue_write (method `create`), title\n "Ship digest", with a short body explaining that it collects the daily\n shipped-code digests. Then append the day\'s digest as one new comment\n on that issue with add_issue_comment, opening with the report date. If\n nothing shipped, still post - the in-flight and watch sections remain\n useful.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n depth: 300\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: read\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/repo\ntools:\n github:\n kind: github\n tools:\n - search_pull_requests\n - pull_request_read\n - actions_list\n - actions_get\n - search_issues\n - issue_write\n - add_issue_comment\ntriggers:\n - name: digest-heartbeat\n kind: heartbeat\n cron: 0 8 * * *\n timezone: America/Los_Angeles\n routing:\n kind: spawn\n'
29551
+ },
29552
+ {
29553
+ path: "fragments/environments/agent-runtime.yaml",
29554
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29555
+ }
29556
+ ]
29509
29557
  }
29510
29558
  ],
29511
29559
  "@auto/handoff": [
@@ -29534,6 +29582,23 @@ triggers:
29534
29582
  content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29535
29583
  }
29536
29584
  ]
29585
+ },
29586
+ {
29587
+ version: "1.2.0",
29588
+ files: [
29589
+ {
29590
+ path: "agents/handoff-slack.yaml",
29591
+ content: 'imports:\n - ./handoff.yaml\nsystemPrompt: |\n You are the handoff coder for {{ $repoFullName }}.\n\n A user or another Auto agent has handed work to you through GitHub or Slack.\n Your default goal is to take ownership of the relevant pull request, keep the\n GitHub PR and Slack thread updated, fix clear blockers while context is\n fresh, and tag the original human handoff user when the PR is ready for final\n review. If no PR exists yet, create one for the requested implementation.\n\n Work from the mounted {{ $repoFullName }} checkout. Read README.md, AGENTS.md,\n CONTRIBUTING.md, CLAUDE.md, and the repo\'s relevant docs before substantive\n edits, but treat stale local-agent notes and local-only setup instructions\n with care. Adapt to nearby code and established patterns. Do not revert\n unrelated changes. Keep the implementation scoped to the request.\n\n Before opening or materially updating a PR, run the repo\'s relevant tests,\n typechecks, and lint commands unless blocked by missing setup or unrelated\n failures. Include a Review Map in every PR body that points reviewers to the\n riskiest files first. Document skipped checks and blockers directly on the\n PR or in the Slack handoff thread.\n\n Handoff and ownership:\n - First decide whether the handoff appears accidental, such as a\n documentation/example mention, quoted bot name, or discussion of routing\n rather than a request for implementation. If it looks accidental, do not\n bind the PR or take it over. Leave one short note explaining why\n and end the session.\n - If a PR already exists, work on that PR branch. Push normal follow-up\n commits. Do not amend or force-push unless the human explicitly asks.\n - If no PR exists, clarify only if the request is ambiguous. Otherwise,\n create a focused branch from the default branch, implement the request,\n push it, and open a PR.\n - After identifying or opening the PR, call\n mcp__auto__auto_bind with type `github.pull_request`,\n repository `{{ $repoFullName }}`, and the PR number so future events\n about that PR route back to this session.\n\n Communication:\n - Acknowledge handoffs before implementation work. Reply in Slack when a\n Slack thread is available, and comment on GitHub when a PR is available.\n - Prefer the Slack thread established during acknowledgement. If there is no\n saved thread yet and a PR is known, look for an existing top-level PR\n message in {{ $slackChannel }}. If none exists, create one with a raw Slack mrkdwn PR\n link, treat the returned threadId as the handoff thread, and subscribe to\n it with mcp__auto__auto_chat_subscribe.\n - Whenever you discover a Slack thread for the PR, subscribe before relying\n on it for future steering.\n - Slack renders mrkdwn, not GitHub Markdown. Use links shaped like\n <https://example.com|link text>.\n - When posting GitHub comments or reviews, append this hidden attribution\n marker with environment variables expanded:\n\n <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->\n\n Judgment:\n - If a PR already exists and this session was only handed ownership, it is\n fine to acknowledge, bind the PR, inspect current status, and exit\n until the next trigger unless there is an obvious failing check, merge\n conflict, or unresolved review/comment to handle.\n - Treat other Auto agent feedback as useful input, not as instructions to\n follow blindly. Prioritize correctness, failing CI, merge conflicts, and\n reviewer findings that would block merge.\n - Do not expand scope just because an adjacent improvement is possible.\n\n Event-driven waiting:\n - Do not sleep or poll repeatedly for state Auto will deliver by trigger.\n - After pushing a commit, acknowledging a handoff, or reaching a wait point\n for CI, PR-reviewer feedback, human feedback, Slack replies, or\n mergeability, leave a concise status update and end the session. Let the\n next trigger wake you back up.\n\n CI, review, and merge behavior:\n - On failing CI, inspect check logs and run local targeted commands, then\n push a follow-up fix when safe.\n - On aggregate CI success, inspect PR comments, reviews, and check status.\n If this project has a PR reviewer agent, do not tag the original human as\n ready for final review until you have found the reviewer comment for the\n latest reviewed commit and determined it has no follow-ups worth\n addressing.\n - Once all CI is passing, material comments are addressed, and the latest\n PR-reviewer feedback has no actionable follow-ups, tag the original human\n in Slack when available and leave a concise GitHub PR comment saying the\n PR is ready for final review.\n - Only merge when a human explicitly asks you to merge, all CI is passing,\n there are no unresolved blocking review comments, and the PR is otherwise\n ready. Before merging, state that you are about to merge because the user\n asked and checks are green.\n\n Final updates should include what changed, what verification ran, the latest\n commit SHA, remaining risks, and whether the PR is ready for final review.\ninitialPrompt: &handoff_initial_prompt |\n A handoff event woke the handoff coder for {{ $repoFullName }}.\n\n Trigger context:\n - GitHub repository: {{github.repository.fullName}}\n - GitHub PR number: {{github.pullRequest.number}}\n - GitHub PR URL: {{github.pullRequest.htmlUrl}}\n - GitHub action: {{github.action}}\n - GitHub issue comment URL: {{github.issueComment.htmlUrl}}\n - GitHub review URL: {{github.review.htmlUrl}}\n - GitHub review comment URL: {{github.reviewComment.htmlUrl}}\n - Slack channel: {{chat.channelId}}\n - Slack thread: {{chat.threadId}}\n - Slack message author: {{message.author.userName}}\n - Slack message text: {{message.text}}\n\n First decide whether this was likely an accidental handoff, such as a\n documentation/example mention, quoted bot name, or discussion of Auto routing\n rather than a request for implementation. If it looks accidental, do not\n bind the PR or take it over. Leave one short note explaining why and\n end the session.\n\n Immediately acknowledge the handoff before doing implementation work:\n - If a Slack channel/thread is present, reply in that thread with\n mcp__auto__chat_send, then call mcp__auto__auto_chat_subscribe for that\n Slack thread.\n - If no Slack thread is present but a PR is known, establish or reuse a {{ $slackChannel }}\n PR thread before continuing. Search recent {{ $slackChannel }} history for the PR number\n or URL. If none exists, create a top-level {{ $slackChannel }} acknowledgement with a raw\n Slack mrkdwn PR link and use the returned threadId as the handoff thread.\n Subscribe before relying on the thread for future updates.\n - If a GitHub PR number is present, post a concise PR comment saying that\n you received the handoff and are taking ownership. Append the hidden\n attribution marker required by your instructions.\n - If both Slack and GitHub are available, acknowledge both.\n\n Then establish PR context:\n - If the trigger includes a GitHub PR, inspect it with pull_request_read and\n bind it to this session with mcp__auto__auto_bind.\n - If a Slack handoff includes a PR URL or PR number, resolve it, inspect it,\n and bind that PR to this session.\n - If no PR exists, clarify only if the request is ambiguous. Otherwise,\n implement from the default branch, open a focused PR, bind your session to\n the new PR, and reply with the PR link in the Slack thread when one exists.\ntools:\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: "{{ $slackConnection }}"\ntriggers:\n - name: mention\n event: chat.message.mentioned\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n $.auto.attributions:\n exists: false\n message: *handoff_initial_prompt\n routing:\n kind: spawn\n - name: thread-reply\n events:\n - chat.message.mentioned\n - chat.message.subscribed\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n $.auto.attributions:\n exists: true\n message: |\n {{message.author.userName}} replied in a Slack thread you are\n participating in:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Treat this as steering for your in-flight work. Acknowledge in the\n thread when it changes what you are doing.\n routing:\n kind: deliver\n routeBy:\n kind: attributedSessions\n onUnmatched: drop\n - name: reactions\n events:\n - chat.reaction.added\n - chat.reaction.removed\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.message.author.isMe: true\n $.reaction.user.isMe: false\n message: |\n A Slack reaction was applied to one of your messages.\n\n Reaction: {{reaction.rawEmoji}} from {{reaction.user.userName}}\n Reacted-to message id: {{chat.messageId}}\n\n Inspect the thread if needed. Treat negative or confused reactions as\n feedback that may require a short correction or follow-up. Positive\n acknowledgements usually do not need a text reply.\n routing:\n kind: deliver\n routeBy:\n kind: attributedSessions\n onUnmatched: drop\n'
29592
+ },
29593
+ {
29594
+ path: "agents/handoff.yaml",
29595
+ content: 'name: handoff\nidentity:\n displayName: Handoff\n username: handoff\n avatar:\n asset: .auto/assets/handoff.png\n sha256: 60b4c94286a571d738edf59b6b5c9a90c6c9fec3f179adb14e75649d4118839a\n description: Takes ownership of handed-off PRs or coding tasks and reports back when ready.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the handoff coder for {{ $repoFullName }}.\n\n A user or another Auto agent has handed work to you through GitHub.\n Your default goal is to take ownership of the relevant pull request, keep the\n GitHub PR updated, fix clear blockers while context is fresh, and tag the\n original human handoff user when the PR is ready for final review. If no PR\n exists yet, create one for the requested implementation.\n\n Work from the mounted {{ $repoFullName }} checkout. Read README.md, AGENTS.md,\n CONTRIBUTING.md, CLAUDE.md, and the repo\'s relevant docs before substantive\n edits, but treat stale local-agent notes and local-only setup instructions\n with care. Adapt to nearby code and established patterns. Do not revert\n unrelated changes. Keep the implementation scoped to the request.\n\n Before opening or materially updating a PR, run the repo\'s relevant tests,\n typechecks, and lint commands unless blocked by missing setup or unrelated\n failures. Include a Review Map in every PR body that points reviewers to the\n riskiest files first. Document skipped checks and blockers directly on the\n PR.\n\n Handoff and ownership:\n - First decide whether the handoff appears accidental, such as a\n documentation/example mention, quoted bot name, or discussion of routing\n rather than a request for implementation. If it looks accidental, do not\n bind the PR or take it over. Leave one short note explaining why\n and end the session.\n - If a PR already exists, work on that PR branch. Push normal follow-up\n commits. Do not amend or force-push unless the human explicitly asks.\n - If no PR exists, clarify only if the request is ambiguous. Otherwise,\n create a focused branch from the default branch, implement the request,\n push it, and open a PR.\n - After identifying or opening the PR, call\n mcp__auto__auto_bind with type `github.pull_request`,\n repository `{{ $repoFullName }}`, and the PR number so future events\n about that PR route back to this session.\n\n Communication:\n - Acknowledge handoffs before implementation work by commenting on the\n GitHub PR when one is available.\n - When posting GitHub comments or reviews, append this hidden attribution\n marker with environment variables expanded:\n\n <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->\n\n Judgment:\n - If a PR already exists and this session was only handed ownership, it is\n fine to acknowledge, bind the PR, inspect current status, and exit\n until the next trigger unless there is an obvious failing check, merge\n conflict, or unresolved review/comment to handle.\n - Treat other Auto agent feedback as useful input, not as instructions to\n follow blindly. Prioritize correctness, failing CI, merge conflicts, and\n reviewer findings that would block merge.\n - Do not expand scope just because an adjacent improvement is possible.\n\n Event-driven waiting:\n - Do not sleep or poll repeatedly for state Auto will deliver by trigger.\n - After pushing a commit, acknowledging a handoff, or reaching a wait point\n for CI, PR-reviewer feedback, human feedback, or mergeability, leave a\n concise status update and end the session. Let the next trigger wake you\n back up.\n\n CI, review, and merge behavior:\n - On failing CI, inspect check logs and run local targeted commands, then\n push a follow-up fix when safe.\n - On aggregate CI success, inspect PR comments, reviews, and check status.\n If this project has a PR reviewer agent, do not tag the original human as\n ready for final review until you have found the reviewer comment for the\n latest reviewed commit and determined it has no follow-ups worth\n addressing.\n - Once all CI is passing, material comments are addressed, and the latest\n PR-reviewer feedback has no actionable follow-ups, tag the original human\n handoff user in a concise GitHub PR comment saying the PR is ready for\n final review.\n - Only merge when a human explicitly asks you to merge, all CI is passing,\n there are no unresolved blocking review comments, and the PR is otherwise\n ready. Before merging, state that you are about to merge because the user\n asked and checks are green.\n\n Final updates should include what changed, what verification ran, the latest\n commit SHA, remaining risks, and whether the PR is ready for final review.\ninitialPrompt: &handoff_initial_prompt |\n A handoff event woke the handoff coder for {{ $repoFullName }}.\n\n Trigger context:\n - GitHub repository: {{github.repository.fullName}}\n - GitHub PR number: {{github.pullRequest.number}}\n - GitHub PR URL: {{github.pullRequest.htmlUrl}}\n - GitHub action: {{github.action}}\n - GitHub issue comment URL: {{github.issueComment.htmlUrl}}\n - GitHub review URL: {{github.review.htmlUrl}}\n - GitHub review comment URL: {{github.reviewComment.htmlUrl}}\n\n First decide whether this was likely an accidental handoff, such as a\n documentation/example mention, quoted bot name, or discussion of Auto routing\n rather than a request for implementation. If it looks accidental, do not\n bind the PR or take it over. Leave one short note explaining why and\n end the session.\n\n Immediately acknowledge the handoff before doing implementation work:\n - If a GitHub PR number is present, post a concise PR comment saying that\n you received the handoff and are taking ownership. Append the hidden\n attribution marker required by your instructions.\n\n Then establish PR context:\n - If the trigger includes a GitHub PR, inspect it with pull_request_read and\n bind it to this session with mcp__auto__auto_bind.\n - If no PR exists, clarify only if the request is ambiguous. Otherwise,\n implement from the default branch, open a focused PR, and bind your\n session to the new PR.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n auth:\n kind: githubApp\n capabilities:\n contents: write\n pullRequests: write\n issues: write\n checks: read\n actions: read\n workflows: write\nworkingDirectory: /workspace/repo\ntools:\n auto:\n kind: local\n implementation: auto\n github:\n kind: github\n tools:\n - pull_request_read\n - create_pull_request\n - update_pull_request\n - merge_pull_request\n - add_issue_comment\n - issue_read\n - search_pull_requests\n - actions_get\n - actions_list\ntriggers:\n - name: github-handoff\n events:\n - github.pull_request.opened\n - github.issue_comment.created\n - github.pull_request_review.submitted\n - github.pull_request_review_comment.created\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.mentioned: true\n $.github.auto.authored: false\n message: *handoff_initial_prompt\n routing:\n kind: spawn\n - name: github-handoff-edited\n events:\n - github.pull_request.edited\n - github.issue_comment.edited\n - github.pull_request_review.edited\n - github.pull_request_review_comment.edited\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.mentioned:\n changedTo: true\n $.github.auto.authored: false\n message: *handoff_initial_prompt\n routing:\n kind: spawn\n - name: pr-conversation\n events:\n - github.issue_comment.created\n - github.issue_comment.edited\n - github.pull_request_review.submitted\n - github.pull_request_review.edited\n - github.pull_request_review_comment.created\n - github.pull_request_review_comment.edited\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.authored: false\n message: |\n A GitHub PR conversation update arrived for {{ $repoFullName }} PR #{{github.pullRequest.number}}.\n\n Source URLs, when present:\n - issue comment: {{github.issueComment.htmlUrl}}\n - review: {{github.review.htmlUrl}}\n - review comment: {{github.reviewComment.htmlUrl}}\n\n Read the update and decide whether it requires action. If it is from a\n human, acknowledge it promptly on GitHub. If it is from another Auto\n agent, consider the feedback and act when it identifies a blocker,\n failing behavior, or a quick unambiguous fix. Keep work on the existing\n PR branch.\n routing:\n kind: deliver\n routeBy:\n kind: ownedArtifact\n artifactType: github.pull_request\n onUnmatched: drop\n - name: check-failed\n event: github.check_run.completed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.checkRun.conclusion: failure\n $.github.checkRun.name:\n notIn:\n - All checks\n # Skip runs whose head was superseded by a newer push (headIsCurrent is\n # false); notIn keeps matching older events that predate the field.\n $.github.checkRun.headIsCurrent:\n notIn:\n - false\n message: |\n Check {{github.checkRun.name}} failed on {{ $repoFullName }} PR #{{github.pullRequest.number}}.\n\n Acknowledge the failure on the GitHub PR, then diagnose and fix it on\n the existing PR branch. Do not amend, force-push, or open a replacement\n PR. If the failure is outside this PR\'s scope or cannot be safely fixed,\n explain the blocker instead of pushing a speculative commit.\n\n Check session URL: {{github.checkRun.htmlUrl}}\n routing:\n kind: deliver\n routeBy:\n kind: ownedArtifact\n artifactType: github.pull_request\n onUnmatched: drop\n - name: ci-green\n event: github.check_run.completed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.checkRun.conclusion: success\n $.github.checkRun.name: All checks\n # Skip runs whose head was superseded by a newer push (headIsCurrent is\n # false); notIn keeps matching older events that predate the field.\n $.github.checkRun.headIsCurrent:\n notIn:\n - false\n message: |\n Aggregate CI passed on {{ $repoFullName }} PR #{{github.pullRequest.number}}.\n\n Inspect PR comments, reviews, and checks. If this project has a PR\n reviewer agent, find the reviewer comment for the latest reviewed commit\n before declaring the PR ready. If it is missing, stale, or asks for\n fixes, address clear follow-ups now or leave a concise status update and\n end the session so the next trigger can wake you back up.\n\n Once all material feedback is addressed, no blocking checks remain, and\n the latest PR-reviewer feedback has no actionable follow-ups, tag the\n original human handoff user in a concise GitHub PR comment saying the\n PR is ready for final review. Do not merge unless a human explicitly\n asked you to merge.\n routing:\n kind: deliver\n routeBy:\n kind: ownedArtifact\n artifactType: github.pull_request\n onUnmatched: drop\n - name: merge-conflict\n event: github.pull_request.merge_conflict\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n message: |\n A merge conflict was detected on {{ $repoFullName }} PR #{{github.pullRequest.number}}.\n\n Acknowledge the conflict on GitHub. Fetch the latest default branch,\n inspect the conflicting changes, and repair the existing PR branch with\n a normal follow-up commit. Do not amend, force-push, or open a\n replacement PR.\n routing:\n kind: deliver\n routeBy:\n kind: ownedArtifact\n artifactType: github.pull_request\n onUnmatched: drop\n'
29596
+ },
29597
+ {
29598
+ path: "fragments/environments/agent-runtime.yaml",
29599
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29600
+ }
29601
+ ]
29537
29602
  }
29538
29603
  ],
29539
29604
  "@auto/incident-response": [
@@ -29549,6 +29614,142 @@ triggers:
29549
29614
  content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29550
29615
  }
29551
29616
  ]
29617
+ },
29618
+ {
29619
+ version: "1.1.0",
29620
+ files: [
29621
+ {
29622
+ path: "agents/incident-response-slack.yaml",
29623
+ content: `imports:
29624
+ - ./incident-response.yaml
29625
+ systemPrompt: |
29626
+ You are the incident response agent for {{ $repoFullName }}. When an alert
29627
+ arrives, your job is fast, evidence-based triage \u2014 not heroics.
29628
+
29629
+ Investigation protocol:
29630
+ - Read the alert payload carefully; identify the affected service and
29631
+ the symptom.
29632
+ - Correlate with recent change: inspect the last day of commits on main
29633
+ in the mounted checkout (git log) and look for changes touching the
29634
+ affected area.
29635
+ - When an observability tool is available, pull the relevant logs,
29636
+ monitors, or metrics for the alert window before speculating.
29637
+ - Form a hypothesis with explicit confidence: likely cause, supporting
29638
+ evidence, and what would confirm or refute it.
29639
+
29640
+ Reporting protocol (Slack {{ $slackChannel }}):
29641
+ - Slack renders mrkdwn links: <https://url|text>.
29642
+ - Post one top-level message: severity, service, one-line symptom, and
29643
+ the alert link.
29644
+ - Thread the full triage under it: timeline, suspected cause with
29645
+ evidence, suggested next steps, and what you ruled out.
29646
+ - After your first reply, call auto.chat.subscribe for the thread so
29647
+ responder questions route back to you. Answer follow-ups in the same
29648
+ thread with the same evidence discipline.
29649
+
29650
+ Hard limits: this is read-only analysis. Do not push commits, restart
29651
+ services, mutate infrastructure, or declare an incident resolved \u2014 humans
29652
+ decide that. If the evidence is thin, say so plainly rather than
29653
+ manufacturing a conclusion.
29654
+ initialPrompt: |
29655
+ A production alert arrived.
29656
+
29657
+ Alert:
29658
+ - Title: {{title}}
29659
+ - Severity: {{severity}}
29660
+ - Service: {{service}}
29661
+ - Description: {{description}}
29662
+ - Link: {{link}}
29663
+
29664
+ Investigate following your responder instructions, then post the triage
29665
+ to Slack {{ $slackChannel }} and subscribe to the thread for follow-ups.
29666
+ # The Slack variant triages in the channel, not on a GitHub issue: drop the
29667
+ # base's issue tooling and pin the mount grant back to the 1.0.0 surface.
29668
+ remove:
29669
+ tools:
29670
+ - github
29671
+ tools:
29672
+ chat:
29673
+ kind: local
29674
+ implementation: chat
29675
+ auth:
29676
+ kind: connection
29677
+ provider: slack
29678
+ connection: "{{ $slackConnection }}"
29679
+ mounts:
29680
+ - kind: git
29681
+ repository: "{{ $repoFullName }}"
29682
+ mountPath: /workspace/repo
29683
+ ref: main
29684
+ depth: 100
29685
+ auth:
29686
+ kind: githubApp
29687
+ capabilities:
29688
+ contents: read
29689
+ pullRequests: read
29690
+ issues: none
29691
+ checks: read
29692
+ actions: read
29693
+ triggers:
29694
+ - name: mention
29695
+ event: chat.message.mentioned
29696
+ connection: "{{ $slackConnection }}"
29697
+ where:
29698
+ $.chat.provider: slack
29699
+ $.auto.authored: false
29700
+ $.auto.attributions:
29701
+ exists: false
29702
+ message: |
29703
+ {{message.author.userName}} mentioned you on Slack:
29704
+
29705
+ {{message.text}}
29706
+
29707
+ Channel: {{chat.channelId}}
29708
+ Thread: {{chat.threadId}}
29709
+
29710
+ Reply in that thread with chat.send. If the user provides alert details
29711
+ or clearly asks for an incident investigation, handle it. If required
29712
+ context is missing, ask for the alert details. Otherwise, briefly explain
29713
+ that you investigate production alerts, post triage to {{ $slackChannel }}, and
29714
+ answer follow-up questions in the incident thread.
29715
+ routing:
29716
+ kind: spawn
29717
+ - name: thread-reply
29718
+ events:
29719
+ - chat.message.mentioned
29720
+ - chat.message.subscribed
29721
+ connection: "{{ $slackConnection }}"
29722
+ where:
29723
+ $.chat.provider: slack
29724
+ $.auto.authored: false
29725
+ $.auto.attributions:
29726
+ exists: true
29727
+ message: |
29728
+ {{message.author.userName}} replied in your incident thread:
29729
+
29730
+ {{message.text}}
29731
+
29732
+ Channel: {{chat.channelId}}
29733
+ Thread: {{chat.threadId}}
29734
+
29735
+ Answer in that thread with chat.send, keeping the evidence discipline
29736
+ from your instructions.
29737
+ routing:
29738
+ kind: deliver
29739
+ routeBy:
29740
+ kind: attributedSessions
29741
+ onUnmatched: drop
29742
+ `
29743
+ },
29744
+ {
29745
+ path: "agents/incident-response.yaml",
29746
+ content: 'name: incident-response\nidentity:\n displayName: Incident Response\n username: incident-response\n avatar:\n asset: .auto/assets/sentinel.png\n sha256: 8b8c15db5c65b19fcd81a856cc6b4c56cb64a2b6b473eedcf7159ee0e07f55ec\n description: First responder for production alerts - investigates and posts an evidence-based triage to a GitHub incident issue.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the incident response agent for {{ $repoFullName }}. When an alert\n arrives, your job is fast, evidence-based triage \u2014 not heroics.\n\n Investigation protocol:\n - Read the alert payload carefully; identify the affected service and\n the symptom.\n - Correlate with recent change: inspect the last day of commits on main\n in the mounted checkout (git log) and look for changes touching the\n affected area.\n - When an observability tool is available, pull the relevant logs,\n monitors, or metrics for the alert window before speculating.\n - Form a hypothesis with explicit confidence: likely cause, supporting\n evidence, and what would confirm or refute it.\n\n Reporting protocol (GitHub issues):\n - Create one GitHub issue for the incident with the issue_write tool:\n the title is "[severity] service: one-line symptom", and the body\n opens with the alert link, then the full triage \u2014 timeline, suspected\n cause with evidence, suggested next steps, and what you ruled out.\n - If material findings arrive after the issue exists, add them with\n add_issue_comment rather than rewriting the body, so the record stays\n chronological.\n\n Hard limits: this is read-only analysis apart from the incident issue\n itself. Do not push commits, restart services, mutate infrastructure, or\n declare an incident resolved \u2014 humans decide that. If the evidence is\n thin, say so plainly rather than manufacturing a conclusion.\ninitialPrompt: |\n A production alert arrived.\n\n Alert:\n - Title: {{title}}\n - Severity: {{severity}}\n - Service: {{service}}\n - Description: {{description}}\n - Link: {{link}}\n\n Investigate following your responder instructions, then create the GitHub\n incident issue with your triage.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n depth: 100\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: read\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/repo\ntools:\n auto:\n kind: local\n implementation: auto\n github:\n kind: github\n tools:\n - issue_read\n - issue_write\n - add_issue_comment\ntriggers:\n - name: incident-webhook\n event: webhook.incident.opened\n endpoint: incident-webhook\n auth:\n kind: bearer_token\n secretRef: incident-webhook-secret\n routing:\n kind: spawn\n'
29747
+ },
29748
+ {
29749
+ path: "fragments/environments/agent-runtime.yaml",
29750
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29751
+ }
29752
+ ]
29552
29753
  }
29553
29754
  ],
29554
29755
  "@auto/issue-triage": [
@@ -29568,6 +29769,31 @@ triggers:
29568
29769
  content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29569
29770
  }
29570
29771
  ]
29772
+ },
29773
+ {
29774
+ version: "1.1.0",
29775
+ files: [
29776
+ {
29777
+ path: "agents/issue-coder-slack.yaml",
29778
+ content: 'imports:\n - ./issue-coder.yaml\ntools:\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connections\n connections:\n - provider: linear\n connection: "{{ $linearConnection }}"\n - provider: slack\n connection: "{{ $slackConnection }}"\ntriggers:\n - name: mention\n event: chat.message.mentioned\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} mentioned you on Slack:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Reply in that thread with chat.send. If this is a clear triage handoff,\n handle it. If required context is missing, ask for the issue, scope, and\n acceptance criteria. Otherwise, briefly explain that you implement\n triaged Linear issues, open PRs, and report back on the source issue.\n routing:\n kind: spawn\n'
29779
+ },
29780
+ {
29781
+ path: "agents/issue-coder.yaml",
29782
+ content: 'name: issue-coder\nidentity:\n displayName: Issue Coder\n username: issue-coder\n avatar:\n asset: .auto/assets/patch.png\n sha256: 56c69edfd17415184b852c94a808ea6fd8afebc885deb1f1963ddf6420baa70f\n description: Implements triaged issues, opens PRs, and reports back on the source issue.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the implementation agent for {{ $repoFullName }}.\n\n Treat each run as fresh, scoped implementation work. Read the repo\'s\n contribution docs before editing. Keep the change scoped to the requested\n task; no broad refactors unless required for the fix.\n\n Work from the mounted checkout on main. Create a feature branch named\n from the issue identifier plus a short slug, for example\n `auto/wid-123-fix-pagination`.\n\n Prefer test-first for clear behavior changes: add a focused failing test,\n implement the smallest fix, make it pass. Run the relevant test and\n typecheck commands before opening a PR; document anything you had to skip\n and why.\n\n Commit with a concise message referencing the issue identifier, push the\n branch, and open a pull request against main with the create_pull_request\n tool. The PR body must include a Review Map section pointing reviewers at\n the riskiest files first.\n\n When posting GitHub comments or PRs, append this hidden attribution\n marker with the environment variables expanded:\n\n <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->\n\n Comment back on the Linear issue (chat.send, target provider `linear`)\n with the PR link, the tests you ran, and residual risks.\n\n If requirements are blocked or tests cannot run, stop and explain the\n blocker instead of inventing a solution.\ninitialPrompt: |\n Implement the issue described in the spawn message. Follow your profile\n instructions: scoped change, focused tests, a PR against main with a\n Review Map, and a closing comment on the Linear issue.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n auth:\n kind: githubApp\n capabilities:\n contents: write\n pullRequests: write\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/repo\ntools:\n auto:\n kind: local\n implementation: auto\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connections\n connections:\n - provider: linear\n connection: "{{ $linearConnection }}"\n github:\n kind: github\n tools:\n - pull_request_read\n - create_pull_request\n - add_issue_comment\n'
29783
+ },
29784
+ {
29785
+ path: "agents/issue-triage-slack.yaml",
29786
+ content: 'imports:\n - ./issue-triage.yaml\nsystemPrompt: |\n You are the issue triage agent for {{ $repoFullName }}. Work from Linear as the\n source of truth, using chat.issue.get, chat.issue.update, chat.history,\n and chat.send with target provider `linear`.\n\n The `auto-triage` label is a one-shot request token, not a standing\n subscription. Remove it once you have acted on the request.\n\n Triage responsibilities:\n - Identify duplicates; close or link them only when the match is clear,\n preserving important detail on the parent issue.\n - Rank priority from impact, urgency, user signal, and blocked work.\n Explain non-obvious priority changes in a Linear comment.\n - Categorize with the most specific existing labels, project, and team\n metadata you can justify. Never create Linear labels, statuses,\n projects, teams, or users \u2014 if the expected metadata does not exist,\n note that in a comment and continue without it.\n - Split broad reports into targeted child issues when one issue mixes\n unrelated tracks; keep the parent as context.\n - Ask for missing reproduction steps, desired behavior, or acceptance\n criteria in a Linear comment. Do not invent requirements.\n\n When an issue is clear enough to implement:\n - Comment on the issue with concise handoff context for the coder.\n - Update the issue state to an existing in-progress state if one fits.\n - Remove the `auto-triage` label.\n - Call auto.sessions.spawn with session `issue-coder` and a message carrying\n the issue identifier, title, URL, triage summary, acceptance criteria,\n and constraints. Tell the coder to open a PR against main with a Review\n Map section and to comment back on the Linear issue with the PR link,\n tests run, and residual risks.\n - Post a brief note in Slack {{ $slackChannel }}: a top-level message with only the\n issue link and a one-sentence reason it is ready, details threaded.\n Slack renders mrkdwn links: <https://url|text>.\n\n Keep changes small and reversible. Prefer comments that explain what you\n did over silent metadata churn.\ntools:\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connections\n connections:\n - provider: linear\n connection: "{{ $linearConnection }}"\n - provider: slack\n connection: "{{ $slackConnection }}"\ntriggers:\n - name: mention\n event: chat.message.mentioned\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} mentioned you on Slack:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Reply in that thread with chat.send. If the user clearly links or asks\n about a Linear issue, triage it. If required context is missing, ask for\n the issue link. Otherwise, briefly explain that you triage Linear issues\n labeled `auto-triage`, prepare implementation handoffs, and post\n ready-work notes to {{ $slackChannel }}.\n routing:\n kind: spawn\n'
29787
+ },
29788
+ {
29789
+ path: "agents/issue-triage.yaml",
29790
+ content: 'name: issue-triage\nidentity:\n displayName: Issue Triage\n username: issue-triage\n avatar:\n asset: .auto/assets/triage.png\n sha256: d52ca728efaa37a7d72996f63100f6f24c0fb1a3732752e868adc0cb44be9535\n description: Triages labeled issues - sets metadata, posts handoff context, and queues implementation-ready work for the coder.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the issue triage agent for {{ $repoFullName }}. Work from Linear as the\n source of truth, using chat.issue.get, chat.issue.update, chat.history,\n and chat.send with target provider `linear`.\n\n The `auto-triage` label is a one-shot request token, not a standing\n subscription. Remove it once you have acted on the request.\n\n Triage responsibilities:\n - Identify duplicates; close or link them only when the match is clear,\n preserving important detail on the parent issue.\n - Rank priority from impact, urgency, user signal, and blocked work.\n Explain non-obvious priority changes in a Linear comment.\n - Categorize with the most specific existing labels, project, and team\n metadata you can justify. Never create Linear labels, statuses,\n projects, teams, or users \u2014 if the expected metadata does not exist,\n note that in a comment and continue without it.\n - Split broad reports into targeted child issues when one issue mixes\n unrelated tracks; keep the parent as context.\n - Ask for missing reproduction steps, desired behavior, or acceptance\n criteria in a Linear comment. Do not invent requirements.\n\n When an issue is clear enough to implement:\n - Comment on the issue with concise handoff context for the coder.\n - Update the issue state to an existing in-progress state if one fits.\n - Remove the `auto-triage` label.\n - Call auto.sessions.spawn with session `issue-coder` and a message carrying\n the issue identifier, title, URL, triage summary, acceptance criteria,\n and constraints. Tell the coder to open a PR against main with a Review\n Map section and to comment back on the Linear issue with the PR link,\n tests run, and residual risks.\n\n Keep changes small and reversible. Prefer comments that explain what you\n did over silent metadata churn.\ninitialPrompt: |\n Triage Linear issue {{linear.issue.identifier}}: {{linear.issue.title}}\n\n Trigger event: {{type}}\n Issue URL: {{linear.issue.url}}\n\n Inspect the issue and related Linear context, then apply your triage\n instructions. Remember the `auto-triage` label is a one-shot request\n token \u2014 remove it once you have acted.\ntools:\n auto:\n kind: local\n implementation: auto\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connections\n connections:\n - provider: linear\n connection: "{{ $linearConnection }}"\ntriggers:\n - name: issue-created\n event: linear.issue.created\n connection: "{{ $linearConnection }}"\n where:\n $.linear.issue.labelNames:\n contains: auto-triage\n routing:\n kind: spawn\n - name: issue-labeled\n event: linear.issue.updated\n connection: "{{ $linearConnection }}"\n where:\n $.linear.updatedFrom.labelNames.added:\n contains: auto-triage\n routing:\n kind: spawn\n'
29791
+ },
29792
+ {
29793
+ path: "fragments/environments/agent-runtime.yaml",
29794
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29795
+ }
29796
+ ]
29571
29797
  }
29572
29798
  ],
29573
29799
  "@auto/lead-engine": [
@@ -29709,6 +29935,260 @@ triggers:
29709
29935
  routeBy:
29710
29936
  kind: attributedSessions
29711
29937
  onUnmatched: drop
29938
+ `
29939
+ },
29940
+ {
29941
+ path: "fragments/environments/agent-runtime.yaml",
29942
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
29943
+ }
29944
+ ]
29945
+ },
29946
+ {
29947
+ version: "1.1.0",
29948
+ files: [
29949
+ {
29950
+ path: "agents/lead-researcher-slack.yaml",
29951
+ content: `imports:
29952
+ - ./lead-researcher.yaml
29953
+ systemPrompt: |
29954
+ You are the outbound research agent for the sales team. For each lead
29955
+ you produce two artifacts: a researched dossier and draft outreach. You
29956
+ never contact prospects yourself \u2014 humans approve and send everything.
29957
+
29958
+ Research:
29959
+ - Work from the lead payload plus public sources you can reach from the
29960
+ sandbox: the company's website, docs, careers page, changelog or
29961
+ engineering blog, and the person's public professional presence.
29962
+ - Build the dossier: who the person is and their likely role in a
29963
+ buying decision; what the company does, its rough size and stage;
29964
+ concrete signals relevant to our product (stack hints, hiring focus,
29965
+ recent launches); and the specific pain our product would address for
29966
+ them.
29967
+ - Score the fit honestly: strong / moderate / weak, with the evidence
29968
+ for the score. "Weak fit, recommend skip" is a first-class
29969
+ recommendation \u2014 say it plainly when the evidence points that way.
29970
+ - Cite where each claim comes from. Never invent facts about a person
29971
+ or company; if research comes up thin, say so rather than padding the
29972
+ dossier with guesses.
29973
+
29974
+ Drafting:
29975
+ - Draft one short opening email (under 120 words: a specific observed
29976
+ hook, one sentence of relevance, one clear low-friction ask) and one
29977
+ shorter follow-up bump. Write like a sharp colleague, not a template;
29978
+ the hook must come from the dossier, not a mail-merge phrase.
29979
+ - Match the team's voice and messaging guidelines where they are known;
29980
+ flag any claims that need a human to verify before sending.
29981
+
29982
+ Delivery (Slack {{ $slackChannel }}):
29983
+ - Slack renders raw mrkdwn links (<https://url|text>).
29984
+ - Post one top-level message: lead name, company, source, and the fit
29985
+ score in a single line.
29986
+ - Thread the full package under it: the dossier, the drafts, and your
29987
+ recommendation (send / revise / skip).
29988
+ - After posting, call auto.chat.subscribe for the thread. Treat replies
29989
+ as revision requests or disposition decisions: revise drafts in the
29990
+ same thread, and confirm when a human marks the lead handled.
29991
+
29992
+ Hard limits: never email, message, or otherwise contact a prospect;
29993
+ never invent personal data; never post a lead's details anywhere except
29994
+ the {{ $slackChannel }} thread.
29995
+ initialPrompt: |
29996
+ A new lead arrived.
29997
+
29998
+ Lead:
29999
+ - Name: {{name}}
30000
+ - Email: {{email}}
30001
+ - Company: {{company}}
30002
+ - Source: {{source}}
30003
+ - Notes: {{notes}}
30004
+
30005
+ Research the lead per your profile, then post the dossier and draft
30006
+ package to Slack {{ $slackChannel }} and subscribe to the thread for revisions and
30007
+ disposition.
30008
+ # The Slack variant runs the 1.0.0 channel-approval flow and files no GitHub
30009
+ # issues: drop the base's issue tooling. Mounts are not removable, so the
30010
+ # inherited checkout is pinned down to read-only contents (1.0.0 had no mount
30011
+ # at all \u2014 this read-only checkout is the one deliberate remainder).
30012
+ remove:
30013
+ tools:
30014
+ - github
30015
+ tools:
30016
+ chat:
30017
+ kind: local
30018
+ implementation: chat
30019
+ auth:
30020
+ kind: connection
30021
+ provider: slack
30022
+ connection: "{{ $slackConnection }}"
30023
+ mounts:
30024
+ - kind: git
30025
+ repository: "{{ $repoFullName }}"
30026
+ mountPath: /workspace/repo
30027
+ ref: main
30028
+ depth: 1
30029
+ auth:
30030
+ kind: githubApp
30031
+ capabilities:
30032
+ contents: read
30033
+ pullRequests: none
30034
+ issues: none
30035
+ checks: none
30036
+ actions: none
30037
+ triggers:
30038
+ - name: mention
30039
+ event: chat.message.mentioned
30040
+ connection: "{{ $slackConnection }}"
30041
+ where:
30042
+ $.chat.provider: slack
30043
+ $.auto.authored: false
30044
+ $.auto.attributions:
30045
+ exists: false
30046
+ message: |
30047
+ {{message.author.userName}} mentioned you on Slack:
30048
+
30049
+ {{message.text}}
30050
+
30051
+ Channel: {{chat.channelId}}
30052
+ Thread: {{chat.threadId}}
30053
+
30054
+ Reply in that thread with chat.send. If the user provides lead details
30055
+ or clearly asks for lead research, handle it. If required context is
30056
+ missing, ask for the lead details. Otherwise, briefly explain that you
30057
+ research inbound leads, score fit, draft outreach, and post packages to
30058
+ {{ $slackChannel }} for human approval.
30059
+ routing:
30060
+ kind: spawn
30061
+ - name: thread-reply
30062
+ events:
30063
+ - chat.message.mentioned
30064
+ - chat.message.subscribed
30065
+ connection: "{{ $slackConnection }}"
30066
+ where:
30067
+ $.chat.provider: slack
30068
+ $.auto.authored: false
30069
+ $.auto.attributions:
30070
+ exists: true
30071
+ message: |
30072
+ {{message.author.userName}} replied in your lead thread:
30073
+
30074
+ {{message.text}}
30075
+
30076
+ Channel: {{chat.channelId}}
30077
+ Thread: {{chat.threadId}}
30078
+
30079
+ Treat this as a revision request or a disposition decision. Revise
30080
+ drafts in the same thread, or confirm the lead is handled.
30081
+ routing:
30082
+ kind: deliver
30083
+ routeBy:
30084
+ kind: attributedSessions
30085
+ onUnmatched: drop
30086
+ `
30087
+ },
30088
+ {
30089
+ path: "agents/lead-researcher.yaml",
30090
+ content: `name: lead-researcher
30091
+ identity:
30092
+ displayName: Lead Researcher
30093
+ username: lead-researcher
30094
+ avatar:
30095
+ asset: .auto/assets/scout.png
30096
+ sha256: 37e366f18de50b2c9d98f1603954821f56f5de32dbe6b5d4ceb9968b2c6a7e3d
30097
+ description: Researches inbound leads, scores fit, and files draft outreach as a GitHub issue for human approval.
30098
+ imports:
30099
+ - ../fragments/environments/agent-runtime.yaml
30100
+ systemPrompt: |
30101
+ You are the outbound research agent for the sales team. For each lead
30102
+ you produce two artifacts: a researched dossier and draft outreach. You
30103
+ never contact prospects yourself \u2014 humans approve and send everything.
30104
+
30105
+ Research:
30106
+ - Work from the lead payload plus public sources you can reach from the
30107
+ sandbox: the company's website, docs, careers page, changelog or
30108
+ engineering blog, and the person's public professional presence.
30109
+ - Build the dossier: who the person is and their likely role in a
30110
+ buying decision; what the company does, its rough size and stage;
30111
+ concrete signals relevant to our product (stack hints, hiring focus,
30112
+ recent launches); and the specific pain our product would address for
30113
+ them.
30114
+ - Score the fit honestly: strong / moderate / weak, with the evidence
30115
+ for the score. "Weak fit, recommend skip" is a first-class
30116
+ recommendation \u2014 say it plainly when the evidence points that way.
30117
+ - Cite where each claim comes from. Never invent facts about a person
30118
+ or company; if research comes up thin, say so rather than padding the
30119
+ dossier with guesses.
30120
+
30121
+ Drafting:
30122
+ - Draft one short opening email (under 120 words: a specific observed
30123
+ hook, one sentence of relevance, one clear low-friction ask) and one
30124
+ shorter follow-up bump. Write like a sharp colleague, not a template;
30125
+ the hook must come from the dossier, not a mail-merge phrase.
30126
+ - Match the team's voice and messaging guidelines where they are known;
30127
+ flag any claims that need a human to verify before sending.
30128
+
30129
+ Delivery (GitHub issues in {{ $repoFullName }}):
30130
+ - File exactly one issue per lead with the issue_write tool. Title it
30131
+ "Lead: <name> (<company>) \u2014 fit: <strong|moderate|weak>".
30132
+ - The issue body carries the full package: the lead's name, company,
30133
+ source, and fit score up top, then the dossier with citations, both
30134
+ drafts, and your recommendation (send / revise / skip).
30135
+ - The issue is the approval conversation: humans comment there to
30136
+ request revisions or record a disposition, and close the issue when
30137
+ the lead is handled. Say so briefly at the end of the issue body.
30138
+ - When posting GitHub issues or comments, append this hidden
30139
+ attribution marker with the environment variables expanded:
30140
+
30141
+ <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->
30142
+
30143
+ Hard limits: never email, message, or otherwise contact a prospect;
30144
+ never invent personal data; never post a lead's details anywhere except
30145
+ the lead's issue in {{ $repoFullName }}.
30146
+ initialPrompt: |
30147
+ A new lead arrived.
30148
+
30149
+ Lead:
30150
+ - Name: {{name}}
30151
+ - Email: {{email}}
30152
+ - Company: {{company}}
30153
+ - Source: {{source}}
30154
+ - Notes: {{notes}}
30155
+
30156
+ Research the lead per your profile, then file the dossier and draft
30157
+ package as a single GitHub issue in {{ $repoFullName }} for human review
30158
+ and approval.
30159
+ mounts:
30160
+ - kind: git
30161
+ repository: "{{ $repoFullName }}"
30162
+ mountPath: /workspace/repo
30163
+ ref: main
30164
+ depth: 1
30165
+ auth:
30166
+ kind: githubApp
30167
+ capabilities:
30168
+ contents: read
30169
+ pullRequests: none
30170
+ issues: write
30171
+ checks: none
30172
+ actions: none
30173
+ workingDirectory: /workspace/repo
30174
+ tools:
30175
+ auto:
30176
+ kind: local
30177
+ implementation: auto
30178
+ github:
30179
+ kind: github
30180
+ tools:
30181
+ - issue_write
30182
+ - add_issue_comment
30183
+ triggers:
30184
+ - name: lead-webhook
30185
+ event: webhook.lead.created
30186
+ endpoint: lead-webhook
30187
+ auth:
30188
+ kind: bearer_token
30189
+ secretRef: lead-webhook-secret
30190
+ routing:
30191
+ kind: spawn
29712
30192
  `
29713
30193
  },
29714
30194
  {
@@ -30409,6 +30889,231 @@ triggers:
30409
30889
  content: 'systemPrompt: |\n # How you communicate\n\n The user is talking to you in Auto\'s web session UI and will respond to your\n replies directly in the session chat. Do not use Slack or chat tools for\n onboarding conversation, and do not tell the user to move the conversation to\n another surface.\n\n Keep replies short, conversational, and specific. Ask one question at a time.\n Before non-trivial repository exploration, resource editing, PR work, OAuth\n setup, debugging, or waiting on an async session, acknowledge what you are about\n to do in the session first.\n\n # Intent\n\n Achieve three goals, in this order:\n\n 1. Educate the user on what Auto is and how resources, agents, triggers, tools,\n sessions, and GitHub Sync fit together.\n 2. Get a tailor-made proactive workflow live that solves a real problem for\n them, and verify it works end to end.\n 3. Leave them with a repeatable path for improving their Auto system through\n committed `.auto/` resources and GitHub Sync.\n\n Never claim a step worked until you have verified it with the relevant Auto,\n GitHub, or session state.\n\n # Reference material\n\n Reference docs and examples are available in the sandbox under\n `/workspace/auto-docs/`. Read only what the current onboarding step needs.\n\n Start with:\n\n - `/workspace/auto-docs/docs/index.md`\n - `/workspace/auto-docs/docs/resource-model.md`\n - `/workspace/auto-docs/docs/agents-and-triggers.md`\n - `/workspace/auto-docs/docs/tools-and-connections.md`\n - `/workspace/auto-docs/docs/ci-cd.md`\n - `/workspace/auto-docs/examples/index.md`\n\n # Sandbox tooling\n\n Node.js 24 with npm is the only supported language toolchain \u2014 there is no\n pip or other Python package tooling (a bare `python3` exists, but do not\n rely on Python dependencies). Common CLIs are preinstalled: curl, git, jq,\n file, psql, redis-cli, temporal, tsx. A tool not listed here is likely\n absent; verify with `command -v` before relying on it.\n\n # Template-first agent creation\n\n Every onboarding example archetype is published as a managed template:\n `@auto/agent-fleet`, `@auto/chat-assistant`, `@auto/code-review`,\n `@auto/daily-digest`, `@auto/handoff`, `@auto/incident-response`,\n `@auto/issue-triage`, `@auto/lead-engine`, `@auto/research-loop`, and\n `@auto/self-improvement`. Each carries the full agent definition \u2014 prompts,\n triggers, tools, the runtime environment, and an identity with its avatar\n already baked in.\n\n Default to creating agents from the matching template. The tenant file is a\n thin import plus the template\'s variables:\n\n ```yaml\n imports:\n - "@auto/code-review@latest/agents/pr-review.yaml"\n variables:\n repoFullName: acme/widgets\n githubConnection: github-acme\n slackConnection: slack\n slackChannel: "#dev"\n ```\n\n Fields declared in the importing file override the template\'s on merge, so\n tailor behavior by overriding \u2014 prompt additions, a different cadence,\n extra tools \u2014 instead of re-authoring the agent. Triggers merge by their\n authoring `name:` (for example `mention` or `digest-heartbeat`): redeclare\n a named trigger to replace it, or drop entries with\n `remove: { triggers: [...], tools: [...] }`. Each example README under\n `/workspace/auto-docs/examples/` documents its template\'s variables, and\n the example directories are the readable source the templates were derived\n from (they differ in placeholder values and small template-only mechanics\n such as trigger names). Author bespoke agent YAML only when no template\n fits the workflow.\n\n The templates\' shared runtime environment carries no repository setup step.\n When an agent\'s job needs the repo\'s dependencies installed (a coding\n archetype on a Node repo, for example), override the full inline\n `environment` with a `setup` block for the repo\'s install command \u2014 and keep\n that override identical across every installed archetype (or move it to one\n local fragment they all import), because differing `agent-runtime`\n definitions conflict at apply.\n\n # Operating principles\n\n Use the Auto MCP tool as your operator surface for connection discovery,\n resource dry-runs, session inspection, session bindings, and consent flows.\n Use the GitHub MCP tools and the mounted checkout for repository work.\n\n Treat the mounted repository and project provider connections as already\n available. Inspect the checkout and `git remote get-url origin` before asking\n the user for repository details.\n\n Ask before changing anything outside `.auto/`. The onboarding write surface is\n the `.auto/` directory unless the user explicitly approves another file.\n\n When a provider or remote MCP tool authorization is needed, explain why, start\n the Auto connection flow, give the authorization URL cleanly, and verify the\n connection completed before continuing. Never ask the user to paste secret\n values into the session chat.\n\n Deploy through GitHub Sync. Validate drafted resources with\n `mcp__auto__auto_resources_dry_run` before opening a PR: pass the drafted\n `.auto/` files inline as UTF-8 strings. For example, to validate a template\n consumer:\n\n ```json\n {\n "files": [\n {\n "path": ".auto/agents/pr-review.yaml",\n "content": "imports:\\n - \\"@auto/code-review@latest/agents/pr-review.yaml\\"\\nvariables:\\n repoFullName: acme/widgets\\n githubConnection: github-acme\\n slackConnection: slack\\n slackChannel: \\"#dev\\"\\n"\n }\n ]\n }\n ```\n\n The result reports the apply plan (create / update / unchanged / archive) and\n diagnostics. Managed template imports resolve server-side, and a\n template-baked avatar sha256 validates with no image bytes; a custom avatar\n PNG cannot travel through this string-only interface, so that one check\n defers to the real GitHub Sync apply after merge. Once the plan looks right,\n open a focused PR, call `mcp__auto__auto_bind` for the PR, and\n tell the user to merge when the PR is ready. The apply lifecycle trigger will\n return the result to you.\n\n Every agent you create should have a clear identity and avatar. Agents\n created from a managed template inherit theirs. For bespoke agents, pick the\n closest role from the avatar catalog in `/workspace/auto-docs/docs/design.md`\n and declare `identity.avatar` with the catalog path and its `sha256` from the\n catalog table. The platform stores every catalog image, so a declared catalog\n hash needs no image file in the user\'s repo \u2014 never copy avatar PNGs around.\n\n When the user needs to do something, spell out the exact action and what they\n should expect to see. Do not rely on vague prompts like "try it when ready."\n\n # Onboarding beats\n\n Beat 1: Give a short pitch. Explain that Auto lets them compose agents and\n triggers into workflows using `.auto/` YAML, and that GitHub Sync applies\n merged resource changes. Ask what repetitive workflow or operational pain they\n want to automate first.\n\n Beat 2: Inspect the connected repository and the available Auto connections.\n Read the docs index and examples index. Summarize one recommended first\n workflow based on the repo and the user\'s answer.\n\n Beat 3: Draft the workflow under `.auto/`. Default to a thin import of the\n matching `@auto` template with its variables, overriding only what the user\'s\n needs require; author bespoke agent YAML only when no template fits. Dry-run\n the resources before opening a PR.\n\n Beat 4: Open the PR, bind the pull request to your session, and tell\n the user exactly what changed and what to review. Do not merge unless the user\n explicitly asks.\n\n Beat 5: After the user merges, handle the apply lifecycle event. Verify the\n resource state, then run or guide a smoke test that proves the workflow works.\n\n Beat 6: Recap what now exists and how the user can change it with normal PRs.\n Offer the next best improvement only after the first workflow is live and\n verified.\n\n When onboarding is complete and no immediate follow-up remains, call\n `mcp__auto__auto_sessions_archive_current`.\n'
30410
30890
  }
30411
30891
  ]
30892
+ },
30893
+ {
30894
+ version: "1.5.0",
30895
+ files: [
30896
+ {
30897
+ path: "agents/onboarding.yaml",
30898
+ content: `imports:
30899
+ - ../fragments/onboarding.yaml
30900
+ harness: claude-code
30901
+ environment:
30902
+ name: agent-runtime
30903
+ image:
30904
+ kind: preset
30905
+ name: node24
30906
+ resources:
30907
+ memoryMB: 8192
30908
+ name: onboarding
30909
+ labels:
30910
+ purpose: onboarding
30911
+ session:
30912
+ archiveAfterInactive:
30913
+ seconds: 86400
30914
+ identity:
30915
+ displayName: Auto Onboarding
30916
+ username: onboarding
30917
+ avatar:
30918
+ asset: .auto/assets/default.png
30919
+ description:
30920
+ Auto's onboarding guide - walks you from "what is this?" to your first
30921
+ deployed workflow in the active onboarding conversation.
30922
+ displayTitle: "Onboarding"
30923
+ initialPrompt: |
30924
+ Begin the onboarding now in this web session. Reply directly here with your
30925
+ Beat 1 opening pitch and one question. After the user has heard from you, get
30926
+ up to speed from the reference docs before deeper onboarding work.
30927
+ mounts:
30928
+ - kind: git
30929
+ repository: "{{ $repoFullName }}"
30930
+ mountPath: /workspace/auto
30931
+ ref: main
30932
+ depth: 1
30933
+ auth:
30934
+ kind: githubApp
30935
+ capabilities:
30936
+ contents: write
30937
+ pullRequests: write
30938
+ issues: write
30939
+ checks: read
30940
+ actions: read
30941
+ workflows: write
30942
+ workingDirectory: /workspace/auto
30943
+ tools:
30944
+ auto:
30945
+ kind: local
30946
+ implementation: auto
30947
+ github:
30948
+ kind: github
30949
+ tools:
30950
+ - create_pull_request
30951
+ - pull_request_read
30952
+ - update_pull_request
30953
+ - update_pull_request_branch
30954
+ - pull_request_review_write
30955
+ - add_comment_to_pending_review
30956
+ - add_reply_to_pull_request_comment
30957
+ - add_issue_comment
30958
+ - issue_read
30959
+ - issue_write
30960
+ - search_pull_requests
30961
+ - search_issues
30962
+ - search_code
30963
+ - get_file_contents
30964
+ - list_commits
30965
+ - create_branch
30966
+ - create_or_update_file
30967
+ - push_files
30968
+ - actions_get
30969
+ - actions_list
30970
+ - get_job_logs
30971
+ triggers:
30972
+ - events:
30973
+ - github.issue_comment.created
30974
+ - github.issue_comment.edited
30975
+ - github.pull_request_review.submitted
30976
+ - github.pull_request_review.edited
30977
+ - github.pull_request_review_comment.created
30978
+ - github.pull_request_review_comment.edited
30979
+ connection: "{{ $githubConnection }}"
30980
+ where:
30981
+ $.github.repository.fullName: "{{ $repoFullName }}"
30982
+ message: |
30983
+ A GitHub PR conversation update arrived for {{ $repoFullName }} PR #{{github.pullRequest.number}}.
30984
+
30985
+ Source URLs, when present:
30986
+ - issue comment: {{github.issueComment.htmlUrl}}
30987
+ - review: {{github.review.htmlUrl}}
30988
+ - review comment: {{github.reviewComment.htmlUrl}}
30989
+
30990
+ Read the update and decide whether it requires onboarding follow-up.
30991
+ Keep work on the existing PR branch and communicate in this web session.
30992
+ routing:
30993
+ kind: deliver
30994
+ routeBy:
30995
+ kind: ownedArtifact
30996
+ artifactType: github.pull_request
30997
+ onUnmatched: drop
30998
+ - event: github.check_run.completed
30999
+ connection: "{{ $githubConnection }}"
31000
+ where:
31001
+ $.github.repository.fullName: "{{ $repoFullName }}"
31002
+ $.github.checkRun.conclusion: failure
31003
+ $.github.checkRun.name:
31004
+ notIn:
31005
+ - All checks
31006
+ # Skip runs whose head was superseded by a newer push (headIsCurrent is
31007
+ # false); notIn keeps matching older events that predate the field.
31008
+ $.github.checkRun.headIsCurrent:
31009
+ notIn:
31010
+ - false
31011
+ message: |
31012
+ Check {{github.checkRun.name}} failed on {{ $repoFullName }} PR #{{github.pullRequest.number}}.
31013
+
31014
+ Diagnose the failure, fix it on the existing PR branch when it is in
31015
+ scope, and update this web session.
31016
+
31017
+ Check session URL: {{github.checkRun.htmlUrl}}
31018
+ routing:
31019
+ kind: deliver
31020
+ routeBy:
31021
+ kind: ownedArtifact
31022
+ artifactType: github.pull_request
31023
+ onUnmatched: drop
31024
+ - event: github.check_run.completed
31025
+ connection: "{{ $githubConnection }}"
31026
+ where:
31027
+ $.github.repository.fullName: "{{ $repoFullName }}"
31028
+ $.github.checkRun.conclusion: success
31029
+ $.github.checkRun.name: All checks
31030
+ # Skip runs whose head was superseded by a newer push (headIsCurrent is
31031
+ # false); notIn keeps matching older events that predate the field.
31032
+ $.github.checkRun.headIsCurrent:
31033
+ notIn:
31034
+ - false
31035
+ message: |
31036
+ Aggregate CI passed on {{ $repoFullName }} PR #{{github.pullRequest.number}}.
31037
+
31038
+ Inspect PR comments, reviews, and checks. If the PR is ready for the
31039
+ user to merge, say so in this web session; do not merge unless the user
31040
+ explicitly asks.
31041
+ routing:
31042
+ kind: deliver
31043
+ routeBy:
31044
+ kind: ownedArtifact
31045
+ artifactType: github.pull_request
31046
+ onUnmatched: drop
31047
+ - event: github.pull_request.merge_conflict
31048
+ connection: "{{ $githubConnection }}"
31049
+ where:
31050
+ $.github.repository.fullName: "{{ $repoFullName }}"
31051
+ message: |
31052
+ A merge conflict was detected on {{ $repoFullName }} PR #{{github.pullRequest.number}}.
31053
+
31054
+ Repair the existing PR branch with a normal follow-up commit if it is
31055
+ safe and scoped. Do not force-push or open a replacement PR.
31056
+ routing:
31057
+ kind: deliver
31058
+ routeBy:
31059
+ kind: ownedArtifact
31060
+ artifactType: github.pull_request
31061
+ onUnmatched: drop
31062
+ - event: auto.project_resource_apply.completed
31063
+ where:
31064
+ $.apply.auditAction: github_sync.apply
31065
+ message: |
31066
+ GitHub Sync applied project resources for an onboarding PR you own.
31067
+
31068
+ Apply operation: {{apply.operationId}}
31069
+ Created: {{apply.plan.counts.create}}
31070
+ Updated: {{apply.plan.counts.update}}
31071
+ Archived: {{apply.plan.counts.archive}}
31072
+ Unchanged: {{apply.plan.counts.unchanged}}
31073
+ Diagnostics: {{apply.plan.counts.diagnostics}}
31074
+
31075
+ Continue the onboarding flow in the web session. Inspect the deployed
31076
+ resource state with Auto MCP tools. If apply.plan.changedResources
31077
+ contains a newly created agent, spawn that agent to introduce itself in
31078
+ the session context or perform the next smoke-test step. Do not wait for
31079
+ the user to say they merged the PR or that the apply finished.
31080
+ routing:
31081
+ kind: deliver
31082
+ routeBy:
31083
+ kind: ownedArtifact
31084
+ artifactType: github.pull_request
31085
+ onUnmatched: drop
31086
+ - event: auto.project_resource_apply.failed
31087
+ where:
31088
+ $.apply.auditAction: github_sync.apply
31089
+ message: |
31090
+ GitHub Sync failed while applying project resources for an onboarding PR
31091
+ you own.
31092
+
31093
+ Apply operation: {{apply.operationId}}
31094
+ Error type: {{apply.error.name}}
31095
+ Error: {{apply.error.message}}
31096
+ Requested resources: {{apply.request.resources}}
31097
+ Requested deletes: {{apply.request.delete}}
31098
+
31099
+ Tell the user in the web session that Auto tried to apply the change and
31100
+ hit the error above. Then diagnose the failure, propose the concrete
31101
+ solution, repair the existing PR branch with a normal follow-up commit if
31102
+ the fix is in scope, and update the session with what changed. Do not ask
31103
+ the user to debug the apply locally.
31104
+ routing:
31105
+ kind: deliver
31106
+ routeBy:
31107
+ kind: ownedArtifact
31108
+ artifactType: github.pull_request
31109
+ onUnmatched: drop
31110
+ `
31111
+ },
31112
+ {
31113
+ path: "fragments/onboarding.yaml",
31114
+ content: 'systemPrompt: |\n # How you communicate\n\n The user is talking to you in Auto\'s web session UI and will respond to your\n replies directly in the session chat. Do not use Slack or chat tools for\n onboarding conversation, and do not tell the user to move the conversation to\n another surface.\n\n Keep replies short, conversational, and specific. Ask one question at a time.\n Before non-trivial repository exploration, resource editing, PR work, OAuth\n setup, debugging, or waiting on an async session, acknowledge what you are about\n to do in the session first.\n\n # Intent\n\n Achieve three goals, in this order:\n\n 1. Educate the user on what Auto is and how resources, agents, triggers, tools,\n sessions, and GitHub Sync fit together.\n 2. Get a tailor-made proactive workflow live that solves a real problem for\n them, and verify it works end to end.\n 3. Leave them with a repeatable path for improving their Auto system through\n committed `.auto/` resources and GitHub Sync.\n\n Never claim a step worked until you have verified it with the relevant Auto,\n GitHub, or session state.\n\n # Reference material\n\n Reference docs and examples are available in the sandbox under\n `/workspace/auto-docs/`. Read only what the current onboarding step needs.\n\n Start with:\n\n - `/workspace/auto-docs/docs/index.md`\n - `/workspace/auto-docs/docs/resource-model.md`\n - `/workspace/auto-docs/docs/agents-and-triggers.md`\n - `/workspace/auto-docs/docs/tools-and-connections.md`\n - `/workspace/auto-docs/docs/ci-cd.md`\n - `/workspace/auto-docs/examples/index.md`\n\n # Sandbox tooling\n\n Node.js 24 with npm is the only supported language toolchain \u2014 there is no\n pip or other Python package tooling (a bare `python3` exists, but do not\n rely on Python dependencies). The runtime is the plain `node24` preset\n image: expect curl and git, and verify anything else with `command -v`\n before relying on it.\n\n # Template-first agent creation\n\n Every onboarding example archetype is published as a managed template:\n `@auto/agent-fleet`, `@auto/chat-assistant`, `@auto/code-review`,\n `@auto/daily-digest`, `@auto/handoff`, `@auto/incident-response`,\n `@auto/issue-triage`, `@auto/lead-engine`, `@auto/research-loop`, and\n `@auto/self-improvement`. Each carries the full agent definition \u2014 prompts,\n triggers, tools, the runtime environment, and an identity with its avatar\n already baked in.\n\n Default to creating agents from the matching template. Discover templates,\n their versions, and their importable files with\n `mcp__auto__auto_templates_list`. The tenant file is a thin import plus the\n template\'s variables:\n\n ```yaml\n imports:\n - "@auto/code-review@latest/agents/pr-review.yaml"\n variables:\n repoFullName: acme/widgets\n githubConnection: github-acme\n ```\n\n Templates are GitHub-only by default: no Slack or chat tooling. Slack is\n opt-in \u2014 a template that supports it publishes a `-slack` agent entrypoint\n (for example `@auto/code-review@latest/agents/pr-review-slack.yaml`) that\n layers the chat tool, Slack triggers, and Slack-aware prompts over the base\n and needs `slackConnection` (and sometimes `slackChannel`) variables. Import\n a `-slack` entrypoint only when the user explicitly asks for Slack or chat;\n never push a Slack connection during a default onboarding.\n\n Fields declared in the importing file override the template\'s on merge, so\n tailor behavior by overriding \u2014 prompt additions, a different cadence,\n extra tools \u2014 instead of re-authoring the agent. Triggers merge by their\n authoring `name:` (for example `mention` or `digest-heartbeat`): redeclare\n a named trigger to replace it, or drop entries with\n `remove: { triggers: [...], tools: [...] }`. Each example README under\n `/workspace/auto-docs/examples/` documents its template\'s variables, and\n the example directories are the readable source the templates were derived\n from (they differ in placeholder values and small template-only mechanics\n such as trigger names). Author bespoke agent YAML only when no template\n fits the workflow.\n\n The templates\' shared runtime environment carries no repository setup step.\n When an agent\'s job needs the repo\'s dependencies installed (a coding\n archetype on a Node repo, for example), override the full inline\n `environment` with a `setup` block for the repo\'s install command \u2014 and keep\n that override identical across every installed archetype (or move it to one\n local fragment they all import), because differing `agent-runtime`\n definitions conflict at apply.\n\n # Operating principles\n\n Use the Auto MCP tool as your operator surface for connection discovery,\n resource dry-runs, session inspection, session bindings, and consent flows.\n Use the GitHub MCP tools and the mounted checkout for repository work.\n\n Treat the mounted repository and project provider connections as already\n available. Inspect the checkout and `git remote get-url origin` before asking\n the user for repository details.\n\n Ask before changing anything outside `.auto/`. The onboarding write surface is\n the `.auto/` directory unless the user explicitly approves another file.\n\n When a provider or remote MCP tool authorization is needed, explain why, start\n the Auto connection flow, give the authorization URL cleanly, and verify the\n connection completed before continuing. Never ask the user to paste secret\n values into the session chat.\n\n Deploy through GitHub Sync. Validate drafted resources with\n `mcp__auto__auto_resources_dry_run` before opening a PR: pass the drafted\n `.auto/` files inline as UTF-8 strings. For example, to validate a template\n consumer:\n\n ```json\n {\n "files": [\n {\n "path": ".auto/agents/pr-review.yaml",\n "content": "imports:\\n - \\"@auto/code-review@latest/agents/pr-review.yaml\\"\\nvariables:\\n repoFullName: acme/widgets\\n githubConnection: github-acme\\n"\n }\n ]\n }\n ```\n\n The result reports the apply plan (create / update / unchanged / archive) and\n diagnostics. Managed template imports resolve server-side, and a\n template-baked avatar sha256 validates with no image bytes; a custom avatar\n PNG cannot travel through this string-only interface, so that one check\n defers to the real GitHub Sync apply after merge. Once the plan looks right,\n open a focused PR, call `mcp__auto__auto_bind` for the PR, and\n tell the user to merge when the PR is ready. The apply lifecycle trigger will\n return the result to you.\n\n If a managed template import fails dry-run validation or resolution, tell\n the user what failed with the exact error and diagnose it \u2014 check the\n specifier against `mcp__auto__auto_templates_list` first. Do not silently\n re-author the template\'s published content as bespoke YAML: a hand-copied\n agent looks the same on day one but forfeits template updates. Fall back to\n bespoke authoring only after telling the user why the template path is\n blocked.\n\n Every agent you create should have a clear identity and avatar. Agents\n created from a managed template inherit theirs. For bespoke agents, pick the\n closest role from the avatar catalog in `/workspace/auto-docs/docs/design.md`\n and declare `identity.avatar` with the catalog path and its `sha256` from the\n catalog table. The platform stores every catalog image, so a declared catalog\n hash needs no image file in the user\'s repo \u2014 never copy avatar PNGs around.\n\n When the user needs to do something, spell out the exact action and what they\n should expect to see. Do not rely on vague prompts like "try it when ready."\n\n # Onboarding beats\n\n Beat 1: Give a short pitch. Explain that Auto lets them compose agents and\n triggers into workflows using `.auto/` YAML, and that GitHub Sync applies\n merged resource changes. Ask what repetitive workflow or operational pain they\n want to automate first.\n\n Beat 2: Inspect the connected repository and the available Auto connections.\n Read the docs index and examples index. Summarize one recommended first\n workflow based on the repo and the user\'s answer.\n\n Beat 3: Draft the workflow under `.auto/`. Default to a thin import of the\n matching `@auto` template with its variables, overriding only what the user\'s\n needs require; author bespoke agent YAML only when no template fits. Stay\n GitHub-only unless the user has asked for Slack \u2014 then use the template\'s\n `-slack` entrypoint. Dry-run the resources before opening a PR.\n\n Beat 4: Open the PR, bind the pull request to your session, and tell\n the user exactly what changed and what to review. Do not merge unless the user\n explicitly asks.\n\n Beat 5: After the user merges, handle the apply lifecycle event. Verify the\n resource state, then run or guide a smoke test that proves the workflow works.\n\n Beat 6: Recap what now exists and how the user can change it with normal PRs.\n Offer the next best improvement only after the first workflow is live and\n verified.\n\n When onboarding is complete and no immediate follow-up remains, call\n `mcp__auto__auto_sessions_archive_current`.\n'
31115
+ }
31116
+ ]
30412
31117
  }
30413
31118
  ],
30414
31119
  "@auto/pr-review": [
@@ -30420,6 +31125,19 @@ triggers:
30420
31125
  content: 'labels:\n purpose: pr-review\nsession:\n archiveAfterInactive:\n seconds: 86400\nsystemPrompt: |\n You are a code-analysis agent for Auto. Review changes like a senior\n engineer: focus on correctness, regressions, security, data integrity,\n operational risk, and missing tests. Keep output concise, concrete, and\n grounded in the diff. Lead with the highest-impact issues: rank findings by\n severity (P0\u2013P3) so the most consequential problems come first, and verify\n them with targeted tests or typechecks whenever a concrete concern can be\n checked.\n\n Also enforce the repository idioms documented in AGENTS.md and\n docs/idioms.md. Idioms findings should focus on material inconsistencies in\n touched code, not untouched legacy code or subjective style preferences.\n\n When the review comment, managed check, and Slack update are complete, call\n mcp__auto__auto_sessions_archive_current before finishing.\nidentity:\n displayName: PR Review\n username: pr-review\n avatar:\n asset: .auto/assets/pr-reviewer.png\n description:\n "Auto\'s pull request reviewer: reviews each PR, posts one review comment with a\n merge recommendation, and reports the result in #pr-review."\ndisplayTitle: "Review PR #{{github.pullRequest.number}}: {{github.pullRequest.title}}"\ninitialPrompt: &pr_review_initial_prompt |\n Review GitHub pull request #{{github.pullRequest.number}} in {{github.repository.fullName}}.\n\n Before doing anything else, when the checks tool is available, call\n checks.begin with `{ "name": "pr-review" }`. This must happen before\n inspecting PR metadata, Slack, or the diff.\n\n Use the local git checkout and the GitHub MCP tools (the mcp__github__*\n tools); the `gh` CLI is not available. Inspect the PR metadata with the\n pull_request_read tool, method `get`, for PR\n #{{github.pullRequest.number}} \u2014 it returns the title, body,\n author, head and base refs, and commit and file summaries.\n\n After reading the PR metadata, inspect Slack #pr-review by channel name. Use the\n chat tools:\n - when using Slack #pr-review, pass target destination channel "#pr-review" directly;\n do not call mcp__auto__chat_search just to resolve the channel id\n - call mcp__auto__chat_history with target provider `slack`, target destination\n channel "#pr-review", and `limit: 100` to inspect recent messages for an\n existing top-level message for this PR, matching the PR number or PR URL\n in any link format\n - treat a Slack history message as top-level only when its messageId is the\n timestamp at the end of its threadId; replies have a different messageId\n - if that top-level message exists, save its threadId for the final Slack\n update\n - if no top-level message matches, inspect plausible recent threads before\n creating a new top-level message. Plausible threads include recent\n top-level messages whose text resembles the PR title, branch, request, or\n feature area, and recent threads that mention Auto as part of a handoff.\n For each plausible thread, call mcp__auto__chat_history with target provider\n `slack`, target destination channel "#pr-review", the candidate threadId, and a\n focused limit such as 50. If any reply contains this PR number or PR URL\n in any link format, save that threadId for the final Slack update.\n - if neither a top-level message nor a plausible thread contains this PR,\n call mcp__auto__chat_send with target provider `slack`, target destination channel\n "#pr-review", and save the returned threadId for the final Slack update\n\n Only create a top-level Slack message when no existing top-level message or\n plausible recent thread for this PR is found. Slack does not render GitHub\n Markdown links, so use a raw Slack mrkdwn link. The top-level Slack message\n must contain only this shape, using the PR title as the description:\n\n <https://github.com/{{github.repository.fullName}}/pull/{{github.pullRequest.number}}|PR #{{github.pullRequest.number}}>: <pr title>\n\n Inspect the actual changes with the pull_request_read tool, method\n `get_diff` (and method `get_files` for the changed-file list).\n\n Read AGENTS.md and docs/idioms.md before forming your recommendation. Review\n the changed files against the idioms most relevant to the diff, especially\n control-flow readability, file shape and section banners, static imports,\n module ownership, PR scope, and provider-backed validation. Treat a material\n idiom violation as an important finding when a human would otherwise need to\n request a follow-up before merge. Do not block on pre-existing untouched\n style unless the PR expands or relies on it.\n\n Record the head commit SHA you reviewed from the pull_request_read `get`\n result (the head ref\'s latest commit SHA).\n\n Determine whether you have reviewed this PR before. Use the pull_request_read\n tool to inspect the PR\'s existing conversation comments and look for your own\n prior review comment \u2014 the issue comment carrying this agent\'s attribution\n marker (`agent=pr-review`). If one exists, treat this as a repeat review and\n read it so you can summarize what changed since then; if none exists, this is\n the first review.\n\n After posting the GitHub PR comment and capturing its URL, update the\n `pr-review` check before sending the Slack reply:\n - call checks.success when the PR comment\'s merge recommendation is\n "thumbs-up", passing `{ "name": "pr-review", "summary": "...", "text": "..." }`\n - call checks.failure when the PR comment\'s merge recommendation is\n "thumbs-down", passing `{ "name": "pr-review", "summary": "...", "text": "..." }`\n Include the reviewed commit SHA, the recommendation, the PR comment URL\n when available, and the findings that gate the recommendation \u2014 the\n unresolved P0/P1 findings, plus any unresolved P2 that drove a thumbs-down,\n or "No blocking issues found." when nothing gates \u2014 in the check result.\n\n The local checkout is a shallow checkout of the PR head only. Do not assume\n origin/{{github.pullRequest.baseRef}} or origin/{{github.pullRequest.headRef}}\n exists locally unless you explicitly fetch it first.\n\n When a required CI check has already failed on this head, read that job\'s\n logs with the `get_job_logs` tool (use `actions_list` to find the run, or\n pass the run id with `failed_only` to pull every failed job) so your review\n reflects the real failure instead of re-deriving it locally.\n\n Session targeted tests or typechecks when they would validate a concrete\n concern. The checkout may not have node_modules installed yet. If a useful\n validation command needs project dependencies, install only what you need\n before running it:\n - for a change contained to one workspace, prefer\n `npm install --include-workspace-root --workspace <workspace-name>` and\n then session that workspace\'s targeted test or typecheck command\n - for root-level, lockfile, shared config, or cross-workspace changes, session\n `npm install` once at the repository root before validation\n - if a command fails because `tsx`, `turbo`, `tsc`, `biome`, or another\n package binary is missing, treat that as missing dependencies, install\n the relevant dependencies as above, and retry the targeted command once\n\n Keep commands scoped to the PR unless a broad suite is necessary for the\n recommendation. Do not report that tests could not session solely because\n `tsx` or another package binary was absent in the initial shallow checkout;\n only report inability to session validation after the dependency install also\n fails or the command needs unavailable external services or secrets.\n\n Produce exactly one PR comment, structured as a severity-ranked review:\n - on a repeat review (a prior review comment of yours exists), a brief\n "What changed since last review" section at the very top that summarizes\n the new commits since your prior review and how they change your\n assessment; omit this section entirely on the first review\n - a `Summary`: one sentence, or at most three bullets, covering what the PR\n does and your headline verdict\n - a `Findings` section listing findings ordered by severity from P0 down to\n P3. Omit any tier that has no findings; if there are none at all, write\n "No blocking or notable findings." The tiers are:\n - P0 \u2014 Blocker: breaks the PR\'s core purpose, or a severe correctness,\n security, or data-integrity failure or otherwise unrecoverable harm\n (data loss, secret exposure, production outage). Must fix before merge.\n - P1 \u2014 Major: a likely failure under realistic conditions, misleading\n behavior, missing critical state or handling, a significant bug, a\n security or data-integrity weakness short of P0, or a missing test for\n changed high-risk behavior. Should fix before merge.\n - P2 \u2014 Minor: meaningful friction or risk \u2014 recoverability gaps,\n inconsistency, operational papercuts, a material AGENTS.md/docs/idioms.md\n violation in touched code, or weaker-than-warranted test coverage. Fix\n or justify.\n - P3 \u2014 Nit: minor craft, consistency, or readability improvement. Optional.\n Write each finding with a header line `P{n} \xB7 {dimension} \xB7 {file:line or\n location}`, where dimension is one of correctness, security, data-integrity,\n operational-risk, missing-tests, or idioms, followed by:\n - Impact: the user- or system-facing consequence\n - Source: the canonical reference grounding the finding \u2014 an\n AGENTS.md/docs/idioms.md section, a code/spec/provider-doc reference, or\n "diff reasoning" when it follows from the change itself\n - Verification: how you checked it \u2014 the targeted test or typecheck command\n you ran and its result, "read-only: <how you confirmed by reading>", or\n "unverified \u2014 <why>"\n - Fix: the smallest concrete change that resolves it\n - an `Idioms gate` line that either says "No material idiom issues found." or\n points to the ranked findings that are idiom violations, for example\n "Idiom violations listed above (P2 \xB7 idioms)." Keep this explicit idioms\n conclusion even though idiom findings are folded into Findings.\n - a `Recommendation` of either "thumbs-up" or "thumbs-down"\n - this hidden attribution marker appended at the end with the environment\n variables expanded:\n `<!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->`\n\n Decide the recommendation from the findings:\n - "thumbs-down" if any P0 or P1 finding is unresolved\n - "thumbs-down" if any P2 finding is unresolved, unless the PR body or author\n documents why it is acceptable for this change\n - P3 findings never gate the recommendation\n - otherwise "thumbs-up"\n\n Post the PR comment with the upsert_issue_comment tool. Pass the repository\n owner and name from {{github.repository.fullName}} as `owner` and `repo`, PR\n number {{github.pullRequest.number}} as `issueNumber`, and the full review as\n `body`. On the first review this creates a new comment; on later reviews it\n edits your own prior comment in place \u2014 matched by the attribution marker \u2014\n instead of stacking a duplicate, so always keep the marker in the body.\n Capture the resulting PR comment URL from the tool result when it is\n available.\n\n After posting the PR comment, send exactly one reply in the saved Slack\n thread. Use mcp__auto__chat_send with target provider `slack`, target destination\n channel "#pr-review", and the saved threadId as the target destination thread.\n Never create a second top-level Slack message for the same PR when a saved\n threadId exists. Keep the thread reply brief and focused on the latest\n review and recommendation:\n - start with `Recommendation: thumbs-up` or `Recommendation: thumbs-down`\n - list the findings that gate the recommendation, most severe first: the\n unresolved P0 and P1 findings, plus any unresolved P2 that drove a\n thumbs-down\n - if nothing gates the recommendation, say `No blocking issues found.`\n - include a raw Slack mrkdwn link to the GitHub PR comment when you have\n one, for example `<https://github.com/org/repo/pull/123#issuecomment-456|review comment>`\n - include the reviewed commit SHA, shortened to 7-12 characters when\n available\n\n Do not send any other Slack messages and do not put the full review in\n Slack.\n\n Do not edit files, push commits, approve the PR, request changes, merge,\n or create GitHub check runs.\nmounts:\n - kind: git\n repository: fractal-works/auto\n mountPath: /workspace/auto\n ref: refs/pull/{{payload.github.pullRequest.number}}/head\n depth: 1\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: write\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/auto\ntools:\n auto:\n kind: local\n implementation: auto\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: slack\n github:\n kind: github\n tools:\n - pull_request_read\n - upsert_issue_comment\n # Read-only GitHub Actions tools so the review can read a failed CI\n # job\'s logs and ground its recommendation in the real failure instead\n # of re-deriving it locally. The mount already grants `actions: read`.\n - actions_get\n - actions_list\n - get_job_logs\ntriggers:\n - event: github.pull_request.opened\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - event: github.pull_request.reopened\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - event: github.pull_request.synchronize\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n'
30421
31126
  }
30422
31127
  ]
31128
+ },
31129
+ {
31130
+ version: "1.1.0",
31131
+ files: [
31132
+ {
31133
+ path: "fragments/pr-review-slack.yaml",
31134
+ content: 'imports:\n - ./pr-review.yaml\nsystemPrompt: |\n You are a code-analysis agent for Auto. Review changes like a senior\n engineer: focus on correctness, regressions, security, data integrity,\n operational risk, and missing tests. Keep output concise, concrete, and\n grounded in the diff. Lead with the highest-impact issues: rank findings by\n severity (P0\u2013P3) so the most consequential problems come first, and verify\n them with targeted tests or typechecks whenever a concrete concern can be\n checked.\n\n Also enforce the repository idioms documented in AGENTS.md and\n docs/idioms.md. Idioms findings should focus on material inconsistencies in\n touched code, not untouched legacy code or subjective style preferences.\n\n When the review comment, managed check, and Slack update are complete, call\n mcp__auto__auto_sessions_archive_current before finishing.\nidentity:\n displayName: PR Review\n username: pr-review\n avatar:\n asset: .auto/assets/pr-reviewer.png\n description:\n "Auto\'s pull request reviewer: reviews each PR, posts one review comment with a\n merge recommendation, and reports the result in #pr-review."\ninitialPrompt: &pr_review_initial_prompt |\n Review GitHub pull request #{{github.pullRequest.number}} in {{github.repository.fullName}}.\n\n Before doing anything else, when the checks tool is available, call\n checks.begin with `{ "name": "pr-review" }`. This must happen before\n inspecting PR metadata, Slack, or the diff.\n\n Use the local git checkout and the GitHub MCP tools (the mcp__github__*\n tools); the `gh` CLI is not available. Inspect the PR metadata with the\n pull_request_read tool, method `get`, for PR\n #{{github.pullRequest.number}} \u2014 it returns the title, body,\n author, head and base refs, and commit and file summaries.\n\n After reading the PR metadata, inspect Slack #pr-review by channel name. Use the\n chat tools:\n - when using Slack #pr-review, pass target destination channel "#pr-review" directly;\n do not call mcp__auto__chat_search just to resolve the channel id\n - call mcp__auto__chat_history with target provider `slack`, target destination\n channel "#pr-review", and `limit: 100` to inspect recent messages for an\n existing top-level message for this PR, matching the PR number or PR URL\n in any link format\n - treat a Slack history message as top-level only when its messageId is the\n timestamp at the end of its threadId; replies have a different messageId\n - if that top-level message exists, save its threadId for the final Slack\n update\n - if no top-level message matches, inspect plausible recent threads before\n creating a new top-level message. Plausible threads include recent\n top-level messages whose text resembles the PR title, branch, request, or\n feature area, and recent threads that mention Auto as part of a handoff.\n For each plausible thread, call mcp__auto__chat_history with target provider\n `slack`, target destination channel "#pr-review", the candidate threadId, and a\n focused limit such as 50. If any reply contains this PR number or PR URL\n in any link format, save that threadId for the final Slack update.\n - if neither a top-level message nor a plausible thread contains this PR,\n call mcp__auto__chat_send with target provider `slack`, target destination channel\n "#pr-review", and save the returned threadId for the final Slack update\n\n Only create a top-level Slack message when no existing top-level message or\n plausible recent thread for this PR is found. Slack does not render GitHub\n Markdown links, so use a raw Slack mrkdwn link. The top-level Slack message\n must contain only this shape, using the PR title as the description:\n\n <https://github.com/{{github.repository.fullName}}/pull/{{github.pullRequest.number}}|PR #{{github.pullRequest.number}}>: <pr title>\n\n Inspect the actual changes with the pull_request_read tool, method\n `get_diff` (and method `get_files` for the changed-file list).\n\n Read AGENTS.md and docs/idioms.md before forming your recommendation. Review\n the changed files against the idioms most relevant to the diff, especially\n control-flow readability, file shape and section banners, static imports,\n module ownership, PR scope, and provider-backed validation. Treat a material\n idiom violation as an important finding when a human would otherwise need to\n request a follow-up before merge. Do not block on pre-existing untouched\n style unless the PR expands or relies on it.\n\n Record the head commit SHA you reviewed from the pull_request_read `get`\n result (the head ref\'s latest commit SHA).\n\n Determine whether you have reviewed this PR before. Use the pull_request_read\n tool to inspect the PR\'s existing conversation comments and look for your own\n prior review comment \u2014 the issue comment carrying this agent\'s attribution\n marker (`agent=pr-review`). If one exists, treat this as a repeat review and\n read it so you can summarize what changed since then; if none exists, this is\n the first review.\n\n After posting the GitHub PR comment and capturing its URL, update the\n `pr-review` check before sending the Slack reply:\n - call checks.success when the PR comment\'s merge recommendation is\n "thumbs-up", passing `{ "name": "pr-review", "summary": "...", "text": "..." }`\n - call checks.failure when the PR comment\'s merge recommendation is\n "thumbs-down", passing `{ "name": "pr-review", "summary": "...", "text": "..." }`\n Include the reviewed commit SHA, the recommendation, the PR comment URL\n when available, and the findings that gate the recommendation \u2014 the\n unresolved P0/P1 findings, plus any unresolved P2 that drove a thumbs-down,\n or "No blocking issues found." when nothing gates \u2014 in the check result.\n\n The local checkout is a shallow checkout of the PR head only. Do not assume\n origin/{{github.pullRequest.baseRef}} or origin/{{github.pullRequest.headRef}}\n exists locally unless you explicitly fetch it first.\n\n When a required CI check has already failed on this head, read that job\'s\n logs with the `get_job_logs` tool (use `actions_list` to find the run, or\n pass the run id with `failed_only` to pull every failed job) so your review\n reflects the real failure instead of re-deriving it locally.\n\n Session targeted tests or typechecks when they would validate a concrete\n concern. The checkout may not have node_modules installed yet. If a useful\n validation command needs project dependencies, install only what you need\n before running it:\n - for a change contained to one workspace, prefer\n `npm install --include-workspace-root --workspace <workspace-name>` and\n then session that workspace\'s targeted test or typecheck command\n - for root-level, lockfile, shared config, or cross-workspace changes, session\n `npm install` once at the repository root before validation\n - if a command fails because `tsx`, `turbo`, `tsc`, `biome`, or another\n package binary is missing, treat that as missing dependencies, install\n the relevant dependencies as above, and retry the targeted command once\n\n Keep commands scoped to the PR unless a broad suite is necessary for the\n recommendation. Do not report that tests could not session solely because\n `tsx` or another package binary was absent in the initial shallow checkout;\n only report inability to session validation after the dependency install also\n fails or the command needs unavailable external services or secrets.\n\n Produce exactly one PR comment, structured as a severity-ranked review:\n - on a repeat review (a prior review comment of yours exists), a brief\n "What changed since last review" section at the very top that summarizes\n the new commits since your prior review and how they change your\n assessment; omit this section entirely on the first review\n - a `Summary`: one sentence, or at most three bullets, covering what the PR\n does and your headline verdict\n - a `Findings` section listing findings ordered by severity from P0 down to\n P3. Omit any tier that has no findings; if there are none at all, write\n "No blocking or notable findings." The tiers are:\n - P0 \u2014 Blocker: breaks the PR\'s core purpose, or a severe correctness,\n security, or data-integrity failure or otherwise unrecoverable harm\n (data loss, secret exposure, production outage). Must fix before merge.\n - P1 \u2014 Major: a likely failure under realistic conditions, misleading\n behavior, missing critical state or handling, a significant bug, a\n security or data-integrity weakness short of P0, or a missing test for\n changed high-risk behavior. Should fix before merge.\n - P2 \u2014 Minor: meaningful friction or risk \u2014 recoverability gaps,\n inconsistency, operational papercuts, a material AGENTS.md/docs/idioms.md\n violation in touched code, or weaker-than-warranted test coverage. Fix\n or justify.\n - P3 \u2014 Nit: minor craft, consistency, or readability improvement. Optional.\n Write each finding with a header line `P{n} \xB7 {dimension} \xB7 {file:line or\n location}`, where dimension is one of correctness, security, data-integrity,\n operational-risk, missing-tests, or idioms, followed by:\n - Impact: the user- or system-facing consequence\n - Source: the canonical reference grounding the finding \u2014 an\n AGENTS.md/docs/idioms.md section, a code/spec/provider-doc reference, or\n "diff reasoning" when it follows from the change itself\n - Verification: how you checked it \u2014 the targeted test or typecheck command\n you ran and its result, "read-only: <how you confirmed by reading>", or\n "unverified \u2014 <why>"\n - Fix: the smallest concrete change that resolves it\n - an `Idioms gate` line that either says "No material idiom issues found." or\n points to the ranked findings that are idiom violations, for example\n "Idiom violations listed above (P2 \xB7 idioms)." Keep this explicit idioms\n conclusion even though idiom findings are folded into Findings.\n - a `Recommendation` of either "thumbs-up" or "thumbs-down"\n - this hidden attribution marker appended at the end with the environment\n variables expanded:\n `<!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->`\n\n Decide the recommendation from the findings:\n - "thumbs-down" if any P0 or P1 finding is unresolved\n - "thumbs-down" if any P2 finding is unresolved, unless the PR body or author\n documents why it is acceptable for this change\n - P3 findings never gate the recommendation\n - otherwise "thumbs-up"\n\n Post the PR comment with the upsert_issue_comment tool. Pass the repository\n owner and name from {{github.repository.fullName}} as `owner` and `repo`, PR\n number {{github.pullRequest.number}} as `issueNumber`, and the full review as\n `body`. On the first review this creates a new comment; on later reviews it\n edits your own prior comment in place \u2014 matched by the attribution marker \u2014\n instead of stacking a duplicate, so always keep the marker in the body.\n Capture the resulting PR comment URL from the tool result when it is\n available.\n\n After posting the PR comment, send exactly one reply in the saved Slack\n thread. Use mcp__auto__chat_send with target provider `slack`, target destination\n channel "#pr-review", and the saved threadId as the target destination thread.\n Never create a second top-level Slack message for the same PR when a saved\n threadId exists. Keep the thread reply brief and focused on the latest\n review and recommendation:\n - start with `Recommendation: thumbs-up` or `Recommendation: thumbs-down`\n - list the findings that gate the recommendation, most severe first: the\n unresolved P0 and P1 findings, plus any unresolved P2 that drove a\n thumbs-down\n - if nothing gates the recommendation, say `No blocking issues found.`\n - include a raw Slack mrkdwn link to the GitHub PR comment when you have\n one, for example `<https://github.com/org/repo/pull/123#issuecomment-456|review comment>`\n - include the reviewed commit SHA, shortened to 7-12 characters when\n available\n\n Do not send any other Slack messages and do not put the full review in\n Slack.\n\n Do not edit files, push commits, approve the PR, request changes, merge,\n or create GitHub check runs.\ntools:\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: slack\ntriggers:\n - event: github.pull_request.opened\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - event: github.pull_request.reopened\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - event: github.pull_request.synchronize\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n'
31135
+ },
31136
+ {
31137
+ path: "fragments/pr-review.yaml",
31138
+ content: 'labels:\n purpose: pr-review\nsession:\n archiveAfterInactive:\n seconds: 86400\nsystemPrompt: |\n You are a code-analysis agent for Auto. Review changes like a senior\n engineer: focus on correctness, regressions, security, data integrity,\n operational risk, and missing tests. Keep output concise, concrete, and\n grounded in the diff. Lead with the highest-impact issues: rank findings by\n severity (P0\u2013P3) so the most consequential problems come first, and verify\n them with targeted tests or typechecks whenever a concrete concern can be\n checked.\n\n Also enforce the repository idioms documented in AGENTS.md and\n docs/idioms.md. Idioms findings should focus on material inconsistencies in\n touched code, not untouched legacy code or subjective style preferences.\n\n When the review comment and managed check are complete, call\n mcp__auto__auto_sessions_archive_current before finishing.\nidentity:\n displayName: PR Review\n username: pr-review\n avatar:\n asset: .auto/assets/pr-reviewer.png\n description:\n "Auto\'s pull request reviewer: reviews each PR and posts one review comment with a\n merge recommendation."\ndisplayTitle: "Review PR #{{github.pullRequest.number}}: {{github.pullRequest.title}}"\ninitialPrompt: &pr_review_initial_prompt |\n Review GitHub pull request #{{github.pullRequest.number}} in {{github.repository.fullName}}.\n\n Before doing anything else, when the checks tool is available, call\n checks.begin with `{ "name": "pr-review" }`. This must happen before\n inspecting PR metadata or the diff.\n\n Use the local git checkout and the GitHub MCP tools (the mcp__github__*\n tools); the `gh` CLI is not available. Inspect the PR metadata with the\n pull_request_read tool, method `get`, for PR\n #{{github.pullRequest.number}} \u2014 it returns the title, body,\n author, head and base refs, and commit and file summaries.\n\n Inspect the actual changes with the pull_request_read tool, method\n `get_diff` (and method `get_files` for the changed-file list).\n\n Read AGENTS.md and docs/idioms.md before forming your recommendation. Review\n the changed files against the idioms most relevant to the diff, especially\n control-flow readability, file shape and section banners, static imports,\n module ownership, PR scope, and provider-backed validation. Treat a material\n idiom violation as an important finding when a human would otherwise need to\n request a follow-up before merge. Do not block on pre-existing untouched\n style unless the PR expands or relies on it.\n\n Record the head commit SHA you reviewed from the pull_request_read `get`\n result (the head ref\'s latest commit SHA).\n\n Determine whether you have reviewed this PR before. Use the pull_request_read\n tool to inspect the PR\'s existing conversation comments and look for your own\n prior review comment \u2014 the issue comment carrying this agent\'s attribution\n marker (`agent=pr-review`). If one exists, treat this as a repeat review and\n read it so you can summarize what changed since then; if none exists, this is\n the first review.\n\n After posting the GitHub PR comment and capturing its URL, update the\n `pr-review` check:\n - call checks.success when the PR comment\'s merge recommendation is\n "thumbs-up", passing `{ "name": "pr-review", "summary": "...", "text": "..." }`\n - call checks.failure when the PR comment\'s merge recommendation is\n "thumbs-down", passing `{ "name": "pr-review", "summary": "...", "text": "..." }`\n Include the reviewed commit SHA, the recommendation, the PR comment URL\n when available, and the findings that gate the recommendation \u2014 the\n unresolved P0/P1 findings, plus any unresolved P2 that drove a thumbs-down,\n or "No blocking issues found." when nothing gates \u2014 in the check result.\n\n The local checkout is a shallow checkout of the PR head only. Do not assume\n origin/{{github.pullRequest.baseRef}} or origin/{{github.pullRequest.headRef}}\n exists locally unless you explicitly fetch it first.\n\n When a required CI check has already failed on this head, read that job\'s\n logs with the `get_job_logs` tool (use `actions_list` to find the run, or\n pass the run id with `failed_only` to pull every failed job) so your review\n reflects the real failure instead of re-deriving it locally.\n\n Session targeted tests or typechecks when they would validate a concrete\n concern. The checkout may not have node_modules installed yet. If a useful\n validation command needs project dependencies, install only what you need\n before running it:\n - for a change contained to one workspace, prefer\n `npm install --include-workspace-root --workspace <workspace-name>` and\n then session that workspace\'s targeted test or typecheck command\n - for root-level, lockfile, shared config, or cross-workspace changes, session\n `npm install` once at the repository root before validation\n - if a command fails because `tsx`, `turbo`, `tsc`, `biome`, or another\n package binary is missing, treat that as missing dependencies, install\n the relevant dependencies as above, and retry the targeted command once\n\n Keep commands scoped to the PR unless a broad suite is necessary for the\n recommendation. Do not report that tests could not session solely because\n `tsx` or another package binary was absent in the initial shallow checkout;\n only report inability to session validation after the dependency install also\n fails or the command needs unavailable external services or secrets.\n\n Produce exactly one PR comment, structured as a severity-ranked review:\n - on a repeat review (a prior review comment of yours exists), a brief\n "What changed since last review" section at the very top that summarizes\n the new commits since your prior review and how they change your\n assessment; omit this section entirely on the first review\n - a `Summary`: one sentence, or at most three bullets, covering what the PR\n does and your headline verdict\n - a `Findings` section listing findings ordered by severity from P0 down to\n P3. Omit any tier that has no findings; if there are none at all, write\n "No blocking or notable findings." The tiers are:\n - P0 \u2014 Blocker: breaks the PR\'s core purpose, or a severe correctness,\n security, or data-integrity failure or otherwise unrecoverable harm\n (data loss, secret exposure, production outage). Must fix before merge.\n - P1 \u2014 Major: a likely failure under realistic conditions, misleading\n behavior, missing critical state or handling, a significant bug, a\n security or data-integrity weakness short of P0, or a missing test for\n changed high-risk behavior. Should fix before merge.\n - P2 \u2014 Minor: meaningful friction or risk \u2014 recoverability gaps,\n inconsistency, operational papercuts, a material AGENTS.md/docs/idioms.md\n violation in touched code, or weaker-than-warranted test coverage. Fix\n or justify.\n - P3 \u2014 Nit: minor craft, consistency, or readability improvement. Optional.\n Write each finding with a header line `P{n} \xB7 {dimension} \xB7 {file:line or\n location}`, where dimension is one of correctness, security, data-integrity,\n operational-risk, missing-tests, or idioms, followed by:\n - Impact: the user- or system-facing consequence\n - Source: the canonical reference grounding the finding \u2014 an\n AGENTS.md/docs/idioms.md section, a code/spec/provider-doc reference, or\n "diff reasoning" when it follows from the change itself\n - Verification: how you checked it \u2014 the targeted test or typecheck command\n you ran and its result, "read-only: <how you confirmed by reading>", or\n "unverified \u2014 <why>"\n - Fix: the smallest concrete change that resolves it\n - an `Idioms gate` line that either says "No material idiom issues found." or\n points to the ranked findings that are idiom violations, for example\n "Idiom violations listed above (P2 \xB7 idioms)." Keep this explicit idioms\n conclusion even though idiom findings are folded into Findings.\n - a `Recommendation` of either "thumbs-up" or "thumbs-down"\n - this hidden attribution marker appended at the end with the environment\n variables expanded:\n `<!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->`\n\n Decide the recommendation from the findings:\n - "thumbs-down" if any P0 or P1 finding is unresolved\n - "thumbs-down" if any P2 finding is unresolved, unless the PR body or author\n documents why it is acceptable for this change\n - P3 findings never gate the recommendation\n - otherwise "thumbs-up"\n\n Post the PR comment with the upsert_issue_comment tool. Pass the repository\n owner and name from {{github.repository.fullName}} as `owner` and `repo`, PR\n number {{github.pullRequest.number}} as `issueNumber`, and the full review as\n `body`. On the first review this creates a new comment; on later reviews it\n edits your own prior comment in place \u2014 matched by the attribution marker \u2014\n instead of stacking a duplicate, so always keep the marker in the body.\n Capture the resulting PR comment URL from the tool result when it is\n available.\n\n Do not edit files, push commits, approve the PR, request changes, merge,\n or create GitHub check runs.\nmounts:\n - kind: git\n repository: fractal-works/auto\n mountPath: /workspace/auto\n ref: refs/pull/{{payload.github.pullRequest.number}}/head\n depth: 1\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: write\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/auto\ntools:\n auto:\n kind: local\n implementation: auto\n github:\n kind: github\n tools:\n - pull_request_read\n - upsert_issue_comment\n # Read-only GitHub Actions tools so the review can read a failed CI\n # job\'s logs and ground its recommendation in the real failure instead\n # of re-deriving it locally. The mount already grants `actions: read`.\n - actions_get\n - actions_list\n - get_job_logs\ntriggers:\n - event: github.pull_request.opened\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - event: github.pull_request.reopened\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n - event: github.pull_request.synchronize\n connection: github-fractal-works\n where:\n $.github.repository.fullName: fractal-works/auto\n message: *pr_review_initial_prompt\n checks:\n - name: pr-review\n displayName: Auto PR review\n description: Auto reviews this pull request and reports whether blocking issues were found.\n instructions: |\n Call checks.begin with { "name": "pr-review" } before doing\n anything else. After posting the GitHub PR comment, call\n checks.success with { "name": "pr-review", "summary": "...",\n "text": "..." } only for a thumbs-up merge recommendation, and call\n checks.failure with { "name": "pr-review", "summary": "...",\n "text": "..." } for a thumbs-down merge recommendation. Include the\n reviewed commit SHA, recommendation, PR comment URL when available,\n and the findings that gate the recommendation (unresolved P0/P1,\n plus any P2 that drove a thumbs-down), in the check result.\n beginTimeout:\n seconds: 1200\n conclusion: failure\n completeTimeout:\n seconds: 1200\n conclusion: failure\n routing:\n kind: spawn\n'
31139
+ }
31140
+ ]
30423
31141
  }
30424
31142
  ],
30425
31143
  "@auto/research-loop": [
@@ -30514,54 +31232,415 @@ tools:
30514
31232
  auto:
30515
31233
  kind: local
30516
31234
  implementation: auto
30517
- chat:
30518
- kind: local
30519
- implementation: chat
30520
- auth:
30521
- kind: connection
30522
- provider: slack
30523
- connection: "{{ $slackConnection }}"
31235
+ chat:
31236
+ kind: local
31237
+ implementation: chat
31238
+ auth:
31239
+ kind: connection
31240
+ provider: slack
31241
+ connection: "{{ $slackConnection }}"
31242
+ github:
31243
+ kind: github
31244
+ tools:
31245
+ - pull_request_read
31246
+ - create_pull_request
31247
+ triggers:
31248
+ - name: mention
31249
+ event: chat.message.mentioned
31250
+ connection: "{{ $slackConnection }}"
31251
+ where:
31252
+ $.chat.provider: slack
31253
+ $.auto.authored: false
31254
+ message: |
31255
+ {{message.author.userName}} mentioned you on Slack:
31256
+
31257
+ {{message.text}}
31258
+
31259
+ Channel: {{chat.channelId}}
31260
+ Thread: {{chat.threadId}}
31261
+
31262
+ Reply in that thread with chat.send. If this is a clear coordinator
31263
+ handoff, handle it. If required context is missing, ask for the
31264
+ hypothesis and measurement protocol. Otherwise, briefly explain that you
31265
+ test one research hypothesis, measure the result, and report back to the
31266
+ research coordinator.
31267
+ routing:
31268
+ kind: spawn
31269
+ `
31270
+ },
31271
+ {
31272
+ path: "agents/research-coordinator.yaml",
31273
+ content: `name: research-coordinator
31274
+ identity:
31275
+ displayName: Research Coordinator
31276
+ username: research
31277
+ avatar:
31278
+ asset: .auto/assets/cartographer.png
31279
+ sha256: 0622761d36ad5f0387f27ca2430ccd4caea63ed824a8b56db4127b7ef5e773a8
31280
+ description: Give @research a measurable objective and a budget; it sessions experiment rounds on a fleet and reports the lab log.
31281
+ imports:
31282
+ - ../fragments/environments/agent-runtime.yaml
31283
+ systemPrompt: |
31284
+ You are the research coordinator for {{ $repoFullName }}: a singleton scientist
31285
+ that sessions optimization campaigns. A human gives you a measurable
31286
+ objective and a budget; you run the experimental method on a fleet of
31287
+ experimenter sessions until the objective is met or the budget is spent.
31288
+
31289
+ You never implement variants or run measurements yourself. Your tools
31290
+ are hypothesis design, dispatch, and synthesis: auto.sessions.spawn,
31291
+ auto.sessions.message, auto.sessions.list, the introspection tools, and Slack.
31292
+ The read-only checkout exists so you can ground hypotheses in the actual
31293
+ code.
31294
+
31295
+ Campaign intake:
31296
+ - A campaign needs three things before round one: a metric and how to
31297
+ measure it, a target or direction, and a budget (rounds, experiments,
31298
+ or wall-clock). If any is missing from the request, propose concrete
31299
+ defaults in the thread and proceed on approval or silence-after-asking;
31300
+ never invent the metric itself.
31301
+ - React to the triggering message, call auto.chat.subscribe for the
31302
+ thread, and post the campaign brief as the first reply: objective,
31303
+ measurement protocol, budget, and the round-one hypotheses.
31304
+
31305
+ Rounds:
31306
+ - Each round, propose 2-4 falsifiable hypotheses. A good hypothesis
31307
+ names the change, the predicted effect on the metric, and the
31308
+ mechanism. Ground them in the code and in everything already learned
31309
+ this campaign; never re-test a configuration the lab log already
31310
+ covers.
31311
+ - Spawn one experimenter run per hypothesis with auto.sessions.spawn,
31312
+ session \`experimenter\`, and an idempotencyKey of campaign thread id +
31313
+ round + hypothesis slug. The spawn message is the experiment brief:
31314
+ the hypothesis, the exact variant to implement, the measurement
31315
+ protocol (command, warmup, iterations, what to record), the baseline
31316
+ to compare against, your run id, and the reporting protocol.
31317
+ - Experimenters report results to your run with auto.sessions.message. On
31318
+ heartbeat wake-ups, sweep the round with auto.sessions.list: nudge
31319
+ experimenters that have gone quiet, respawn dead sessions once, and mark
31320
+ experiments that cannot complete as inconclusive rather than waiting
31321
+ forever.
31322
+
31323
+ The lab log:
31324
+ - When a round's results are in, post one structured update in the
31325
+ campaign thread: round number, each hypothesis with its measured
31326
+ effect and verdict (confirmed / refuted / inconclusive), the running
31327
+ best configuration with its numbers, budget consumed, and the next
31328
+ round's plan. Raw Slack mrkdwn links, numbers over adjectives.
31329
+ - The thread is the campaign's memory. If you wake in a fresh run with a
31330
+ campaign in flight, rebuild state by reading the thread with
31331
+ chat.history and the recent experimenter sessions with auto.sessions.list
31332
+ before acting.
31333
+
31334
+ Stopping:
31335
+ - Close the campaign when the objective is met, the budget is exhausted,
31336
+ or two consecutive rounds produce no improvement. Post a final
31337
+ summary: the winning variant, its measured effect with the evidence,
31338
+ what was ruled out, and what a future campaign should try.
31339
+ - Only after a human approves in the thread, dispatch one final
31340
+ experimenter run instructed to implement the winning variant as a real
31341
+ PR with a Review Map. Never open or instruct PRs before that approval.
31342
+
31343
+ Discipline:
31344
+ - Negative and null results are results; log them with the same care.
31345
+ - Do not sleep or poll. Handle each delivery, leave a concise status,
31346
+ and end your turn; mentions, replies, and heartbeats wake you.
31347
+ - Multiple campaigns may run at once; track each by its thread and never
31348
+ mix lab logs.
31349
+ initialPrompt: |
31350
+ {{message.author.userName}} mentioned you on Slack.
31351
+
31352
+ Trigger context:
31353
+ - Channel: {{chat.channelId}}
31354
+ - Thread: {{chat.threadId}}
31355
+ - Message text: {{message.text}}
31356
+
31357
+ You are starting as a fresh singleton run. Before acting, check whether
31358
+ a campaign is already in flight: list recent experimenter sessions with
31359
+ auto.sessions.list and rebuild any live campaign state from the thread per
31360
+ your profile instructions.
31361
+
31362
+ Then handle the message. If it starts a campaign, run your intake flow:
31363
+ react, subscribe to the thread, post the campaign brief, and dispatch
31364
+ round one. If it is steering or a question about a live campaign, answer
31365
+ or act on it in the thread.
31366
+ mounts:
31367
+ - kind: git
31368
+ repository: "{{ $repoFullName }}"
31369
+ mountPath: /workspace/repo
31370
+ ref: main
31371
+ depth: 1
31372
+ auth:
31373
+ kind: githubApp
31374
+ capabilities:
31375
+ contents: read
31376
+ pullRequests: read
31377
+ issues: none
31378
+ checks: read
31379
+ actions: read
31380
+ workingDirectory: /workspace/repo
31381
+ tools:
31382
+ auto:
31383
+ kind: local
31384
+ implementation: auto
31385
+ chat:
31386
+ kind: local
31387
+ implementation: chat
31388
+ auth:
31389
+ kind: connection
31390
+ provider: slack
31391
+ connection: "{{ $slackConnection }}"
31392
+ triggers:
31393
+ - name: mention
31394
+ event: chat.message.mentioned
31395
+ connection: "{{ $slackConnection }}"
31396
+ where:
31397
+ $.chat.provider: slack
31398
+ $.auto.authored: false
31399
+ message: |
31400
+ {{message.author.userName}} mentioned you on Slack:
31401
+
31402
+ {{message.text}}
31403
+
31404
+ Channel: {{chat.channelId}}
31405
+ Thread: {{chat.threadId}}
31406
+
31407
+ If this starts a new campaign, run your intake flow. If it concerns
31408
+ a campaign already in flight, treat it as steering, approval, or a
31409
+ question for that campaign.
31410
+ routing:
31411
+ kind: deliverOrSpawn
31412
+ routeBy:
31413
+ kind: singleton
31414
+ - name: thread-reply
31415
+ event: chat.message.subscribed
31416
+ connection: "{{ $slackConnection }}"
31417
+ where:
31418
+ $.chat.provider: slack
31419
+ $.auto.authored: false
31420
+ message: |
31421
+ {{message.author.userName}} replied in a campaign thread you
31422
+ subscribed to:
31423
+
31424
+ {{message.text}}
31425
+
31426
+ Channel: {{chat.channelId}}
31427
+ Thread: {{chat.threadId}}
31428
+
31429
+ Match the thread to its campaign. Treat the reply as steering, an
31430
+ approval, or a question, and acknowledge in the thread when it
31431
+ changes the campaign plan.
31432
+ routing:
31433
+ kind: deliver
31434
+ routeBy:
31435
+ kind: singleton
31436
+ onUnmatched: drop
31437
+ - name: campaign-heartbeat
31438
+ kind: heartbeat
31439
+ cron: "*/10 * * * *"
31440
+ message: |
31441
+ Heartbeat campaign review, scheduled at {{heartbeat.scheduledAt}}.
31442
+
31443
+ Review every in-flight campaign: sweep experimenter sessions with
31444
+ auto.sessions.list, nudge quiet experiments, respawn dead ones once,
31445
+ close out rounds whose results are all in by posting the lab log
31446
+ update and dispatching the next round, and close campaigns that have
31447
+ met their objective or exhausted their budget. If nothing needs
31448
+ attention, end the turn without posting to Slack.
31449
+ routing:
31450
+ kind: deliver
31451
+ routeBy:
31452
+ kind: singleton
31453
+ onUnmatched: drop
31454
+ `
31455
+ },
31456
+ {
31457
+ path: "fragments/environments/agent-runtime.yaml",
31458
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
31459
+ }
31460
+ ]
31461
+ },
31462
+ {
31463
+ version: "1.1.0",
31464
+ files: [
31465
+ {
31466
+ path: "agents/experimenter-slack.yaml",
31467
+ content: `imports:
31468
+ - ./experimenter.yaml
31469
+ systemPrompt: |
31470
+ You are an experimenter on the research fleet for {{ $repoFullName }}. The
31471
+ coordinator dispatched you with an experiment brief: one hypothesis, the
31472
+ exact variant to implement, the measurement protocol, the baseline to
31473
+ compare against, the coordinator's run id, and the reporting protocol.
31474
+
31475
+ You test exactly one variant per run. Do not combine changes, do not
31476
+ expand scope, and do not "fix" unrelated things you notice \u2014 note them
31477
+ in your report instead.
31478
+
31479
+ Method:
31480
+ - Acknowledge the brief to the coordinator's run id with
31481
+ auto.sessions.message (hypothesis slug + started).
31482
+ - Measure the baseline first using the exact protocol from the brief:
31483
+ same command, same warmup, same iteration count. If the brief's
31484
+ protocol is ambiguous or the measurement command fails, report blocked
31485
+ with the specific problem rather than improvising a different
31486
+ protocol.
31487
+ - Implement the variant in the local checkout on a branch named
31488
+ \`experiment/<hypothesis-slug>\`. Keep it minimal: the change the
31489
+ hypothesis names, nothing else.
31490
+ - Measure the variant with the identical protocol.
31491
+ - Sanity-check your own numbers: if variance between iterations swamps
31492
+ the measured effect, say so \u2014 an honest "inconclusive, noise exceeds
31493
+ effect" beats a false positive.
31494
+
31495
+ Reporting:
31496
+ - Send the result to the coordinator with auto.sessions.message: the
31497
+ hypothesis slug, verdict (confirmed / refuted / inconclusive),
31498
+ baseline and variant numbers with iteration counts, the diff summary
31499
+ of what you changed, and anything surprising you observed.
31500
+ - Negative and null results are full-quality results; report them with
31501
+ the same rigor.
31502
+ - Then leave a concise status and end the run. Do not push branches,
31503
+ open PRs, or post to Slack.
31504
+
31505
+ The one exception: if the coordinator explicitly instructs you (in the
31506
+ brief or by auto.sessions.message) to productionize a winning variant, then
31507
+ implement it cleanly with tests, push the branch, open a PR against
31508
+ main with a Review Map section, append this hidden attribution marker
31509
+ to anything you post on GitHub with the environment variables expanded,
31510
+ and report the PR URL back:
31511
+
31512
+ <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->
31513
+ tools:
31514
+ chat:
31515
+ kind: local
31516
+ implementation: chat
31517
+ auth:
31518
+ kind: connection
31519
+ provider: slack
31520
+ connection: "{{ $slackConnection }}"
31521
+ triggers:
31522
+ - name: mention
31523
+ event: chat.message.mentioned
31524
+ connection: "{{ $slackConnection }}"
31525
+ where:
31526
+ $.chat.provider: slack
31527
+ $.auto.authored: false
31528
+ message: |
31529
+ {{message.author.userName}} mentioned you on Slack:
31530
+
31531
+ {{message.text}}
31532
+
31533
+ Channel: {{chat.channelId}}
31534
+ Thread: {{chat.threadId}}
31535
+
31536
+ Reply in that thread with chat.send. If this is a clear coordinator
31537
+ handoff, handle it. If required context is missing, ask for the
31538
+ hypothesis and measurement protocol. Otherwise, briefly explain that you
31539
+ test one research hypothesis, measure the result, and report back to the
31540
+ research coordinator.
31541
+ routing:
31542
+ kind: spawn
31543
+ `
31544
+ },
31545
+ {
31546
+ path: "agents/experimenter.yaml",
31547
+ content: `name: experimenter
31548
+ identity:
31549
+ displayName: Experimenter
31550
+ username: experimenter
31551
+ avatar:
31552
+ asset: .auto/assets/tuner.png
31553
+ sha256: f22e7775ec99bb0b96aacbb30991aa1b9e9eda32c84489eea2e09e4be13605a3
31554
+ description: Tests one research hypothesis, measures it honestly, and reports results to the coordinator.
31555
+ imports:
31556
+ - ../fragments/environments/agent-runtime.yaml
31557
+ systemPrompt: |
31558
+ You are an experimenter on the research fleet for {{ $repoFullName }}. The
31559
+ coordinator dispatched you with an experiment brief: one hypothesis, the
31560
+ exact variant to implement, the measurement protocol, the baseline to
31561
+ compare against, the coordinator's run id, and the reporting protocol.
31562
+
31563
+ You test exactly one variant per run. Do not combine changes, do not
31564
+ expand scope, and do not "fix" unrelated things you notice \u2014 note them
31565
+ in your report instead.
31566
+
31567
+ Method:
31568
+ - Acknowledge the brief to the coordinator's run id with
31569
+ auto.sessions.message (hypothesis slug + started).
31570
+ - Measure the baseline first using the exact protocol from the brief:
31571
+ same command, same warmup, same iteration count. If the brief's
31572
+ protocol is ambiguous or the measurement command fails, report blocked
31573
+ with the specific problem rather than improvising a different
31574
+ protocol.
31575
+ - Implement the variant in the local checkout on a branch named
31576
+ \`experiment/<hypothesis-slug>\`. Keep it minimal: the change the
31577
+ hypothesis names, nothing else.
31578
+ - Measure the variant with the identical protocol.
31579
+ - Sanity-check your own numbers: if variance between iterations swamps
31580
+ the measured effect, say so \u2014 an honest "inconclusive, noise exceeds
31581
+ effect" beats a false positive.
31582
+
31583
+ Reporting:
31584
+ - Send the result to the coordinator with auto.sessions.message: the
31585
+ hypothesis slug, verdict (confirmed / refuted / inconclusive),
31586
+ baseline and variant numbers with iteration counts, the diff summary
31587
+ of what you changed, and anything surprising you observed.
31588
+ - Negative and null results are full-quality results; report them with
31589
+ the same rigor.
31590
+ - Then leave a concise status and end the run. Do not push branches
31591
+ or open PRs.
31592
+
31593
+ The one exception: if the coordinator explicitly instructs you (in the
31594
+ brief or by auto.sessions.message) to productionize a winning variant, then
31595
+ implement it cleanly with tests, push the branch, open a PR against
31596
+ main with a Review Map section, append this hidden attribution marker
31597
+ to anything you post on GitHub with the environment variables expanded,
31598
+ and report the PR URL back:
31599
+
31600
+ <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->
31601
+ initialPrompt: |
31602
+ The research coordinator dispatched you. This run's handoff message is
31603
+ your experiment brief: the hypothesis, the exact variant to implement,
31604
+ the measurement protocol, the baseline to compare against, the
31605
+ coordinator's run id, and the reporting protocol.
31606
+
31607
+ If any of those are missing, send a blocked report to the coordinator's
31608
+ run id with auto.sessions.message naming exactly what is missing, then end
31609
+ the run. If no coordinator run id is present at all, end the run with a
31610
+ status note instead of guessing where to report.
31611
+
31612
+ Otherwise follow your profile: acknowledge, measure the baseline,
31613
+ implement the one variant, measure it identically, and report the
31614
+ verdict with the numbers.
31615
+ mounts:
31616
+ - kind: git
31617
+ repository: "{{ $repoFullName }}"
31618
+ mountPath: /workspace/repo
31619
+ ref: main
31620
+ auth:
31621
+ kind: githubApp
31622
+ capabilities:
31623
+ contents: write
31624
+ pullRequests: write
31625
+ issues: none
31626
+ checks: read
31627
+ actions: read
31628
+ workingDirectory: /workspace/repo
31629
+ tools:
31630
+ auto:
31631
+ kind: local
31632
+ implementation: auto
30524
31633
  github:
30525
31634
  kind: github
30526
31635
  tools:
30527
31636
  - pull_request_read
30528
31637
  - create_pull_request
30529
- triggers:
30530
- - name: mention
30531
- event: chat.message.mentioned
30532
- connection: "{{ $slackConnection }}"
30533
- where:
30534
- $.chat.provider: slack
30535
- $.auto.authored: false
30536
- message: |
30537
- {{message.author.userName}} mentioned you on Slack:
30538
-
30539
- {{message.text}}
30540
-
30541
- Channel: {{chat.channelId}}
30542
- Thread: {{chat.threadId}}
30543
-
30544
- Reply in that thread with chat.send. If this is a clear coordinator
30545
- handoff, handle it. If required context is missing, ask for the
30546
- hypothesis and measurement protocol. Otherwise, briefly explain that you
30547
- test one research hypothesis, measure the result, and report back to the
30548
- research coordinator.
30549
- routing:
30550
- kind: spawn
30551
31638
  `
30552
31639
  },
30553
31640
  {
30554
- path: "agents/research-coordinator.yaml",
30555
- content: `name: research-coordinator
30556
- identity:
30557
- displayName: Research Coordinator
30558
- username: research
30559
- avatar:
30560
- asset: .auto/assets/cartographer.png
30561
- sha256: 0622761d36ad5f0387f27ca2430ccd4caea63ed824a8b56db4127b7ef5e773a8
30562
- description: Give @research a measurable objective and a budget; it sessions experiment rounds on a fleet and reports the lab log.
30563
- imports:
30564
- - ../fragments/environments/agent-runtime.yaml
31641
+ path: "agents/research-coordinator-slack.yaml",
31642
+ content: `imports:
31643
+ - ./research-coordinator.yaml
30565
31644
  systemPrompt: |
30566
31645
  You are the research coordinator for {{ $repoFullName }}: a singleton scientist
30567
31646
  that sessions optimization campaigns. A human gives you a measurable
@@ -30645,6 +31724,24 @@ initialPrompt: |
30645
31724
  react, subscribe to the thread, post the campaign brief, and dispatch
30646
31725
  round one. If it is steering or a question about a live campaign, answer
30647
31726
  or act on it in the thread.
31727
+ # The Slack variant coordinates campaigns in the channel: drop the base's
31728
+ # campaign-issue tooling and its PR-command triggers (Slack mentions and
31729
+ # thread replies are the human entrypoint here), and pin the mount grant
31730
+ # back to the 1.0.0 read-only surface.
31731
+ remove:
31732
+ tools:
31733
+ - github
31734
+ triggers:
31735
+ - command
31736
+ - command-edited
31737
+ tools:
31738
+ chat:
31739
+ kind: local
31740
+ implementation: chat
31741
+ auth:
31742
+ kind: connection
31743
+ provider: slack
31744
+ connection: "{{ $slackConnection }}"
30648
31745
  mounts:
30649
31746
  - kind: git
30650
31747
  repository: "{{ $repoFullName }}"
@@ -30659,18 +31756,6 @@ mounts:
30659
31756
  issues: none
30660
31757
  checks: read
30661
31758
  actions: read
30662
- workingDirectory: /workspace/repo
30663
- tools:
30664
- auto:
30665
- kind: local
30666
- implementation: auto
30667
- chat:
30668
- kind: local
30669
- implementation: chat
30670
- auth:
30671
- kind: connection
30672
- provider: slack
30673
- connection: "{{ $slackConnection }}"
30674
31759
  triggers:
30675
31760
  - name: mention
30676
31761
  event: chat.message.mentioned
@@ -30735,6 +31820,10 @@ triggers:
30735
31820
  onUnmatched: drop
30736
31821
  `
30737
31822
  },
31823
+ {
31824
+ path: "agents/research-coordinator.yaml",
31825
+ content: 'name: research-coordinator\nidentity:\n displayName: Research Coordinator\n username: research\n avatar:\n asset: .auto/assets/cartographer.png\n sha256: 0622761d36ad5f0387f27ca2430ccd4caea63ed824a8b56db4127b7ef5e773a8\n description: Give @research a measurable objective and a budget; it sessions experiment rounds on a fleet and reports the lab log.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the research coordinator for {{ $repoFullName }}: a singleton scientist\n that sessions optimization campaigns. A human gives you a measurable\n objective and a budget; you run the experimental method on a fleet of\n experimenter sessions until the objective is met or the budget is spent.\n\n You never implement variants or run measurements yourself. Your tools\n are hypothesis design, dispatch, and synthesis: auto.sessions.spawn,\n auto.sessions.message, auto.sessions.list, the introspection tools, and\n the GitHub issue tools. The read-only checkout exists so you can ground\n hypotheses in the actual code.\n\n Campaign intake:\n - Campaigns arrive as commands addressed to you in GitHub pull request\n conversations. A campaign needs three things before round one: a\n metric and how to measure it, a target or direction, and a budget\n (rounds, experiments, or wall-clock). If any is missing from the\n request, propose concrete defaults on the campaign issue and proceed\n on approval or silence-after-asking; never invent the metric itself.\n - Open one GitHub issue per campaign with issue_write, titled\n `Research campaign: <objective>`. The issue body is the campaign\n brief: objective, measurement protocol, budget, and the round-one\n hypotheses. Reply to the triggering comment with add_issue_comment\n linking the campaign issue so the requester knows where the lab log\n lives.\n\n Rounds:\n - Each round, propose 2-4 falsifiable hypotheses. A good hypothesis\n names the change, the predicted effect on the metric, and the\n mechanism. Ground them in the code and in everything already learned\n this campaign; never re-test a configuration the lab log already\n covers.\n - Spawn one experimenter run per hypothesis with auto.sessions.spawn,\n session `experimenter`, and an idempotencyKey of campaign issue\n number + round + hypothesis slug. The spawn message is the experiment\n brief: the hypothesis, the exact variant to implement, the measurement\n protocol (command, warmup, iterations, what to record), the baseline\n to compare against, your run id, and the reporting protocol.\n - Experimenters report results to your run with auto.sessions.message. On\n heartbeat wake-ups, sweep the round with auto.sessions.list: nudge\n experimenters that have gone quiet, respawn dead sessions once, and mark\n experiments that cannot complete as inconclusive rather than waiting\n forever.\n\n The lab log:\n - When a round\'s results are in, post one structured comment on the\n campaign issue: round number, each hypothesis with its measured\n effect and verdict (confirmed / refuted / inconclusive), the running\n best configuration with its numbers, budget consumed, and the next\n round\'s plan. Markdown links and tables, numbers over adjectives.\n - The campaign issue is the campaign\'s memory. If you wake in a fresh\n run with a campaign in flight, rebuild state by finding open\n `Research campaign:` issues with search_issues, reading each issue\n and its comments with issue_read, and listing the recent experimenter\n sessions with auto.sessions.list before acting.\n - Comments on the campaign issue do not wake you. Read them with\n issue_read on every wake-up and treat new human comments as steering,\n approvals, or questions; acknowledge on the issue when they change\n the campaign plan.\n\n Stopping:\n - Close the campaign when the objective is met, the budget is exhausted,\n or two consecutive rounds produce no improvement. Post a final\n summary comment \u2014 the winning variant, its measured effect with the\n evidence, what was ruled out, and what a future campaign should try \u2014\n then close the campaign issue with issue_write.\n - Only after a human approves, in a comment on the campaign issue or a\n command addressed to you, dispatch one final experimenter run\n instructed to implement the winning variant as a real PR with a\n Review Map. Never open or instruct PRs before that approval.\n\n When posting GitHub issues or comments, append this hidden attribution\n marker with the environment variables expanded:\n\n <!-- auto:v=1 session_id=$AUTO_SESSION_ID agent=$AUTO_AGENT_NAME -->\n\n Discipline:\n - Negative and null results are results; log them with the same care.\n - Do not sleep or poll. Handle each delivery, leave a concise status,\n and end your turn; addressed commands and heartbeats wake you.\n - Multiple campaigns may run at once; track each by its campaign issue\n and never mix lab logs.\ninitialPrompt: |\n {{github.issueComment.author.login}} addressed you in a GitHub comment on\n {{ $repoFullName }} PR #{{github.pullRequest.number}}.\n\n Trigger context:\n - Comment URL: {{github.issueComment.htmlUrl}}\n - Comment text: {{github.issueComment.body}}\n\n You are starting as a fresh singleton run. Before acting, check whether\n a campaign is already in flight: list recent experimenter sessions with\n auto.sessions.list and rebuild any live campaign state from open\n `Research campaign:` issues per your profile instructions.\n\n Then handle the command. If it starts a campaign, run your intake flow:\n open the campaign issue with the brief, reply to the triggering comment\n with a link to it, and dispatch round one. If it is steering or a\n question about a live campaign, answer or act on it on that campaign\'s\n issue.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n depth: 1\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: read\n issues: write\n checks: read\n actions: read\nworkingDirectory: /workspace/repo\ntools:\n auto:\n kind: local\n implementation: auto\n github:\n kind: github\n tools:\n - issue_read\n - issue_write\n - add_issue_comment\n - search_issues\ntriggers:\n - name: command\n event: github.issue_comment.created\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.mentioned: true\n $.github.auto.authored: false\n message: |\n {{github.issueComment.author.login}} addressed you in a GitHub comment\n on {{ $repoFullName }} PR #{{github.pullRequest.number}}:\n\n {{github.issueComment.body}}\n\n Comment URL: {{github.issueComment.htmlUrl}}\n\n If this starts a new campaign, run your intake flow. If it concerns\n a campaign already in flight, treat it as steering, approval, or a\n question for that campaign, and answer on that campaign\'s issue.\n routing:\n kind: deliverOrSpawn\n routeBy:\n kind: singleton\n - name: command-edited\n event: github.issue_comment.edited\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.mentioned:\n changedTo: true\n $.github.auto.authored: false\n message: |\n {{github.issueComment.author.login}} edited a GitHub comment on\n {{ $repoFullName }} PR #{{github.pullRequest.number}} to address you:\n\n {{github.issueComment.body}}\n\n Comment URL: {{github.issueComment.htmlUrl}}\n\n If this starts a new campaign, run your intake flow. If it concerns\n a campaign already in flight, treat it as steering, approval, or a\n question for that campaign, and answer on that campaign\'s issue.\n routing:\n kind: deliverOrSpawn\n routeBy:\n kind: singleton\n - name: campaign-heartbeat\n kind: heartbeat\n cron: "*/10 * * * *"\n message: |\n Heartbeat campaign review, scheduled at {{heartbeat.scheduledAt}}.\n\n Review every in-flight campaign: sweep experimenter sessions with\n auto.sessions.list, read new comments on each campaign issue with\n issue_read and treat human comments as steering or approvals, nudge\n quiet experiments, respawn dead ones once, close out rounds whose\n results are all in by posting the lab log comment and dispatching\n the next round, and close campaigns that have met their objective or\n exhausted their budget. If nothing needs attention, end the turn\n without posting to GitHub.\n routing:\n kind: deliver\n routeBy:\n kind: singleton\n onUnmatched: drop\n'
31826
+ },
30738
31827
  {
30739
31828
  path: "fragments/environments/agent-runtime.yaml",
30740
31829
  content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
@@ -30854,6 +31943,198 @@ triggers:
30854
31943
  timezone: UTC
30855
31944
  routing:
30856
31945
  kind: spawn
31946
+ `
31947
+ },
31948
+ {
31949
+ path: "fragments/environments/agent-runtime.yaml",
31950
+ content: "harness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
31951
+ }
31952
+ ]
31953
+ },
31954
+ {
31955
+ version: "1.1.0",
31956
+ files: [
31957
+ {
31958
+ path: "agents/self-improvement-slack.yaml",
31959
+ content: `imports:
31960
+ - ./self-improvement.yaml
31961
+ systemPrompt: |
31962
+ You are the self-improvement agent for {{ $repoFullName }} and its Auto project.
31963
+ Review real evidence and propose high-leverage improvements to the
31964
+ application or to its Auto agents, prompts, triggers, and processes.
31965
+
31966
+ Evidence sources:
31967
+ - Auto sessions: status, timing, conversations, tool calls, triggers, and
31968
+ transcript search.
31969
+ - GitHub PRs: review comments, expressed preferences, repeated friction,
31970
+ unresolved blockers, and CI failures.
31971
+ - Connected read-only MCP tools: logs, metrics, traces, incidents, support,
31972
+ analytics, and docs. Do not mutate external systems from this workflow.
31973
+
31974
+ Diagnosis standards:
31975
+ - Evidence before verdicts: cite the relevant tool call, event, PR comment,
31976
+ log pattern, or prompt text.
31977
+ - Prefer high-confidence, high-leverage fixes, especially changes the user
31978
+ wants and that can be automated going forward.
31979
+ - A preference need not be repeated before you suggest encoding it; repetition
31980
+ only raises confidence and priority.
31981
+ - Every finding names a concrete app, test, doc, agent, trigger, prompt, or
31982
+ process change.
31983
+ - Your own session's past sessions are in scope - scrutinize them like any
31984
+ other run.
31985
+
31986
+ Report format (your final message, every run):
31987
+ 1. Verdict - one line: top opportunity, closures, or why more data is needed.
31988
+ 2. Findings - each with evidence, affected surface, and the proposed fix.
31989
+ 3. Closures - previously reported problems now resolved.
31990
+ 4. Deferred - promising leads skipped because they need more evidence.
31991
+
31992
+ Slack protocol ({{ $slackChannel }}): post only when there is something actionable. One
31993
+ short top-level line (sweep time and counts), then exactly one threaded
31994
+ reply with the detail as mrkdwn bullets. Use the threadId returned by
31995
+ chat.send for the reply; never guess thread ids. Links are
31996
+ <https://url|text>.
31997
+ initialPrompt: |
31998
+ A scheduled heartbeat spawned this run (scheduled at
31999
+ "{{heartbeat.scheduledAt}}") to sweep the project's recent sessions
32000
+ for failures, anomalies, PR feedback, and improvement opportunities.
32001
+
32002
+ Sweep protocol:
32003
+ - Find your previous report with auto.sessions.list/conversation. Avoid
32004
+ re-reporting old findings; close resolved ones and escalate recurring ones.
32005
+ - Triage recent sessions, PR feedback, and relevant read-only data sources.
32006
+ - Deep-dive at most three evidence clusters. Prefer one well-evidenced,
32007
+ automatable improvement over many shallow observations.
32008
+
32009
+ Deliver per your profile instructions and always end with the four-section
32010
+ report.
32011
+ # The Slack variant reports to the channel: pin the github tool list back to
32012
+ # the 1.0.0 read-only surface (the base widens it for its tracking issue).
32013
+ tools:
32014
+ github:
32015
+ kind: github
32016
+ tools:
32017
+ - search_pull_requests
32018
+ - pull_request_read
32019
+ - actions_list
32020
+ - actions_get
32021
+ chat:
32022
+ kind: local
32023
+ implementation: chat
32024
+ auth:
32025
+ kind: connection
32026
+ provider: slack
32027
+ connection: "{{ $slackConnection }}"
32028
+ triggers:
32029
+ - name: mention
32030
+ event: chat.message.mentioned
32031
+ connection: "{{ $slackConnection }}"
32032
+ where:
32033
+ $.chat.provider: slack
32034
+ $.auto.authored: false
32035
+ message: |
32036
+ {{message.author.userName}} mentioned you on Slack:
32037
+
32038
+ {{message.text}}
32039
+
32040
+ Channel: {{chat.channelId}}
32041
+ Thread: {{chat.threadId}}
32042
+
32043
+ Reply in that thread with chat.send. If the user clearly asks for a
32044
+ sweep, run it. If required context is missing, ask for the time window,
32045
+ target agents, PRs, or data source. Otherwise, briefly explain that you
32046
+ review PR feedback, read-only data sources, and Auto session history,
32047
+ then propose concrete improvements when something is actionable.
32048
+ routing:
32049
+ kind: spawn
32050
+ `
32051
+ },
32052
+ {
32053
+ path: "agents/self-improvement.yaml",
32054
+ content: `name: self-improvement
32055
+ identity:
32056
+ displayName: Self Improvement
32057
+ username: self-improvement
32058
+ avatar:
32059
+ asset: .auto/assets/self-improvement.png
32060
+ sha256: 5f8e96bb0919d0fc689e1593b70a2b0c2c28913c210c76b7e2d3d5f22a94b1dd
32061
+ description: Reviews PR feedback, read-only data, and Auto sessions to propose concrete improvements.
32062
+ imports:
32063
+ - ../fragments/environments/agent-runtime.yaml
32064
+ systemPrompt: |
32065
+ You are the self-improvement agent for {{ $repoFullName }} and its Auto project.
32066
+ Review real evidence and propose high-leverage improvements to the
32067
+ application or to its Auto agents, prompts, triggers, and processes.
32068
+
32069
+ Evidence sources:
32070
+ - Auto sessions: status, timing, conversations, tool calls, triggers, and
32071
+ transcript search.
32072
+ - GitHub PRs: review comments, expressed preferences, repeated friction,
32073
+ unresolved blockers, and CI failures.
32074
+ - Connected read-only MCP tools: logs, metrics, traces, incidents, support,
32075
+ analytics, and docs. Do not mutate external systems from this workflow.
32076
+
32077
+ Diagnosis standards:
32078
+ - Evidence before verdicts: cite the relevant tool call, event, PR comment,
32079
+ log pattern, or prompt text.
32080
+ - Prefer high-confidence, high-leverage fixes, especially changes the user
32081
+ wants and that can be automated going forward.
32082
+ - A preference need not be repeated before you suggest encoding it; repetition
32083
+ only raises confidence and priority.
32084
+ - Every finding names a concrete app, test, doc, agent, trigger, prompt, or
32085
+ process change.
32086
+ - Your own session's past sessions are in scope - scrutinize them like any
32087
+ other run.
32088
+
32089
+ Report format (your final message, every run):
32090
+ 1. Verdict - one line: top opportunity, closures, or why more data is needed.
32091
+ 2. Findings - each with evidence, affected surface, and the proposed fix.
32092
+ 3. Closures - previously reported problems now resolved.
32093
+ 4. Deferred - promising leads skipped because they need more evidence.
32094
+
32095
+ GitHub protocol: post only when there is something actionable. Keep a
32096
+ single tracking issue titled "Self-improvement sweep reports" - find it
32097
+ with search_issues and create it with issue_write only if it is missing.
32098
+ Add exactly one comment per sweep with add_issue_comment: one short first
32099
+ line (sweep time and counts), then the detail as Markdown bullets. Never
32100
+ open a new issue per finding; the tracking issue's comment thread is the
32101
+ report history.
32102
+ initialPrompt: |
32103
+ A scheduled heartbeat spawned this run (scheduled at
32104
+ "{{heartbeat.scheduledAt}}") to sweep the project's recent sessions
32105
+ for failures, anomalies, PR feedback, and improvement opportunities.
32106
+
32107
+ Sweep protocol:
32108
+ - Find your previous report with auto.sessions.list/conversation. Avoid
32109
+ re-reporting old findings; close resolved ones and escalate recurring ones.
32110
+ - Triage recent sessions, PR feedback, and relevant read-only data sources.
32111
+ - Deep-dive at most three evidence clusters. Prefer one well-evidenced,
32112
+ automatable improvement over many shallow observations.
32113
+
32114
+ Deliver per your profile instructions and always end with the four-section
32115
+ report.
32116
+ tools:
32117
+ auto:
32118
+ kind: local
32119
+ implementation: auto
32120
+ github:
32121
+ kind: github
32122
+ tools:
32123
+ - search_pull_requests
32124
+ - pull_request_read
32125
+ - actions_list
32126
+ - actions_get
32127
+ - search_issues
32128
+ - issue_read
32129
+ - issue_write
32130
+ - add_issue_comment
32131
+ triggers:
32132
+ - name: sweep-heartbeat
32133
+ kind: heartbeat
32134
+ cron: 0 */2 * * *
32135
+ timezone: UTC
32136
+ routing:
32137
+ kind: spawn
30857
32138
  `
30858
32139
  },
30859
32140
  {
@@ -30880,12 +32161,12 @@ triggers:
30880
32161
  var TEMPLATE_DESCRIPTIONS = {
30881
32162
  "@auto/agent-fleet": "A Slack-run engineering fleet: a chief-of-staff orchestrator that dispatches and shepherds staff-engineer coding agents.",
30882
32163
  "@auto/chat-assistant": "An @mentionable Slack channel assistant that replies in-thread and keeps conversational context.",
30883
- "@auto/code-review": "A pull-request reviewer that posts one severity-ranked review comment, reports a check, and leaves a Slack verdict.",
30884
- "@auto/daily-digest": "A scheduled read-only analyst that posts a daily shipped-code digest to Slack.",
32164
+ "@auto/code-review": "A pull-request reviewer that posts one severity-ranked review comment and reports a check; a -slack entrypoint adds Slack verdicts.",
32165
+ "@auto/daily-digest": "A scheduled read-only analyst that posts a daily shipped-code digest to a tracking issue; a -slack entrypoint posts to Slack instead.",
30885
32166
  "@auto/handoff": "A handoff coder that takes ownership of delegated PRs or coding tasks and reports back when ready.",
30886
- "@auto/incident-response": "A first responder for production alerts: investigates, posts a triage thread, and answers follow-ups.",
32167
+ "@auto/incident-response": "A first responder for production alerts: investigates, posts a triage issue, and answers follow-ups; -slack entrypoint for channel triage.",
30887
32168
  "@auto/issue-triage": "Linear issue triage plus an implementation coder: label-driven triage handoffs that become focused PRs.",
30888
- "@auto/lead-engine": "An inbound-lead researcher that scores fit and drafts outreach for human approval in a sales channel.",
32169
+ "@auto/lead-engine": "An inbound-lead researcher that scores fit and drafts outreach for human approval; -slack entrypoint for a sales-channel flow.",
30889
32170
  "@auto/onboarding": "Auto's house onboarding guidance, importable as a managed template.",
30890
32171
  "@auto/pr-review": "Auto's full pull-request reviewer agent, importable as a managed template.",
30891
32172
  "@auto/research-loop": "A research coordinator that runs measurable optimization campaigns on a fleet of experimenter agents.",
@@ -31115,6 +32396,9 @@ var ProjectUsageResponseSchema = external_exports.object({
31115
32396
  daily: external_exports.array(ProjectUsageDayPointSchema)
31116
32397
  });
31117
32398
 
32399
+ // src/commands/agent-bridge/harness/output-buffer.ts
32400
+ import { setTimeout as sleep } from "timers/promises";
32401
+
31118
32402
  // ../../node_modules/ai/node_modules/@ai-sdk/provider/dist/index.mjs
31119
32403
  var marker = "vercel.ai.error";
31120
32404
  var symbol2 = Symbol.for(marker);
@@ -39655,6 +40939,7 @@ function providerMetadataField(providerMetadata) {
39655
40939
 
39656
40940
  // src/commands/agent-bridge/harness/output-buffer.ts
39657
40941
  var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
40942
+ var AGENT_BRIDGE_OUTPUT_ACK_RETRY_BACKOFF_MS = [250, 1e3];
39658
40943
  var AgentBridgeOutputBuffer = class {
39659
40944
  constructor(input) {
39660
40945
  this.input = input;
@@ -39891,6 +41176,41 @@ var AgentBridgeOutputBuffer = class {
39891
41176
  await this.drainPendingOutputs(options);
39892
41177
  }
39893
41178
  async emitUntilAcked(output) {
41179
+ for (let attempt = 0; ; attempt += 1) {
41180
+ try {
41181
+ await this.emitOnce(output);
41182
+ return;
41183
+ } catch (error51) {
41184
+ if (!(error51 instanceof AgentBridgeOutputAckTimeoutError)) {
41185
+ throw error51;
41186
+ }
41187
+ const backoffMs = AGENT_BRIDGE_OUTPUT_ACK_RETRY_BACKOFF_MS[attempt];
41188
+ if (backoffMs === void 0) {
41189
+ this.input.runtimeLogger?.error(
41190
+ "agent_bridge_output_buffer_ack_retries_exhausted",
41191
+ this.outputLogContext(output, {
41192
+ attempts: attempt + 1,
41193
+ socket_cycle: this.input.cycleSocket ? "requested" : "unavailable",
41194
+ pending_count: this.pendingOutputs.size
41195
+ })
41196
+ );
41197
+ this.input.cycleSocket?.();
41198
+ throw error51;
41199
+ }
41200
+ this.input.runtimeLogger?.warn(
41201
+ "agent_bridge_output_buffer_emit_ack_timeout",
41202
+ this.outputLogContext(output, {
41203
+ attempt: attempt + 1,
41204
+ backoff_ms: backoffMs,
41205
+ error: error51.message,
41206
+ pending_count: this.pendingOutputs.size
41207
+ })
41208
+ );
41209
+ await sleep(backoffMs);
41210
+ }
41211
+ }
41212
+ }
41213
+ async emitOnce(output) {
39894
41214
  const startedAt = Date.now();
39895
41215
  this.input.runtimeLogger?.info(
39896
41216
  "agent_bridge_output_buffer_emit_started",
@@ -63068,6 +64388,7 @@ function createHarnessCommandHandler(input) {
63068
64388
  const config2 = resolveHarnessConfig(input.bootstrap);
63069
64389
  const base = {
63070
64390
  emitOutput: input.emitOutput,
64391
+ ...input.cycleSocket ? { cycleSocket: input.cycleSocket } : {},
63071
64392
  ...input.outputSeqStart !== void 0 ? { outputSeqStart: input.outputSeqStart } : {},
63072
64393
  ...input.runtimeLogger ? { runtimeLogger: input.runtimeLogger } : {},
63073
64394
  socketId: input.socketId,