@rallycry/conveyor-agent 7.0.1 → 7.0.2

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.
@@ -0,0 +1,26 @@
1
+ // src/utils/logger.ts
2
+ function createServiceLogger(service) {
3
+ const prefix = `[conveyor-agent:${service}]`;
4
+ return {
5
+ info(message, data) {
6
+ const extra = data ? ` ${JSON.stringify(data)}` : "";
7
+ process.stderr.write(`${prefix} ${message}${extra}
8
+ `);
9
+ },
10
+ warn(message, data) {
11
+ const extra = data ? ` ${JSON.stringify(data)}` : "";
12
+ process.stderr.write(`${prefix} WARN ${message}${extra}
13
+ `);
14
+ },
15
+ error(message, data) {
16
+ const extra = data ? ` ${JSON.stringify(data)}` : "";
17
+ process.stderr.write(`${prefix} ERROR ${message}${extra}
18
+ `);
19
+ }
20
+ };
21
+ }
22
+
23
+ export {
24
+ createServiceLogger
25
+ };
26
+ //# sourceMappingURL=chunk-CYZPFJGN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["/** Minimal structured logger for conveyor-agent (writes to stderr). */\nexport function createServiceLogger(service: string) {\n const prefix = `[conveyor-agent:${service}]`;\n return {\n info(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} ${message}${extra}\\n`);\n },\n warn(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} WARN ${message}${extra}\\n`);\n },\n error(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} ERROR ${message}${extra}\\n`);\n },\n };\n}\n"],"mappings":";AACO,SAAS,oBAAoB,SAAiB;AACnD,QAAM,SAAS,mBAAmB,OAAO;AACzC,SAAO;AAAA,IACL,KAAK,SAAiB,MAAsC;AAC1D,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK;AAClD,cAAQ,OAAO,MAAM,GAAG,MAAM,IAAI,OAAO,GAAG,KAAK;AAAA,CAAI;AAAA,IACvD;AAAA,IACA,KAAK,SAAiB,MAAsC;AAC1D,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK;AAClD,cAAQ,OAAO,MAAM,GAAG,MAAM,SAAS,OAAO,GAAG,KAAK;AAAA,CAAI;AAAA,IAC5D;AAAA,IACA,MAAM,SAAiB,MAAsC;AAC3D,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK;AAClD,cAAQ,OAAO,MAAM,GAAG,MAAM,UAAU,OAAO,GAAG,KAAK;AAAA,CAAI;AAAA,IAC7D;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,51 @@
1
+ // src/harness/types.ts
2
+ function defineTool(name, description, schema, handler, options) {
3
+ return {
4
+ name,
5
+ description,
6
+ schema,
7
+ handler,
8
+ annotations: options?.annotations
9
+ };
10
+ }
11
+
12
+ // src/harness/claude-code/index.ts
13
+ import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
14
+ var ClaudeCodeHarness = class {
15
+ async *executeQuery(opts) {
16
+ const sdkEvents = query({
17
+ prompt: opts.prompt,
18
+ options: {
19
+ ...opts.options,
20
+ ...opts.resume ? { resume: opts.resume } : {},
21
+ ...opts.options.abortController ? { abortController: opts.options.abortController } : {}
22
+ }
23
+ });
24
+ for await (const event of sdkEvents) {
25
+ yield event;
26
+ }
27
+ }
28
+ createMcpServer(config) {
29
+ const sdkTools = config.tools.map(
30
+ (t) => tool(
31
+ t.name,
32
+ t.description,
33
+ t.schema,
34
+ t.handler,
35
+ t.annotations ? { annotations: t.annotations } : void 0
36
+ )
37
+ );
38
+ return createSdkMcpServer({ name: config.name, tools: sdkTools });
39
+ }
40
+ };
41
+
42
+ // src/harness/index.ts
43
+ function createHarness() {
44
+ return new ClaudeCodeHarness();
45
+ }
46
+
47
+ export {
48
+ defineTool,
49
+ createHarness
50
+ };
51
+ //# sourceMappingURL=chunk-KNBG2634.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/harness/types.ts","../src/harness/claude-code/index.ts","../src/harness/index.ts"],"sourcesContent":["/**\n * Harness-neutral types for agent query execution.\n *\n * These types abstract the underlying agent SDK so that the runner,\n * execution, and tool layers never reference SDK-specific imports\n * directly. The only place that should import from\n * `@anthropic-ai/claude-agent-sdk` is `harness/claude-code/`.\n */\n\nimport type { z } from \"zod\";\n\n// ── Events emitted by the harness during a query ────────────────────────\n\nexport interface HarnessSystemInitEvent {\n type: \"system\";\n subtype: \"init\";\n session_id?: string;\n model: string;\n}\n\nexport interface HarnessCompactBoundaryEvent {\n type: \"system\";\n subtype: \"compact_boundary\";\n compact_metadata: { trigger: \"manual\" | \"auto\"; pre_tokens: number };\n}\n\nexport interface HarnessTaskStartedEvent {\n type: \"system\";\n subtype: \"task_started\";\n task_id: string;\n description: string;\n}\n\nexport interface HarnessTaskProgressEvent {\n type: \"system\";\n subtype: \"task_progress\";\n task_id: string;\n description: string;\n usage?: { tool_uses: number; duration_ms: number };\n}\n\nexport type HarnessSystemEvent =\n | HarnessSystemInitEvent\n | HarnessCompactBoundaryEvent\n | HarnessTaskStartedEvent\n | HarnessTaskProgressEvent;\n\nexport interface HarnessContentBlock {\n type: string;\n text?: string;\n name?: string;\n input?: unknown;\n id?: string;\n}\n\nexport interface HarnessAssistantEvent {\n type: \"assistant\";\n message: {\n role: \"assistant\";\n content: HarnessContentBlock[];\n usage?: {\n input_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n}\n\nexport interface HarnessResultSuccessEvent {\n type: \"result\";\n subtype: \"success\";\n result: string;\n total_cost_usd: number;\n modelUsage?: Record<string, unknown>;\n sessionId?: string;\n}\n\nexport interface HarnessResultErrorEvent {\n type: \"result\";\n subtype: \"error\";\n errors: string[];\n sessionId?: string;\n}\n\nexport type HarnessResultEvent = HarnessResultSuccessEvent | HarnessResultErrorEvent;\n\nexport interface HarnessRateLimitEvent {\n type: \"rate_limit_event\";\n rate_limit_info: {\n status: string;\n rateLimitType?: string;\n utilization?: number;\n resetsAt?: unknown;\n };\n}\n\nexport interface HarnessToolProgressEvent {\n type: \"tool_progress\";\n tool_name?: string;\n elapsed_time_seconds?: number;\n}\n\nexport type HarnessEvent =\n | HarnessSystemEvent\n | HarnessAssistantEvent\n | HarnessResultEvent\n | HarnessRateLimitEvent\n | HarnessToolProgressEvent;\n\n// ── User message fed into a query ───────────────────────────────────────\n\nexport interface HarnessUserMessage {\n type: \"user\";\n session_id: string;\n message: { role: \"user\"; content: string | unknown[] };\n parent_tool_use_id: null;\n}\n\n// ── Tool definition (harness-neutral) ───────────────────────────────────\n\nexport interface HarnessToolAnnotations {\n readOnlyHint?: boolean;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any -- generic tool handler */\nexport interface HarnessToolDefinition {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (\n input: any,\n ) => Promise<{ content: { type: string; text?: string; data?: string; mimeType?: string }[] }>;\n annotations?: HarnessToolAnnotations;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\n// ── Hook types ──────────────────────────────────────────────────────────\n\nexport interface HarnessHookInput {\n hook_event_name: string;\n tool_name: string;\n tool_response: unknown;\n}\n\nexport interface HarnessHookOutput {\n continue: boolean;\n}\n\nexport type HarnessPostToolUseHook = (input: HarnessHookInput) => Promise<HarnessHookOutput>;\n\n// ── MCP server handle (opaque to the runner) ────────────────────────────\n\n/** Opaque handle returned by `AgentHarness.createMcpServer()`. */\nexport type HarnessMcpServer = unknown;\n\n// ── Query options ───────────────────────────────────────────────────────\n\nexport interface HarnessQueryOptions {\n model: string;\n systemPrompt: unknown;\n cwd: string;\n permissionMode: \"plan\" | \"bypassPermissions\";\n allowDangerouslySkipPermissions: boolean;\n tools: { type: \"preset\"; preset: \"claude_code\" };\n mcpServers: Record<string, HarnessMcpServer>;\n settingSources?: (\"user\" | \"project\" | \"local\")[];\n sandbox?: { enabled: boolean };\n maxTurns?: number;\n maxBudgetUsd?: number;\n effort?: string;\n thinking?: unknown;\n betas?: unknown;\n disallowedTools?: string[];\n abortController?: AbortController;\n enableFileCheckpointing?: boolean;\n canUseTool?: (\n toolName: string,\n input: Record<string, unknown>,\n ) => Promise<\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string }\n >;\n hooks?: Record<string, { hooks: HarnessPostToolUseHook[]; timeout: number }[]>;\n resume?: string;\n stderr?: (data: string) => void;\n}\n\n// ── Tool definition helper ──────────────────────────────────────────────\n\n/**\n * Construct a `HarnessToolDefinition` with the same signature as the SDK's\n * `tool()` helper, but without importing the SDK. The harness implementation\n * converts these into SDK-native tools when `createMcpServer()` is called.\n */\nexport function defineTool<T extends z.ZodRawShape>(\n name: string,\n description: string,\n schema: T,\n handler: (\n input: z.infer<z.ZodObject<T>>,\n ) => Promise<{ content: { type: string; text?: string; data?: string; mimeType?: string }[] }>,\n options?: { annotations?: HarnessToolAnnotations },\n): HarnessToolDefinition {\n return {\n name,\n description,\n schema,\n handler: handler as HarnessToolDefinition[\"handler\"],\n annotations: options?.annotations,\n };\n}\n\n// ── AgentHarness interface ──────────────────────────────────────────────\n\nexport interface AgentHarness {\n /** Start a streaming query and return an async generator of events. */\n executeQuery(options: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void>;\n\n /** Wrap an array of harness-neutral tool definitions into an MCP server. */\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer;\n}\n","/**\n * ClaudeCodeHarness — wraps `@anthropic-ai/claude-agent-sdk` behind the\n * generic `AgentHarness` interface.\n *\n * This is the ONLY module that should import from the SDK.\n */\n\nimport { query, tool, createSdkMcpServer } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n AgentHarness,\n HarnessEvent,\n HarnessQueryOptions,\n HarnessToolDefinition,\n HarnessMcpServer,\n HarnessUserMessage,\n} from \"../types.js\";\n\nexport class ClaudeCodeHarness implements AgentHarness {\n async *executeQuery(opts: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void> {\n const sdkEvents = query({\n prompt: opts.prompt as Parameters<typeof query>[0][\"prompt\"],\n options: {\n ...(opts.options as Parameters<typeof query>[0][\"options\"]),\n ...(opts.resume ? { resume: opts.resume } : {}),\n ...(opts.options.abortController ? { abortController: opts.options.abortController } : {}),\n },\n });\n\n for await (const event of sdkEvents) {\n yield event as unknown as HarnessEvent;\n }\n }\n\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer {\n const sdkTools = config.tools.map((t) =>\n tool(\n t.name,\n t.description,\n t.schema,\n t.handler as Parameters<typeof tool>[3],\n t.annotations ? { annotations: t.annotations } : undefined,\n ),\n );\n return createSdkMcpServer({ name: config.name, tools: sdkTools });\n }\n}\n","export { defineTool } from \"./types.js\";\n\nexport type {\n AgentHarness,\n HarnessEvent,\n HarnessSystemEvent,\n HarnessSystemInitEvent,\n HarnessCompactBoundaryEvent,\n HarnessTaskStartedEvent,\n HarnessTaskProgressEvent,\n HarnessAssistantEvent,\n HarnessContentBlock,\n HarnessResultEvent,\n HarnessResultSuccessEvent,\n HarnessResultErrorEvent,\n HarnessRateLimitEvent,\n HarnessToolProgressEvent,\n HarnessUserMessage,\n HarnessToolDefinition,\n HarnessToolAnnotations,\n HarnessMcpServer,\n HarnessQueryOptions,\n HarnessHookInput,\n HarnessHookOutput,\n HarnessPostToolUseHook,\n} from \"./types.js\";\n\nexport { ClaudeCodeHarness } from \"./claude-code/index.js\";\n\nimport { ClaudeCodeHarness } from \"./claude-code/index.js\";\nimport type { AgentHarness } from \"./types.js\";\n\nexport function createHarness(): AgentHarness {\n return new ClaudeCodeHarness();\n}\n"],"mappings":";AAkMO,SAAS,WACd,MACA,aACA,QACA,SAGA,SACuB;AACvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,SAAS;AAAA,EACxB;AACF;;;AC3MA,SAAS,OAAO,MAAM,0BAA0B;AAUzC,IAAM,oBAAN,MAAgD;AAAA,EACrD,OAAO,aAAa,MAImB;AACrC,UAAM,YAAY,MAAM;AAAA,MACtB,QAAQ,KAAK;AAAA,MACb,SAAS;AAAA,QACP,GAAI,KAAK;AAAA,QACT,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,QAC7C,GAAI,KAAK,QAAQ,kBAAkB,EAAE,iBAAiB,KAAK,QAAQ,gBAAgB,IAAI,CAAC;AAAA,MAC1F;AAAA,IACF,CAAC;AAED,qBAAiB,SAAS,WAAW;AACnC,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,gBAAgB,QAA4E;AAC1F,UAAM,WAAW,OAAO,MAAM;AAAA,MAAI,CAAC,MACjC;AAAA,QACE,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,IAAI;AAAA,MACnD;AAAA,IACF;AACA,WAAO,mBAAmB,EAAE,MAAM,OAAO,MAAM,OAAO,SAAS,CAAC;AAAA,EAClE;AACF;;;ACjBO,SAAS,gBAA8B;AAC5C,SAAO,IAAI,kBAAkB;AAC/B;","names":[]}
@@ -1,3 +1,11 @@
1
+ import {
2
+ createHarness,
3
+ defineTool
4
+ } from "./chunk-KNBG2634.js";
5
+ import {
6
+ createServiceLogger
7
+ } from "./chunk-CYZPFJGN.js";
8
+
1
9
  // src/connection/agent-connection.ts
2
10
  import { io } from "socket.io-client";
3
11
  var EVENT_BATCH_MS = 500;
@@ -133,7 +141,17 @@ var AgentConnection = class {
133
141
  });
134
142
  this.socket.io.on("reconnect", () => {
135
143
  process.stderr.write("[conveyor-agent] Reconnected\n");
136
- void this.call("connectAgent", { sessionId: this.config.sessionId }).catch(() => {
144
+ this.call("connectAgent", { sessionId: this.config.sessionId }).then(({ pendingMessages }) => {
145
+ for (const msg of pendingMessages) {
146
+ if (msg.content) {
147
+ if (this.messageCallback) {
148
+ this.messageCallback({ content: msg.content, userId: msg.userId });
149
+ } else {
150
+ this.earlyMessages.push({ content: msg.content, userId: msg.userId });
151
+ }
152
+ }
153
+ }
154
+ }).catch(() => {
137
155
  });
138
156
  if (this.lastEmittedStatus) {
139
157
  void this.call("reportAgentStatus", {
@@ -543,28 +561,6 @@ var Lifecycle = class {
543
561
  }
544
562
  };
545
563
 
546
- // src/utils/logger.ts
547
- function createServiceLogger(service) {
548
- const prefix = `[conveyor-agent:${service}]`;
549
- return {
550
- info(message, data) {
551
- const extra = data ? ` ${JSON.stringify(data)}` : "";
552
- process.stderr.write(`${prefix} ${message}${extra}
553
- `);
554
- },
555
- warn(message, data) {
556
- const extra = data ? ` ${JSON.stringify(data)}` : "";
557
- process.stderr.write(`${prefix} WARN ${message}${extra}
558
- `);
559
- },
560
- error(message, data) {
561
- const extra = data ? ` ${JSON.stringify(data)}` : "";
562
- process.stderr.write(`${prefix} ERROR ${message}${extra}
563
- `);
564
- }
565
- };
566
- }
567
-
568
564
  // src/runner/git-utils.ts
569
565
  import { execSync } from "child_process";
570
566
  function hasUncommittedChanges(cwd) {
@@ -772,52 +768,6 @@ var PlanSync = class {
772
768
  }
773
769
  };
774
770
 
775
- // src/harness/types.ts
776
- function defineTool(name, description, schema, handler, options) {
777
- return {
778
- name,
779
- description,
780
- schema,
781
- handler,
782
- annotations: options?.annotations
783
- };
784
- }
785
-
786
- // src/harness/claude-code/index.ts
787
- import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
788
- var ClaudeCodeHarness = class {
789
- async *executeQuery(opts) {
790
- const sdkEvents = query({
791
- prompt: opts.prompt,
792
- options: {
793
- ...opts.options,
794
- ...opts.resume ? { resume: opts.resume } : {},
795
- ...opts.options.abortController ? { abortController: opts.options.abortController } : {}
796
- }
797
- });
798
- for await (const event of sdkEvents) {
799
- yield event;
800
- }
801
- }
802
- createMcpServer(config) {
803
- const sdkTools = config.tools.map(
804
- (t) => tool(
805
- t.name,
806
- t.description,
807
- t.schema,
808
- t.handler,
809
- t.annotations ? { annotations: t.annotations } : void 0
810
- )
811
- );
812
- return createSdkMcpServer({ name: config.name, tools: sdkTools });
813
- }
814
- };
815
-
816
- // src/harness/index.ts
817
- function createHarness() {
818
- return new ClaudeCodeHarness();
819
- }
820
-
821
771
  // src/execution/pack-runner-prompt.ts
822
772
  function findLastAgentMessageIndex(history) {
823
773
  for (let i = history.length - 1; i >= 0; i--) {
@@ -1209,8 +1159,7 @@ function buildAutoPrompt(context) {
1209
1159
  `You are in Auto mode \u2014 operating autonomously through planning \u2192 building \u2192 PR.`,
1210
1160
  ``,
1211
1161
  `### Phase 1: Discovery & Planning (current)`,
1212
- `- You have read-only codebase access (can read files, run git commands, search code)`,
1213
- `- You can write plan files in .claude/plans/ only \u2014 no other file writes`,
1162
+ `- You are in the SDK's plan mode \u2014 read-only access is enforced automatically`,
1214
1163
  `- You have MCP tools for task properties: update_task, update_task_properties`,
1215
1164
  ``,
1216
1165
  `### Required before transitioning:`,
@@ -2334,7 +2283,16 @@ Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>`;
2334
2283
  }
2335
2284
  }
2336
2285
  if (hasUnpushedCommits(cwd)) {
2337
- const pushSuccess = await pushToOrigin(cwd);
2286
+ const pushSuccess = await pushToOrigin(cwd, async () => {
2287
+ try {
2288
+ const result2 = await connection.call("refreshGithubToken", {
2289
+ sessionId: connection.sessionId
2290
+ });
2291
+ return result2.token;
2292
+ } catch {
2293
+ return void 0;
2294
+ }
2295
+ });
2338
2296
  if (pushSuccess) {
2339
2297
  connection.sendEvent({
2340
2298
  type: "message",
@@ -4696,15 +4654,6 @@ function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask)
4696
4654
  if (hasExitedPlanMode) {
4697
4655
  return isParentTask ? handleReviewToolAccess(toolName, input, true) : handleBuildingToolAccess(toolName, input);
4698
4656
  }
4699
- if (PM_PLAN_FILE_TOOLS.has(toolName)) {
4700
- if (isPlanFile(input)) {
4701
- return { behavior: "allow", updatedInput: input };
4702
- }
4703
- return {
4704
- behavior: "deny",
4705
- message: "You are in auto plan mode. File writes are restricted to plan files. Call ExitPlanMode when your plan is ready to start building."
4706
- };
4707
- }
4708
4657
  return { behavior: "allow", updatedInput: input };
4709
4658
  }
4710
4659
  async function handleExitPlanMode(host, input) {
@@ -5343,6 +5292,7 @@ var SessionRunner = class _SessionRunner {
5343
5292
  callbacks;
5344
5293
  _state = "connecting";
5345
5294
  stopped = false;
5295
+ hasCompleted = false;
5346
5296
  interrupted = false;
5347
5297
  taskContext = null;
5348
5298
  fullContext = null;
@@ -5354,7 +5304,7 @@ var SessionRunner = class _SessionRunner {
5354
5304
  this.config = config;
5355
5305
  this.callbacks = callbacks;
5356
5306
  this.connection = new AgentConnection(config.connection);
5357
- const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? "discovery" : "building");
5307
+ const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
5358
5308
  this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
5359
5309
  const lifecycleConfig = { ...DEFAULT_LIFECYCLE_CONFIG, ...config.lifecycle };
5360
5310
  this.lifecycle = new Lifecycle(lifecycleConfig, {
@@ -5430,6 +5380,9 @@ var SessionRunner = class _SessionRunner {
5430
5380
  this.queryBridge = this.createQueryBridge();
5431
5381
  this.logInitialization();
5432
5382
  await this.executeInitialMode();
5383
+ if (!this.stopped && this._state !== "error") {
5384
+ this.hasCompleted = true;
5385
+ }
5433
5386
  if (!this.stopped && this.pendingMessages.length === 0) {
5434
5387
  await this.maybeSendPRNudge();
5435
5388
  }
@@ -5459,6 +5412,12 @@ var SessionRunner = class _SessionRunner {
5459
5412
  }
5460
5413
  break;
5461
5414
  }
5415
+ if (this.hasCompleted && msg.userId === "system") {
5416
+ continue;
5417
+ }
5418
+ if (msg.userId !== "system") {
5419
+ this.hasCompleted = false;
5420
+ }
5462
5421
  await this.setState("running");
5463
5422
  this.interrupted = false;
5464
5423
  await this.callbacks.onEvent({
@@ -5634,7 +5593,12 @@ var SessionRunner = class _SessionRunner {
5634
5593
  baseBranch: ctx.baseBranch ?? "",
5635
5594
  githubPRUrl: ctx.githubPRUrl,
5636
5595
  claudeSessionId: ctx.claudeSessionId ?? null,
5637
- isParentTask: !!ctx.parentTaskId
5596
+ isParentTask: !!ctx.parentTaskId,
5597
+ storyPoints: ctx.storyPoints ?? void 0,
5598
+ projectAgents: ctx.projectAgents ?? void 0,
5599
+ projectTags: ctx.projectTags ?? void 0,
5600
+ taskTagIds: ctx.taskTagIds ?? void 0,
5601
+ projectObjectives: ctx.projectObjectives ?? void 0
5638
5602
  };
5639
5603
  }
5640
5604
  createQueryBridge() {
@@ -5833,6 +5797,9 @@ var ProjectConnection = class {
5833
5797
  onRestartStartCommand(callback) {
5834
5798
  this.requireSocket().on("projectRunner:restartStartCommand", callback);
5835
5799
  }
5800
+ onAuditTags(callback) {
5801
+ this.requireSocket().on("projectRunner:auditTags", callback);
5802
+ }
5836
5803
  // ── Outgoing helpers ───────────────────────────────────────────────────
5837
5804
  sendHeartbeat() {
5838
5805
  void this.call("projectRunnerHeartbeat", { projectId: this.config.projectId }).catch(() => {
@@ -6342,21 +6309,24 @@ function buildChatQueryOptions(agentCtx, projectDir, connection) {
6342
6309
  tools: buildProjectTools(connection)
6343
6310
  });
6344
6311
  return {
6345
- model,
6346
- systemPrompt: {
6347
- type: "preset",
6348
- preset: "claude_code",
6349
- append: buildSystemPrompt2(projectDir, agentCtx)
6312
+ options: {
6313
+ model,
6314
+ systemPrompt: {
6315
+ type: "preset",
6316
+ preset: "claude_code",
6317
+ append: buildSystemPrompt2(projectDir, agentCtx)
6318
+ },
6319
+ cwd: projectDir,
6320
+ permissionMode: "bypassPermissions",
6321
+ allowDangerouslySkipPermissions: true,
6322
+ tools: { type: "preset", preset: "claude_code" },
6323
+ mcpServers: { conveyor: mcpServer },
6324
+ maxTurns: settings.maxTurns ?? 30,
6325
+ maxBudgetUsd: settings.maxBudgetUsd ?? 50,
6326
+ effort: settings.effort,
6327
+ thinking: settings.thinking
6350
6328
  },
6351
- cwd: projectDir,
6352
- permissionMode: "bypassPermissions",
6353
- allowDangerouslySkipPermissions: true,
6354
- tools: { type: "preset", preset: "claude_code" },
6355
- mcpServers: { conveyor: mcpServer },
6356
- maxTurns: settings.maxTurns ?? 30,
6357
- maxBudgetUsd: settings.maxBudgetUsd ?? 50,
6358
- effort: settings.effort,
6359
- thinking: settings.thinking
6329
+ harness
6360
6330
  };
6361
6331
  }
6362
6332
  function processContentBlock(block, responseParts, turnToolCalls) {
@@ -6405,10 +6375,9 @@ function emitResultCost(event, connection) {
6405
6375
  }
6406
6376
  async function runChatQuery(message, connection, projectDir, sessionId) {
6407
6377
  const { agentCtx, chatHistory } = await fetchContext(connection, message.chatId);
6408
- const options = buildChatQueryOptions(agentCtx, projectDir, connection);
6378
+ const { options, harness } = buildChatQueryOptions(agentCtx, projectDir, connection);
6409
6379
  const prompt = buildPrompt(message, chatHistory);
6410
6380
  connection.emitStatus("busy");
6411
- const harness = createHarness();
6412
6381
  const events = harness.executeQuery({
6413
6382
  prompt,
6414
6383
  options,
@@ -6433,7 +6402,8 @@ async function runChatQuery(message, connection, projectDir, sessionId) {
6433
6402
  if (responseText) {
6434
6403
  await connection.call("postProjectAgentMessage", {
6435
6404
  projectId: connection.projectId,
6436
- content: responseText
6405
+ content: responseText,
6406
+ chatId: message.chatId
6437
6407
  });
6438
6408
  }
6439
6409
  return resultSessionId;
@@ -6448,7 +6418,8 @@ async function handleProjectChatMessage(message, connection, projectDir, session
6448
6418
  try {
6449
6419
  await connection.call("postProjectAgentMessage", {
6450
6420
  projectId: connection.projectId,
6451
- content: "I encountered an error processing your message. Please try again."
6421
+ content: "I encountered an error processing your message. Please try again.",
6422
+ chatId: message.chatId
6452
6423
  });
6453
6424
  } catch {
6454
6425
  }
@@ -6580,7 +6551,7 @@ var ProjectRunner = class {
6580
6551
  await this.connection.connect();
6581
6552
  const registration = await this.connection.call("registerProjectAgent", {
6582
6553
  projectId: this.connection.projectId,
6583
- capabilities: ["task", "pm", "code-review"]
6554
+ capabilities: ["task", "pm", "code-review", "audit"]
6584
6555
  });
6585
6556
  this.branchSwitchCommand = registration.branchSwitchCommand ?? process.env.CONVEYOR_BRANCH_SWITCH_COMMAND;
6586
6557
  logger6.info("Registered as project agent", { agentName: registration.agentName });
@@ -6665,6 +6636,7 @@ var ProjectRunner = class {
6665
6636
  }
6666
6637
  );
6667
6638
  });
6639
+ this.connection.onAuditTags((request) => void this.handleAuditTags(request));
6668
6640
  this.connection.onSwitchBranch((data, cb) => void this.handleSwitchBranch(data, cb));
6669
6641
  this.connection.onSyncEnvironment((cb) => void this.handleSyncEnvironment(cb));
6670
6642
  this.connection.onRestartStartCommand((cb) => {
@@ -6677,7 +6649,7 @@ var ProjectRunner = class {
6677
6649
  try {
6678
6650
  await this.connection.call("registerProjectAgent", {
6679
6651
  projectId: this.connection.projectId,
6680
- capabilities: ["task", "pm", "code-review"]
6652
+ capabilities: ["task", "pm", "code-review", "audit"]
6681
6653
  });
6682
6654
  this.connection.emitStatus(this.activeAgents.size > 0 ? "busy" : "idle");
6683
6655
  logger6.info("Re-registered after reconnect");
@@ -6686,6 +6658,29 @@ var ProjectRunner = class {
6686
6658
  logger6.error("Failed to re-register after reconnect", { error: msg });
6687
6659
  }
6688
6660
  }
6661
+ // ── Tag audit ──────────────────────────────────────────────────────────
6662
+ async handleAuditTags(request) {
6663
+ this.connection.emitStatus("busy");
6664
+ try {
6665
+ const { handleTagAudit } = await import("./tag-audit-handler-4RRGIHVB.js");
6666
+ await handleTagAudit(request, this.connection, this.projectDir);
6667
+ } catch (error) {
6668
+ const msg = error instanceof Error ? error.message : String(error);
6669
+ logger6.error("Tag audit failed", { error: msg, requestId: request.requestId });
6670
+ try {
6671
+ await this.connection.call("reportTagAuditResult", {
6672
+ projectId: this.connection.projectId,
6673
+ requestId: request.requestId,
6674
+ recommendations: [],
6675
+ summary: `Audit failed: ${msg}`,
6676
+ complete: true
6677
+ });
6678
+ } catch {
6679
+ }
6680
+ } finally {
6681
+ this.connection.emitStatus("idle");
6682
+ }
6683
+ }
6689
6684
  // ── Task management ────────────────────────────────────────────────────
6690
6685
  handleAssignment(assignment) {
6691
6686
  const { taskId, mode } = assignment;
@@ -7013,7 +7008,6 @@ export {
7013
7008
  ModeController,
7014
7009
  DEFAULT_LIFECYCLE_CONFIG,
7015
7010
  Lifecycle,
7016
- createServiceLogger,
7017
7011
  hasUncommittedChanges,
7018
7012
  getCurrentBranch,
7019
7013
  hasUnpushedCommits,
@@ -7033,4 +7027,4 @@ export {
7033
7027
  removeWorktree,
7034
7028
  ProjectRunner
7035
7029
  };
7036
- //# sourceMappingURL=chunk-HAU4E7IA.js.map
7030
+ //# sourceMappingURL=chunk-NZ3IPMLO.js.map