opencode-swarm 7.164.11 → 7.164.13
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.
- package/.opencode/skills/engineering-conventions/SKILL.md +1 -1
- package/.opencode/skills/loop/SKILL.md +1 -1
- package/.opencode/skills/{plan → swarm-plan}/SKILL.md +1 -1
- package/dist/background/pending-delegations.d.ts +7 -2
- package/dist/background/pr-subscriptions.d.ts +3 -3
- package/dist/cli/{coder-settlement-0rfk8y11.js → coder-settlement-em2fgg4p.js} +16 -17
- package/dist/cli/{config-doctor-j17b7qq2.js → config-doctor-1m4mrybp.js} +4 -4
- package/dist/cli/{core-evhjjrtt.js → core-zbzdffha.js} +3 -3
- package/dist/cli/{curation-policy-vj6z5hvr.js → curation-policy-bqpmry2n.js} +5 -6
- package/dist/cli/{curator-drift-ez81vg2t.js → curator-drift-hbc3w5zj.js} +14 -12
- package/dist/cli/curator-llm-factory-j76c96t7.js +70 -0
- package/dist/cli/{curator-vqd5yeck.js → curator-tn3x5j02.js} +49 -47
- package/dist/cli/{dispatch-dqybvj8v.js → dispatch-c7xjt7js.js} +3 -3
- package/dist/cli/{evidence-summary-service-937x7rbg.js → evidence-summary-service-7cn9z4sn.js} +25 -24
- package/dist/cli/{gate-evidence-q1cehr4k.js → gate-evidence-deyzt3hz.js} +10 -11
- package/dist/cli/guardrail-explain-4k2pqj46.js +71 -0
- package/dist/cli/{guardrail-log-3g93f3g2.js → guardrail-log-cnbv6vry.js} +11 -11
- package/dist/cli/{guardrail-reset-qe2r5qzq.js → guardrail-reset-xhh61cax.js} +49 -47
- package/dist/cli/hive-promoter-1m8zpz4d.js +85 -0
- package/dist/cli/{index-rhqdsc1x.js → index-0mwjamha.js} +9 -9
- package/dist/cli/{index-y1yqmkv7.js → index-3c0z1jnc.js} +56 -52
- package/dist/cli/{index-kch6yenm.js → index-4fhcbe14.js} +8 -8
- package/dist/cli/{index-ww6zm5hr.js → index-5ebgzb5a.js} +3 -3
- package/dist/cli/{index-4vb6qa73.js → index-5h60rtaa.js} +37 -3
- package/dist/cli/{index-w3gtqey0.js → index-6chhqq2n.js} +4 -4
- package/dist/cli/index-6m24v15v.js +429 -0
- package/dist/cli/{index-vdn32nws.js → index-6rx1rdaq.js} +3 -3
- package/dist/cli/{index-x43debgx.js → index-74514zkh.js} +15 -17
- package/dist/cli/{index-1ww7wj8d.js → index-7f2r3ysr.js} +41 -17
- package/dist/cli/{index-kc2tgcm7.js → index-7z9zqxqt.js} +4 -4
- package/dist/cli/{index-n8688d12.js → index-8bdk7124.js} +2 -2
- package/dist/cli/{index-3146wmgv.js → index-8d90gzaz.js} +1 -1
- package/dist/cli/{index-b2nj04q6.js → index-9ss2m4rs.js} +1 -434
- package/dist/cli/{index-50j914b5.js → index-a0d4fp6r.js} +29 -7
- package/dist/cli/{index-ggtmsm84.js → index-ajknebrc.js} +1 -1
- package/dist/cli/{index-zjg4chy2.js → index-anxs69ad.js} +2 -2
- package/dist/cli/{index-aqppaaqx.js → index-asey3tb3.js} +6 -4
- package/dist/cli/{index-kv2tdkk5.js → index-bvkd7at6.js} +1 -1
- package/dist/cli/{index-r656jh9j.js → index-c98rjgjq.js} +4301 -2877
- package/dist/cli/{index-r5q5gd2a.js → index-d224mhr9.js} +3 -3
- package/dist/cli/{index-nqsj0g5y.js → index-dh5th4jn.js} +8 -8
- package/dist/cli/index-e45htt92.js +361 -0
- package/dist/cli/{index-w95vxjde.js → index-f36hy1x4.js} +39 -8
- package/dist/cli/{index-hp22pzn5.js → index-f8jdar6q.js} +2 -2
- package/dist/cli/{index-47kh2103.js → index-fnyw5rzg.js} +14 -14
- package/dist/cli/{index-7m32fjb4.js → index-g11h1qpk.js} +9 -9
- package/dist/cli/{index-d9entpn3.js → index-g9weyhq6.js} +4 -4
- package/dist/cli/{index-qbw3yw2d.js → index-grn6tkbt.js} +11 -11
- package/dist/cli/{index-9gxbjkts.js → index-gy0nyfbw.js} +24 -21
- package/dist/cli/{index-5jx22kwc.js → index-hhzzyjm3.js} +544 -15
- package/dist/cli/{index-dsg9dw3b.js → index-j2svfhzk.js} +2 -2
- package/dist/cli/{index-2bgr671r.js → index-jre6tm3v.js} +20 -2
- package/dist/cli/{index-77z98j76.js → index-mpf1tvwf.js} +314 -130
- package/dist/cli/{index-e90em0x4.js → index-ndjjvxzz.js} +12 -17
- package/dist/cli/{index-r3mvsbtq.js → index-p612v1mv.js} +7 -1
- package/dist/cli/{index-zfs3zqeq.js → index-ptsqnxwd.js} +771 -21
- package/dist/cli/{index-ggrp3v00.js → index-qtxevgdx.js} +15 -17
- package/dist/cli/{index-c5v1w13g.js → index-s3k7xbqd.js} +807 -629
- package/dist/cli/{index-pp2nya9v.js → index-tqw8w2n5.js} +2 -4
- package/dist/cli/index-w6988bbc.js +675 -0
- package/dist/cli/{index-4gqxppcx.js → index-xwbn7c8m.js} +2 -2
- package/dist/cli/{index-mmjamc9b.js → index-y5hfk7ya.js} +6 -6
- package/dist/cli/{index-5kcvrpkt.js → index-zb6gdym8.js} +2 -2
- package/dist/cli/index.js +161 -80
- package/dist/cli/{knowledge-escalator-j04g450p.js → knowledge-escalator-3fax9y3s.js} +18 -19
- package/dist/cli/{knowledge-events-53z45rs0.js → knowledge-events-9cpdyhmb.js} +16 -17
- package/dist/cli/{knowledge-link-a6kfg3qm.js → knowledge-link-dgvbqjqg.js} +4 -5
- package/dist/cli/{knowledge-store-whm0gagt.js → knowledge-store-y35rka0p.js} +6 -7
- package/dist/cli/{knowledge-validator-h8m7065g.js → knowledge-validator-fd761gpx.js} +8 -9
- package/dist/cli/{model-preflight-288nsgpw.js → model-preflight-3s1c0zpc.js} +1 -1
- package/dist/cli/{pending-delegations-6hkpe5ze.js → pending-delegations-t3y19j3n.js} +17 -8
- package/dist/cli/{pr-subscriptions-11zca1mh.js → pr-subscriptions-00zp69mt.js} +17 -8
- package/dist/cli/{pr-workflow-gate-6g29rkg7.js → pr-workflow-gate-2h0j8c92.js} +51 -49
- package/dist/cli/{runner-5abw3t35.js → runner-0e3bjeev.js} +6 -7
- package/dist/cli/{scan-cursor-mkfx410t.js → scan-cursor-wppe2gxw.js} +9 -10
- package/dist/cli/{schema-jbbam3ev.js → schema-sec49ppy.js} +2 -2
- package/dist/cli/{scope-persistence-q1ct4k42.js → scope-persistence-59eyqaz4.js} +20 -13
- package/dist/cli/{skill-generator-cv8fg96x.js → skill-generator-56rbmpj7.js} +21 -22
- package/dist/cli/snapshot-coordination-init-dnkdc7gx.js +84 -0
- package/dist/cli/{telemetry-mbqqamsj.js → telemetry-a1yvjerj.js} +1 -1
- package/dist/cli/{workspace-snapshot-eh18vgkn.js → workspace-snapshot-6z9rk7xw.js} +3 -3
- package/dist/cli/{worktree-collision-ownership-xgnn8dsq.js → worktree-collision-ownership-fj9n4mhk.js} +21 -12
- package/dist/cli/{worktree-isolation-k2dgfmeg.js → worktree-isolation-vd1s86ya.js} +49 -47
- package/dist/commands/benchmark.d.ts +5 -1
- package/dist/commands/close.d.ts +13 -6
- package/dist/commands/registry.d.ts +34 -43
- package/dist/commands/reset-session.d.ts +4 -0
- package/dist/commands/turbo.d.ts +1 -1
- package/dist/config/bundled-skills.d.ts +4 -3
- package/dist/config/constants.d.ts +13 -0
- package/dist/db/coordination-store.d.ts +85 -0
- package/dist/db/durability.d.ts +22 -5
- package/dist/db/index.d.ts +1 -0
- package/dist/db/project-db.d.ts +12 -0
- package/dist/hooks/extractors.d.ts +9 -0
- package/dist/hooks/non-architect-advisory.d.ts +18 -0
- package/dist/hooks/repo-graph-injection.d.ts +16 -0
- package/dist/index.js +837 -730
- package/dist/memory/schema.d.ts +3 -3
- package/dist/pr-review/authorization.d.ts +5 -4
- package/dist/pr-review/persistence.d.ts +10 -1
- package/dist/scope/scope-binding.d.ts +10 -0
- package/dist/scope/scope-persistence.d.ts +10 -0
- package/dist/services/decision-drift-analyzer.d.ts +7 -0
- package/dist/services/handoff-service.d.ts +12 -0
- package/dist/services/status-service.d.ts +31 -0
- package/dist/session/snapshot-coordination-init.d.ts +49 -0
- package/dist/session/snapshot-reader.d.ts +2 -0
- package/dist/session/snapshot-store.d.ts +42 -0
- package/dist/session/snapshot-writer.d.ts +4 -1
- package/dist/state.d.ts +14 -3
- package/dist/tools/repo-graph/builder.d.ts +1 -25
- package/dist/tools/repo-graph/cache.d.ts +5 -1
- package/dist/tools/repo-graph/fallback-scanner.d.ts +71 -0
- package/dist/tools/repo-graph/indexed-storage.d.ts +11 -0
- package/dist/tools/repo-graph/storage.d.ts +7 -0
- package/dist/turbo/epic/state.d.ts +4 -20
- package/dist/utils/bun-compat.d.ts +10 -0
- package/dist/utils/context-decisions.d.ts +77 -0
- package/dist/utils/external-tool-runner.d.ts +2 -0
- package/dist/utils/sanitize-display.d.ts +7 -0
- package/package.json +5 -3
- package/dist/cli/curator-llm-factory-sxcpmcqq.js +0 -68
- package/dist/cli/guardrail-explain-xv9aw1bf.js +0 -69
- package/dist/cli/hive-promoter-09yc9mp5.js +0 -83
- package/dist/cli/index-xnb3tk7x.js +0 -24
- package/dist/cli/{ast-diff-ekd9v10f.js → ast-diff-b0esr2kf.js} +3 -3
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
derivePlanId,
|
|
4
|
+
derivePlanIdentityHash
|
|
5
|
+
} from "./index-e45htt92.js";
|
|
6
|
+
import {
|
|
7
|
+
DURABILITY_CLASSES,
|
|
8
|
+
getProjectDb,
|
|
9
|
+
projectDbExists,
|
|
10
|
+
withImmediateTransaction
|
|
11
|
+
} from "./index-w6988bbc.js";
|
|
12
|
+
import {
|
|
13
|
+
init_logger,
|
|
14
|
+
warn
|
|
15
|
+
} from "./index-zgwm4ryv.js";
|
|
16
|
+
// src/db/qa-gate-profile.ts
|
|
17
|
+
import { createHash } from "crypto";
|
|
18
|
+
|
|
19
|
+
// src/qa-gate/recovery.ts
|
|
20
|
+
function formatLegacyQaBindingOnlyCall(identity) {
|
|
21
|
+
return `set_qa_gates({ swarm_id: ${JSON.stringify(identity.swarm)}, plan_title: ${JSON.stringify(identity.title)}, adopt_legacy_binding_only: true })`;
|
|
22
|
+
}
|
|
23
|
+
function formatLegacyQaBindingRecovery(identity, retryAction) {
|
|
24
|
+
return `Run ${formatLegacyQaBindingOnlyCall(identity)} from the current persisted plan identity to exact-bind the existing QA profile without changing gates or its lock, then ${retryAction}.`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/db/qa-gate-profile.ts
|
|
28
|
+
init_logger();
|
|
29
|
+
var _internals = {
|
|
30
|
+
getProfile,
|
|
31
|
+
getProfileLookupForIdentity,
|
|
32
|
+
getProfileForIdentity,
|
|
33
|
+
getOrCreateProfile,
|
|
34
|
+
getOrCreateProfileForIdentity,
|
|
35
|
+
setGates,
|
|
36
|
+
setGatesForIdentity,
|
|
37
|
+
lockProfileForIdentity,
|
|
38
|
+
getEffectiveGates,
|
|
39
|
+
computeProfileHash,
|
|
40
|
+
hasAnyProfileWithEnabledGate,
|
|
41
|
+
afterSetGatesRead: () => {},
|
|
42
|
+
lastTxnSynchronous: -1
|
|
43
|
+
};
|
|
44
|
+
var DEFAULT_QA_GATES = {
|
|
45
|
+
reviewer: true,
|
|
46
|
+
test_engineer: true,
|
|
47
|
+
council_mode: false,
|
|
48
|
+
sme_enabled: true,
|
|
49
|
+
critic_pre_plan: true,
|
|
50
|
+
hallucination_guard: false,
|
|
51
|
+
sast_enabled: true,
|
|
52
|
+
mutation_test: false,
|
|
53
|
+
phase_council: false,
|
|
54
|
+
drift_check: true,
|
|
55
|
+
final_council: false
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
class QaGateProfileIdentityUnboundError extends Error {
|
|
59
|
+
identity;
|
|
60
|
+
constructor(identity) {
|
|
61
|
+
super(`QA gate profile exists for readable plan_id='${identity.planId}' but is not exact-bound to swarm_id='${identity.swarm}' and plan_title='${identity.title}'. ${formatLegacyQaBindingRecovery(identity, "retry the blocked read-only or enforcement operation")}`);
|
|
62
|
+
this.name = "QaGateProfileIdentityUnboundError";
|
|
63
|
+
this.identity = identity;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function buildProfileIdentity(identity) {
|
|
67
|
+
return {
|
|
68
|
+
swarm: identity.swarm,
|
|
69
|
+
title: identity.title,
|
|
70
|
+
planId: derivePlanId(identity),
|
|
71
|
+
identityHash: derivePlanIdentityHash(identity)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function withImmediateTransaction2(db, fn) {
|
|
75
|
+
return withImmediateTransaction(db, DURABILITY_CLASSES.qa_gate_profile, fn, {
|
|
76
|
+
beforeOuterCommit: (connection) => {
|
|
77
|
+
_internals.lastTxnSynchronous = connection.query("PRAGMA synchronous").get()?.synchronous ?? -1;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function rowToProfile(row) {
|
|
82
|
+
return rowToProfileWithBinding(row);
|
|
83
|
+
}
|
|
84
|
+
function rowToProfileWithBinding(row, binding) {
|
|
85
|
+
let parsed = {};
|
|
86
|
+
try {
|
|
87
|
+
const maybeGates = JSON.parse(row.gates);
|
|
88
|
+
if (maybeGates && typeof maybeGates === "object" && !Array.isArray(maybeGates)) {
|
|
89
|
+
parsed = maybeGates;
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
parsed = {};
|
|
93
|
+
}
|
|
94
|
+
const raw = parsed;
|
|
95
|
+
if (raw.council_mode === true && raw.phase_council === undefined) {
|
|
96
|
+
parsed.phase_council = true;
|
|
97
|
+
parsed.council_mode = false;
|
|
98
|
+
}
|
|
99
|
+
const knownKeys = new Set(Object.keys(DEFAULT_QA_GATES));
|
|
100
|
+
const filteredParsed = {};
|
|
101
|
+
for (const key of Object.keys(parsed)) {
|
|
102
|
+
if (knownKeys.has(key) && typeof parsed[key] === "boolean") {
|
|
103
|
+
filteredParsed[key] = parsed[key];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const gates = { ...DEFAULT_QA_GATES, ...filteredParsed };
|
|
107
|
+
return {
|
|
108
|
+
id: row.id,
|
|
109
|
+
plan_id: binding?.readable_plan_id ?? row.plan_id,
|
|
110
|
+
created_at: row.created_at,
|
|
111
|
+
project_type: row.project_type,
|
|
112
|
+
gates,
|
|
113
|
+
locked_at: row.locked_at,
|
|
114
|
+
locked_by_snapshot_seq: row.locked_by_snapshot_seq,
|
|
115
|
+
raw_swarm: binding?.raw_swarm ?? row.raw_swarm,
|
|
116
|
+
raw_title: binding?.raw_title ?? row.raw_title,
|
|
117
|
+
identity_hash: binding?.identity_hash ?? row.identity_hash
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function readProfileRowByPlanId(db, planId) {
|
|
121
|
+
return db.query("SELECT * FROM qa_gate_profile WHERE plan_id = ?").get(planId) ?? null;
|
|
122
|
+
}
|
|
123
|
+
function readProfileRowById(db, id) {
|
|
124
|
+
return db.query("SELECT * FROM qa_gate_profile WHERE id = ?").get(id) ?? null;
|
|
125
|
+
}
|
|
126
|
+
function readIdentityBindingByHash(db, identityHash) {
|
|
127
|
+
return db.query("SELECT * FROM qa_gate_profile_identity WHERE identity_hash = ?").get(identityHash) ?? null;
|
|
128
|
+
}
|
|
129
|
+
function readUnboundLegacyProfileRowByReadablePlanId(db, readablePlanId) {
|
|
130
|
+
return db.query(`SELECT p.*
|
|
131
|
+
FROM qa_gate_profile AS p
|
|
132
|
+
LEFT JOIN qa_gate_profile_identity AS qi
|
|
133
|
+
ON qi.profile_id = p.id
|
|
134
|
+
WHERE p.plan_id = ?
|
|
135
|
+
AND qi.profile_id IS NULL
|
|
136
|
+
LIMIT 1`).get(readablePlanId) ?? null;
|
|
137
|
+
}
|
|
138
|
+
function buildExactStoragePlanId(identityHash) {
|
|
139
|
+
return `qa2-${identityHash}`;
|
|
140
|
+
}
|
|
141
|
+
function hasAnyGatePatch(gates) {
|
|
142
|
+
return Object.values(gates).some((value) => value !== undefined);
|
|
143
|
+
}
|
|
144
|
+
function verifyBoundIdentityBinding(binding, identity) {
|
|
145
|
+
if (binding.identity_hash !== identity.identityHash || binding.raw_swarm !== identity.swarm || binding.raw_title !== identity.title || binding.readable_plan_id !== identity.planId) {
|
|
146
|
+
throw new Error(`QA gate profile identity binding is corrupt for swarm_id='${identity.swarm}' and plan_title='${identity.title}'`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function lookupProfileForIdentityTx(db, identity) {
|
|
150
|
+
const binding = readIdentityBindingByHash(db, identity.identityHash);
|
|
151
|
+
if (binding) {
|
|
152
|
+
verifyBoundIdentityBinding(binding, identity);
|
|
153
|
+
const row = readProfileRowById(db, binding.profile_id);
|
|
154
|
+
if (!row) {
|
|
155
|
+
throw new Error(`QA gate profile identity binding points to missing profile_id=${binding.profile_id}`);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
kind: "bound",
|
|
159
|
+
identity,
|
|
160
|
+
profile: rowToProfileWithBinding(row, binding)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const legacyRow = readUnboundLegacyProfileRowByReadablePlanId(db, identity.planId);
|
|
164
|
+
if (legacyRow) {
|
|
165
|
+
return {
|
|
166
|
+
kind: "unbound_legacy",
|
|
167
|
+
identity,
|
|
168
|
+
profile: rowToProfile(legacyRow)
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
kind: "missing",
|
|
173
|
+
identity
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function createExactIdentityBindingTx(db, profileId, identity) {
|
|
177
|
+
db.run("INSERT INTO qa_gate_profile_identity (identity_hash, profile_id, raw_swarm, raw_title, readable_plan_id) VALUES (?, ?, ?, ?, ?)", [
|
|
178
|
+
identity.identityHash,
|
|
179
|
+
profileId,
|
|
180
|
+
identity.swarm,
|
|
181
|
+
identity.title,
|
|
182
|
+
identity.planId
|
|
183
|
+
]);
|
|
184
|
+
}
|
|
185
|
+
function createExactProfileTx(db, identity, projectType, initialGates) {
|
|
186
|
+
const gatesJson = JSON.stringify({ ...DEFAULT_QA_GATES, ...initialGates });
|
|
187
|
+
db.run("INSERT INTO qa_gate_profile (plan_id, project_type, gates) VALUES (?, ?, ?)", [
|
|
188
|
+
buildExactStoragePlanId(identity.identityHash),
|
|
189
|
+
projectType ?? null,
|
|
190
|
+
gatesJson
|
|
191
|
+
]);
|
|
192
|
+
const row = readProfileRowByPlanId(db, buildExactStoragePlanId(identity.identityHash));
|
|
193
|
+
if (!row) {
|
|
194
|
+
throw new Error(`Failed to create QA gate profile row for exact identity plan_id=${identity.planId}`);
|
|
195
|
+
}
|
|
196
|
+
createExactIdentityBindingTx(db, row.id, identity);
|
|
197
|
+
const binding = readIdentityBindingByHash(db, identity.identityHash);
|
|
198
|
+
if (!binding) {
|
|
199
|
+
throw new Error(`Failed to create QA gate profile identity binding for plan_id=${identity.planId}`);
|
|
200
|
+
}
|
|
201
|
+
return rowToProfileWithBinding(row, binding);
|
|
202
|
+
}
|
|
203
|
+
function shouldAdoptLegacyProfile(identity, options) {
|
|
204
|
+
if (options.allowLegacyAdoption !== true) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
return options.legacyAdoptionIdentity?.swarm === identity.swarm && options.legacyAdoptionIdentity?.title === identity.title;
|
|
208
|
+
}
|
|
209
|
+
function getProfile(directory, planId) {
|
|
210
|
+
if (!projectDbExists(directory))
|
|
211
|
+
return null;
|
|
212
|
+
const db = getProjectDb(directory);
|
|
213
|
+
const row = readProfileRowByPlanId(db, planId);
|
|
214
|
+
return row ? rowToProfile(row) : null;
|
|
215
|
+
}
|
|
216
|
+
function getProfileForIdentity(directory, identity) {
|
|
217
|
+
const lookup = getProfileLookupForIdentity(directory, identity);
|
|
218
|
+
if (lookup.kind === "bound") {
|
|
219
|
+
return lookup.profile;
|
|
220
|
+
}
|
|
221
|
+
if (lookup.kind === "unbound_legacy") {
|
|
222
|
+
throw new QaGateProfileIdentityUnboundError(lookup.identity);
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
function getProfileLookupForIdentity(directory, identity) {
|
|
227
|
+
const exact = buildProfileIdentity(identity);
|
|
228
|
+
if (!projectDbExists(directory)) {
|
|
229
|
+
return {
|
|
230
|
+
kind: "missing",
|
|
231
|
+
identity: exact
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const db = getProjectDb(directory);
|
|
235
|
+
return lookupProfileForIdentityTx(db, exact);
|
|
236
|
+
}
|
|
237
|
+
function hasAnyProfileWithEnabledGate(directory, gate) {
|
|
238
|
+
if (!projectDbExists(directory))
|
|
239
|
+
return false;
|
|
240
|
+
const db = getProjectDb(directory);
|
|
241
|
+
const rows = db.query("SELECT gates FROM qa_gate_profile").all();
|
|
242
|
+
for (const row of rows) {
|
|
243
|
+
try {
|
|
244
|
+
const parsed = JSON.parse(row.gates);
|
|
245
|
+
if (parsed?.[gate] === true)
|
|
246
|
+
return true;
|
|
247
|
+
} catch (err) {
|
|
248
|
+
warn(`[qa-gate-profile] skipping unparseable qa_gate_profile row while checking gate "${gate}": ${err instanceof Error ? err.message : String(err)}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
function getOrCreateProfile(directory, planId, projectType, initialGates = {}) {
|
|
254
|
+
const existing = _internals.getProfile(directory, planId);
|
|
255
|
+
if (existing)
|
|
256
|
+
return existing;
|
|
257
|
+
const db = getProjectDb(directory);
|
|
258
|
+
const seededGates = { ...DEFAULT_QA_GATES };
|
|
259
|
+
for (const key of Object.keys(DEFAULT_QA_GATES)) {
|
|
260
|
+
if (typeof initialGates[key] === "boolean") {
|
|
261
|
+
seededGates[key] = initialGates[key];
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const gatesJson = JSON.stringify(seededGates);
|
|
265
|
+
try {
|
|
266
|
+
withImmediateTransaction2(db, () => {
|
|
267
|
+
db.run("INSERT INTO qa_gate_profile (plan_id, project_type, gates) VALUES (?, ?, ?)", [planId, projectType ?? null, gatesJson]);
|
|
268
|
+
});
|
|
269
|
+
} catch (err) {
|
|
270
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
271
|
+
if (!msg.toLowerCase().includes("unique")) {
|
|
272
|
+
throw err;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const after = _internals.getProfile(directory, planId);
|
|
276
|
+
if (!after) {
|
|
277
|
+
throw new Error(`Failed to create or load QA gate profile for plan_id=${planId}`);
|
|
278
|
+
}
|
|
279
|
+
return after;
|
|
280
|
+
}
|
|
281
|
+
function getOrCreateProfileForIdentity(directory, identity, projectType, initialGates = {}) {
|
|
282
|
+
const db = getProjectDb(directory);
|
|
283
|
+
const exact = buildProfileIdentity(identity);
|
|
284
|
+
return withImmediateTransaction2(db, () => {
|
|
285
|
+
const lookup = lookupProfileForIdentityTx(db, exact);
|
|
286
|
+
if (lookup.kind === "bound") {
|
|
287
|
+
return lookup.profile;
|
|
288
|
+
}
|
|
289
|
+
return createExactProfileTx(db, exact, projectType, initialGates);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
function setGates(directory, planId, gates) {
|
|
293
|
+
const db = getProjectDb(directory);
|
|
294
|
+
return withImmediateTransaction2(db, () => {
|
|
295
|
+
const currentRow = db.query("SELECT * FROM qa_gate_profile WHERE plan_id = ?").get(planId);
|
|
296
|
+
if (!currentRow) {
|
|
297
|
+
throw new Error(`No QA gate profile found for plan_id=${planId} \u2014 call getOrCreateProfile first`);
|
|
298
|
+
}
|
|
299
|
+
const current = rowToProfile(currentRow);
|
|
300
|
+
if (current.locked_at !== null) {
|
|
301
|
+
throw new Error("Cannot modify gates: QA gate profile is locked after critic approval");
|
|
302
|
+
}
|
|
303
|
+
_internals.afterSetGatesRead(current);
|
|
304
|
+
const merged = { ...current.gates };
|
|
305
|
+
for (const key of Object.keys(gates)) {
|
|
306
|
+
const incoming = gates[key];
|
|
307
|
+
if (incoming === undefined)
|
|
308
|
+
continue;
|
|
309
|
+
if (incoming === false && current.gates[key] === true) {
|
|
310
|
+
throw new Error(`Cannot disable gate '${key}': sessions can only ratchet tighter`);
|
|
311
|
+
}
|
|
312
|
+
if (incoming === true) {
|
|
313
|
+
merged[key] = true;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
db.run("UPDATE qa_gate_profile SET gates = ? WHERE plan_id = ?", [
|
|
317
|
+
JSON.stringify(merged),
|
|
318
|
+
planId
|
|
319
|
+
]);
|
|
320
|
+
const updatedRow = db.query("SELECT * FROM qa_gate_profile WHERE plan_id = ?").get(planId);
|
|
321
|
+
if (!updatedRow) {
|
|
322
|
+
throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
|
|
323
|
+
}
|
|
324
|
+
return rowToProfile(updatedRow);
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function setGatesForIdentity(directory, identity, gates, options = {}) {
|
|
328
|
+
const db = getProjectDb(directory);
|
|
329
|
+
const exact = buildProfileIdentity(identity);
|
|
330
|
+
return withImmediateTransaction2(db, () => {
|
|
331
|
+
let lookup = lookupProfileForIdentityTx(db, exact);
|
|
332
|
+
if (lookup.kind === "missing") {
|
|
333
|
+
return createExactProfileTx(db, exact, options.projectType, gates);
|
|
334
|
+
}
|
|
335
|
+
if (lookup.kind === "unbound_legacy") {
|
|
336
|
+
if (shouldAdoptLegacyProfile(exact, options)) {
|
|
337
|
+
createExactIdentityBindingTx(db, lookup.profile.id, exact);
|
|
338
|
+
lookup = lookupProfileForIdentityTx(db, exact);
|
|
339
|
+
if (lookup.kind !== "bound") {
|
|
340
|
+
throw new Error(`Failed to adopt legacy QA gate profile for exact identity plan_id=${exact.planId}`);
|
|
341
|
+
}
|
|
342
|
+
} else if (options.allowLegacyCollisionCreate === true) {
|
|
343
|
+
return createExactProfileTx(db, exact, options.projectType, gates);
|
|
344
|
+
} else {
|
|
345
|
+
throw new QaGateProfileIdentityUnboundError(lookup.identity);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const current = lookup.profile;
|
|
349
|
+
const currentRow = readProfileRowById(db, current.id);
|
|
350
|
+
if (!currentRow) {
|
|
351
|
+
throw new Error(`Failed to read QA gate profile row for profile_id=${current.id}`);
|
|
352
|
+
}
|
|
353
|
+
_internals.afterSetGatesForIdentityRead?.({
|
|
354
|
+
directory,
|
|
355
|
+
identity: exact,
|
|
356
|
+
profileId: current.id,
|
|
357
|
+
storagePlanId: currentRow.plan_id
|
|
358
|
+
});
|
|
359
|
+
if (current.locked_at !== null) {
|
|
360
|
+
if (!hasAnyGatePatch(gates)) {
|
|
361
|
+
return current;
|
|
362
|
+
}
|
|
363
|
+
throw new Error("Cannot modify gates: QA gate profile is locked after critic approval");
|
|
364
|
+
}
|
|
365
|
+
const merged = { ...current.gates };
|
|
366
|
+
for (const key of Object.keys(gates)) {
|
|
367
|
+
const incoming = gates[key];
|
|
368
|
+
if (incoming === undefined)
|
|
369
|
+
continue;
|
|
370
|
+
if (incoming === false && current.gates[key] === true) {
|
|
371
|
+
throw new Error(`Cannot disable gate '${key}': sessions can only ratchet tighter`);
|
|
372
|
+
}
|
|
373
|
+
if (incoming === true) {
|
|
374
|
+
merged[key] = true;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
db.run("UPDATE qa_gate_profile SET gates = ? WHERE id = ?", [
|
|
378
|
+
JSON.stringify(merged),
|
|
379
|
+
current.id
|
|
380
|
+
]);
|
|
381
|
+
const updatedRow = readProfileRowById(db, current.id);
|
|
382
|
+
const binding = readIdentityBindingByHash(db, exact.identityHash);
|
|
383
|
+
if (!updatedRow || !binding) {
|
|
384
|
+
throw new Error(`Failed to re-read QA gate profile after exact-identity update for plan_id=${exact.planId}`);
|
|
385
|
+
}
|
|
386
|
+
return rowToProfileWithBinding(updatedRow, binding);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
function lockProfileForIdentity(directory, identity, snapshotSeq) {
|
|
390
|
+
const db = getProjectDb(directory);
|
|
391
|
+
const exact = buildProfileIdentity(identity);
|
|
392
|
+
return withImmediateTransaction2(db, () => {
|
|
393
|
+
const lookup = lookupProfileForIdentityTx(db, exact);
|
|
394
|
+
if (lookup.kind === "missing") {
|
|
395
|
+
throw new Error(`No QA gate profile found for exact identity plan_id=${exact.planId} \u2014 cannot lock`);
|
|
396
|
+
}
|
|
397
|
+
if (lookup.kind === "unbound_legacy") {
|
|
398
|
+
throw new QaGateProfileIdentityUnboundError(lookup.identity);
|
|
399
|
+
}
|
|
400
|
+
if (lookup.profile.locked_at !== null) {
|
|
401
|
+
return lookup.profile;
|
|
402
|
+
}
|
|
403
|
+
db.run("UPDATE qa_gate_profile SET locked_at = datetime('now'), locked_by_snapshot_seq = ? WHERE id = ?", [snapshotSeq, lookup.profile.id]);
|
|
404
|
+
const updatedRow = readProfileRowById(db, lookup.profile.id);
|
|
405
|
+
const binding = readIdentityBindingByHash(db, exact.identityHash);
|
|
406
|
+
if (!updatedRow || !binding) {
|
|
407
|
+
throw new Error(`Failed to re-read locked QA gate profile for exact identity plan_id=${exact.planId}`);
|
|
408
|
+
}
|
|
409
|
+
return rowToProfileWithBinding(updatedRow, binding);
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function computeProfileHash(profile) {
|
|
413
|
+
const payload = JSON.stringify({
|
|
414
|
+
plan_id: profile.plan_id,
|
|
415
|
+
identity_hash: profile.identity_hash,
|
|
416
|
+
gates: profile.gates
|
|
417
|
+
});
|
|
418
|
+
return createHash("sha256").update(payload).digest("hex");
|
|
419
|
+
}
|
|
420
|
+
function getEffectiveGates(profile, sessionOverrides) {
|
|
421
|
+
const merged = { ...profile.gates };
|
|
422
|
+
for (const key of Object.keys(sessionOverrides)) {
|
|
423
|
+
if (sessionOverrides[key] === true) {
|
|
424
|
+
merged[key] = true;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return merged;
|
|
428
|
+
}
|
|
429
|
+
export { formatLegacyQaBindingOnlyCall, DEFAULT_QA_GATES, getProfileLookupForIdentity, setGatesForIdentity, computeProfileHash, getEffectiveGates };
|
|
@@ -2,18 +2,27 @@
|
|
|
2
2
|
import {
|
|
3
3
|
autoCommitDirty,
|
|
4
4
|
cleanUntrackedFiles
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-5h60rtaa.js";
|
|
6
|
+
import {
|
|
7
|
+
validateSwarmPath
|
|
8
|
+
} from "./index-anxs69ad.js";
|
|
9
|
+
import {
|
|
10
|
+
bunSpawn,
|
|
11
|
+
classifySpawnFailure
|
|
12
|
+
} from "./index-p612v1mv.js";
|
|
6
13
|
import {
|
|
7
14
|
isPathWithinDeclaredScope,
|
|
8
15
|
unsafePathTextReason
|
|
9
16
|
} from "./index-556ja8an.js";
|
|
10
17
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
assertProjectRoot,
|
|
19
|
+
atomicWriteFile,
|
|
20
|
+
taskEvidencePath,
|
|
21
|
+
withTaskEvidenceLock
|
|
22
|
+
} from "./index-jre6tm3v.js";
|
|
13
23
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from "./index-r3mvsbtq.js";
|
|
24
|
+
telemetry
|
|
25
|
+
} from "./index-5ebgzb5a.js";
|
|
17
26
|
import {
|
|
18
27
|
init_git_executable,
|
|
19
28
|
resolveGitExecutable
|
|
@@ -22,17 +31,6 @@ import {
|
|
|
22
31
|
advisoryWarn,
|
|
23
32
|
init_warning_buffer
|
|
24
33
|
} from "./index-4rhhvd1a.js";
|
|
25
|
-
import {
|
|
26
|
-
atomicWriteFile,
|
|
27
|
-
taskEvidencePath,
|
|
28
|
-
withTaskEvidenceLock
|
|
29
|
-
} from "./index-xnb3tk7x.js";
|
|
30
|
-
import {
|
|
31
|
-
assertProjectRoot
|
|
32
|
-
} from "./index-2bgr671r.js";
|
|
33
|
-
import {
|
|
34
|
-
telemetry
|
|
35
|
-
} from "./index-ww6zm5hr.js";
|
|
36
34
|
import {
|
|
37
35
|
exports_external,
|
|
38
36
|
init_zod
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
ALLOWED_SKILL_PATH_PREFIXES,
|
|
4
|
-
validateSkillPath
|
|
5
|
-
} from "./index-kc2tgcm7.js";
|
|
6
2
|
import {
|
|
7
3
|
withTimeoutSignal
|
|
8
4
|
} from "./index-q7sjgr1y.js";
|
|
5
|
+
import {
|
|
6
|
+
effectiveRetrievalOutcomes,
|
|
7
|
+
readAuthoritativeKnowledgeCounterRollups
|
|
8
|
+
} from "./index-qtxevgdx.js";
|
|
9
|
+
import {
|
|
10
|
+
ALLOWED_SKILL_PATH_PREFIXES,
|
|
11
|
+
validateSkillPath
|
|
12
|
+
} from "./index-7z9zqxqt.js";
|
|
9
13
|
import {
|
|
10
14
|
computeOutcomeSignal,
|
|
11
15
|
readKnowledge,
|
|
12
16
|
resolveHiveKnowledgePath,
|
|
13
17
|
resolveSwarmKnowledgePath,
|
|
14
18
|
transactKnowledge
|
|
15
|
-
} from "./index-
|
|
19
|
+
} from "./index-grn6tkbt.js";
|
|
16
20
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
canonicalRootKeyFresh
|
|
22
|
+
} from "./index-7qefgq4j.js";
|
|
23
|
+
import {
|
|
24
|
+
atomicWriteFileAnyRoot,
|
|
25
|
+
atomicWriteSwarmFile
|
|
26
|
+
} from "./index-gy0nyfbw.js";
|
|
20
27
|
import {
|
|
21
28
|
advisoryWarn,
|
|
22
29
|
init_warning_buffer
|
|
@@ -25,13 +32,6 @@ import {
|
|
|
25
32
|
init_knowledge_types,
|
|
26
33
|
isActiveStatus
|
|
27
34
|
} from "./index-bk5tah7q.js";
|
|
28
|
-
import {
|
|
29
|
-
canonicalRootKeyFresh
|
|
30
|
-
} from "./index-7qefgq4j.js";
|
|
31
|
-
import {
|
|
32
|
-
atomicWriteFileAnyRoot,
|
|
33
|
-
atomicWriteSwarmFile
|
|
34
|
-
} from "./index-9gxbjkts.js";
|
|
35
35
|
import {
|
|
36
36
|
init_logger,
|
|
37
37
|
log,
|
|
@@ -73,7 +73,7 @@ var BUNDLED_PROJECT_SKILLS = [
|
|
|
73
73
|
"swarm-pr-subscribe",
|
|
74
74
|
"swarm-ci-monitor",
|
|
75
75
|
"issue-ingest",
|
|
76
|
-
"plan",
|
|
76
|
+
"swarm-plan",
|
|
77
77
|
"critic-gate",
|
|
78
78
|
"execute",
|
|
79
79
|
"phase-wrap",
|
|
@@ -95,7 +95,10 @@ var BUNDLED_PROJECT_SKILLS = [
|
|
|
95
95
|
"orchestrating-subagents",
|
|
96
96
|
"durable-session-state"
|
|
97
97
|
];
|
|
98
|
-
var RETIRED_BUNDLED_PROJECT_SKILLS = [
|
|
98
|
+
var RETIRED_BUNDLED_PROJECT_SKILLS = [
|
|
99
|
+
"resume",
|
|
100
|
+
"plan"
|
|
101
|
+
];
|
|
99
102
|
var BUNDLED_PROJECT_SKILL_ROOT = ".swarm/bundled-skills";
|
|
100
103
|
function bundledProjectSkillFileReference(slug) {
|
|
101
104
|
return `file:${BUNDLED_PROJECT_SKILL_ROOT}/${slug}/SKILL.md`;
|
|
@@ -304,6 +307,27 @@ async function removeRetiredBundledSkillDirsAsync(skillsDir) {
|
|
|
304
307
|
continue;
|
|
305
308
|
throw err;
|
|
306
309
|
}
|
|
310
|
+
const backupTarget = `${target}.retired-backup`;
|
|
311
|
+
let backupExists = true;
|
|
312
|
+
try {
|
|
313
|
+
await fsp.lstat(backupTarget);
|
|
314
|
+
} catch {
|
|
315
|
+
backupExists = false;
|
|
316
|
+
}
|
|
317
|
+
if (!backupExists) {
|
|
318
|
+
try {
|
|
319
|
+
await fsp.rename(target, backupTarget);
|
|
320
|
+
log("preserved retired bundled skill as .retired-backup", {
|
|
321
|
+
slug
|
|
322
|
+
});
|
|
323
|
+
continue;
|
|
324
|
+
} catch (renameErr) {
|
|
325
|
+
log("could not preserve retired bundled skill (continuing to removal)", {
|
|
326
|
+
slug,
|
|
327
|
+
message: renameErr instanceof Error ? renameErr.message : String(renameErr)
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
307
331
|
await fsp.rm(target, { recursive: true, force: true });
|
|
308
332
|
log("removed retired bundled skill", { slug });
|
|
309
333
|
} catch (err) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
authorizeCuration
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-ajknebrc.js";
|
|
5
5
|
import {
|
|
6
6
|
findNearDuplicate,
|
|
7
7
|
inferTags,
|
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
resolveSwarmKnowledgePath,
|
|
10
10
|
resolveSwarmRejectedPath,
|
|
11
11
|
transactKnowledge
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-grn6tkbt.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveKnowledgeStoreDir
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-6rx1rdaq.js";
|
|
16
16
|
import {
|
|
17
17
|
atomicWriteFile
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-jre6tm3v.js";
|
|
19
19
|
import {
|
|
20
20
|
require_proper_lockfile
|
|
21
21
|
} from "./index-7g4c7s5r.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
validateSwarmPath
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-anxs69ad.js";
|
|
5
5
|
import {
|
|
6
6
|
atomicWriteSwarmFileSync
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-gy0nyfbw.js";
|
|
8
8
|
|
|
9
9
|
// src/hooks/delegation-gate/worktree-provisioning-owner.ts
|
|
10
10
|
import { createHash } from "crypto";
|