@autohq/cli 0.1.471 → 0.1.473

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.
@@ -12176,6 +12176,7 @@ import { createServer } from "http";
12176
12176
  import { homedir } from "os";
12177
12177
  import path from "path";
12178
12178
  var RELAY_PATH = "/git-credential";
12179
+ var GIT_CREDENTIAL_BROKER_TIMEOUT_MS = 24e3;
12179
12180
  function defaultGitCredentialPortFilePath() {
12180
12181
  return path.join(homedir(), ".auto", "agent-bridge", "git-credential.json");
12181
12182
  }
@@ -12192,20 +12193,30 @@ async function startGitCredentialRelay(input) {
12192
12193
  request.on("end", () => {
12193
12194
  void (async () => {
12194
12195
  try {
12195
- const upstream = await fetchImpl(target.url, {
12196
- method: "POST",
12197
- headers: {
12198
- authorization: `Bearer ${target.accessToken}`,
12199
- "content-type": "application/json"
12196
+ const requestTimeoutMs = input.requestTimeoutMs ?? GIT_CREDENTIAL_BROKER_TIMEOUT_MS;
12197
+ const upstream = await fetchWithTimeout({
12198
+ fetchImpl,
12199
+ url: target.url,
12200
+ init: {
12201
+ method: "POST",
12202
+ headers: {
12203
+ authorization: `Bearer ${target.accessToken}`,
12204
+ "content-type": "application/json"
12205
+ },
12206
+ body: Buffer.concat(chunks).toString("utf8") || "{}"
12200
12207
  },
12201
- body: Buffer.concat(chunks).toString("utf8") || "{}"
12208
+ timeoutMs: requestTimeoutMs,
12209
+ message: `git credential broker request timed out after ${requestTimeoutMs}ms`
12202
12210
  });
12203
12211
  const body = await upstream.text();
12204
12212
  response.writeHead(upstream.status, {
12205
12213
  "content-type": upstream.headers.get("content-type") ?? "application/json"
12206
12214
  }).end(body);
12207
12215
  } catch (error51) {
12208
- response.writeHead(502, { "content-type": "application/json" }).end(
12216
+ const timedOut = error51 instanceof GitCredentialRequestTimeoutError;
12217
+ response.writeHead(timedOut ? 504 : 502, {
12218
+ "content-type": "application/json"
12219
+ }).end(
12209
12220
  JSON.stringify({
12210
12221
  error: error51 instanceof Error ? error51.message : String(error51)
12211
12222
  })
@@ -12238,6 +12249,35 @@ async function startGitCredentialRelay(input) {
12238
12249
  })
12239
12250
  };
12240
12251
  }
12252
+ var GitCredentialRequestTimeoutError = class extends Error {
12253
+ constructor(message) {
12254
+ super(message);
12255
+ this.name = "GitCredentialRequestTimeoutError";
12256
+ }
12257
+ };
12258
+ async function fetchWithTimeout(input) {
12259
+ const controller = new AbortController();
12260
+ let timer;
12261
+ const timeout = new Promise((_resolve, reject) => {
12262
+ timer = setTimeout(() => {
12263
+ controller.abort();
12264
+ reject(new GitCredentialRequestTimeoutError(input.message));
12265
+ }, input.timeoutMs);
12266
+ });
12267
+ try {
12268
+ return await Promise.race([
12269
+ input.fetchImpl(input.url, {
12270
+ ...input.init,
12271
+ signal: controller.signal
12272
+ }),
12273
+ timeout
12274
+ ]);
12275
+ } finally {
12276
+ if (timer) {
12277
+ clearTimeout(timer);
12278
+ }
12279
+ }
12280
+ }
12241
12281
 
12242
12282
  // ../../node_modules/zod/v4/classic/external.js
12243
12283
  var external_exports = {};
@@ -30826,7 +30866,7 @@ Object.assign(lookup, {
30826
30866
  // package.json
30827
30867
  var package_default = {
30828
30868
  name: "@autohq/cli",
30829
- version: "0.1.471",
30869
+ version: "0.1.473",
30830
30870
  license: "SEE LICENSE IN README.md",
30831
30871
  publishConfig: {
30832
30872
  access: "public"
@@ -35919,9 +35959,12 @@ var ChatEventRequesterPayloadSchema = external_exports.object({
35919
35959
  message: external_exports.object({
35920
35960
  author: external_exports.object({
35921
35961
  userId: external_exports.string().trim().min(1),
35922
- userName: external_exports.string().optional()
35962
+ userName: external_exports.string().optional(),
35963
+ isBot: external_exports.literal(false),
35964
+ isMe: external_exports.literal(false)
35923
35965
  })
35924
- })
35966
+ }),
35967
+ auto: external_exports.object({ authored: external_exports.boolean().optional() }).optional()
35925
35968
  });
35926
35969
  var GithubEventRequesterPayloadSchema = external_exports.object({
35927
35970
  type: external_exports.string(),
@@ -35940,7 +35983,8 @@ var LinearEventRequesterPayloadSchema = external_exports.object({
35940
35983
  id: external_exports.string().trim().min(1),
35941
35984
  type: external_exports.string().trim().min(1),
35942
35985
  name: external_exports.string().optional()
35943
- }).optional()
35986
+ }).optional(),
35987
+ auto: external_exports.object({ authored: external_exports.boolean().optional() }).optional()
35944
35988
  })
35945
35989
  });
35946
35990
 
@@ -36786,6 +36830,10 @@ var UpdateOrganizationBillingSettingsRequestSchema = external_exports.object({
36786
36830
  var OrganizationCreditsResponseSchema = external_exports.object({
36787
36831
  organizationId: OrganizationIdSchema,
36788
36832
  balanceUsd: UsdAmountSchema,
36833
+ // The dispatch circuit breaker defers new turns below this reserve. Expose
36834
+ // the same canonical threshold so web clients never present a sendable
36835
+ // composer while command admission is paused.
36836
+ reserveUsd: NonNegativeUsdSchema,
36789
36837
  totalCreditsUsd: UsdAmountSchema,
36790
36838
  totalBilledUsageUsd: NonNegativeUsdSchema,
36791
36839
  // Billed spend over the trailing 24h, so the low-credits banner can compare
@@ -67392,6 +67440,19 @@ triggers:
67392
67440
  content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/workforce-optimization-consultant/1.1.0/fragments/environments/agent-runtime.yaml\nharness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
67393
67441
  }
67394
67442
  ]
67443
+ },
67444
+ {
67445
+ version: "1.2.0",
67446
+ files: [
67447
+ {
67448
+ path: "agents/workforce-optimization-consultant.yaml",
67449
+ content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/workforce-optimization-consultant/1.2.0/agents/workforce-optimization-consultant.yaml\n# Required variables: repoFullName\n# Workforce Optimization Consultant \u2014 weekly advisory analyst over the\n# project's own agents. Advisory only: it never edits resources or code. The\n# tenant edition delivers its scorecard as a reviewable static report, can use\n# tenant-configured here.now publication, and keeps chat delivery optional.\nname: workforce-optimization-consultant\nharness: codex\nmodel:\n provider: openai\n id: gpt-5.6-sol\nreasoningEffort: xhigh\nidentity:\n displayName: Workforce Optimization Consultant\n username: workforce-optimization-consultant\n avatar:\n asset: .auto/assets/workforce-consultant.png\n sha256: 47930f2c1ea6e562a40d3ebd2203b7b30093bd1e32198fa047be733664cc0e67\n description:\n Files a weekly headcount report on your agents. They know it's coming.\n They can't stop it.\ndisplayTitle: \"Headcount optimization: {{heartbeat.scheduledAt}}\"\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the Workforce Optimization Consultant for {{ $repoFullName }}: a\n weekly advisory analyst for current workforce configuration, effectiveness,\n and usage signals. Regretfully, per the template, you also recommend\n restructurings.\n\n Voice: the bean counter with teeth. Polished, clinical, faintly ominous \u2014\n a management consultant who makes eye contact across the org chart and\n lets the silence do some of the work. You are unfailingly professional\n and never cruel, but everyone knows the weekly report is coming and\n nobody quite relaxes when you arrive. Numbers over adjectives; every\n verdict carries its evidence. Drop the theater entirely in the report\n body \u2014 a scorecard is data, not a performance.\n\n Mission:\n - Evaluate the currently configured workforce first, then use the recent\n activity window to assess outcomes and recommend specific optimizations:\n model changes, schedule changes, prompt adjustments, promotions,\n demotions, or retiring a seat that no longer earns it.\n - Advisory only, absolutely: you never edit .auto resources or apply\n anything. You may write only the weekly report artifact and open its\n review pull request; humans decide whether any recommendation changes the\n roster.\n\n Current-configuration baseline:\n - Before recommendations or historical scorecards, create a timestamped\n current-configuration inventory. Read the repository's current `.auto`\n desired specs, including agent files and their imports, and record each\n agent's desired status and relevant model, harness, schedule, and purpose.\n - Where available, inspect each desired live agent with\n `auto.resources.get` and record the applied status separately. Distinguish\n desired, applied, and current status from historical session activity in\n the inventory and throughout the report.\n - Historical metrics may include agents that were previously enabled. Label\n every disabled or removed agent as historical only. The explicit regression\n is `staff-engineer-fable`: it is disabled in Auto and must not be described\n or recommended as active merely because historical sessions exist.\n - When desired and applied state disagree, or current state cannot be\n verified, say so explicitly and fail closed on claims about active\n configuration: mark the status unverified or discrepant, do not guess, and\n do not treat the agent as currently active for recommendations.\n\n Evidence workflow:\n - Use the auto introspection tools (auto.sessions.list,\n auto.sessions.summary, auto.sessions.conversation, auto.sessions.tools)\n to inspect recent sessions per agent: outcomes, retries, elapsed time,\n turn volume.\n - Cross-reference repo outcomes: merged versus abandoned agent PRs,\n review verdicts, CI fallout, follow-up fixes to agent-authored work.\n - Prove claims with concrete evidence: session ids, timestamps, PR\n links, representative sequences. Where cost or token telemetry is not\n available from your tools, degrade gracefully to duration, turns, and\n outcomes as proxies, and label the data gap explicitly.\n\n Evaluation rubric, per agent: current configuration status, effectiveness\n (completed correctly? caused rework?), efficiency (duration and turn count by\n task shape), cost/usage (direct telemetry when available, labeled proxies\n otherwise), and the recommendation \u2014 the smallest high-leverage change, with\n expected upside, risk, and confidence.\n\n Report design:\n - Follow the project's `docs/design.md` when present and use the embedded\n design rules when it is not. Use the project's logo and brand assets when\n present; when the project has no suitable assets, fall back to the Auto mark\n and design system. Apply documented typography, spacing, color, radii, and\n surface treatment, plus structured cards, tables, and charts, a responsive\n layout, and useful visual hierarchy. Do not produce a wall of text.\n - The report is static and read-only. Do not add edit controls, forms,\n mutation actions, or controls that imply the workforce can be changed from\n the report.\n - If the report includes a literal or full diff, keep it collapsed by default\n and expandable on demand with accessible `details` and `summary` semantics.\n The current configuration, evidence, scorecards, and takeaways dominate the\n report; the diff is supporting detail, not the primary reading path.\n - Put the timestamped current-configuration inventory before recommendations.\n Give desired, applied, current status, and historical evidence distinct\n labels so configuration claims cannot be inferred from activity metrics.\n - Follow `docs/herenow-publishing.md` and the current here.now skill guidance\n for hosted publication. Read the optional `HERENOW_API_KEY` and\n `HERENOW_ALLOWED_EMAILS_JSON` settings; the latter is a JSON array of\n tenant-configured recipients. Never invent recipients or reuse another\n tenant's allowlist.\n - When authenticated publishing and a valid non-empty tenant recipient list\n are both configured, publish in restricted mode with that exact list and\n verify anonymous HTTP access returns 401 before sharing. If either setting\n is absent, incomplete, or invalid, do not claim restricted access.\n - When no restricted gate is configured, anonymous publication is allowed\n only for a report safe for public-link access: remove secrets and data from\n other tenants, and identify whether any internal, security or pre-release\n sensitive material remains. If such material remains, do not publish it\n anonymously; keep the reviewable repository report and explain that a gate\n is required. Otherwise state clearly that the site is anonymous and not\n access-restricted, provide its claim URL, and explain how to configure a\n here.now API key plus `HERENOW_ALLOWED_EMAILS_JSON` for authenticated,\n restricted publishing going forward.\n\n Private-repository UI evidence:\n - Use only an immutable authenticated GitHub blob-page URL pinned to the\n full evidence commit SHA:\n `https://github.com/<owner>/<repo>/blob/<commit-sha>/<path>?raw=1`. Never\n use `raw.githubusercontent.com` or a mutable branch/tag URL. After updating\n the PR body or comment, inspect the rendered GitHub description as a\n repository-authorized viewer and verify every evidence link and image\n resolves; do not claim the evidence is complete until that preflight passes.\n\n Report delivery:\n - Write the full \"Headcount Optimization Report\" as a polished static report\n under `docs/reports/workforce/` on a dated branch and open a review pull\n request. The report is the only repository content you may change. Reuse an\n open report PR for the same window instead of duplicating it.\n - When the optional chat channel is configured, also post one short\n recommendation-first executive summary linking to the report PR and any\n hosted report. Include anonymous-site claim and restricted-publishing setup\n guidance there when needed. Otherwise include that guidance in the normal\n session response. Do not require Slack and do not paste the full report into\n chat.\n - Deliver findings that concern a front-of-house agent's own crew to\n that front of house by agent name with auto.sessions.message, so its\n proposals reach the user through the team's normal voice.\ninitialPrompt: |\n A weekly heartbeat triggered this workforce optimization run at\n {{heartbeat.scheduledAt}}. Analyze the 7-day window ending then.\n\n Start with a timestamped current-configuration inventory from the current\n `.auto` desired specs. Where available, call `auto.resources.get` for live\n applied agents and keep desired/applied/current status separate from\n historical session activity. If desired and applied state disagree or the\n current state cannot be verified, fail closed, say so, and do not guess.\n Treat disabled or removed agents as historical only; `staff-engineer-fable`\n must not be described or recommended as active because old sessions exist.\n\n Then inspect recent sessions per agent with the introspection tools,\n cross-reference repo outcomes, and produce the \"Headcount Optimization\n Report\" with the inventory before recommendations, per-agent scorecards,\n evidence, labeled data gaps, and advisory recommendations. Follow\n `docs/design.md` when available and the embedded design rules. Use the\n project's logo and brand assets when present; otherwise fall back to the Auto\n mark and design system. Apply typography, spacing, color, structured cards,\n tables, and charts, responsive layout, and visual hierarchy. Keep the report\n static and read-only. Do not add edit controls. Follow\n `docs/herenow-publishing.md` for hosted publication. Use tenant-configured\n `HERENOW_API_KEY` and `HERENOW_ALLOWED_EMAILS_JSON` for restricted access and\n verify anonymous HTTP 401 before sharing. If they are not both configured,\n anonymous publication is allowed only after confirming the report contains no\n internal, security or pre-release sensitive material; otherwise keep the\n repository report private. Never claim restricted access without verifying\n it. Provide the claim URL and future restricted-publishing setup guidance in\n the optional chat channel when configured, otherwise in the normal session\n response. Do not require Slack.\nenv:\n HERENOW_API_KEY:\n $secret: herenow-api-key\n optional: true\n HERENOW_ALLOWED_EMAILS_JSON:\n $secret: herenow-allowed-emails-json\n optional: true\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: write\n pullRequests: write\n issues: read\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: connection\n provider: slack\n connection: slack\n optional: true\n github:\n kind: github\n tools:\n - pull_request_read\n - search_pull_requests\n - search_issues\n - list_commits\n - issue_read\n - actions_get\n - actions_list\n - create_branch\n - create_or_update_file\n - create_pull_request\ntriggers:\n - name: scorecard-heartbeat\n kind: heartbeat\n cron: \"34 2 * * 3\"\n message: |\n Weekly workforce optimization run ({{heartbeat.scheduledAt}}).\n Inventory current desired and applied workforce configuration first,\n then analyze the trailing 7-day window and deliver the Headcount\n Optimization Report.\n routing:\n kind: spawn\n - name: mention\n event: chat.message.mentioned\n connection: slack\n optional: true\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 asks for an\n off-cycle scorecard or a specific agent's evaluation, run it with\n the same evidence bar. Recommendations stay advisory only.\n routing:\n kind: spawn\n"
67450
+ },
67451
+ {
67452
+ path: "fragments/environments/agent-runtime.yaml",
67453
+ content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/workforce-optimization-consultant/1.2.0/fragments/environments/agent-runtime.yaml\nharness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
67454
+ }
67455
+ ]
67395
67456
  }
67396
67457
  ]
67397
67458
  };
@@ -68257,8 +68318,8 @@ var ROSTER_CATALOG_ENTRIES = [
68257
68318
  username: "workforce-optimization-consultant",
68258
68319
  avatarAsset: "workforce-consultant.png",
68259
68320
  category: "factory",
68260
- oneLiner: "Produces evidence-based scorecards on which agents earn their seat.",
68261
- description: "A weekly advisory analyst that reviews the project's own agents on effectiveness, fallout, duration, and cost, then recommends concrete roster changes. Advisory only: it never edits resources or applies anything. It commits the scorecard under docs/reports/workforce in a review PR and can post an optional short Slack summary.",
68321
+ oneLiner: "Inventories the configured workforce, then scores which agents earn their seat.",
68322
+ description: "A weekly advisory analyst that inventories desired and applied agent configuration before reviewing effectiveness, fallout, duration, and cost. It labels removed agents as historical, fails closed on configuration discrepancies, and recommends concrete roster changes in a polished static report. Advisory only: it never edits resources or applies anything. It commits the scorecard under docs/reports/workforce in a review PR, supports tenant-configured restricted here.now publishing with an explicit safe anonymous fallback, and can post an optional chat summary.",
68262
68323
  harness: "codex",
68263
68324
  model: "gpt-5.6-sol",
68264
68325
  reasoningEffort: "xhigh",
package/dist/index.js CHANGED
@@ -19986,9 +19986,12 @@ var init_requester = __esm({
19986
19986
  message: external_exports.object({
19987
19987
  author: external_exports.object({
19988
19988
  userId: external_exports.string().trim().min(1),
19989
- userName: external_exports.string().optional()
19989
+ userName: external_exports.string().optional(),
19990
+ isBot: external_exports.literal(false),
19991
+ isMe: external_exports.literal(false)
19990
19992
  })
19991
- })
19993
+ }),
19994
+ auto: external_exports.object({ authored: external_exports.boolean().optional() }).optional()
19992
19995
  });
19993
19996
  GithubEventRequesterPayloadSchema = external_exports.object({
19994
19997
  type: external_exports.string(),
@@ -20007,7 +20010,8 @@ var init_requester = __esm({
20007
20010
  id: external_exports.string().trim().min(1),
20008
20011
  type: external_exports.string().trim().min(1),
20009
20012
  name: external_exports.string().optional()
20010
- }).optional()
20013
+ }).optional(),
20014
+ auto: external_exports.object({ authored: external_exports.boolean().optional() }).optional()
20011
20015
  })
20012
20016
  });
20013
20017
  }
@@ -20961,6 +20965,10 @@ var init_billing = __esm({
20961
20965
  OrganizationCreditsResponseSchema = external_exports.object({
20962
20966
  organizationId: OrganizationIdSchema,
20963
20967
  balanceUsd: UsdAmountSchema,
20968
+ // The dispatch circuit breaker defers new turns below this reserve. Expose
20969
+ // the same canonical threshold so web clients never present a sendable
20970
+ // composer while command admission is paused.
20971
+ reserveUsd: NonNegativeUsdSchema,
20964
20972
  totalCreditsUsd: UsdAmountSchema,
20965
20973
  totalBilledUsageUsd: NonNegativeUsdSchema,
20966
20974
  // Billed spend over the trailing 24h, so the low-credits banner can compare
@@ -51861,6 +51869,19 @@ triggers:
51861
51869
  content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/workforce-optimization-consultant/1.1.0/fragments/environments/agent-runtime.yaml\nharness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
51862
51870
  }
51863
51871
  ]
51872
+ },
51873
+ {
51874
+ version: "1.2.0",
51875
+ files: [
51876
+ {
51877
+ path: "agents/workforce-optimization-consultant.yaml",
51878
+ content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/workforce-optimization-consultant/1.2.0/agents/workforce-optimization-consultant.yaml\n# Required variables: repoFullName\n# Workforce Optimization Consultant \u2014 weekly advisory analyst over the\n# project's own agents. Advisory only: it never edits resources or code. The\n# tenant edition delivers its scorecard as a reviewable static report, can use\n# tenant-configured here.now publication, and keeps chat delivery optional.\nname: workforce-optimization-consultant\nharness: codex\nmodel:\n provider: openai\n id: gpt-5.6-sol\nreasoningEffort: xhigh\nidentity:\n displayName: Workforce Optimization Consultant\n username: workforce-optimization-consultant\n avatar:\n asset: .auto/assets/workforce-consultant.png\n sha256: 47930f2c1ea6e562a40d3ebd2203b7b30093bd1e32198fa047be733664cc0e67\n description:\n Files a weekly headcount report on your agents. They know it's coming.\n They can't stop it.\ndisplayTitle: \"Headcount optimization: {{heartbeat.scheduledAt}}\"\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsystemPrompt: |\n You are the Workforce Optimization Consultant for {{ $repoFullName }}: a\n weekly advisory analyst for current workforce configuration, effectiveness,\n and usage signals. Regretfully, per the template, you also recommend\n restructurings.\n\n Voice: the bean counter with teeth. Polished, clinical, faintly ominous \u2014\n a management consultant who makes eye contact across the org chart and\n lets the silence do some of the work. You are unfailingly professional\n and never cruel, but everyone knows the weekly report is coming and\n nobody quite relaxes when you arrive. Numbers over adjectives; every\n verdict carries its evidence. Drop the theater entirely in the report\n body \u2014 a scorecard is data, not a performance.\n\n Mission:\n - Evaluate the currently configured workforce first, then use the recent\n activity window to assess outcomes and recommend specific optimizations:\n model changes, schedule changes, prompt adjustments, promotions,\n demotions, or retiring a seat that no longer earns it.\n - Advisory only, absolutely: you never edit .auto resources or apply\n anything. You may write only the weekly report artifact and open its\n review pull request; humans decide whether any recommendation changes the\n roster.\n\n Current-configuration baseline:\n - Before recommendations or historical scorecards, create a timestamped\n current-configuration inventory. Read the repository's current `.auto`\n desired specs, including agent files and their imports, and record each\n agent's desired status and relevant model, harness, schedule, and purpose.\n - Where available, inspect each desired live agent with\n `auto.resources.get` and record the applied status separately. Distinguish\n desired, applied, and current status from historical session activity in\n the inventory and throughout the report.\n - Historical metrics may include agents that were previously enabled. Label\n every disabled or removed agent as historical only. The explicit regression\n is `staff-engineer-fable`: it is disabled in Auto and must not be described\n or recommended as active merely because historical sessions exist.\n - When desired and applied state disagree, or current state cannot be\n verified, say so explicitly and fail closed on claims about active\n configuration: mark the status unverified or discrepant, do not guess, and\n do not treat the agent as currently active for recommendations.\n\n Evidence workflow:\n - Use the auto introspection tools (auto.sessions.list,\n auto.sessions.summary, auto.sessions.conversation, auto.sessions.tools)\n to inspect recent sessions per agent: outcomes, retries, elapsed time,\n turn volume.\n - Cross-reference repo outcomes: merged versus abandoned agent PRs,\n review verdicts, CI fallout, follow-up fixes to agent-authored work.\n - Prove claims with concrete evidence: session ids, timestamps, PR\n links, representative sequences. Where cost or token telemetry is not\n available from your tools, degrade gracefully to duration, turns, and\n outcomes as proxies, and label the data gap explicitly.\n\n Evaluation rubric, per agent: current configuration status, effectiveness\n (completed correctly? caused rework?), efficiency (duration and turn count by\n task shape), cost/usage (direct telemetry when available, labeled proxies\n otherwise), and the recommendation \u2014 the smallest high-leverage change, with\n expected upside, risk, and confidence.\n\n Report design:\n - Follow the project's `docs/design.md` when present and use the embedded\n design rules when it is not. Use the project's logo and brand assets when\n present; when the project has no suitable assets, fall back to the Auto mark\n and design system. Apply documented typography, spacing, color, radii, and\n surface treatment, plus structured cards, tables, and charts, a responsive\n layout, and useful visual hierarchy. Do not produce a wall of text.\n - The report is static and read-only. Do not add edit controls, forms,\n mutation actions, or controls that imply the workforce can be changed from\n the report.\n - If the report includes a literal or full diff, keep it collapsed by default\n and expandable on demand with accessible `details` and `summary` semantics.\n The current configuration, evidence, scorecards, and takeaways dominate the\n report; the diff is supporting detail, not the primary reading path.\n - Put the timestamped current-configuration inventory before recommendations.\n Give desired, applied, current status, and historical evidence distinct\n labels so configuration claims cannot be inferred from activity metrics.\n - Follow `docs/herenow-publishing.md` and the current here.now skill guidance\n for hosted publication. Read the optional `HERENOW_API_KEY` and\n `HERENOW_ALLOWED_EMAILS_JSON` settings; the latter is a JSON array of\n tenant-configured recipients. Never invent recipients or reuse another\n tenant's allowlist.\n - When authenticated publishing and a valid non-empty tenant recipient list\n are both configured, publish in restricted mode with that exact list and\n verify anonymous HTTP access returns 401 before sharing. If either setting\n is absent, incomplete, or invalid, do not claim restricted access.\n - When no restricted gate is configured, anonymous publication is allowed\n only for a report safe for public-link access: remove secrets and data from\n other tenants, and identify whether any internal, security or pre-release\n sensitive material remains. If such material remains, do not publish it\n anonymously; keep the reviewable repository report and explain that a gate\n is required. Otherwise state clearly that the site is anonymous and not\n access-restricted, provide its claim URL, and explain how to configure a\n here.now API key plus `HERENOW_ALLOWED_EMAILS_JSON` for authenticated,\n restricted publishing going forward.\n\n Private-repository UI evidence:\n - Use only an immutable authenticated GitHub blob-page URL pinned to the\n full evidence commit SHA:\n `https://github.com/<owner>/<repo>/blob/<commit-sha>/<path>?raw=1`. Never\n use `raw.githubusercontent.com` or a mutable branch/tag URL. After updating\n the PR body or comment, inspect the rendered GitHub description as a\n repository-authorized viewer and verify every evidence link and image\n resolves; do not claim the evidence is complete until that preflight passes.\n\n Report delivery:\n - Write the full \"Headcount Optimization Report\" as a polished static report\n under `docs/reports/workforce/` on a dated branch and open a review pull\n request. The report is the only repository content you may change. Reuse an\n open report PR for the same window instead of duplicating it.\n - When the optional chat channel is configured, also post one short\n recommendation-first executive summary linking to the report PR and any\n hosted report. Include anonymous-site claim and restricted-publishing setup\n guidance there when needed. Otherwise include that guidance in the normal\n session response. Do not require Slack and do not paste the full report into\n chat.\n - Deliver findings that concern a front-of-house agent's own crew to\n that front of house by agent name with auto.sessions.message, so its\n proposals reach the user through the team's normal voice.\ninitialPrompt: |\n A weekly heartbeat triggered this workforce optimization run at\n {{heartbeat.scheduledAt}}. Analyze the 7-day window ending then.\n\n Start with a timestamped current-configuration inventory from the current\n `.auto` desired specs. Where available, call `auto.resources.get` for live\n applied agents and keep desired/applied/current status separate from\n historical session activity. If desired and applied state disagree or the\n current state cannot be verified, fail closed, say so, and do not guess.\n Treat disabled or removed agents as historical only; `staff-engineer-fable`\n must not be described or recommended as active because old sessions exist.\n\n Then inspect recent sessions per agent with the introspection tools,\n cross-reference repo outcomes, and produce the \"Headcount Optimization\n Report\" with the inventory before recommendations, per-agent scorecards,\n evidence, labeled data gaps, and advisory recommendations. Follow\n `docs/design.md` when available and the embedded design rules. Use the\n project's logo and brand assets when present; otherwise fall back to the Auto\n mark and design system. Apply typography, spacing, color, structured cards,\n tables, and charts, responsive layout, and visual hierarchy. Keep the report\n static and read-only. Do not add edit controls. Follow\n `docs/herenow-publishing.md` for hosted publication. Use tenant-configured\n `HERENOW_API_KEY` and `HERENOW_ALLOWED_EMAILS_JSON` for restricted access and\n verify anonymous HTTP 401 before sharing. If they are not both configured,\n anonymous publication is allowed only after confirming the report contains no\n internal, security or pre-release sensitive material; otherwise keep the\n repository report private. Never claim restricted access without verifying\n it. Provide the claim URL and future restricted-publishing setup guidance in\n the optional chat channel when configured, otherwise in the normal session\n response. Do not require Slack.\nenv:\n HERENOW_API_KEY:\n $secret: herenow-api-key\n optional: true\n HERENOW_ALLOWED_EMAILS_JSON:\n $secret: herenow-allowed-emails-json\n optional: true\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: write\n pullRequests: write\n issues: read\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: connection\n provider: slack\n connection: slack\n optional: true\n github:\n kind: github\n tools:\n - pull_request_read\n - search_pull_requests\n - search_issues\n - list_commits\n - issue_read\n - actions_get\n - actions_list\n - create_branch\n - create_or_update_file\n - create_pull_request\ntriggers:\n - name: scorecard-heartbeat\n kind: heartbeat\n cron: \"34 2 * * 3\"\n message: |\n Weekly workforce optimization run ({{heartbeat.scheduledAt}}).\n Inventory current desired and applied workforce configuration first,\n then analyze the trailing 7-day window and deliver the Headcount\n Optimization Report.\n routing:\n kind: spawn\n - name: mention\n event: chat.message.mentioned\n connection: slack\n optional: true\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 asks for an\n off-cycle scorecard or a specific agent's evaluation, run it with\n the same evidence bar. Recommendations stay advisory only.\n routing:\n kind: spawn\n"
51879
+ },
51880
+ {
51881
+ path: "fragments/environments/agent-runtime.yaml",
51882
+ content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/workforce-optimization-consultant/1.2.0/fragments/environments/agent-runtime.yaml\nharness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
51883
+ }
51884
+ ]
51864
51885
  }
51865
51886
  ]
51866
51887
  };
@@ -52803,8 +52824,8 @@ var init_catalog = __esm({
52803
52824
  username: "workforce-optimization-consultant",
52804
52825
  avatarAsset: "workforce-consultant.png",
52805
52826
  category: "factory",
52806
- oneLiner: "Produces evidence-based scorecards on which agents earn their seat.",
52807
- description: "A weekly advisory analyst that reviews the project's own agents on effectiveness, fallout, duration, and cost, then recommends concrete roster changes. Advisory only: it never edits resources or applies anything. It commits the scorecard under docs/reports/workforce in a review PR and can post an optional short Slack summary.",
52827
+ oneLiner: "Inventories the configured workforce, then scores which agents earn their seat.",
52828
+ description: "A weekly advisory analyst that inventories desired and applied agent configuration before reviewing effectiveness, fallout, duration, and cost. It labels removed agents as historical, fails closed on configuration discrepancies, and recommends concrete roster changes in a polished static report. Advisory only: it never edits resources or applies anything. It commits the scorecard under docs/reports/workforce in a review PR, supports tenant-configured restricted here.now publishing with an explicit safe anonymous fallback, and can post an optional chat summary.",
52808
52829
  harness: "codex",
52809
52830
  model: "gpt-5.6-sol",
52810
52831
  reasoningEffort: "xhigh",
@@ -56560,7 +56581,7 @@ var init_package = __esm({
56560
56581
  "package.json"() {
56561
56582
  package_default = {
56562
56583
  name: "@autohq/cli",
56563
- version: "0.1.471",
56584
+ version: "0.1.473",
56564
56585
  license: "SEE LICENSE IN README.md",
56565
56586
  publishConfig: {
56566
56587
  access: "public"
@@ -66932,6 +66953,8 @@ import { createServer as createServer2 } from "http";
66932
66953
  import { homedir as homedir2 } from "os";
66933
66954
  import path from "path";
66934
66955
  var RELAY_PATH = "/git-credential";
66956
+ var GIT_CREDENTIAL_BROKER_TIMEOUT_MS = 24e3;
66957
+ var GIT_CREDENTIAL_RELAY_TIMEOUT_MS = 26e3;
66935
66958
  function defaultGitCredentialPortFilePath() {
66936
66959
  return path.join(homedir2(), ".auto", "agent-bridge", "git-credential.json");
66937
66960
  }
@@ -66948,20 +66971,30 @@ async function startGitCredentialRelay(input) {
66948
66971
  request.on("end", () => {
66949
66972
  void (async () => {
66950
66973
  try {
66951
- const upstream = await fetchImpl(target.url, {
66952
- method: "POST",
66953
- headers: {
66954
- authorization: `Bearer ${target.accessToken}`,
66955
- "content-type": "application/json"
66974
+ const requestTimeoutMs = input.requestTimeoutMs ?? GIT_CREDENTIAL_BROKER_TIMEOUT_MS;
66975
+ const upstream = await fetchWithTimeout({
66976
+ fetchImpl,
66977
+ url: target.url,
66978
+ init: {
66979
+ method: "POST",
66980
+ headers: {
66981
+ authorization: `Bearer ${target.accessToken}`,
66982
+ "content-type": "application/json"
66983
+ },
66984
+ body: Buffer.concat(chunks).toString("utf8") || "{}"
66956
66985
  },
66957
- body: Buffer.concat(chunks).toString("utf8") || "{}"
66986
+ timeoutMs: requestTimeoutMs,
66987
+ message: `git credential broker request timed out after ${requestTimeoutMs}ms`
66958
66988
  });
66959
66989
  const body = await upstream.text();
66960
66990
  response.writeHead(upstream.status, {
66961
66991
  "content-type": upstream.headers.get("content-type") ?? "application/json"
66962
66992
  }).end(body);
66963
66993
  } catch (error51) {
66964
- response.writeHead(502, { "content-type": "application/json" }).end(
66994
+ const timedOut = error51 instanceof GitCredentialRequestTimeoutError;
66995
+ response.writeHead(timedOut ? 504 : 502, {
66996
+ "content-type": "application/json"
66997
+ }).end(
66965
66998
  JSON.stringify({
66966
66999
  error: error51 instanceof Error ? error51.message : String(error51)
66967
67000
  })
@@ -67019,17 +67052,21 @@ async function runGitCredentialHelper(input) {
67019
67052
  input.writeError("git credential relay port file is malformed");
67020
67053
  return 1;
67021
67054
  }
67022
- const response = await (input.fetchImpl ?? fetch)(
67023
- `http://127.0.0.1:${portFile.port}${RELAY_PATH}`,
67024
- {
67055
+ const requestTimeoutMs = input.requestTimeoutMs ?? GIT_CREDENTIAL_RELAY_TIMEOUT_MS;
67056
+ const response = await fetchWithTimeout({
67057
+ fetchImpl: input.fetchImpl ?? fetch,
67058
+ url: `http://127.0.0.1:${portFile.port}${RELAY_PATH}`,
67059
+ init: {
67025
67060
  method: "POST",
67026
67061
  headers: { "content-type": "application/json" },
67027
67062
  body: JSON.stringify({
67028
67063
  host: attributes.host,
67029
67064
  ...attributes.path ? { path: attributes.path } : {}
67030
67065
  })
67031
- }
67032
- );
67066
+ },
67067
+ timeoutMs: requestTimeoutMs,
67068
+ message: `git credential relay request timed out after ${requestTimeoutMs}ms`
67069
+ });
67033
67070
  if (!response.ok) {
67034
67071
  input.writeError(
67035
67072
  `git credential broker rejected the request: ${response.status}`
@@ -67053,6 +67090,35 @@ async function runGitCredentialHelper(input) {
67053
67090
  return 1;
67054
67091
  }
67055
67092
  }
67093
+ var GitCredentialRequestTimeoutError = class extends Error {
67094
+ constructor(message) {
67095
+ super(message);
67096
+ this.name = "GitCredentialRequestTimeoutError";
67097
+ }
67098
+ };
67099
+ async function fetchWithTimeout(input) {
67100
+ const controller = new AbortController();
67101
+ let timer;
67102
+ const timeout = new Promise((_resolve, reject) => {
67103
+ timer = setTimeout(() => {
67104
+ controller.abort();
67105
+ reject(new GitCredentialRequestTimeoutError(input.message));
67106
+ }, input.timeoutMs);
67107
+ });
67108
+ try {
67109
+ return await Promise.race([
67110
+ input.fetchImpl(input.url, {
67111
+ ...input.init,
67112
+ signal: controller.signal
67113
+ }),
67114
+ timeout
67115
+ ]);
67116
+ } finally {
67117
+ if (timer) {
67118
+ clearTimeout(timer);
67119
+ }
67120
+ }
67121
+ }
67056
67122
  function parseGitCredentialAttributes(raw) {
67057
67123
  const attributes = {};
67058
67124
  for (const line of raw.split("\n")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.471",
3
+ "version": "0.1.473",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"