@renseiai/agentfactory 0.8.18 → 0.8.20

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 (117) hide show
  1. package/dist/src/config/repository-config.d.ts +7 -0
  2. package/dist/src/config/repository-config.d.ts.map +1 -1
  3. package/dist/src/config/repository-config.js +15 -1
  4. package/dist/src/config/repository-config.test.js +1 -1
  5. package/dist/src/governor/decision-engine-adapter.d.ts +43 -0
  6. package/dist/src/governor/decision-engine-adapter.d.ts.map +1 -0
  7. package/dist/src/governor/decision-engine-adapter.js +417 -0
  8. package/dist/src/governor/decision-engine-adapter.test.d.ts +2 -0
  9. package/dist/src/governor/decision-engine-adapter.test.d.ts.map +1 -0
  10. package/dist/src/governor/decision-engine-adapter.test.js +362 -0
  11. package/dist/src/governor/decision-engine.js +3 -7
  12. package/dist/src/governor/decision-engine.test.js +5 -5
  13. package/dist/src/governor/index.d.ts +1 -0
  14. package/dist/src/governor/index.d.ts.map +1 -1
  15. package/dist/src/governor/index.js +1 -0
  16. package/dist/src/index.d.ts +1 -0
  17. package/dist/src/index.d.ts.map +1 -1
  18. package/dist/src/index.js +1 -0
  19. package/dist/src/manifest/route-manifest.d.ts.map +1 -1
  20. package/dist/src/manifest/route-manifest.js +4 -0
  21. package/dist/src/merge-queue/adapters/local.d.ts +68 -0
  22. package/dist/src/merge-queue/adapters/local.d.ts.map +1 -0
  23. package/dist/src/merge-queue/adapters/local.js +136 -0
  24. package/dist/src/merge-queue/adapters/local.test.d.ts +2 -0
  25. package/dist/src/merge-queue/adapters/local.test.d.ts.map +1 -0
  26. package/dist/src/merge-queue/adapters/local.test.js +176 -0
  27. package/dist/src/merge-queue/index.d.ts +13 -5
  28. package/dist/src/merge-queue/index.d.ts.map +1 -1
  29. package/dist/src/merge-queue/index.js +13 -6
  30. package/dist/src/merge-queue/merge-queue.integration.test.js +19 -0
  31. package/dist/src/merge-queue/merge-worker.d.ts.map +1 -1
  32. package/dist/src/merge-queue/merge-worker.js +29 -0
  33. package/dist/src/merge-queue/types.d.ts +1 -1
  34. package/dist/src/merge-queue/types.d.ts.map +1 -1
  35. package/dist/src/orchestrator/index.d.ts +4 -0
  36. package/dist/src/orchestrator/index.d.ts.map +1 -1
  37. package/dist/src/orchestrator/index.js +3 -0
  38. package/dist/src/orchestrator/orchestrator.d.ts +58 -0
  39. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
  40. package/dist/src/orchestrator/orchestrator.js +552 -97
  41. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
  42. package/dist/src/orchestrator/parse-work-result.js +3 -1
  43. package/dist/src/orchestrator/parse-work-result.test.js +6 -0
  44. package/dist/src/orchestrator/quality-baseline.d.ts +83 -0
  45. package/dist/src/orchestrator/quality-baseline.d.ts.map +1 -0
  46. package/dist/src/orchestrator/quality-baseline.js +313 -0
  47. package/dist/src/orchestrator/quality-baseline.test.d.ts +2 -0
  48. package/dist/src/orchestrator/quality-baseline.test.d.ts.map +1 -0
  49. package/dist/src/orchestrator/quality-baseline.test.js +448 -0
  50. package/dist/src/orchestrator/quality-ratchet.d.ts +70 -0
  51. package/dist/src/orchestrator/quality-ratchet.d.ts.map +1 -0
  52. package/dist/src/orchestrator/quality-ratchet.js +162 -0
  53. package/dist/src/orchestrator/quality-ratchet.test.d.ts +2 -0
  54. package/dist/src/orchestrator/quality-ratchet.test.d.ts.map +1 -0
  55. package/dist/src/orchestrator/quality-ratchet.test.js +335 -0
  56. package/dist/src/orchestrator/types.d.ts +2 -0
  57. package/dist/src/orchestrator/types.d.ts.map +1 -1
  58. package/dist/src/providers/claude-provider.d.ts.map +1 -1
  59. package/dist/src/providers/claude-provider.js +11 -0
  60. package/dist/src/providers/codex-app-server-provider.d.ts +237 -0
  61. package/dist/src/providers/codex-app-server-provider.d.ts.map +1 -0
  62. package/dist/src/providers/codex-app-server-provider.js +1041 -0
  63. package/dist/src/providers/codex-app-server-provider.test.d.ts +2 -0
  64. package/dist/src/providers/codex-app-server-provider.test.d.ts.map +1 -0
  65. package/dist/src/providers/codex-app-server-provider.test.js +589 -0
  66. package/dist/src/providers/codex-approval-bridge.d.ts +49 -0
  67. package/dist/src/providers/codex-approval-bridge.d.ts.map +1 -0
  68. package/dist/src/providers/codex-approval-bridge.js +117 -0
  69. package/dist/src/providers/codex-approval-bridge.test.d.ts +2 -0
  70. package/dist/src/providers/codex-approval-bridge.test.d.ts.map +1 -0
  71. package/dist/src/providers/codex-approval-bridge.test.js +188 -0
  72. package/dist/src/providers/codex-provider.d.ts +24 -4
  73. package/dist/src/providers/codex-provider.d.ts.map +1 -1
  74. package/dist/src/providers/codex-provider.js +58 -6
  75. package/dist/src/providers/index.d.ts +1 -0
  76. package/dist/src/providers/index.d.ts.map +1 -1
  77. package/dist/src/providers/index.js +1 -0
  78. package/dist/src/providers/types.d.ts +25 -0
  79. package/dist/src/providers/types.d.ts.map +1 -1
  80. package/dist/src/routing/observation-recorder.test.js +1 -1
  81. package/dist/src/routing/observation-store.d.ts +15 -1
  82. package/dist/src/routing/observation-store.d.ts.map +1 -1
  83. package/dist/src/routing/observation-store.test.js +17 -11
  84. package/dist/src/routing/types.d.ts +1 -1
  85. package/dist/src/templates/adapters.d.ts +25 -0
  86. package/dist/src/templates/adapters.d.ts.map +1 -1
  87. package/dist/src/templates/adapters.js +70 -0
  88. package/dist/src/templates/adapters.test.js +49 -0
  89. package/dist/src/templates/index.d.ts +3 -1
  90. package/dist/src/templates/index.d.ts.map +1 -1
  91. package/dist/src/templates/index.js +1 -0
  92. package/dist/src/templates/registry.d.ts +31 -0
  93. package/dist/src/templates/registry.d.ts.map +1 -1
  94. package/dist/src/templates/registry.js +91 -0
  95. package/dist/src/templates/schema.d.ts +31 -0
  96. package/dist/src/templates/schema.d.ts.map +1 -0
  97. package/dist/src/templates/schema.js +139 -0
  98. package/dist/src/templates/schema.test.d.ts +2 -0
  99. package/dist/src/templates/schema.test.d.ts.map +1 -0
  100. package/dist/src/templates/schema.test.js +215 -0
  101. package/dist/src/templates/types.d.ts +22 -0
  102. package/dist/src/templates/types.d.ts.map +1 -1
  103. package/dist/src/templates/types.js +12 -0
  104. package/dist/src/tools/index.d.ts +2 -0
  105. package/dist/src/tools/index.d.ts.map +1 -1
  106. package/dist/src/tools/index.js +1 -0
  107. package/dist/src/tools/registry.d.ts +9 -1
  108. package/dist/src/tools/registry.d.ts.map +1 -1
  109. package/dist/src/tools/registry.js +13 -1
  110. package/dist/src/tools/stdio-server-entry.d.ts +25 -0
  111. package/dist/src/tools/stdio-server-entry.d.ts.map +1 -0
  112. package/dist/src/tools/stdio-server-entry.js +205 -0
  113. package/dist/src/tools/stdio-server.d.ts +87 -0
  114. package/dist/src/tools/stdio-server.d.ts.map +1 -0
  115. package/dist/src/tools/stdio-server.js +138 -0
  116. package/dist/src/workflow/workflow-types.d.ts +3 -3
  117. package/package.json +3 -2
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Local Merge Queue Adapter
3
+ *
4
+ * Self-hosted merge queue that uses the built-in merge worker + Redis storage
5
+ * instead of an external service like GitHub's merge queue. This is the default
6
+ * provider — it works with any GitHub repository without requiring GitHub's
7
+ * paid merge queue feature.
8
+ *
9
+ * The adapter handles queue management (enqueue/dequeue/status). The merge worker
10
+ * (merge-worker.ts) handles the actual rebase → resolve → test → merge pipeline.
11
+ *
12
+ * PR eligibility is checked via `gh pr view` CLI (no GraphQL needed).
13
+ */
14
+ import { exec } from 'child_process';
15
+ import { promisify } from 'util';
16
+ const execAsync = promisify(exec);
17
+ /** Timeout for gh CLI calls */
18
+ const GH_CLI_TIMEOUT = 15_000;
19
+ // ---------------------------------------------------------------------------
20
+ // Adapter
21
+ // ---------------------------------------------------------------------------
22
+ export class LocalMergeQueueAdapter {
23
+ storage;
24
+ name = 'local';
25
+ constructor(storage) {
26
+ this.storage = storage;
27
+ }
28
+ /**
29
+ * Check if a PR is eligible for the local merge queue.
30
+ * Uses `gh pr view` to verify PR is open. Does NOT require the PR to be
31
+ * conflict-free — the merge worker handles rebasing.
32
+ */
33
+ async canEnqueue(owner, repo, prNumber) {
34
+ try {
35
+ const { stdout } = await execAsync(`gh pr view ${prNumber} --repo ${owner}/${repo} --json state,headRefName`, { timeout: GH_CLI_TIMEOUT });
36
+ const pr = JSON.parse(stdout);
37
+ // PR must be open
38
+ return pr.state === 'OPEN';
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ /**
45
+ * Add a PR to the local merge queue.
46
+ * The merge worker will pick it up and process it (rebase, test, merge).
47
+ */
48
+ async enqueue(owner, repo, prNumber) {
49
+ const repoId = `${owner}/${repo}`;
50
+ // Check if already enqueued
51
+ const alreadyQueued = await this.storage.isEnqueued(repoId, prNumber);
52
+ if (alreadyQueued) {
53
+ return this.getStatus(owner, repo, prNumber);
54
+ }
55
+ // Fetch PR details for the queue entry
56
+ let sourceBranch = `pr-${prNumber}`;
57
+ let prUrl = `https://github.com/${owner}/${repo}/pull/${prNumber}`;
58
+ try {
59
+ const { stdout } = await execAsync(`gh pr view ${prNumber} --repo ${owner}/${repo} --json headRefName,url`, { timeout: GH_CLI_TIMEOUT });
60
+ const pr = JSON.parse(stdout);
61
+ sourceBranch = pr.headRefName ?? sourceBranch;
62
+ prUrl = pr.url ?? prUrl;
63
+ }
64
+ catch {
65
+ // Fall back to defaults
66
+ }
67
+ await this.storage.enqueue({
68
+ repoId,
69
+ prNumber,
70
+ prUrl,
71
+ issueIdentifier: `PR-${prNumber}`,
72
+ priority: 3, // Default priority; orchestrator can override
73
+ sourceBranch,
74
+ targetBranch: 'main',
75
+ });
76
+ return this.getStatus(owner, repo, prNumber);
77
+ }
78
+ /**
79
+ * Get the status of a PR in the local merge queue.
80
+ */
81
+ async getStatus(owner, repo, prNumber) {
82
+ const repoId = `${owner}/${repo}`;
83
+ // Check if in queue
84
+ const position = await this.storage.getPosition(repoId, prNumber);
85
+ if (position !== null) {
86
+ return {
87
+ state: position === 1 ? 'merging' : 'queued',
88
+ position,
89
+ checksStatus: [],
90
+ };
91
+ }
92
+ // Check if failed
93
+ const failedReason = await this.storage.getFailedReason(repoId, prNumber);
94
+ if (failedReason) {
95
+ return {
96
+ state: 'failed',
97
+ failureReason: failedReason,
98
+ checksStatus: [],
99
+ };
100
+ }
101
+ // Check if blocked (conflict)
102
+ const blockedReason = await this.storage.getBlockedReason(repoId, prNumber);
103
+ if (blockedReason) {
104
+ return {
105
+ state: 'blocked',
106
+ failureReason: blockedReason,
107
+ checksStatus: [],
108
+ };
109
+ }
110
+ // Check if PR was already merged
111
+ try {
112
+ const { stdout } = await execAsync(`gh pr view ${prNumber} --repo ${owner}/${repo} --json state`, { timeout: GH_CLI_TIMEOUT });
113
+ const pr = JSON.parse(stdout);
114
+ if (pr.state === 'MERGED') {
115
+ return { state: 'merged', checksStatus: [] };
116
+ }
117
+ }
118
+ catch {
119
+ // Fall through to not-queued
120
+ }
121
+ return { state: 'not-queued', checksStatus: [] };
122
+ }
123
+ /**
124
+ * Remove a PR from the local merge queue.
125
+ */
126
+ async dequeue(owner, repo, prNumber) {
127
+ const repoId = `${owner}/${repo}`;
128
+ await this.storage.remove(repoId, prNumber);
129
+ }
130
+ /**
131
+ * Local merge queue is always available (no external service dependency).
132
+ */
133
+ async isEnabled(_owner, _repo) {
134
+ return true;
135
+ }
136
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.test.d.ts","sourceRoot":"","sources":["../../../../src/merge-queue/adapters/local.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,176 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { LocalMergeQueueAdapter } from './local.js';
3
+ // Mock child_process.exec
4
+ vi.mock('child_process', () => ({
5
+ exec: vi.fn(),
6
+ }));
7
+ import { exec } from 'child_process';
8
+ function mockExec(stdout) {
9
+ ;
10
+ exec.mockImplementation((_cmd, _opts, cb) => {
11
+ // promisify wraps exec — the 2-arg form is (cmd, opts) returning Promise
12
+ // but we also need to handle the 3-arg callback form
13
+ if (typeof _opts === 'function') {
14
+ cb = _opts;
15
+ _opts = undefined;
16
+ }
17
+ if (cb) {
18
+ cb(null, { stdout, stderr: '' });
19
+ return;
20
+ }
21
+ return { stdout, stderr: '' };
22
+ });
23
+ }
24
+ function mockExecReject(error) {
25
+ ;
26
+ exec.mockImplementation((_cmd, _opts, cb) => {
27
+ if (typeof _opts === 'function') {
28
+ cb = _opts;
29
+ }
30
+ if (cb) {
31
+ cb(error, null);
32
+ return;
33
+ }
34
+ throw error;
35
+ });
36
+ }
37
+ function createMockStorage(overrides = {}) {
38
+ return {
39
+ enqueue: vi.fn().mockResolvedValue(undefined),
40
+ dequeue: vi.fn().mockResolvedValue(null),
41
+ getQueueDepth: vi.fn().mockResolvedValue(0),
42
+ isEnqueued: vi.fn().mockResolvedValue(false),
43
+ getPosition: vi.fn().mockResolvedValue(null),
44
+ remove: vi.fn().mockResolvedValue(undefined),
45
+ getFailedReason: vi.fn().mockResolvedValue(null),
46
+ getBlockedReason: vi.fn().mockResolvedValue(null),
47
+ ...overrides,
48
+ };
49
+ }
50
+ describe('LocalMergeQueueAdapter', () => {
51
+ let storage;
52
+ let adapter;
53
+ beforeEach(() => {
54
+ vi.clearAllMocks();
55
+ storage = createMockStorage();
56
+ adapter = new LocalMergeQueueAdapter(storage);
57
+ });
58
+ it('has name "local"', () => {
59
+ expect(adapter.name).toBe('local');
60
+ });
61
+ describe('isEnabled', () => {
62
+ it('always returns true', async () => {
63
+ expect(await adapter.isEnabled('owner', 'repo')).toBe(true);
64
+ });
65
+ });
66
+ describe('canEnqueue', () => {
67
+ it('returns true for open PR', async () => {
68
+ mockExec(JSON.stringify({ state: 'OPEN', headRefName: 'feat/test' }));
69
+ expect(await adapter.canEnqueue('owner', 'repo', 42)).toBe(true);
70
+ });
71
+ it('returns false for merged PR', async () => {
72
+ mockExec(JSON.stringify({ state: 'MERGED', headRefName: 'feat/test' }));
73
+ expect(await adapter.canEnqueue('owner', 'repo', 42)).toBe(false);
74
+ });
75
+ it('returns false for closed PR', async () => {
76
+ mockExec(JSON.stringify({ state: 'CLOSED', headRefName: 'feat/test' }));
77
+ expect(await adapter.canEnqueue('owner', 'repo', 42)).toBe(false);
78
+ });
79
+ it('returns false on gh CLI error', async () => {
80
+ mockExecReject(new Error('gh: not found'));
81
+ expect(await adapter.canEnqueue('owner', 'repo', 42)).toBe(false);
82
+ });
83
+ });
84
+ describe('enqueue', () => {
85
+ it('adds PR to storage and returns queued status', async () => {
86
+ mockExec(JSON.stringify({ headRefName: 'feat/my-branch', url: 'https://github.com/o/r/pull/10' }));
87
+ storage.isEnqueued.mockResolvedValue(false);
88
+ storage.getPosition.mockResolvedValue(1);
89
+ const status = await adapter.enqueue('owner', 'repo', 10);
90
+ expect(storage.enqueue).toHaveBeenCalledWith(expect.objectContaining({
91
+ repoId: 'owner/repo',
92
+ prNumber: 10,
93
+ sourceBranch: 'feat/my-branch',
94
+ targetBranch: 'main',
95
+ priority: 3,
96
+ }));
97
+ expect(status.state).toBe('merging'); // position 1 = merging
98
+ });
99
+ it('returns existing status if already enqueued', async () => {
100
+ ;
101
+ storage.isEnqueued.mockResolvedValue(true);
102
+ storage.getPosition.mockResolvedValue(3);
103
+ const status = await adapter.enqueue('owner', 'repo', 10);
104
+ expect(storage.enqueue).not.toHaveBeenCalled();
105
+ expect(status.state).toBe('queued');
106
+ expect(status.position).toBe(3);
107
+ });
108
+ it('falls back to default branch name on gh CLI error', async () => {
109
+ mockExecReject(new Error('gh: not found'));
110
+ storage.isEnqueued.mockResolvedValue(false);
111
+ storage.getPosition.mockResolvedValue(2);
112
+ await adapter.enqueue('owner', 'repo', 5);
113
+ expect(storage.enqueue).toHaveBeenCalledWith(expect.objectContaining({
114
+ sourceBranch: 'pr-5',
115
+ prUrl: 'https://github.com/owner/repo/pull/5',
116
+ }));
117
+ });
118
+ });
119
+ describe('getStatus', () => {
120
+ it('returns queued with position when in queue', async () => {
121
+ ;
122
+ storage.getPosition.mockResolvedValue(3);
123
+ const status = await adapter.getStatus('owner', 'repo', 10);
124
+ expect(status.state).toBe('queued');
125
+ expect(status.position).toBe(3);
126
+ });
127
+ it('returns merging when position is 1', async () => {
128
+ ;
129
+ storage.getPosition.mockResolvedValue(1);
130
+ const status = await adapter.getStatus('owner', 'repo', 10);
131
+ expect(status.state).toBe('merging');
132
+ expect(status.position).toBe(1);
133
+ });
134
+ it('returns failed when PR has failed reason', async () => {
135
+ ;
136
+ storage.getPosition.mockResolvedValue(null);
137
+ storage.getFailedReason.mockResolvedValue('Tests failed');
138
+ const status = await adapter.getStatus('owner', 'repo', 10);
139
+ expect(status.state).toBe('failed');
140
+ expect(status.failureReason).toBe('Tests failed');
141
+ });
142
+ it('returns blocked when PR has blocked reason', async () => {
143
+ ;
144
+ storage.getPosition.mockResolvedValue(null);
145
+ storage.getFailedReason.mockResolvedValue(null);
146
+ storage.getBlockedReason.mockResolvedValue('Merge conflict in utils.ts');
147
+ const status = await adapter.getStatus('owner', 'repo', 10);
148
+ expect(status.state).toBe('blocked');
149
+ expect(status.failureReason).toBe('Merge conflict in utils.ts');
150
+ });
151
+ it('returns merged when PR is already merged', async () => {
152
+ ;
153
+ storage.getPosition.mockResolvedValue(null);
154
+ storage.getFailedReason.mockResolvedValue(null);
155
+ storage.getBlockedReason.mockResolvedValue(null);
156
+ mockExec(JSON.stringify({ state: 'MERGED' }));
157
+ const status = await adapter.getStatus('owner', 'repo', 10);
158
+ expect(status.state).toBe('merged');
159
+ });
160
+ it('returns not-queued when PR is not in any state', async () => {
161
+ ;
162
+ storage.getPosition.mockResolvedValue(null);
163
+ storage.getFailedReason.mockResolvedValue(null);
164
+ storage.getBlockedReason.mockResolvedValue(null);
165
+ mockExec(JSON.stringify({ state: 'OPEN' }));
166
+ const status = await adapter.getStatus('owner', 'repo', 10);
167
+ expect(status.state).toBe('not-queued');
168
+ });
169
+ });
170
+ describe('dequeue', () => {
171
+ it('removes PR from storage', async () => {
172
+ await adapter.dequeue('owner', 'repo', 10);
173
+ expect(storage.remove).toHaveBeenCalledWith('owner/repo', 10);
174
+ });
175
+ });
176
+ });
@@ -3,16 +3,24 @@
3
3
  *
4
4
  * Factory and exports for merge queue adapters.
5
5
  */
6
+ import type { LocalMergeQueueStorage } from './adapters/local.js';
6
7
  export type { MergeQueueAdapter, MergeQueueStatus, MergeQueueProviderName } from './types.js';
8
+ export type { LocalMergeQueueStorage } from './adapters/local.js';
9
+ export { LocalMergeQueueAdapter } from './adapters/local.js';
10
+ export { MergeWorker } from './merge-worker.js';
11
+ export type { MergeWorkerConfig, MergeWorkerDeps, MergeProcessResult } from './merge-worker.js';
12
+ /** Optional dependencies for adapter construction */
13
+ export interface MergeQueueAdapterDeps {
14
+ /** Required for 'local' provider — Redis-backed queue storage */
15
+ storage?: LocalMergeQueueStorage;
16
+ }
7
17
  /**
8
18
  * Create a merge queue adapter by provider name.
9
19
  *
10
- * Currently only 'github-native' is implemented.
11
- * 'mergify' and 'trunk' will throw until implemented.
12
- *
13
20
  * @param name - Provider name
21
+ * @param deps - Optional dependencies (storage required for 'local' provider)
14
22
  * @returns MergeQueueAdapter instance
15
- * @throws Error if provider is not yet implemented
23
+ * @throws Error if provider is not yet implemented or required deps are missing
16
24
  */
17
- export declare function createMergeQueueAdapter(name: import('./types.js').MergeQueueProviderName): import('./types.js').MergeQueueAdapter;
25
+ export declare function createMergeQueueAdapter(name: import('./types.js').MergeQueueProviderName, deps?: MergeQueueAdapterDeps): import('./types.js').MergeQueueAdapter;
18
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/merge-queue/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAE7F;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,YAAY,EAAE,sBAAsB,GAAG,OAAO,YAAY,EAAE,iBAAiB,CAiBjI"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/merge-queue/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEjE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAC7F,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE/F,qDAAqD;AACrD,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,OAAO,CAAC,EAAE,sBAAsB,CAAA;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,YAAY,EAAE,sBAAsB,EACjD,IAAI,CAAC,EAAE,qBAAqB,GAC3B,OAAO,YAAY,EAAE,iBAAiB,CAyBxC"}
@@ -4,25 +4,32 @@
4
4
  * Factory and exports for merge queue adapters.
5
5
  */
6
6
  import { GitHubNativeMergeQueueAdapter } from './adapters/github-native.js';
7
+ import { LocalMergeQueueAdapter } from './adapters/local.js';
8
+ export { LocalMergeQueueAdapter } from './adapters/local.js';
9
+ export { MergeWorker } from './merge-worker.js';
7
10
  /**
8
11
  * Create a merge queue adapter by provider name.
9
12
  *
10
- * Currently only 'github-native' is implemented.
11
- * 'mergify' and 'trunk' will throw until implemented.
12
- *
13
13
  * @param name - Provider name
14
+ * @param deps - Optional dependencies (storage required for 'local' provider)
14
15
  * @returns MergeQueueAdapter instance
15
- * @throws Error if provider is not yet implemented
16
+ * @throws Error if provider is not yet implemented or required deps are missing
16
17
  */
17
- export function createMergeQueueAdapter(name) {
18
+ export function createMergeQueueAdapter(name, deps) {
18
19
  switch (name) {
19
20
  case 'github-native':
20
21
  return new GitHubNativeMergeQueueAdapter();
22
+ case 'local':
23
+ if (!deps?.storage) {
24
+ throw new Error("Local merge queue adapter requires 'storage' dependency. " +
25
+ 'Pass a LocalMergeQueueStorage implementation via deps.storage.');
26
+ }
27
+ return new LocalMergeQueueAdapter(deps.storage);
21
28
  case 'mergify':
22
29
  throw new Error('Mergify merge queue adapter not yet implemented. Contributions welcome.');
23
30
  case 'trunk':
24
31
  throw new Error('Trunk merge queue adapter not yet implemented. Contributions welcome.');
25
32
  default:
26
- throw new Error(`Unknown merge queue provider: ${name}. Supported: github-native, mergify, trunk.`);
33
+ throw new Error(`Unknown merge queue provider: ${name}. Supported: github-native, local, mergify, trunk.`);
27
34
  }
28
35
  }
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
2
  import { createMergeQueueAdapter } from './index.js';
3
3
  import { GitHubNativeMergeQueueAdapter } from './adapters/github-native.js';
4
+ import { LocalMergeQueueAdapter } from './adapters/local.js';
4
5
  describe('merge queue integration', () => {
5
6
  describe('createMergeQueueAdapter factory', () => {
6
7
  it('creates GitHub native adapter', () => {
@@ -8,6 +9,24 @@ describe('merge queue integration', () => {
8
9
  expect(adapter).toBeInstanceOf(GitHubNativeMergeQueueAdapter);
9
10
  expect(adapter.name).toBe('github-native');
10
11
  });
12
+ it('creates local adapter with storage', () => {
13
+ const mockStorage = {
14
+ enqueue: vi.fn(),
15
+ dequeue: vi.fn(),
16
+ getQueueDepth: vi.fn(),
17
+ isEnqueued: vi.fn(),
18
+ getPosition: vi.fn(),
19
+ remove: vi.fn(),
20
+ getFailedReason: vi.fn(),
21
+ getBlockedReason: vi.fn(),
22
+ };
23
+ const adapter = createMergeQueueAdapter('local', { storage: mockStorage });
24
+ expect(adapter).toBeInstanceOf(LocalMergeQueueAdapter);
25
+ expect(adapter.name).toBe('local');
26
+ });
27
+ it('throws for local adapter without storage', () => {
28
+ expect(() => createMergeQueueAdapter('local')).toThrow('storage');
29
+ });
11
30
  it('throws for mergify (not yet implemented)', () => {
12
31
  expect(() => createMergeQueueAdapter('mergify')).toThrow('not yet implemented');
13
32
  });
@@ -1 +1 @@
1
- {"version":3,"file":"merge-worker.d.ts","sourceRoot":"","sources":["../../../src/merge-queue/merge-worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge-worker.d.ts","sourceRoot":"","sources":["../../../src/merge-queue/merge-worker.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,8 @@ import { promisify } from 'util';
12
12
  import { createMergeStrategy } from './strategies/index.js';
13
13
  import { ConflictResolver } from './conflict-resolver.js';
14
14
  import { LockFileRegeneration } from './lock-file-regeneration.js';
15
+ import { loadQualityRatchet, checkQualityRatchet, updateQualityRatchet, formatRatchetResult, } from '../orchestrator/quality-ratchet.js';
16
+ import { captureQualityBaseline } from '../orchestrator/quality-baseline.js';
15
17
  const exec = promisify(execCb);
16
18
  // ---------------------------------------------------------------------------
17
19
  // MergeWorker
@@ -155,6 +157,33 @@ export class MergeWorker {
155
157
  if (!testResult.passed) {
156
158
  return { prNumber: entry.prNumber, status: 'test-failure', message: testResult.output };
157
159
  }
160
+ // 5.5. Quality ratchet check (if ratchet file exists)
161
+ const ratchet = loadQualityRatchet(ctx.worktreePath);
162
+ if (ratchet) {
163
+ const qualityConfig = {
164
+ testCommand: this.config.testCommand,
165
+ packageManager: this.config.packageManager,
166
+ };
167
+ const current = captureQualityBaseline(ctx.worktreePath, qualityConfig);
168
+ const ratchetResult = checkQualityRatchet(ratchet, current);
169
+ if (!ratchetResult.passed) {
170
+ return {
171
+ prNumber: entry.prNumber,
172
+ status: 'test-failure',
173
+ message: `Quality ratchet violated: ${formatRatchetResult(ratchetResult)}`,
174
+ };
175
+ }
176
+ // Tighten ratchet if metrics improved (will be included in the merge)
177
+ const updated = updateQualityRatchet(ctx.worktreePath, current, entry.issueIdentifier ?? `PR-${entry.prNumber}`);
178
+ if (updated) {
179
+ try {
180
+ await exec('git add .agentfactory/quality-ratchet.json && git commit -m "chore: tighten quality ratchet"', { cwd: ctx.worktreePath });
181
+ }
182
+ catch {
183
+ // Ratchet update commit is best-effort
184
+ }
185
+ }
186
+ }
158
187
  // 6. Finalize: push and merge
159
188
  await strategy.finalize(ctx);
160
189
  // 7. Delete branch if configured
@@ -6,7 +6,7 @@
6
6
  * Concrete implementations live in adapters/ subdirectory.
7
7
  */
8
8
  /** Supported merge queue provider names */
9
- export type MergeQueueProviderName = 'github-native' | 'mergify' | 'trunk';
9
+ export type MergeQueueProviderName = 'github-native' | 'local' | 'mergify' | 'trunk';
10
10
  /** Status of a PR in the merge queue */
11
11
  export interface MergeQueueStatus {
12
12
  /** Current state in the merge queue */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/merge-queue/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG,SAAS,GAAG,OAAO,CAAA;AAE1E,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAA;IAC5E,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,IAAI,CAAA;IACzB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gCAAgC;IAChC,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,EAAE,CAAA;CACtE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;IAErC,sDAAsD;IACtD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAE3E,kCAAkC;IAClC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAEjF,wCAAwC;IACxC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAEnF,uCAAuC;IACvC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAErE,oDAAoD;IACpD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACzD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/merge-queue/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAA;AAEpF,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAA;IAC5E,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,IAAI,CAAA;IACzB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gCAAgC;IAChC,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,EAAE,CAAA;CACtE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;IAErC,sDAAsD;IACtD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAE3E,kCAAkC;IAClC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAEjF,wCAAwC;IACxC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAEnF,uCAAuC;IACvC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAErE,oDAAoD;IACpD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACzD"}
@@ -27,6 +27,10 @@ export { getCompletionContract, validateCompletion, formatMissingFields, } from
27
27
  export type { CompletionContract, CompletionField, CompletionFieldType, CompletionValidationResult, SessionOutputs, BackstopAction, BackstopResult, } from './completion-contracts.js';
28
28
  export { runBackstop, collectSessionOutputs, formatBackstopComment, } from './session-backstop.js';
29
29
  export type { SessionContext, BackstopOptions, BackstopRunResult, } from './session-backstop.js';
30
+ export { captureQualityBaseline, computeQualityDelta, formatQualityReport, saveBaseline, loadBaseline, } from './quality-baseline.js';
31
+ export type { QualityBaseline, QualityDelta, QualityConfig, } from './quality-baseline.js';
32
+ export { loadQualityRatchet, checkQualityRatchet, updateQualityRatchet, initializeQualityRatchet, formatRatchetResult, } from './quality-ratchet.js';
33
+ export type { QualityRatchet, RatchetCheckResult, } from './quality-ratchet.js';
30
34
  export { LogAnalyzer, createLogAnalyzer } from './log-analyzer.js';
31
35
  export { ArtifactTracker, } from './artifact-tracker.js';
32
36
  export type { TrackedFileAction, TrackedFile, ArtifactIndex, } from './artifact-tracker.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/index.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,9 @@ export { SecurityScanEventSchema, parseSecurityScanOutput, parseSemgrepOutput, p
24
24
  // Completion Contracts & Session Backstop
25
25
  export { getCompletionContract, validateCompletion, formatMissingFields, } from './completion-contracts.js';
26
26
  export { runBackstop, collectSessionOutputs, formatBackstopComment, } from './session-backstop.js';
27
+ // Quality Baseline & Ratchet
28
+ export { captureQualityBaseline, computeQualityDelta, formatQualityReport, saveBaseline, loadBaseline, } from './quality-baseline.js';
29
+ export { loadQualityRatchet, checkQualityRatchet, updateQualityRatchet, initializeQualityRatchet, formatRatchetResult, } from './quality-ratchet.js';
27
30
  // Log Analyzer
28
31
  export { LogAnalyzer, createLogAnalyzer } from './log-analyzer.js';
29
32
  // Artifact Tracker (for context window management)
@@ -229,6 +229,18 @@ export declare class AgentOrchestrator {
229
229
  * Falls back silently to default git merge if mergiraf is not installed.
230
230
  */
231
231
  private configureMergiraf;
232
+ /**
233
+ * Check if quality baseline capture is enabled via repository config.
234
+ */
235
+ private isQualityBaselineEnabled;
236
+ /**
237
+ * Build quality config from orchestrator settings.
238
+ */
239
+ private buildQualityConfig;
240
+ /**
241
+ * Load quality baseline from a worktree and convert to TemplateContext shape.
242
+ */
243
+ private loadQualityBaselineForContext;
232
244
  /**
233
245
  * Link dependencies from the main repo into a worktree via symlinks.
234
246
  *
@@ -242,6 +254,22 @@ export declare class AgentOrchestrator {
242
254
  * Falls back to `pnpm install --frozen-lockfile` if symlinking fails.
243
255
  */
244
256
  linkDependencies(worktreePath: string, identifier: string): void;
257
+ /**
258
+ * Verify that critical dependency symlinks are intact and resolvable.
259
+ * Returns true if verification passes, false if re-linking is needed.
260
+ */
261
+ private verifyDependencyLinks;
262
+ /**
263
+ * Remove all node_modules directories from a worktree (root + per-workspace).
264
+ */
265
+ private removeWorktreeNodeModules;
266
+ /**
267
+ * Create or update a symlink atomically, handling EEXIST races.
268
+ *
269
+ * If the destination already exists and points to the correct target, this is a no-op.
270
+ * If it points elsewhere or isn't a symlink, it's replaced.
271
+ */
272
+ private safeSymlink;
245
273
  /**
246
274
  * Create a real node_modules directory and symlink each entry from the source.
247
275
  *
@@ -249,6 +277,9 @@ export declare class AgentOrchestrator {
249
277
  * resolve through the symlink and corrupt the original), we create a real
250
278
  * directory and symlink each entry individually. If pnpm "recreates" this
251
279
  * directory, it only destroys the worktree's symlinks — not the originals.
280
+ *
281
+ * Supports incremental sync: if the destination already exists, only missing
282
+ * or stale entries are updated (safe for concurrent agents and phase reuse).
252
283
  */
253
284
  private linkNodeModulesContents;
254
285
  /**
@@ -256,6 +287,14 @@ export declare class AgentOrchestrator {
256
287
  * Only called when symlinking fails.
257
288
  */
258
289
  private installDependencies;
290
+ /**
291
+ * Sync dependencies between worktree and main repo before linking.
292
+ *
293
+ * When a development agent adds new packages on a branch, the lockfile in the
294
+ * worktree diverges from the main repo. This method detects lockfile drift,
295
+ * updates the main repo's node_modules, then re-links into the worktree.
296
+ */
297
+ syncDependencies(worktreePath: string, identifier: string): void;
259
298
  /**
260
299
  * @deprecated Use linkDependencies() instead. This now delegates to linkDependencies.
261
300
  */
@@ -264,6 +303,20 @@ export declare class AgentOrchestrator {
264
303
  * Resolve the provider for a specific spawn, using the full priority cascade.
265
304
  * Returns a cached provider instance (creating one if needed) and the resolved name.
266
305
  */
306
+ /**
307
+ * Build base instructions for Codex App Server agents (SUP-1746).
308
+ *
309
+ * Assembles safety rules and project-specific instructions (AGENTS.md / CLAUDE.md)
310
+ * into a persistent system prompt passed via `instructions` on `thread/start`.
311
+ */
312
+ private buildCodexBaseInstructions;
313
+ /**
314
+ * Build Codex permission config from template permissions (SUP-1748).
315
+ *
316
+ * Translates abstract template `tools.allow` / `tools.disallow` into
317
+ * structured regex patterns for the Codex approval bridge.
318
+ */
319
+ private buildCodexPermissionConfig;
267
320
  private resolveProviderForSpawn;
268
321
  /**
269
322
  * Spawn a Claude agent for a specific issue using the Agent SDK
@@ -380,6 +433,11 @@ export declare class AgentOrchestrator {
380
433
  * If autoTransition is enabled, also transitions the issue status to the appropriate working state
381
434
  */
382
435
  spawnAgentWithResume(options: SpawnAgentWithResumeOptions): Promise<AgentProcess>;
436
+ /**
437
+ * Create a resume handle that falls back to a fresh spawn if the session is stale.
438
+ * This avoids wasting a recovery attempt when the Claude Code session has expired.
439
+ */
440
+ private createResumeWithFallbackHandle;
383
441
  /**
384
442
  * Stop all running agents
385
443
  */