quorumkit-engine 3.0.0

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,211 @@
1
+ export const id = 992;
2
+ export const ids = [992,563];
3
+ export const modules = {
4
+
5
+ /***/ 3563:
6
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
7
+
8
+ __webpack_require__.r(__webpack_exports__);
9
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10
+ /* harmony export */ isRetryable: () => (/* binding */ isRetryable),
11
+ /* harmony export */ withRetry: () => (/* binding */ withRetry)
12
+ /* harmony export */ });
13
+ /**
14
+ * runtimes/_retry.js
15
+ * Bounded exponential-backoff retry helper shared by all runtime adapters
16
+ * (ADR-007 §8, FR-030).
17
+ *
18
+ * Policy (defaults): 3 attempts, base 2 s, jitter ±25 %, max wait 30 s total.
19
+ * Retries are triggered by network errors, HTTP 5xx, and HTTP 429 (rate-limit).
20
+ * Non-retryable errors are rethrown immediately.
21
+ *
22
+ * Returns the function's resolved value plus the number of retries used,
23
+ * so the caller can record `runtime_retries` in the audit comment without
24
+ * counting the invocation as a separate loop-budget iteration.
25
+ */
26
+
27
+ const DEFAULT_OPTS = Object.freeze({
28
+ maxAttempts: 3,
29
+ baseMs: 2_000,
30
+ maxTotalMs: 30_000,
31
+ jitter: 0.25,
32
+ });
33
+
34
+ /**
35
+ * Determine whether an error is retryable.
36
+ * @param {any} err
37
+ * @returns {boolean}
38
+ */
39
+ function isRetryable(err) {
40
+ if (!err) return false;
41
+ // Octokit / fetch error styles
42
+ if (err.status === 429) return true;
43
+ if (typeof err.status === 'number' && err.status >= 500 && err.status < 600) return true;
44
+ // Node fetch network errors
45
+ const code = err.code ?? err.cause?.code;
46
+ if (code && /^(ECONNRESET|ETIMEDOUT|ENETUNREACH|EAI_AGAIN|UND_ERR_SOCKET)$/.test(code)) return true;
47
+ if (typeof err.message === 'string' && /timeout|network/i.test(err.message)) return true;
48
+ return false;
49
+ }
50
+
51
+ /**
52
+ * Run `fn` with bounded exponential backoff.
53
+ *
54
+ * @template T
55
+ * @param {() => Promise<T>} fn
56
+ * @param {object} [options]
57
+ * @param {object} [options.clock] - injectable clock { now(): number, sleep(ms): Promise<void> }
58
+ * @returns {Promise<{ value: T, retries: number }>}
59
+ */
60
+ async function withRetry(fn, options = {}) {
61
+ const opts = { ...DEFAULT_OPTS, ...options };
62
+ const clock = options.clock ?? defaultClock;
63
+
64
+ const start = clock.now();
65
+ let attempt = 0;
66
+ let lastError;
67
+
68
+ while (attempt < opts.maxAttempts) {
69
+ try {
70
+ const value = await fn();
71
+ return { value, retries: attempt };
72
+ } catch (err) {
73
+ lastError = err;
74
+ attempt += 1;
75
+ if (!isRetryable(err) || attempt >= opts.maxAttempts) break;
76
+
77
+ const elapsed = clock.now() - start;
78
+ if (elapsed >= opts.maxTotalMs) break;
79
+
80
+ const exp = Math.pow(2, attempt - 1) * opts.baseMs;
81
+ const jitter = exp * opts.jitter * (Math.random() * 2 - 1);
82
+ const wait = Math.max(0, Math.min(exp + jitter, opts.maxTotalMs - elapsed));
83
+ await clock.sleep(wait);
84
+ }
85
+ }
86
+
87
+ throw lastError;
88
+ }
89
+
90
+ const defaultClock = {
91
+ now: () => Date.now(),
92
+ sleep: ms => new Promise(r => setTimeout(r, ms)),
93
+ };
94
+
95
+
96
+ /***/ }),
97
+
98
+ /***/ 1992:
99
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
100
+
101
+ __webpack_require__.r(__webpack_exports__);
102
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
103
+ /* harmony export */ KIND: () => (/* binding */ KIND),
104
+ /* harmony export */ invoke: () => (/* binding */ invoke),
105
+ /* harmony export */ requiredPermissions: () => (/* binding */ requiredPermissions)
106
+ /* harmony export */ });
107
+ /* harmony import */ var _retry_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3563);
108
+ /**
109
+ * runtimes/copilot.js
110
+ * Adapter for the Copilot (GitHub Models) runtime kind (ADR-005, ADR-003).
111
+ *
112
+ * Dispatches the agent's Copilot workflow file (`copilot-agent-<slug>.yml`)
113
+ * via repository_dispatch / workflow_dispatch through the supplied client.
114
+ * Wraps the call in the shared bounded-backoff retry helper (ADR-007 §8).
115
+ *
116
+ * The adapter is purely a dispatch layer — the LLM call itself happens
117
+ * inside the dispatched GHA workflow, where the GITHUB_TOKEN is already
118
+ * scoped via the workflow file. No secret value ever crosses this module.
119
+ *
120
+ * Exports:
121
+ * requiredPermissions — GH Actions token scopes consumed by this kind
122
+ * invoke(context) — dispatch entry point
123
+ */
124
+
125
+
126
+
127
+ const KIND = 'copilot';
128
+
129
+ /**
130
+ * Permissions consumed by the dispatched copilot workflow. The orchestrator
131
+ * unions these with the scopes of every other adapter actually used at run
132
+ * time (ADR-007 §7) when composing dispatched workflow `permissions:` blocks.
133
+ */
134
+ const requiredPermissions = Object.freeze({
135
+ contents: 'read',
136
+ issues: 'write',
137
+ 'pull-requests': 'write',
138
+ models: 'read', // GitHub Models inference
139
+ });
140
+
141
+ /**
142
+ * Resolve the credential for a runtime entry. Returns the env var value or
143
+ * throws { code: 'runtime-credential-missing', credential_ref } if absent.
144
+ *
145
+ * NEVER returns the value to a caller that logs/comments — only the dispatch
146
+ * call uses it, and only the *name* (credential_ref) is recorded in audits.
147
+ */
148
+ function resolveCredential(runtime, env = process.env) {
149
+ const ref = runtime.credential_ref;
150
+ if (!ref) {
151
+ const e = new Error('runtime-credential-missing');
152
+ e.code = 'runtime-credential-missing';
153
+ e.credential_ref = '(none declared)';
154
+ throw e;
155
+ }
156
+ const value = env[ref];
157
+ if (!value) {
158
+ const e = new Error('runtime-credential-missing');
159
+ e.code = 'runtime-credential-missing';
160
+ e.credential_ref = ref;
161
+ throw e;
162
+ }
163
+ return value;
164
+ }
165
+
166
+ /**
167
+ * Invoke the runtime for one step.
168
+ *
169
+ * @param {object} context
170
+ * @param {object} context.client - GitHub client with triggerWorkflow()
171
+ * @param {string} context.owner
172
+ * @param {string} context.repo
173
+ * @param {string} context.agent - agent slug (e.g. "qa-agent")
174
+ * @param {string} context.ref - git ref to dispatch on
175
+ * @param {number} context.issueNumber
176
+ * @param {string} context.runId
177
+ * @param {string} context.step
178
+ * @param {number} context.iteration
179
+ * @param {object} context.runtime - resolved runtime entry
180
+ * @param {string} context.runtimeName
181
+ * @param {object} [context.env] - injectable env (for tests)
182
+ * @returns {Promise<{ dispatched: true, retries: number, workflow: string }>}
183
+ */
184
+ async function invoke(context) {
185
+ const env = context.env ?? process.env;
186
+ // Trigger credential check (throws on absence) but never expose value:
187
+ resolveCredential(context.runtime, env);
188
+
189
+ const workflow = `copilot-agent-${context.agent}.yml`;
190
+ const dispatchRef = context.ref ?? 'main';
191
+ const inputs = {
192
+ issue_number: String(context.issueNumber),
193
+ run_id: context.runId ?? '',
194
+ step: context.step ?? '',
195
+ iteration: String(context.iteration ?? 1),
196
+ runtime: context.runtimeName ?? '',
197
+ };
198
+
199
+ const { retries } = await (0,_retry_js__WEBPACK_IMPORTED_MODULE_0__.withRetry)(
200
+ () => context.client.triggerWorkflow(context.owner, context.repo, workflow, dispatchRef, inputs),
201
+ { clock: context.clock }
202
+ );
203
+ return { dispatched: true, retries, workflow };
204
+ }
205
+
206
+
207
+ /***/ })
208
+
209
+ };
210
+
211
+ //# sourceMappingURL=992.index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"992.index.js","mappings":";;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","sources":[".././orchestrator/runtimes/_retry.js",".././orchestrator/runtimes/copilot.js"],"sourcesContent":["/**\n * runtimes/_retry.js\n * Bounded exponential-backoff retry helper shared by all runtime adapters\n * (ADR-007 §8, FR-030).\n *\n * Policy (defaults): 3 attempts, base 2 s, jitter ±25 %, max wait 30 s total.\n * Retries are triggered by network errors, HTTP 5xx, and HTTP 429 (rate-limit).\n * Non-retryable errors are rethrown immediately.\n *\n * Returns the function's resolved value plus the number of retries used,\n * so the caller can record `runtime_retries` in the audit comment without\n * counting the invocation as a separate loop-budget iteration.\n */\n\nconst DEFAULT_OPTS = Object.freeze({\n maxAttempts: 3,\n baseMs: 2_000,\n maxTotalMs: 30_000,\n jitter: 0.25,\n});\n\n/**\n * Determine whether an error is retryable.\n * @param {any} err\n * @returns {boolean}\n */\nexport function isRetryable(err) {\n if (!err) return false;\n // Octokit / fetch error styles\n if (err.status === 429) return true;\n if (typeof err.status === 'number' && err.status >= 500 && err.status < 600) return true;\n // Node fetch network errors\n const code = err.code ?? err.cause?.code;\n if (code && /^(ECONNRESET|ETIMEDOUT|ENETUNREACH|EAI_AGAIN|UND_ERR_SOCKET)$/.test(code)) return true;\n if (typeof err.message === 'string' && /timeout|network/i.test(err.message)) return true;\n return false;\n}\n\n/**\n * Run `fn` with bounded exponential backoff.\n *\n * @template T\n * @param {() => Promise<T>} fn\n * @param {object} [options]\n * @param {object} [options.clock] - injectable clock { now(): number, sleep(ms): Promise<void> }\n * @returns {Promise<{ value: T, retries: number }>}\n */\nexport async function withRetry(fn, options = {}) {\n const opts = { ...DEFAULT_OPTS, ...options };\n const clock = options.clock ?? defaultClock;\n\n const start = clock.now();\n let attempt = 0;\n let lastError;\n\n while (attempt < opts.maxAttempts) {\n try {\n const value = await fn();\n return { value, retries: attempt };\n } catch (err) {\n lastError = err;\n attempt += 1;\n if (!isRetryable(err) || attempt >= opts.maxAttempts) break;\n\n const elapsed = clock.now() - start;\n if (elapsed >= opts.maxTotalMs) break;\n\n const exp = Math.pow(2, attempt - 1) * opts.baseMs;\n const jitter = exp * opts.jitter * (Math.random() * 2 - 1);\n const wait = Math.max(0, Math.min(exp + jitter, opts.maxTotalMs - elapsed));\n await clock.sleep(wait);\n }\n }\n\n throw lastError;\n}\n\nconst defaultClock = {\n now: () => Date.now(),\n sleep: ms => new Promise(r => setTimeout(r, ms)),\n};\n","/**\n * runtimes/copilot.js\n * Adapter for the Copilot (GitHub Models) runtime kind (ADR-005, ADR-003).\n *\n * Dispatches the agent's Copilot workflow file (`copilot-agent-<slug>.yml`)\n * via repository_dispatch / workflow_dispatch through the supplied client.\n * Wraps the call in the shared bounded-backoff retry helper (ADR-007 §8).\n *\n * The adapter is purely a dispatch layer — the LLM call itself happens\n * inside the dispatched GHA workflow, where the GITHUB_TOKEN is already\n * scoped via the workflow file. No secret value ever crosses this module.\n *\n * Exports:\n * requiredPermissions — GH Actions token scopes consumed by this kind\n * invoke(context) — dispatch entry point\n */\n\nimport { withRetry } from './_retry.js';\n\nexport const KIND = 'copilot';\n\n/**\n * Permissions consumed by the dispatched copilot workflow. The orchestrator\n * unions these with the scopes of every other adapter actually used at run\n * time (ADR-007 §7) when composing dispatched workflow `permissions:` blocks.\n */\nexport const requiredPermissions = Object.freeze({\n contents: 'read',\n issues: 'write',\n 'pull-requests': 'write',\n models: 'read', // GitHub Models inference\n});\n\n/**\n * Resolve the credential for a runtime entry. Returns the env var value or\n * throws { code: 'runtime-credential-missing', credential_ref } if absent.\n *\n * NEVER returns the value to a caller that logs/comments — only the dispatch\n * call uses it, and only the *name* (credential_ref) is recorded in audits.\n */\nfunction resolveCredential(runtime, env = process.env) {\n const ref = runtime.credential_ref;\n if (!ref) {\n const e = new Error('runtime-credential-missing');\n e.code = 'runtime-credential-missing';\n e.credential_ref = '(none declared)';\n throw e;\n }\n const value = env[ref];\n if (!value) {\n const e = new Error('runtime-credential-missing');\n e.code = 'runtime-credential-missing';\n e.credential_ref = ref;\n throw e;\n }\n return value;\n}\n\n/**\n * Invoke the runtime for one step.\n *\n * @param {object} context\n * @param {object} context.client - GitHub client with triggerWorkflow()\n * @param {string} context.owner\n * @param {string} context.repo\n * @param {string} context.agent - agent slug (e.g. \"qa-agent\")\n * @param {string} context.ref - git ref to dispatch on\n * @param {number} context.issueNumber\n * @param {string} context.runId\n * @param {string} context.step\n * @param {number} context.iteration\n * @param {object} context.runtime - resolved runtime entry\n * @param {string} context.runtimeName\n * @param {object} [context.env] - injectable env (for tests)\n * @returns {Promise<{ dispatched: true, retries: number, workflow: string }>}\n */\nexport async function invoke(context) {\n const env = context.env ?? process.env;\n // Trigger credential check (throws on absence) but never expose value:\n resolveCredential(context.runtime, env);\n\n const workflow = `copilot-agent-${context.agent}.yml`;\n const dispatchRef = context.ref ?? 'main';\n const inputs = {\n issue_number: String(context.issueNumber),\n run_id: context.runId ?? '',\n step: context.step ?? '',\n iteration: String(context.iteration ?? 1),\n runtime: context.runtimeName ?? '',\n };\n\n const { retries } = await withRetry(\n () => context.client.triggerWorkflow(context.owner, context.repo, workflow, dispatchRef, inputs),\n { clock: context.clock }\n );\n return { dispatched: true, retries, workflow };\n}\n"],"names":[],"sourceRoot":""}
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://apm.dev/schemas/agent-identities.schema.json",
4
+ "title": "QuorumKit Agent Identity Registry",
5
+ "description": "Maps GitHub user/app identities to agent slugs (FR-013).",
6
+ "type": "object",
7
+ "required": ["identities"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "identities": {
11
+ "type": "array",
12
+ "minItems": 1,
13
+ "items": {
14
+ "type": "object",
15
+ "required": ["agent", "logins"],
16
+ "additionalProperties": false,
17
+ "properties": {
18
+ "agent": {
19
+ "type": "string",
20
+ "minLength": 1,
21
+ "description": "Agent slug (e.g. 'qa-agent')."
22
+ },
23
+ "logins": {
24
+ "type": "array",
25
+ "minItems": 1,
26
+ "items": { "type": "string", "minLength": 1 },
27
+ "description": "GitHub logins or app installation slugs that map to this agent."
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://apm.dev/schemas/apm-msg.schema.json",
4
+ "title": "QuorumKit Agent Message (apm-msg)",
5
+ "description": "Single machine-readable message emitted by an agent at the end of a step (FR-011, FR-012).",
6
+ "type": "object",
7
+ "required": ["version", "runId", "step", "agent", "iteration", "outcome", "summary"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "version": {
11
+ "type": "string",
12
+ "enum": ["2"],
13
+ "description": "apm-msg schema version. v2 is the only supported value."
14
+ },
15
+ "runId": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "description": "Pipeline run UUID; must equal the active run."
19
+ },
20
+ "step": {
21
+ "type": "string",
22
+ "minLength": 1,
23
+ "description": "Step name as declared in the pipeline."
24
+ },
25
+ "agent": {
26
+ "type": "string",
27
+ "minLength": 1,
28
+ "description": "Agent slug (e.g. 'qa-agent', 'dev-agent') matching the agent identity registry."
29
+ },
30
+ "iteration": {
31
+ "type": "integer",
32
+ "minimum": 1,
33
+ "description": "1-based iteration counter for the step on the current edge."
34
+ },
35
+ "outcome": {
36
+ "type": "string",
37
+ "enum": [
38
+ "success",
39
+ "fail",
40
+ "blocker",
41
+ "spec_gap",
42
+ "timeout",
43
+ "needs-human",
44
+ "runtime-error",
45
+ "protocol-violation",
46
+ "orchestrator-failure"
47
+ ],
48
+ "description": "Declared outcome enum. Source of truth: docs/AGENT_PROTOCOL.md."
49
+ },
50
+ "summary": {
51
+ "type": "string",
52
+ "minLength": 1,
53
+ "maxLength": 280,
54
+ "description": "Single-line human summary (max 280 chars)."
55
+ },
56
+ "payload": {
57
+ "type": "object",
58
+ "description": "Optional per-outcome payload. Schema is per-outcome; see regulation document.",
59
+ "additionalProperties": true
60
+ }
61
+ }
62
+ }