@developerz.ai/aitm 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/agent-config/agent-config-detector.js +0 -3
  2. package/dist/cli/args.js +0 -10
  3. package/dist/cli/cli.js +0 -8
  4. package/dist/cli/commands.js +4 -46
  5. package/dist/compaction/compactor.js +0 -24
  6. package/dist/config/config-loader.js +3 -29
  7. package/dist/config/config-writer.js +0 -5
  8. package/dist/config/schema.d.ts +2 -0
  9. package/dist/config/schema.js +1 -12
  10. package/dist/credentials/credentials.js +0 -14
  11. package/dist/credentials/defaults.js +0 -15
  12. package/dist/fs/atomic-write.js +0 -7
  13. package/dist/github/errors.js +0 -2
  14. package/dist/github/github-client.d.ts +7 -0
  15. package/dist/github/github-client.js +85 -21
  16. package/dist/github/schema.js +0 -2
  17. package/dist/index.js +0 -2
  18. package/dist/logger/logger.js +0 -6
  19. package/dist/loop/run-loop-adapter.js +4 -46
  20. package/dist/loop/take-over-flow.d.ts +14 -0
  21. package/dist/loop/take-over-flow.js +22 -43
  22. package/dist/loop/work-loop.js +0 -36
  23. package/dist/mcp/mcp-client.js +0 -13
  24. package/dist/mcp/schema.js +0 -15
  25. package/dist/openrouter/client.js +0 -4
  26. package/dist/openrouter/model-limits.js +0 -4
  27. package/dist/openrouter/server-tools.js +0 -16
  28. package/dist/orchestrator/orchestrator.js +0 -26
  29. package/dist/orchestrator/subagent-tools.js +0 -22
  30. package/dist/orchestrator/system-prompts.js +0 -3
  31. package/dist/plan/plan-graph.js +0 -9
  32. package/dist/plan/schema.js +0 -8
  33. package/dist/state/pr-context-store.d.ts +20 -0
  34. package/dist/state/pr-context-store.js +60 -0
  35. package/dist/state/schema.js +0 -5
  36. package/dist/state/state-store.js +0 -8
  37. package/dist/subagents/factory.js +0 -9
  38. package/dist/subagents/planner.js +0 -9
  39. package/dist/subagents/reviewer.js +0 -25
  40. package/dist/subagents/worker.d.ts +3 -1
  41. package/dist/subagents/worker.js +10 -28
  42. package/dist/testing/temp-repo.js +0 -4
  43. package/dist/tools/datetime.js +0 -9
  44. package/dist/tools/fetch-html.js +0 -24
  45. package/dist/tools/github-thread-tool.js +0 -15
  46. package/dist/tools/web-fetch.js +0 -32
  47. package/dist/workspace/worktree-pool.js +0 -21
  48. package/package.json +2 -2
  49. package/dist/agent-config/agent-config-detector.js.map +0 -1
  50. package/dist/cli/args.js.map +0 -1
  51. package/dist/cli/cli.js.map +0 -1
  52. package/dist/cli/commands.js.map +0 -1
  53. package/dist/compaction/compactor.js.map +0 -1
  54. package/dist/config/config-loader.js.map +0 -1
  55. package/dist/config/config-writer.js.map +0 -1
  56. package/dist/config/schema.js.map +0 -1
  57. package/dist/credentials/credentials.js.map +0 -1
  58. package/dist/credentials/defaults.js.map +0 -1
  59. package/dist/fs/atomic-write.js.map +0 -1
  60. package/dist/github/errors.js.map +0 -1
  61. package/dist/github/github-client.js.map +0 -1
  62. package/dist/github/schema.js.map +0 -1
  63. package/dist/index.js.map +0 -1
  64. package/dist/logger/logger.js.map +0 -1
  65. package/dist/loop/run-loop-adapter.js.map +0 -1
  66. package/dist/loop/take-over-flow.js.map +0 -1
  67. package/dist/loop/work-loop.js.map +0 -1
  68. package/dist/mcp/mcp-client.js.map +0 -1
  69. package/dist/mcp/schema.js.map +0 -1
  70. package/dist/openrouter/client.js.map +0 -1
  71. package/dist/openrouter/model-limits.js.map +0 -1
  72. package/dist/openrouter/server-tools.js.map +0 -1
  73. package/dist/orchestrator/orchestrator.js.map +0 -1
  74. package/dist/orchestrator/subagent-tools.js.map +0 -1
  75. package/dist/orchestrator/system-prompts.js.map +0 -1
  76. package/dist/plan/plan-graph.js.map +0 -1
  77. package/dist/plan/schema.js.map +0 -1
  78. package/dist/state/schema.js.map +0 -1
  79. package/dist/state/state-store.js.map +0 -1
  80. package/dist/subagents/factory.js.map +0 -1
  81. package/dist/subagents/planner.js.map +0 -1
  82. package/dist/subagents/reviewer.js.map +0 -1
  83. package/dist/subagents/worker.js.map +0 -1
  84. package/dist/testing/temp-repo.js.map +0 -1
  85. package/dist/tools/datetime.js.map +0 -1
  86. package/dist/tools/fetch-html.js.map +0 -1
  87. package/dist/tools/github-thread-tool.js.map +0 -1
  88. package/dist/tools/web-fetch.js.map +0 -1
  89. package/dist/workspace/worktree-pool.js.map +0 -1
@@ -1,13 +1,3 @@
1
- // Connects to every MCP server declared in `mcpServers` (config) and exposes the
2
- // union of their tools to subagents. The Vercel AI SDK's @ai-sdk/mcp client gives
3
- // us tool-conversion; we wire transport per entry and merge the tool maps.
4
- //
5
- // docs/vendor/ai-sdk/chunk-15.md §"Initializing an MCP Client"
6
- // docs/mcp.md
7
- //
8
- // Lifecycle: connectAll() at run start, toolsForRole() during agent build, close() on exit
9
- // (success / blocked / SIGINT). Failures on individual servers are logged + skipped — a
10
- // broken MCP server should not block the whole run.
11
1
  import { experimental_createMCPClient } from '@ai-sdk/mcp';
12
2
  import { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio';
13
3
  export class McpClientManager {
@@ -20,8 +10,6 @@ export class McpClientManager {
20
10
  }
21
11
  async connectAll() {
22
12
  for (const [name, server] of Object.entries(this.init.servers)) {
23
- // Track the client outside the try so a failure during tools() can still
24
- // close the spawned process / socket instead of leaking it.
25
13
  let client;
26
14
  try {
27
15
  const transport = transportKind(server);
@@ -120,4 +108,3 @@ function clientNameFor(name) {
120
108
  function errorMessage(err) {
121
109
  return err instanceof Error ? err.message : String(err);
122
110
  }
123
- //# sourceMappingURL=mcp-client.js.map
@@ -1,23 +1,9 @@
1
- // MCP *client* config — aitm consumes external MCP servers as additional tool surfaces
2
- // for subagents. aitm is NOT exposed as an MCP server (banned by CLAUDE.md §"Out of scope").
3
- //
4
- // Shape mirrors Claude Code's `mcpServers` config — three transports, same keys.
5
- // Refs:
6
- // https://code.claude.com/docs/en/mcp (Claude Code reference)
7
- // https://modelcontextprotocol.io/ (spec)
8
- // docs/vendor/ai-sdk/chunk-15.md §"Model Context Protocol" (Vercel AI SDK client)
9
- //
10
- // Transports:
11
- // stdio — local binary launched as a child process. Default when `type` omitted.
12
- // sse — HTTP server-sent events. URL + optional headers.
13
- // http — Streamable HTTP transport. URL + optional headers. Preferred for production.
14
1
  import { z } from 'zod';
15
2
  export const McpStdioServerSchema = z.object({
16
3
  type: z.literal('stdio').optional(),
17
4
  command: z.string(),
18
5
  args: z.array(z.string()).optional(),
19
6
  env: z.record(z.string(), z.string()).optional(),
20
- // Working directory for the spawned process. Defaults to repo root.
21
7
  cwd: z.string().optional(),
22
8
  });
23
9
  export const McpSseServerSchema = z.object({
@@ -36,4 +22,3 @@ export const McpServerSchema = z.union([
36
22
  McpHttpServerSchema,
37
23
  ]);
38
24
  export const McpServersSchema = z.record(z.string(), McpServerSchema);
39
- //# sourceMappingURL=schema.js.map
@@ -1,6 +1,3 @@
1
- // Thin OpenRouter API client. Only the endpoints we actually need:
2
- // GET /api/v1/models — model catalog including context length / pricing.
3
- // docs/auth.md §"LLM provider", docs/runtime.md (web fetch, not Bun.fetch).
4
1
  import { z } from 'zod';
5
2
  export const OpenRouterModelSchema = z
6
3
  .object({
@@ -37,4 +34,3 @@ export class OpenRouterClient {
37
34
  return OpenRouterModelsResponseSchema.parse(json).data;
38
35
  }
39
36
  }
40
- //# sourceMappingURL=client.js.map
@@ -1,6 +1,3 @@
1
- // Exposes per-model limits (context window, pricing hints) used by the Compactor.
2
- // Cached per-run after first fetch — model catalog changes slowly.
3
- // docs/auth.md, src/compaction/compactor.ts
4
1
  export class ModelNotFound extends Error {
5
2
  modelId;
6
3
  name = 'ModelNotFound';
@@ -36,4 +33,3 @@ export class ModelLimitsRegistry {
36
33
  this.cache = next;
37
34
  }
38
35
  }
39
- //# sourceMappingURL=model-limits.js.map
@@ -1,25 +1,9 @@
1
- // OpenRouter server tools — model-decides tools executed on OpenRouter's side.
2
- // These are NOT Vercel AI SDK function tools; they ride in `providerOptions.openrouter`
3
- // (or equivalent extraBody) so OpenRouter sees them in the request `tools[]` array verbatim.
4
- //
5
- // Refs:
6
- // https://openrouter.ai/docs/guides/features/server-tools/web-search
7
- // https://openrouter.ai/docs/guides/features/server-tools/web-fetch
8
- //
9
- // Web search → citations land as annotations[].url_citation on the assistant message,
10
- // plus usage.server_tool_use.web_search_requests for cost accounting. No round-trip.
11
- // Web fetch → standard tool_call round-trip with { url, title, content, status, retrieved_at }.
12
1
  export function webSearchTool(options = {}) {
13
2
  return { type: 'openrouter:web_search', parameters: options };
14
3
  }
15
- // Renamed from webFetchTool — the canonical webFetchTool is now the local variant in
16
- // src/tools/web-fetch.ts. This one is the explicit "delegate to OpenRouter" opt-in.
17
4
  export function webFetchServerTool(options = {}) {
18
5
  return { type: 'openrouter:web_fetch', parameters: options };
19
6
  }
20
- // Build the providerOptions.openrouter fragment to be merged into an AI SDK call.
21
- // Usage at the model handle layer (src/credentials/credentials.ts) — see Credentials.modelFor.
22
7
  export function providerOptionsWithServerTools(tools) {
23
8
  return { openrouter: { tools: [...tools] } };
24
9
  }
25
- //# sourceMappingURL=server-tools.js.map
@@ -1,17 +1,3 @@
1
- // docs/architecture.md §Flow, docs/subagents.md §Composition
2
- // Top-level agent. Owns:
3
- // - prompt composition (style payload + role prefix + rolling context)
4
- // - routing between Planner / Worker / Reviewer (each exposed as a tool)
5
- // - **PR creation** — title, body, commit message: docs say Worker opens the PR,
6
- // but the Worker can be inconsistent on global-context narration. Orchestrator
7
- // re-composes the commit message and opens the PR via GitHubClient, taking the
8
- // Worker's draft as input. This is the reliability win: one place that knows
9
- // the whole plan writes the PR-level prose.
10
- //
11
- // SDK references:
12
- // docs/vendor/ai-sdk/chunk-04.md §"ToolLoopAgent"
13
- // docs/vendor/ai-sdk/chunk-09.md §"Subagents" §"Controlling What the Model Sees"
14
- // docs/vendor/ai-sdk/chunk-09.md §"Loop Control" — stopWhen: [stepCountIs(N), hasToolCall('done')]
15
1
  import { generateText, hasToolCall, Output, stepCountIs, ToolLoopAgent } from 'ai';
16
2
  import { ExecaError, execa } from 'execa';
17
3
  import { z } from 'zod';
@@ -36,8 +22,6 @@ export const defaultRunCmd = async (file, args, options) => {
36
22
  throw err;
37
23
  }
38
24
  };
39
- // Inlined per CLAUDE.md "no premature abstraction". Full system prompt is
40
- // `agentConfig.contents + ORCHESTRATOR_ROLE_PREFIX + rollingContext`.
41
25
  export const ORCHESTRATOR_ROLE_PREFIX = [
42
26
  '',
43
27
  '## Role: Orchestrator',
@@ -56,16 +40,11 @@ export const ORCHESTRATOR_ROLE_PREFIX = [
56
40
  ' - Be specific and terse. No marketing prose.',
57
41
  ' - Conventional commit subjects, ≤72 chars.',
58
42
  ].join('\n');
59
- // Structured-output schema for PR composition. Title cap reinforces conventional-commit
60
- // brevity; body is free-form markdown.
61
43
  const PrCompositionSchema = z.object({
62
44
  title: z.string().min(1).max(72),
63
45
  body: z.string().min(1),
64
46
  });
65
- // Fallback session cap when caller passes null / 0 / negative `maxSessions`.
66
47
  export const DEFAULT_MAX_STEPS = 50;
67
- // Resolve the agent step cap from caller-provided `maxSessions`. Falls back to the
68
- // default when the value is null, zero, or negative. Exported for unit testing.
69
48
  export function resolveMaxSteps(maxSessions) {
70
49
  return typeof maxSessions === 'number' && maxSessions > 0 ? maxSessions : DEFAULT_MAX_STEPS;
71
50
  }
@@ -111,8 +90,6 @@ export class Orchestrator {
111
90
  this.init.rollingContext,
112
91
  ].join('\n');
113
92
  }
114
- // Re-write the Worker's draft commit message via the orchestrator model, then
115
- // `git commit --amend` on the active worktree. Returns the new HEAD SHA.
116
93
  async finalizeCommit(group, delivery, worktreePath) {
117
94
  const refined = await this.refineCommitMessage(group, delivery);
118
95
  const runCmd = this.init.runCmd ?? defaultRunCmd;
@@ -126,8 +103,6 @@ export class Orchestrator {
126
103
  }
127
104
  return sha.stdout.trim();
128
105
  }
129
- // Compose PR title + body via the orchestrator model, then open the PR through the github
130
- // client. Falls back to `aitm/<group.id>` when `group.branch` is unset.
131
106
  async openPr(group, delivery, baseBranch) {
132
107
  const { title, body } = await this.composePr(group, delivery);
133
108
  const head = group.branch ?? `aitm/${group.id}`;
@@ -177,4 +152,3 @@ export class Orchestrator {
177
152
  ].join('\n');
178
153
  }
179
154
  }
180
- //# sourceMappingURL=orchestrator.js.map
@@ -1,16 +1,3 @@
1
- // Wrap each subagent as a tool consumable by the Orchestrator agent.
2
- // Pattern verbatim from docs/vendor/ai-sdk/chunk-09.md §"Subagents" and §"Controlling What the
3
- // Model Sees" — `toModelOutput` keeps the Orchestrator context lean by collapsing the full
4
- // subagent result to a one-line `<role> [<status>]: <summary>`.
5
- //
6
- // Note: AI SDK 6 names the field `toModelOutput` (the SDK-5 name was
7
- // `experimental_toToolResultContent`; the task brief uses the older spelling).
8
- //
9
- // Each wrapper:
10
- // - inputSchema — Zod schema; the Orchestrator's model fills it in per call
11
- // - execute — builds the subagent via its factory using `credentials.modelFor(role)` and
12
- // runs the matching runner; returns the full structured result
13
- // - toModelOutput — collapses that result to a single status line for the Orchestrator
14
1
  import { tool } from 'ai';
15
2
  import { z } from 'zod';
16
3
  import { createPlannerAgent, PLANNER_SYSTEM_PREFIX, runPlanner, } from "../subagents/planner.js";
@@ -21,8 +8,6 @@ const plannerInputSchema = z.object({
21
8
  criteria: z.string().optional().describe('Optional acceptance criteria'),
22
9
  maxPrs: z.number().int().positive().describe('Cap on PR-group count'),
23
10
  });
24
- // Worker + Reviewer have all state bound in deps — the Orchestrator's model invokes them with
25
- // no arguments, signalling "process the currently-active group / review threads".
26
11
  const emptyInputSchema = z.object({});
27
12
  export function makePlannerTool(deps) {
28
13
  return tool({
@@ -85,13 +70,7 @@ export function makeReviewerTool(deps) {
85
70
  toModelOutput: ({ output }) => ({ type: 'text', value: summarizeReviewerResult(output) }),
86
71
  });
87
72
  }
88
- // Cap per-line summary length so a verbose subagent reply (long IDs, multiline draft
89
- // commit messages, error payloads) can't bloat the orchestrator's context. 220 chars
90
- // is enough for a status line + a few tens of chars of free text.
91
73
  const MAX_SUMMARY_CHARS = 220;
92
- // Show only the first N planner group IDs, then `+M more` — the count alone is what
93
- // matters to the orchestrator; the orchestrator can re-read the plan if it needs the
94
- // full ID list.
95
74
  const MAX_PREVIEW_IDS = 8;
96
75
  function compactOneLine(text, max = MAX_SUMMARY_CHARS) {
97
76
  return text.replace(/\s+/g, ' ').trim().slice(0, max);
@@ -130,4 +109,3 @@ function summarizeReviewerResult(r) {
130
109
  return compactOneLine(`reviewer [blocked]: ${r.reason}`);
131
110
  return compactOneLine(`reviewer [error]: ${r.error}`);
132
111
  }
133
- //# sourceMappingURL=subagent-tools.js.map
@@ -1,5 +1,3 @@
1
- // Role system-prompt prefixes for each agent. Inlined per CLAUDE.md "no premature abstraction".
2
- // Appended after `agentConfig.contents` (house style) to form the full instructions string.
3
1
  export const ORCHESTRATOR_PREFIX = [
4
2
  '',
5
3
  '## Role: Orchestrator',
@@ -75,4 +73,3 @@ export const REVIEWER_PREFIX = [
75
73
  ' - Resolve the thread for "fixed" and "wontfix"; leave it open for "replied".',
76
74
  ' - Return JSON that matches the ThreadResolutionOutput schema exactly.',
77
75
  ].join('\n');
78
- //# sourceMappingURL=system-prompts.js.map
@@ -1,6 +1,3 @@
1
- // Dependency DAG over PR groups. Drives concurrent execution in src/loop/work-loop.ts.
2
- // Why a graph and not a list — docs/task-groups.md (extended): large goals split into
3
- // independent PRs that can run in parallel. A linear list serializes work needlessly.
4
1
  export class PlanGraph {
5
2
  groups;
6
3
  index;
@@ -9,12 +6,10 @@ export class PlanGraph {
9
6
  PlanGraph.validate(groups);
10
7
  this.index = new Map(groups.map((g) => [g.id, g]));
11
8
  }
12
- // Groups currently ready to run: status === 'pending' AND all deps merged.
13
9
  ready() {
14
10
  return this.groups.filter((g) => g.status === 'pending' &&
15
11
  g.dependsOn.every((dep) => this.index.get(dep)?.status === 'merged'));
16
12
  }
17
- // Groups blocked on at least one unmerged dep.
18
13
  blocked() {
19
14
  return this.groups.filter((g) => g.status === 'pending' &&
20
15
  g.dependsOn.some((dep) => this.index.get(dep)?.status !== 'merged'));
@@ -22,12 +17,9 @@ export class PlanGraph {
22
17
  byId(id) {
23
18
  return this.index.get(id);
24
19
  }
25
- // True when every group is in a terminal state (merged or blocked).
26
20
  isComplete() {
27
21
  return this.groups.every((g) => g.status === 'merged' || g.status === 'blocked');
28
22
  }
29
- // Static: detect cycles + dangling deps at plan-acceptance time.
30
- // DFS coloring — white=unvisited, gray=on stack, black=fully explored.
31
23
  static validate(groups) {
32
24
  const ids = new Set();
33
25
  for (const g of groups) {
@@ -66,4 +58,3 @@ export class PlanGraph {
66
58
  visit(g.id, []);
67
59
  }
68
60
  }
69
- //# sourceMappingURL=plan-graph.js.map
@@ -1,19 +1,12 @@
1
- // Plan-time output of Planner subagent — see docs/subagents.md §Roster (Planner row).
2
- // PrGroup is persisted via src/state/schema.ts; the plan schema below is what
3
- // Planner returns to the Orchestrator before that persistence step.
4
1
  import { z } from 'zod';
5
2
  export const PlannedTaskSchema = z.object({
6
3
  description: z.string(),
7
- // Optional file hint helps Worker plan its parallel file-edit fanout.
8
- // See docs/vendor/ai-sdk/chunk-09.md §"Orchestrator-Worker" — Worker uses this
9
- // to emit a file manifest, then Promise.all over per-file editor subagents.
10
4
  filesHint: z.array(z.string()).optional(),
11
5
  });
12
6
  export const PlannedGroupSchema = z.object({
13
7
  id: z.string(),
14
8
  title: z.string(),
15
9
  tasks: z.array(PlannedTaskSchema),
16
- // Group ids that must merge before this group runs. Empty = root of DAG.
17
10
  dependsOn: z.array(z.string()).default([]),
18
11
  });
19
12
  export const PlanSchema = z.object({
@@ -21,4 +14,3 @@ export const PlanSchema = z.object({
21
14
  criteria: z.string().optional(),
22
15
  groups: z.array(PlannedGroupSchema),
23
16
  });
24
- //# sourceMappingURL=schema.js.map
@@ -0,0 +1,20 @@
1
+ import type { ReviewThread } from '../github/schema.ts';
2
+ export type CiFailure = {
3
+ check: string;
4
+ logs: string;
5
+ };
6
+ export type PrContextSummary = {
7
+ prDir: string;
8
+ ciDir: string | null;
9
+ commentsDir: string | null;
10
+ ciCount: number;
11
+ commentCount: number;
12
+ };
13
+ export declare class PrContextStore {
14
+ private readonly stateDir;
15
+ constructor(stateDir: string);
16
+ prDir(pr: number): string;
17
+ clear(pr: number): Promise<void>;
18
+ saveCiFailures(pr: number, failures: readonly CiFailure[]): Promise<string | null>;
19
+ saveComments(pr: number, threads: readonly ReviewThread[]): Promise<string | null>;
20
+ }
@@ -0,0 +1,60 @@
1
+ import { mkdir, rm, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ export class PrContextStore {
4
+ stateDir;
5
+ constructor(stateDir) {
6
+ this.stateDir = stateDir;
7
+ }
8
+ prDir(pr) {
9
+ return join(this.stateDir, 'debugging', 'pr', String(pr));
10
+ }
11
+ async clear(pr) {
12
+ await rm(this.prDir(pr), { recursive: true, force: true });
13
+ }
14
+ async saveCiFailures(pr, failures) {
15
+ if (failures.length === 0)
16
+ return null;
17
+ const ciDir = join(this.prDir(pr), 'ci');
18
+ await mkdir(ciDir, { recursive: true });
19
+ const used = new Map();
20
+ for (const { check, logs } of failures) {
21
+ const base = sanitize(check);
22
+ const n = used.get(base) ?? 0;
23
+ used.set(base, n + 1);
24
+ const file = n === 0 ? `failed_${base}.txt` : `failed_${base}_${n}.txt`;
25
+ const header = `CI check failed: ${check}\nPR: #${pr}\n${'='.repeat(60)}\n\n`;
26
+ await writeFile(join(ciDir, file), header + logs);
27
+ }
28
+ await writeFile(join(ciDir, 'summary.txt'), [
29
+ `PR #${pr} — ${failures.length} failed check(s):`,
30
+ ...failures.map((f) => ` - ${f.check}`),
31
+ ].join('\n'));
32
+ return ciDir;
33
+ }
34
+ async saveComments(pr, threads) {
35
+ if (threads.length === 0)
36
+ return null;
37
+ const commentsDir = join(this.prDir(pr), 'comments');
38
+ await mkdir(commentsDir, { recursive: true });
39
+ let i = 0;
40
+ for (const thread of threads) {
41
+ i += 1;
42
+ const path = thread.path ?? 'general';
43
+ const body = thread.comments
44
+ .map((c) => `@${c.author}:\n${c.body}`)
45
+ .join(`\n${'-'.repeat(40)}\n`);
46
+ const header = `Review thread on ${path} (thread ${thread.id})\nPR: #${pr}\n${'='.repeat(60)}\n\n`;
47
+ await writeFile(join(commentsDir, `${String(i).padStart(3, '0')}_${sanitize(path)}.txt`), header + body);
48
+ }
49
+ const paths = [...new Set(threads.map((t) => t.path ?? 'general'))].sort();
50
+ await writeFile(join(commentsDir, 'summary.txt'), [
51
+ `PR #${pr} — ${threads.length} unresolved review thread(s).`,
52
+ 'Files with comments:',
53
+ ...paths.map((p) => ` - ${p}`),
54
+ ].join('\n'));
55
+ return commentsDir;
56
+ }
57
+ }
58
+ function sanitize(s) {
59
+ return s.replace(/[^a-zA-Z0-9._-]+/g, '_').replace(/^_+|_+$/g, '') || 'unnamed';
60
+ }
@@ -1,5 +1,3 @@
1
- // docs/state.md §"state.json schema" and §"PrGroup sub-schema"
2
- // Source of truth for run-state shape. Extended with PrGroup.dependsOn to support DAG planning.
3
1
  import { z } from 'zod';
4
2
  export const PrGroupStatusSchema = z.enum([
5
3
  'pending',
@@ -12,8 +10,6 @@ export const PrGroupSchema = z.object({
12
10
  id: z.string(),
13
11
  title: z.string(),
14
12
  tasks: z.array(z.string()),
15
- // Group ids that must be merged before this group is runnable.
16
- // Empty array means the group is in the initial ready set. See src/plan/plan-graph.ts.
17
13
  dependsOn: z.array(z.string()).default([]),
18
14
  branch: z.string().nullable(),
19
15
  pr: z.number().int().positive().nullable(),
@@ -50,4 +46,3 @@ export const RunStateSchema = z.object({
50
46
  concurrency: z.number().int().positive(),
51
47
  }),
52
48
  });
53
- //# sourceMappingURL=schema.js.map
@@ -1,5 +1,3 @@
1
- // docs/state.md
2
- // Only module that reads or writes .ai-task-master/. Atomic writes via temp file + fsync + rename.
3
1
  import { appendFile, mkdir, readdir, readFile, rm } from 'node:fs/promises';
4
2
  import { join } from 'node:path';
5
3
  import { ZodError } from 'zod';
@@ -14,9 +12,6 @@ const CONTEXT_FILE = 'context.md';
14
12
  const LOGS_DIR = 'logs';
15
13
  export class StateStore {
16
14
  stateDir;
17
- // Chained promise serializes concurrent update() calls so they observe linear semantics.
18
- // Each caller awaits the prior in-flight update before its read → mutate → write runs,
19
- // preventing lost updates when callers race via Promise.all.
20
15
  updateChain = Promise.resolve();
21
16
  constructor(stateDir) {
22
17
  this.stateDir = stateDir;
@@ -49,8 +44,6 @@ export class StateStore {
49
44
  await atomicWrite(this.path(STATE_FILE), `${JSON.stringify(validated, null, 2)}\n`);
50
45
  return validated;
51
46
  });
52
- // Swallow rejection on the chain so a failed update doesn't poison subsequent callers.
53
- // The original `next` promise still rejects for the caller that owns this update.
54
47
  this.updateChain = next.catch(() => undefined);
55
48
  return next;
56
49
  }
@@ -126,4 +119,3 @@ function isNotFound(err) {
126
119
  function formatZodError(err) {
127
120
  return err.issues.map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`).join('; ');
128
121
  }
129
- //# sourceMappingURL=state-store.js.map
@@ -1,10 +1 @@
1
- // docs/subagents.md §"SRP + tested" — every subagent is a pure factory:
2
- // (model, tools, systemPrompt) -> Agent
3
- // SDK reference: docs/vendor/ai-sdk/chunk-04.md §"ToolLoopAgent" (note: CLAUDE.md
4
- // still says experimental_Agent — that is the legacy AI SDK 5 name; v6 ships ToolLoopAgent).
5
- //
6
- // The ToolLoopAgent wrapper (`createSubagent`) and the system-prompt composer
7
- // (`composeSystemPrompt`) now live in @developerz.ai/ai-claude-compat; the concrete factories
8
- // (planner.ts/worker.ts/reviewer.ts) call createSubagent with their own tools + output type.
9
1
  export {};
10
- //# sourceMappingURL=factory.js.map
@@ -1,12 +1,6 @@
1
- // docs/subagents.md (Planner row), docs/task-groups.md, docs/agent-config-detection.md
2
- // Goal + repo survey → ordered PR groups (DAG) with Zod-validated output.
3
- // SDK reference: docs/vendor/ai-sdk/chunk-09.md §"Subagents" + chunk-05.md §"Generating Structured Data".
4
1
  import { createSubagent } from '@developerz.ai/ai-claude-compat';
5
2
  import { Output } from 'ai';
6
3
  import { PlanSchema } from "../plan/schema.js";
7
- // Inlined per CLAUDE.md "no premature abstraction". The Orchestrator builds the
8
- // caller-side system prompt as `styleContents + PLANNER_SYSTEM_PREFIX` so the
9
- // agent inherits the repo's house style alongside its role.
10
4
  export const PLANNER_SYSTEM_PREFIX = [
11
5
  '',
12
6
  'You are the Planner subagent. You receive a goal and an optional acceptance criteria.',
@@ -60,8 +54,6 @@ function buildUserPrompt(input) {
60
54
  lines.push('Survey the repo with the read-only tools, then emit the Plan JSON.');
61
55
  return lines.join('\n');
62
56
  }
63
- // Truncate to maxPrs groups; fold any overflow into a single remainder task on
64
- // the last kept group so no work is silently dropped.
65
57
  function capGroups(plan, maxPrs) {
66
58
  if (plan.groups.length <= maxPrs)
67
59
  return plan;
@@ -80,4 +72,3 @@ function capGroups(plan, maxPrs) {
80
72
  function summarizeGroup(g) {
81
73
  return `${g.id} (${g.tasks.length} tasks)`;
82
74
  }
83
- //# sourceMappingURL=planner.js.map
@@ -1,26 +1,6 @@
1
- // docs/subagents.md (Reviewer row), docs/commands/merge-pr.md
2
- // Input: unresolved review threads. Output: per-thread resolution (reply / push fix / mark stale).
3
- // Pushes go through Worker tools (FS write, bash); thread ops via a `github` tool that wraps a
4
- // subset of GitHubClient (replyToThread / resolveThread).
5
- //
6
- // Strategy:
7
- // - One agent.generate call per thread, scoped to that thread's conversation.
8
- // - Agent emits a structured ThreadResolutionOutput JSON describing the chosen outcome.
9
- // - For "fixed", the runner — not the agent — performs the git commit so commit shas are
10
- // deterministic and observable (worker pattern).
11
- //
12
- // SDK references:
13
- // chunk-04.md §"ToolLoopAgent"
14
- // chunk-05.md §"Generating Structured Data"
15
- // chunk-09.md §"Subagents"
16
1
  import { createSubagent } from '@developerz.ai/ai-claude-compat';
17
2
  import { Output } from 'ai';
18
3
  import { z } from 'zod';
19
- // Per-thread structured output emitted by the model. A FLAT object (not a discriminatedUnion):
20
- // a discriminated union compiles to JSON-Schema `oneOf`, which several OpenRouter-routed
21
- // providers reject for structured output (`output_config.format.schema: Schema type 'oneOf' is
22
- // not supported` — seen on Anthropic, which is also aitm's default tier). `kind` selects the
23
- // outcome; `commitMessage` is expected for "fixed" and `reason` for "wontfix".
24
4
  export const ThreadResolutionOutputSchema = z.object({
25
5
  kind: z.enum(['fixed', 'replied', 'wontfix']),
26
6
  commitMessage: z.string().optional(),
@@ -48,8 +28,6 @@ export const REVIEWER_SYSTEM_PREFIX = [
48
28
  '- Resolve the thread for "fixed" and "wontfix" outcomes; "replied" leaves it open.',
49
29
  '- Return JSON that matches the ThreadResolutionOutput schema exactly.',
50
30
  ].join('\n');
51
- // Module-private link from agent to its init so runReviewer can drive bash commits with the
52
- // same tools without exposing them on the public agent surface (worker uses the same pattern).
53
31
  const reviewerInitRegistry = new WeakMap();
54
32
  export function createReviewerAgent(init) {
55
33
  const agent = createSubagent({
@@ -92,7 +70,6 @@ async function resolveOneThread(agent, init, input, thread) {
92
70
  const out = result.experimental_output;
93
71
  switch (out.kind) {
94
72
  case 'fixed': {
95
- // commitMessage is optional on the flat schema; fall back to a generic subject.
96
73
  const message = out.commitMessage?.trim() || `fix: address review thread ${thread.id}`;
97
74
  const commitSha = await commitFix(init.tools.bash, input.worktreePath, message);
98
75
  return { threadId: thread.id, kind: 'fixed', commitSha };
@@ -152,8 +129,6 @@ async function execBash(exec, command) {
152
129
  function isAsyncIterable(v) {
153
130
  return v !== null && typeof v === 'object' && Symbol.asyncIterator in v;
154
131
  }
155
- // POSIX shell-quote: wrap in single quotes, escape embedded single quotes.
156
132
  function shQuote(s) {
157
133
  return `'${s.replace(/'/g, "'\\''")}'`;
158
134
  }
159
- //# sourceMappingURL=reviewer.js.map
@@ -1,4 +1,4 @@
1
- import type { BashInput, BashOutput, EditFileInput, EditFileOutput, GlobInput, GlobOutput, GrepInput, GrepOutput, MultiEditInput, MultiEditOutput, ReadFileInput, ReadFileOutput, WriteFileInput, WriteFileOutput } from '@developerz.ai/ai-claude-compat';
1
+ import type { BashInput, BashOutput, EditFileInput, EditFileOutput, GlobInput, GlobOutput, GrepInput, GrepOutput, MultiBashInput, MultiBashOutput, MultiEditInput, MultiEditOutput, ReadFileInput, ReadFileOutput, WriteFileInput, WriteFileOutput } from '@developerz.ai/ai-claude-compat';
2
2
  import { type DeepPartial, Output, type Tool, type ToolLoopAgent } from 'ai';
3
3
  import { z } from 'zod';
4
4
  import type { PrGroup } from '../state/schema.ts';
@@ -11,6 +11,7 @@ export type WorkerTools = {
11
11
  grep: Tool<GrepInput, GrepOutput>;
12
12
  glob: Tool<GlobInput, GlobOutput>;
13
13
  bash: Tool<BashInput, BashOutput>;
14
+ multiBash: Tool<MultiBashInput, MultiBashOutput>;
14
15
  };
15
16
  export declare const FileManifestEntrySchema: z.ZodObject<{
16
17
  path: z.ZodString;
@@ -43,6 +44,7 @@ export type WorkerInput = {
43
44
  baseBranch: string;
44
45
  styleContents: string;
45
46
  rollingContext: string;
47
+ formatCommand?: string;
46
48
  };
47
49
  export type FileChange = {
48
50
  path: string;
@@ -1,27 +1,6 @@
1
- // docs/subagents.md (Worker row), docs/task-groups.md, docs/commands/start.md
2
- // One PR group: produce file changes + commits on a dedicated branch. Does NOT open the PR
3
- // and does NOT finalize the commit message — those belong to the Orchestrator (more reliable
4
- // at composing global-context narration: PR title, body, squash commit message).
5
- //
6
- // Strategy for *really big PRs* (the explicit design goal) — two layers of parallelism:
7
- //
8
- // Layer A (outer, across files): plan a file manifest via Output.object() that lists every
9
- // file to create/modify/delete (docs/vendor/ai-sdk/chunk-09.md §"Orchestrator-Worker"),
10
- // then Promise.all over per-file editor sub-subagents.
11
- //
12
- // Layer B (inner, within one step): each editor enables `parallelToolCalls: true` (default
13
- // in the SDK — chunk-02.md §"parallelToolCalls") so the model can issue multiple readFile /
14
- // writeFile tool calls in a single step and the runtime executes them concurrently.
15
- //
16
- // SDK references:
17
- // chunk-09.md §"Orchestrator-Worker" (manifest + per-file workers)
18
- // chunk-09.md §"Subagents" §"Controlling What the Model Sees" (toModelOutput one-line summary)
19
- // chunk-04.md §"ToolLoopAgent" (agent class)
20
- // chunk-02.md §"Tool Calling" (parallelToolCalls)
21
1
  import { composeSystemPrompt, createSubagent } from '@developerz.ai/ai-claude-compat';
22
2
  import { generateText, Output, stepCountIs, } from 'ai';
23
3
  import { z } from 'zod';
24
- // File manifest — Phase 1 structured output. Each entry drives one editor in Phase 2.
25
4
  export const FileManifestEntrySchema = z.object({
26
5
  path: z.string().min(1),
27
6
  kind: z.enum(['create', 'modify', 'delete']),
@@ -49,8 +28,6 @@ export const WORKER_SYSTEM_PREFIX = [
49
28
  '- draftCommitMessage is a hint to the Orchestrator; keep the subject under 72 chars.',
50
29
  '- Return the FileManifest JSON exactly matching the schema.',
51
30
  ].join('\n');
52
- // Editor subagent prompt — applied to every per-file fanout. Kept here so the Worker
53
- // owns the contract its editors run under.
54
31
  const EDITOR_SYSTEM_PREFIX = [
55
32
  '',
56
33
  'You are a per-file editor subagent. You receive one file path and a purpose.',
@@ -59,13 +36,14 @@ const EDITOR_SYSTEM_PREFIX = [
59
36
  ' replacement) or `multiEdit` (several replacements applied atomically). Use `writeFile` only',
60
37
  ' for a full rewrite.',
61
38
  '- To DELETE a file, use `bash` with `rm -f <path>`.',
39
+ '- For a dependent sequence of shell steps (e.g. `mkdir … && generate && test`), prefer',
40
+ ' `multiBash` with an ordered `commands` array — it stops at the first failure, so you',
41
+ ' see exactly which step broke without chaining `&&` by hand.',
62
42
  'You may issue multiple tool calls in parallel.',
63
43
  '',
64
44
  "IMPORTANT: your final assistant message is returned to the outer Worker as this file's",
65
45
  'summary. Keep it to one line, present-tense, and specific.',
66
46
  ].join('\n');
67
- // Module-private link from a Worker agent back to its init, so runWorker can spawn editor
68
- // sub-agents with the same model + tool handles without exposing them on the public surface.
69
47
  const workerInitRegistry = new WeakMap();
70
48
  export function createWorkerAgent(init) {
71
49
  const agent = createSubagent({
@@ -90,7 +68,10 @@ export async function runWorker(agent, input) {
90
68
  try {
91
69
  const manifest = await planManifest(agent, input);
92
70
  if (manifest.files.length === 0) {
93
- return { kind: 'blocked', reason: 'worker produced an empty file manifest' };
71
+ return {
72
+ kind: 'blocked',
73
+ reason: 'The Worker returned an empty file manifest — the configured coding model produced no files to change for this PR group. This usually means the model is not capable enough to plan the work; try a more capable coding model (set `models.coding` in .ai-task-master/config.json or pass a stronger --model).',
74
+ };
94
75
  }
95
76
  const changes = await Promise.all(manifest.files.map((file) => runEditor(init, file, input)));
96
77
  await commitOnBranch(init.tools.bash, input, branch, manifest.draftCommitMessage);
@@ -158,6 +139,9 @@ async function commitOnBranch(bash, input, branch, message) {
158
139
  }
159
140
  const wt = shQuote(input.worktreePath);
160
141
  await runBash(exec, `git -C ${wt} checkout -B ${shQuote(branch)}`);
142
+ if (input.formatCommand) {
143
+ await runBash(exec, `cd ${wt} && ${input.formatCommand}`);
144
+ }
161
145
  await runBash(exec, `git -C ${wt} add -A`);
162
146
  await runBash(exec, `git -C ${wt} commit -m ${shQuote(message)}`);
163
147
  }
@@ -173,8 +157,6 @@ async function runBash(exec, command) {
173
157
  function isAsyncIterable(v) {
174
158
  return v !== null && typeof v === 'object' && Symbol.asyncIterator in v;
175
159
  }
176
- // POSIX shell-quote: wrap in single quotes, escape embedded single quotes.
177
160
  function shQuote(s) {
178
161
  return `'${s.replace(/'/g, "'\\''")}'`;
179
162
  }
180
- //# sourceMappingURL=worker.js.map
@@ -1,6 +1,3 @@
1
- // Shared test helper: spin up a throwaway git repo in a tempdir.
2
- // Used by *.test.ts (unit) for filesystem-touching cases AND by test/integration/*.test.ts.
3
- // docs/runtime.md §Testing — integration tests run against real temp git repos.
4
1
  import { mkdtemp, rm, writeFile } from 'node:fs/promises';
5
2
  import { tmpdir } from 'node:os';
6
3
  import { join } from 'node:path';
@@ -18,4 +15,3 @@ export async function makeTempRepo(opts) {
18
15
  };
19
16
  return { path, cleanup };
20
17
  }
21
- //# sourceMappingURL=temp-repo.js.map