opencode-swarm 7.183.1 → 7.184.1
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/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/background/delegation-health.d.ts +1 -1
- package/dist/background/index.d.ts +1 -0
- package/dist/background/pr-event-delivery.d.ts +29 -14
- package/dist/background/pr-event-subscribers.d.ts +6 -5
- package/dist/background/pr-feedback-event-queue.d.ts +19 -2
- package/dist/background/pr-feedback-loop-runtime.d.ts +75 -0
- package/dist/background/pr-feedback-loop.d.ts +47 -12
- package/dist/cli/{coder-settlement-rserb0hm.js → coder-settlement-yvpewr52.js} +15 -12
- package/dist/cli/{config-doctor-r4fmzprn.js → config-doctor-qgwpvrbz.js} +7 -3
- package/dist/cli/{core-rzek3e2n.js → core-9qt388hq.js} +4 -4
- package/dist/cli/{curation-policy-g0jjwrg5.js → curation-policy-49f8jx48.js} +7 -6
- package/dist/cli/{curator-drift-a0r5krfx.js → curator-drift-wf0sm2te.js} +9 -9
- package/dist/cli/{curator-v84tfqcr.js → curator-ffz5pxgc.js} +40 -39
- package/dist/cli/curator-llm-factory-drs36v1q.js +75 -0
- package/dist/cli/{dispatch-p5zjg5e6.js → dispatch-cv89p2y1.js} +1 -1
- package/dist/cli/{evidence-summary-service-t4csk176.js → evidence-summary-service-8dfzjnxe.js} +21 -20
- package/dist/cli/{gate-evidence-3z04zprn.js → gate-evidence-aa5q30f4.js} +14 -7
- package/dist/cli/guardrail-explain-9g5y2gjm.js +76 -0
- package/dist/cli/{guardrail-log-cbzdh4qj.js → guardrail-log-0g51p94w.js} +8 -8
- package/dist/cli/{guardrail-reset-5e75rz44.js → guardrail-reset-dcbmt2wr.js} +40 -39
- package/dist/cli/{hive-promoter-f54nrhqn.js → hive-promoter-2g8nga0y.js} +40 -39
- package/dist/cli/{index-31e105jf.js → index-046psajf.js} +80 -2
- package/dist/cli/{index-rhw6m7s9.js → index-0874kghs.js} +9 -3
- package/dist/cli/{index-6h81yvyc.js → index-131ay7x1.js} +3 -3
- package/dist/cli/{index-raws06d3.js → index-2c91cxdv.js} +4 -4
- package/dist/cli/{index-9f930sy8.js → index-32vszgv0.js} +3 -3
- package/dist/cli/{index-0bpr8vag.js → index-3n5zsp31.js} +2 -2
- package/dist/cli/{index-b26hje53.js → index-3skvygca.js} +5 -5
- package/dist/cli/{index-w81jmdkt.js → index-456awy1p.js} +2 -2
- package/dist/cli/{index-hb1zqz50.js → index-475bkab8.js} +2 -2
- package/dist/cli/{index-80qhm8aq.js → index-49ptc9xx.js} +10 -4
- package/dist/cli/{index-bsjwchw7.js → index-57swfxyp.js} +8 -8
- package/dist/cli/{index-y5hhkx1n.js → index-5ppx86w1.js} +38 -18
- package/dist/cli/{index-jb7ywm4w.js → index-6b427dy8.js} +6 -6
- package/dist/cli/{index-3qy7v4k1.js → index-6cvdk98y.js} +2 -2
- package/dist/cli/{index-hsvsz3mj.js → index-6g664sy8.js} +1 -1
- package/dist/cli/{index-8me6m6ew.js → index-76abqm8d.js} +2 -2
- package/dist/cli/{index-z425p51d.js → index-7hvy33gc.js} +271 -80
- package/dist/cli/{index-4xr4gtwd.js → index-7p4ym4q3.js} +1 -1
- package/dist/cli/{index-j8ty457v.js → index-aghd9kcx.js} +2 -2
- package/dist/cli/{index-h01p5ygy.js → index-ar2gsn6b.js} +8 -8
- package/dist/cli/{index-ak1dd17g.js → index-dbshccrr.js} +3 -3
- package/dist/cli/{index-908k7jhw.js → index-depfky1j.js} +158 -27
- package/dist/cli/{index-5t08vc6m.js → index-earq3mda.js} +1 -1
- package/dist/cli/{index-6dm6ettv.js → index-ejb7ejhd.js} +1 -1
- package/dist/cli/{index-3rb5gs4w.js → index-f0nj3d8z.js} +1 -1
- package/dist/cli/{index-qjzbs971.js → index-gsgy1psq.js} +4 -4
- package/dist/cli/{index-jk05g11c.js → index-jc8pcf0r.js} +7 -7
- package/dist/cli/{index-mt0s67hg.js → index-jkxef52n.js} +2 -2
- package/dist/cli/{index-wpn7ftw1.js → index-jvk95e6y.js} +2 -2
- package/dist/cli/{index-5cve9g2b.js → index-k53a69vb.js} +6 -6
- package/dist/cli/{index-1xnse449.js → index-mc72pk74.js} +1 -1
- package/dist/cli/{index-w196wb3a.js → index-mz4zz59c.js} +42 -41
- package/dist/cli/{index-4hnk9npg.js → index-n107956q.js} +5 -5
- package/dist/cli/{index-gaykghrm.js → index-qczxr0wh.js} +12 -10
- package/dist/cli/{index-nazzb4em.js → index-s7bseqza.js} +3220 -1893
- package/dist/cli/{index-dg3f2sqq.js → index-t7hmqgjy.js} +90 -141
- package/dist/cli/{index-08x7gsnf.js → index-w9hxzcz4.js} +2 -2
- package/dist/cli/{index-bqphhrwf.js → index-wfdx7yw2.js} +39 -15
- package/dist/cli/{index-xtysafzj.js → index-wsb0wbw6.js} +40 -39
- package/dist/cli/{index-nmh0s6dg.js → index-wy3zpwjy.js} +1 -1
- package/dist/cli/{index-tt705bap.js → index-x1gyqgze.js} +7 -7
- package/dist/cli/index-xf69xty9.js +105 -0
- package/dist/cli/{index-ydefv5fn.js → index-ya32wfkp.js} +4 -2
- package/dist/cli/{index-1hnknn34.js → index-yk0r42nr.js} +4 -4
- package/dist/cli/{index-77650pyg.js → index-zzvxj02e.js} +3 -3
- package/dist/cli/index.js +41 -40
- package/dist/cli/{knowledge-escalator-cs7fjgy0.js → knowledge-escalator-pt21q3eh.js} +14 -13
- package/dist/cli/{knowledge-events-262c1jg2.js → knowledge-events-hp96b55k.js} +12 -11
- package/dist/cli/{knowledge-link-8kcms7pj.js → knowledge-link-ap2274vm.js} +6 -5
- package/dist/cli/{knowledge-store-yjrkfens.js → knowledge-store-rnw1e7zp.js} +7 -6
- package/dist/cli/{knowledge-validator-t98cvpt5.js → knowledge-validator-xy7r6eyx.js} +9 -8
- package/dist/cli/{mcp-wj6143vj.js → mcp-3nd85kww.js} +15 -1
- package/dist/cli/mcp.d.ts +1 -0
- package/dist/cli/{model-preflight-tz4ar9ys.js → model-preflight-xe0chjad.js} +40 -39
- package/dist/cli/{pending-delegations-vvbkqe24.js → pending-delegations-2pdngdzq.js} +13 -12
- package/dist/cli/{pr-subscriptions-maeppcws.js → pr-subscriptions-hxxwszyr.js} +13 -12
- package/dist/cli/{pr-workflow-gate-en54gabv.js → pr-workflow-gate-m37ynr6h.js} +40 -39
- package/dist/cli/{runner-618229m8.js → runner-yz3ysehf.js} +7 -6
- package/dist/cli/{scan-cursor-sxwh1ax8.js → scan-cursor-be9hbq1v.js} +8 -7
- package/dist/cli/{schema-fb8vm14k.js → schema-j17hv98z.js} +3 -1
- package/dist/cli/{scope-persistence-sc2zhr15.js → scope-persistence-rmt56rma.js} +16 -15
- package/dist/cli/{server-7ksq9wr7.js → server-wzrb59mh.js} +40 -39
- package/dist/cli/{skill-generator-ccmq47cm.js → skill-generator-vsfya55z.js} +16 -15
- package/dist/cli/{snapshot-coordination-init-h8eg88w2.js → snapshot-coordination-init-pc8ykvh8.js} +40 -39
- package/dist/cli/{speckit-checkoff-vkqn317p.js → speckit-checkoff-j407j8ew.js} +4 -4
- package/dist/cli/{telemetry-vqyy5nha.js → telemetry-39zmx4fp.js} +2 -2
- package/dist/cli/{workspace-snapshot-t22m6gbd.js → workspace-snapshot-0q1n1xq5.js} +4 -4
- package/dist/cli/{worktree-collision-ownership-8hr7aycc.js → worktree-collision-ownership-je4fb407.js} +14 -13
- package/dist/cli/{worktree-isolation-gwq3y9tf.js → worktree-isolation-27rt584e.js} +40 -39
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/config/schema.d.ts +15 -0
- package/dist/context/role-filter.d.ts +2 -0
- package/dist/db/qa-gate-session-override.d.ts +12 -12
- package/dist/gate-evidence.d.ts +43 -1
- package/dist/hooks/final-context-accounting.d.ts +3 -2
- package/dist/hooks/guardrails/index.d.ts +13 -7
- package/dist/hooks/host-boundary.d.ts +10 -0
- package/dist/hooks/system-enhancer.d.ts +9 -2
- package/dist/hooks/system-guidance-carrier.d.ts +18 -0
- package/dist/index.js +520 -514
- package/dist/plan/ledger.d.ts +20 -4
- package/dist/plan/manager.d.ts +20 -2
- package/dist/services/config-doctor.d.ts +24 -0
- package/dist/services/injection-budget.d.ts +56 -8
- package/dist/session/hydration-ownership.d.ts +39 -12
- package/dist/session/snapshot-coordination-init.d.ts +11 -4
- package/dist/session/snapshot-reader.d.ts +9 -4
- package/dist/session/snapshot-writer.d.ts +2 -3
- package/dist/state.d.ts +35 -5
- package/dist/tools/phase-complete.d.ts +1 -0
- package/dist/tools/save-plan.d.ts +12 -0
- package/dist/tools/update-task-status.d.ts +1 -1
- package/dist/utils/project-boundary.d.ts +32 -1
- package/dist/workflow/coder-settlement.d.ts +8 -0
- package/dist/workflow/task-terminal.d.ts +2 -1
- package/dist/workflow/workflow-wal-schema.d.ts +2 -0
- package/opencode-swarm.schema.json +8 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-xp4hgd8r.js +0 -74
- package/dist/cli/guardrail-explain-j2y5sj4d.js +0 -75
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
emit
|
|
4
|
-
} from "./index-tt705bap.js";
|
|
5
|
-
import {
|
|
6
|
-
tryAcquireLock
|
|
7
|
-
} from "./index-ejhxgyvm.js";
|
|
8
|
-
import {
|
|
9
|
-
atomicWriteFileAnyRoot
|
|
10
|
-
} from "./index-5cve9g2b.js";
|
|
11
2
|
import {
|
|
12
3
|
init_logger,
|
|
13
4
|
warn
|
|
@@ -61,6 +52,56 @@ function isStrictPathDescendant(candidate, root) {
|
|
|
61
52
|
const relative2 = path.relative(root, candidate);
|
|
62
53
|
return relative2 !== "" && relative2 !== ".." && !relative2.startsWith(`..${path.sep}`) && !path.isAbsolute(relative2);
|
|
63
54
|
}
|
|
55
|
+
function walkProjectBoundary(resolved, dependencies) {
|
|
56
|
+
if (hasExplicitProjectBoundary(resolved))
|
|
57
|
+
return { outcome: "marker-root" };
|
|
58
|
+
let current = resolved;
|
|
59
|
+
let depth = 0;
|
|
60
|
+
while (true) {
|
|
61
|
+
if (depth >= MAX_PROJECT_ROOT_DEPTH) {
|
|
62
|
+
return { outcome: "fail-closed", reason: "depth" };
|
|
63
|
+
}
|
|
64
|
+
depth++;
|
|
65
|
+
const parent = path.dirname(current);
|
|
66
|
+
if (parent === current)
|
|
67
|
+
return { outcome: "unclaimed" };
|
|
68
|
+
if (path.dirname(parent) === parent) {
|
|
69
|
+
current = parent;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const parentSwarm = path.join(parent, ".swarm");
|
|
73
|
+
let parentSwarmStat;
|
|
74
|
+
try {
|
|
75
|
+
parentSwarmStat = dependencies.statSync(parentSwarm);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (isMissingPathError(error)) {
|
|
78
|
+
current = parent;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
outcome: "fail-closed",
|
|
83
|
+
reason: "ancestor-swarm",
|
|
84
|
+
path: parentSwarm
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (parentSwarmStat.isDirectory()) {
|
|
88
|
+
const indicatorState = projectIndicatorState(parent, dependencies, {
|
|
89
|
+
allowConfigOnly: !isWeakConfigContainerRoot(parent, dependencies)
|
|
90
|
+
});
|
|
91
|
+
if (indicatorState === "inaccessible") {
|
|
92
|
+
return {
|
|
93
|
+
outcome: "fail-closed",
|
|
94
|
+
reason: "ancestor-indicators",
|
|
95
|
+
path: parent
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (indicatorState === "present") {
|
|
99
|
+
return { outcome: "claimed", ancestor: parent };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
current = parent;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
64
105
|
function isMissingPathError(error) {
|
|
65
106
|
const code = error?.code;
|
|
66
107
|
return code === "ENOENT" || code === "ENOTDIR";
|
|
@@ -98,143 +139,51 @@ function assertProjectRoot(directory, dependencies = fs, artifactLabel = "runtim
|
|
|
98
139
|
warn(`[project-boundary] Cannot canonicalize directory "${directory}" \u2014 failing closed`);
|
|
99
140
|
throw new Error(`Cannot verify project root for "${directory}" \u2014 directory may not exist or is inaccessible`);
|
|
100
141
|
}
|
|
101
|
-
|
|
142
|
+
const walk = walkProjectBoundary(resolved, dependencies);
|
|
143
|
+
if (walk.outcome === "marker-root" || walk.outcome === "unclaimed")
|
|
102
144
|
return;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (depth >= MAX_PROJECT_ROOT_DEPTH) {
|
|
107
|
-
warn(`[project-boundary] Ancestor search exceeded ${MAX_PROJECT_ROOT_DEPTH} levels for "${resolved}" \u2014 failing closed`);
|
|
108
|
-
throw new Error(`Cannot verify project root for "${resolved}" \u2014 ancestor search exceeded ${MAX_PROJECT_ROOT_DEPTH} levels`);
|
|
109
|
-
}
|
|
110
|
-
depth++;
|
|
111
|
-
const parent = path.dirname(current);
|
|
112
|
-
if (parent === current)
|
|
113
|
-
break;
|
|
114
|
-
if (path.dirname(parent) === parent) {
|
|
115
|
-
current = parent;
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
const parentSwarm = path.join(parent, ".swarm");
|
|
119
|
-
let parentSwarmStat;
|
|
120
|
-
try {
|
|
121
|
-
parentSwarmStat = dependencies.statSync(parentSwarm);
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (isMissingPathError(error)) {
|
|
124
|
-
current = parent;
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
warn(`[project-boundary] Cannot inspect ancestor state "${parentSwarm}" \u2014 failing closed`);
|
|
128
|
-
throw new Error(`Cannot verify project root for "${resolved}" \u2014 ancestor state "${parentSwarm}" is inaccessible`);
|
|
129
|
-
}
|
|
130
|
-
if (parentSwarmStat.isDirectory()) {
|
|
131
|
-
const indicatorState = projectIndicatorState(parent, dependencies, {
|
|
132
|
-
allowConfigOnly: !isWeakConfigContainerRoot(parent, dependencies)
|
|
133
|
-
});
|
|
134
|
-
if (indicatorState === "inaccessible") {
|
|
135
|
-
warn(`[project-boundary] Cannot inspect project indicators in ancestor "${parent}" \u2014 failing closed`);
|
|
136
|
-
throw new Error(`Cannot verify project root for "${resolved}" \u2014 project indicators in ancestor "${parent}" are inaccessible`);
|
|
137
|
-
}
|
|
138
|
-
if (indicatorState === "present") {
|
|
139
|
-
warn(`[project-boundary] Rejecting write to subdirectory "${resolved}" \u2014 parent "${parent}" already contains .swarm/`);
|
|
140
|
-
throw new Error(`Cannot write ${artifactLabel} in "${resolved}" \u2014 parent directory "${parent}" already contains a .swarm/ folder. Runtime state must be written to the project root.`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
current = parent;
|
|
145
|
+
if (walk.outcome === "claimed") {
|
|
146
|
+
warn(`[project-boundary] Rejecting write to subdirectory "${resolved}" \u2014 parent "${walk.ancestor}" already contains .swarm/`);
|
|
147
|
+
throw new Error(`Cannot write ${artifactLabel} in "${resolved}" \u2014 parent directory "${walk.ancestor}" already contains a .swarm/ folder. Runtime state must be written to the project root.`);
|
|
144
148
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
// src/evidence/lock.ts
|
|
151
|
-
class EvidenceLockTimeoutError extends Error {
|
|
152
|
-
directory;
|
|
153
|
-
evidencePath;
|
|
154
|
-
agent;
|
|
155
|
-
taskId;
|
|
156
|
-
constructor(directory, evidencePath, agent, taskId, timeoutMs) {
|
|
157
|
-
super(`Evidence lock timeout after ${timeoutMs}ms for ${evidencePath} (agent=${agent}, task=${taskId})`);
|
|
158
|
-
this.name = "EvidenceLockTimeoutError";
|
|
159
|
-
this.directory = directory;
|
|
160
|
-
this.evidencePath = evidencePath;
|
|
161
|
-
this.agent = agent;
|
|
162
|
-
this.taskId = taskId;
|
|
149
|
+
if (walk.reason === "depth") {
|
|
150
|
+
warn(`[project-boundary] Ancestor search exceeded ${MAX_PROJECT_ROOT_DEPTH} levels for "${resolved}" \u2014 failing closed`);
|
|
151
|
+
throw new Error(`Cannot verify project root for "${resolved}" \u2014 ancestor search exceeded ${MAX_PROJECT_ROOT_DEPTH} levels`);
|
|
163
152
|
}
|
|
153
|
+
if (walk.reason === "ancestor-swarm") {
|
|
154
|
+
warn(`[project-boundary] Cannot inspect ancestor state "${walk.path}" \u2014 failing closed`);
|
|
155
|
+
throw new Error(`Cannot verify project root for "${resolved}" \u2014 ancestor state "${walk.path}" is inaccessible`);
|
|
156
|
+
}
|
|
157
|
+
warn(`[project-boundary] Cannot inspect project indicators in ancestor "${walk.path}" \u2014 failing closed`);
|
|
158
|
+
throw new Error(`Cannot verify project root for "${resolved}" \u2014 project indicators in ancestor "${walk.path}" are inaccessible`);
|
|
164
159
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
async function withEvidenceLock(directory, evidencePath, agent, taskId, fn, timeoutMs = 60000) {
|
|
174
|
-
assertProjectRoot(directory);
|
|
175
|
-
const deadline = Date.now() + timeoutMs;
|
|
176
|
-
let attempt = 0;
|
|
177
|
-
while (true) {
|
|
178
|
-
const result = await tryAcquireLock(directory, evidencePath, agent, taskId);
|
|
179
|
-
if (result.acquired) {
|
|
180
|
-
const lock = result.lock;
|
|
181
|
-
if (attempt > 0) {
|
|
182
|
-
emit("evidence_lock_stale_recovered", {
|
|
183
|
-
directory,
|
|
184
|
-
evidencePath,
|
|
185
|
-
agent,
|
|
186
|
-
taskId,
|
|
187
|
-
attempt
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
emit("evidence_lock_acquired", {
|
|
191
|
-
directory,
|
|
192
|
-
evidencePath,
|
|
193
|
-
agent,
|
|
194
|
-
taskId,
|
|
195
|
-
attempt
|
|
196
|
-
});
|
|
197
|
-
try {
|
|
198
|
-
return await fn();
|
|
199
|
-
} finally {
|
|
200
|
-
if (lock._release) {
|
|
201
|
-
try {
|
|
202
|
-
await lock._release();
|
|
203
|
-
} catch {}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
if (Date.now() >= deadline) {
|
|
208
|
-
throw new EvidenceLockTimeoutError(directory, evidencePath, agent, taskId, timeoutMs);
|
|
209
|
-
}
|
|
210
|
-
emit("evidence_lock_contended", {
|
|
160
|
+
function resolveProjectRootDecision(directory, dependencies = fs) {
|
|
161
|
+
let resolved;
|
|
162
|
+
try {
|
|
163
|
+
resolved = dependencies.realpathSync(directory);
|
|
164
|
+
} catch {
|
|
165
|
+
return {
|
|
166
|
+
kind: "fail-closed",
|
|
211
167
|
directory,
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
taskId,
|
|
215
|
-
attempt
|
|
216
|
-
});
|
|
217
|
-
const delay = Math.min(backoffMs(attempt), deadline - Date.now());
|
|
218
|
-
if (delay > 0) {
|
|
219
|
-
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
220
|
-
}
|
|
221
|
-
attempt++;
|
|
168
|
+
reason: `cannot canonicalize directory "${directory}" \u2014 it may not exist or is inaccessible`
|
|
169
|
+
};
|
|
222
170
|
}
|
|
171
|
+
const walk = walkProjectBoundary(resolved, dependencies);
|
|
172
|
+
if (walk.outcome === "marker-root" || walk.outcome === "unclaimed") {
|
|
173
|
+
return { kind: "root", directory: resolved };
|
|
174
|
+
}
|
|
175
|
+
if (walk.outcome === "claimed") {
|
|
176
|
+
return {
|
|
177
|
+
kind: "redirect",
|
|
178
|
+
directory: resolved,
|
|
179
|
+
owningRoot: walk.ancestor
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const reason = walk.reason === "depth" ? `ancestor search exceeded ${MAX_PROJECT_ROOT_DEPTH} levels` : walk.reason === "ancestor-swarm" ? `ancestor state "${walk.path}" is inaccessible` : `project indicators in ancestor "${walk.path}" are inaccessible`;
|
|
183
|
+
return { kind: "fail-closed", directory: resolved, reason };
|
|
223
184
|
}
|
|
185
|
+
var _internals = {
|
|
186
|
+
lstatSync: fs.lstatSync
|
|
187
|
+
};
|
|
224
188
|
|
|
225
|
-
|
|
226
|
-
import * as path2 from "path";
|
|
227
|
-
function taskEvidenceRelPath(taskId) {
|
|
228
|
-
return path2.join("evidence", `${taskId}.json`);
|
|
229
|
-
}
|
|
230
|
-
function taskEvidencePath(directory, taskId) {
|
|
231
|
-
return path2.join(directory, ".swarm", taskEvidenceRelPath(taskId));
|
|
232
|
-
}
|
|
233
|
-
async function atomicWriteFile(targetPath, content) {
|
|
234
|
-
await atomicWriteFileAnyRoot(targetPath, content);
|
|
235
|
-
}
|
|
236
|
-
function withTaskEvidenceLock(directory, taskId, agent, fn) {
|
|
237
|
-
return withEvidenceLock(directory, taskEvidenceRelPath(taskId), agent, taskId, fn);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export { hasExplicitProjectBoundary, isStrictPathDescendant, assertProjectRoot, EvidenceLockTimeoutError, withEvidenceLock, taskEvidencePath, atomicWriteFile, withTaskEvidenceLock };
|
|
189
|
+
export { hasExplicitProjectBoundary, isStrictPathDescendant, assertProjectRoot, resolveProjectRootDecision };
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
canonicalRootKeyFresh,
|
|
10
10
|
lexicalRootAliasKey
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-mc72pk74.js";
|
|
12
12
|
import {
|
|
13
13
|
atomicWriteSwarmFileSync
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-k53a69vb.js";
|
|
15
15
|
|
|
16
16
|
// src/db/project-db.ts
|
|
17
17
|
import { existsSync, mkdirSync, unlinkSync } from "fs";
|
|
@@ -2,20 +2,22 @@
|
|
|
2
2
|
import {
|
|
3
3
|
derivePlanId,
|
|
4
4
|
derivePlanIdentityHash
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-f0nj3d8z.js";
|
|
6
6
|
import {
|
|
7
7
|
getProjectDb,
|
|
8
8
|
projectDbExists,
|
|
9
9
|
withImmediateTransaction,
|
|
10
10
|
withProjectDbReadOnly
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-w9hxzcz4.js";
|
|
12
12
|
import {
|
|
13
|
-
assertProjectRoot,
|
|
14
13
|
withEvidenceLock
|
|
15
|
-
} from "./index-
|
|
14
|
+
} from "./index-xf69xty9.js";
|
|
15
|
+
import {
|
|
16
|
+
assertProjectRoot
|
|
17
|
+
} from "./index-t7hmqgjy.js";
|
|
16
18
|
import {
|
|
17
19
|
emit
|
|
18
|
-
} from "./index-
|
|
20
|
+
} from "./index-x1gyqgze.js";
|
|
19
21
|
import {
|
|
20
22
|
ExecutionProfileSchema,
|
|
21
23
|
PlanSchema,
|
|
@@ -25,11 +27,11 @@ import {
|
|
|
25
27
|
import {
|
|
26
28
|
init_loader,
|
|
27
29
|
loadPluginConfig
|
|
28
|
-
} from "./index-
|
|
30
|
+
} from "./index-49ptc9xx.js";
|
|
29
31
|
import {
|
|
30
32
|
init_package,
|
|
31
33
|
package_default
|
|
32
|
-
} from "./index-
|
|
34
|
+
} from "./index-0874kghs.js";
|
|
33
35
|
import {
|
|
34
36
|
criticalWarn,
|
|
35
37
|
init_logger,
|
|
@@ -1235,7 +1237,7 @@ async function readLedgerEvents(directory) {
|
|
|
1235
1237
|
const events = result.truncated ? result.lenientEvents ?? result.events : result.events;
|
|
1236
1238
|
return [...events].sort((a, b) => a.seq - b.seq);
|
|
1237
1239
|
}
|
|
1238
|
-
async function initLedger(directory, planId, initialPlanHash, initialPlan) {
|
|
1240
|
+
async function initLedger(directory, planId, initialPlanHash, initialPlan, options) {
|
|
1239
1241
|
assertProjectRoot(directory);
|
|
1240
1242
|
const ledgerPath = getLedgerPath(directory);
|
|
1241
1243
|
const planJsonPath = getPlanJsonPath(directory);
|
|
@@ -1275,10 +1277,12 @@ async function initLedger(directory, planId, initialPlanHash, initialPlan) {
|
|
|
1275
1277
|
const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
1276
1278
|
const line = `${JSON.stringify(event)}
|
|
1277
1279
|
`;
|
|
1280
|
+
options?.preCommitCheck?.();
|
|
1278
1281
|
writeFileFsyncedThenRename(tempPath, ledgerPath, line);
|
|
1279
1282
|
const initialized = readFileLedgerExact(directory);
|
|
1280
1283
|
if (hasSqliteLedger(directory)) {
|
|
1281
1284
|
const priorMode = getPlanLedgerState(directory)?.authorityMode ?? "file_shadow";
|
|
1285
|
+
options?.preCommitCheck?.();
|
|
1282
1286
|
try {
|
|
1283
1287
|
replaceSqliteLedger(directory, {
|
|
1284
1288
|
canonicalEvents: initialized.lines,
|
|
@@ -1424,6 +1428,7 @@ async function appendLedgerEvent(directory, eventInput, options) {
|
|
|
1424
1428
|
const state = getPlanLedgerState(directory);
|
|
1425
1429
|
const authorityMode = state?.authorityMode ?? "file_shadow";
|
|
1426
1430
|
if (authorityMode === "sqlite") {
|
|
1431
|
+
options?.preCommitCheck?.();
|
|
1427
1432
|
try {
|
|
1428
1433
|
const existing = sqliteEventsAsLedger(directory);
|
|
1429
1434
|
appendSqliteLedger(directory, {
|
|
@@ -1448,6 +1453,7 @@ async function appendLedgerEvent(directory, eventInput, options) {
|
|
|
1448
1453
|
throw new Error("Ledger not initialized. Call initLedger() first.");
|
|
1449
1454
|
}
|
|
1450
1455
|
const existingContent = fs.readFileSync(ledgerPath);
|
|
1456
|
+
options?.preCommitCheck?.();
|
|
1451
1457
|
writeFileFsyncedThenRename(tempPath, ledgerPath, Buffer.concat([
|
|
1452
1458
|
existingContent,
|
|
1453
1459
|
Buffer.from(canonicalEvent),
|
|
@@ -1479,7 +1485,8 @@ async function appendLedgerEventWithRetry(directory, eventInput, options) {
|
|
|
1479
1485
|
try {
|
|
1480
1486
|
return await appendLedgerEvent(directory, eventInput, {
|
|
1481
1487
|
expectedHash: currentExpected,
|
|
1482
|
-
planHashAfter: options.planHashAfter
|
|
1488
|
+
planHashAfter: options.planHashAfter,
|
|
1489
|
+
preCommitCheck: options.preCommitCheck
|
|
1483
1490
|
});
|
|
1484
1491
|
} catch (error) {
|
|
1485
1492
|
if (!(error instanceof LedgerStaleWriterError) || attempt >= maxRetries) {
|
|
@@ -1534,6 +1541,7 @@ async function takeSnapshotEvent(directory, plan, options) {
|
|
|
1534
1541
|
snapshotPayload.approval = options.approvalMetadata;
|
|
1535
1542
|
}
|
|
1536
1543
|
const planId = derivePlanId(plan);
|
|
1544
|
+
options?.preCommitCheck?.();
|
|
1537
1545
|
return appendLedgerEvent(directory, {
|
|
1538
1546
|
event_type: "snapshot",
|
|
1539
1547
|
source: options?.source ?? "takeSnapshotEvent",
|
|
@@ -1542,7 +1550,8 @@ async function takeSnapshotEvent(directory, plan, options) {
|
|
|
1542
1550
|
}, {
|
|
1543
1551
|
planHashAfter: options?.planHashAfter,
|
|
1544
1552
|
expectedSeq: options?.expectedSeq,
|
|
1545
|
-
expectedLedgerHash: options?.expectedLedgerHash
|
|
1553
|
+
expectedLedgerHash: options?.expectedLedgerHash,
|
|
1554
|
+
preCommitCheck: options?.preCommitCheck
|
|
1546
1555
|
});
|
|
1547
1556
|
}
|
|
1548
1557
|
async function replaceTruncatedLedgerWithRecoveryRoot(directory, plan, expected) {
|
|
@@ -1649,12 +1658,13 @@ async function clearPlanLedgerForReset(directory) {
|
|
|
1649
1658
|
}
|
|
1650
1659
|
});
|
|
1651
1660
|
}
|
|
1652
|
-
async function replacePlanLedgerWithRoot(directory, plan, source) {
|
|
1661
|
+
async function replacePlanLedgerWithRoot(directory, plan, source, options) {
|
|
1653
1662
|
assertProjectRoot(directory);
|
|
1654
1663
|
const validated = PlanSchema.parse(plan);
|
|
1655
1664
|
await withEvidenceLock(directory, LEDGER_LOCK_PATH, "plan-ledger", "replace-plan-ledger-root", async () => {
|
|
1656
1665
|
const ledgerPath = getLedgerPath(directory);
|
|
1657
1666
|
if (fs.existsSync(ledgerPath)) {
|
|
1667
|
+
options?.preCommitCheck?.();
|
|
1658
1668
|
archiveLegacyLedger(directory, fs.readFileSync(ledgerPath));
|
|
1659
1669
|
}
|
|
1660
1670
|
const planHash = computePlanLedgerHash(validated);
|
|
@@ -1676,7 +1686,9 @@ async function replacePlanLedgerWithRoot(directory, plan, source) {
|
|
|
1676
1686
|
const line = new TextEncoder().encode(serializeLedgerEvent(root));
|
|
1677
1687
|
const priorMode = getPlanLedgerState(directory)?.authorityMode ?? "file_shadow";
|
|
1678
1688
|
if (priorMode === "file_shadow") {
|
|
1689
|
+
options?.preCommitCheck?.();
|
|
1679
1690
|
writePortableLedger(directory, [line]);
|
|
1691
|
+
options?.preCommitCheck?.();
|
|
1680
1692
|
try {
|
|
1681
1693
|
replaceSqliteLedger(directory, {
|
|
1682
1694
|
canonicalEvents: [line],
|
|
@@ -1690,6 +1702,7 @@ async function replacePlanLedgerWithRoot(directory, plan, source) {
|
|
|
1690
1702
|
}
|
|
1691
1703
|
return;
|
|
1692
1704
|
}
|
|
1705
|
+
options?.preCommitCheck?.();
|
|
1693
1706
|
replaceSqliteLedger(directory, {
|
|
1694
1707
|
canonicalEvents: [line],
|
|
1695
1708
|
state: stateForEvents(directory, [root], priorMode),
|
|
@@ -1697,6 +1710,7 @@ async function replacePlanLedgerWithRoot(directory, plan, source) {
|
|
|
1697
1710
|
mode: priorMode,
|
|
1698
1711
|
version: package_default.version
|
|
1699
1712
|
});
|
|
1713
|
+
options?.preCommitCheck?.();
|
|
1700
1714
|
try {
|
|
1701
1715
|
writePortableLedger(directory, [line]);
|
|
1702
1716
|
} catch (error) {
|
|
@@ -1739,12 +1753,16 @@ async function peekPlanFromLedger(directory, _options) {
|
|
|
1739
1753
|
};
|
|
1740
1754
|
}
|
|
1741
1755
|
async function replayFromLedgerWithStatus(directory, _options) {
|
|
1742
|
-
const
|
|
1756
|
+
const integrity = await readLedgerEventsWithIntegrity(directory);
|
|
1757
|
+
_options?.preCommitCheck?.();
|
|
1758
|
+
const { events, truncated, badSuffix } = integrity;
|
|
1743
1759
|
if (events.length === 0) {
|
|
1744
1760
|
return { plan: null, truncated, badSuffix };
|
|
1745
1761
|
}
|
|
1746
1762
|
if (truncated && badSuffix !== null) {
|
|
1747
|
-
await quarantineLedgerSuffix(directory, badSuffix
|
|
1763
|
+
await quarantineLedgerSuffix(directory, badSuffix, {
|
|
1764
|
+
preCommitCheck: _options?.preCommitCheck
|
|
1765
|
+
});
|
|
1748
1766
|
}
|
|
1749
1767
|
const plan = reconstructPlanFromEvents(directory, events);
|
|
1750
1768
|
return { plan, truncated, badSuffix };
|
|
@@ -1916,7 +1934,7 @@ async function readLedgerEventsWithIntegrity(directory, options) {
|
|
|
1916
1934
|
throw error;
|
|
1917
1935
|
}
|
|
1918
1936
|
}
|
|
1919
|
-
async function quarantineLedgerSuffix(directory, badSuffix) {
|
|
1937
|
+
async function quarantineLedgerSuffix(directory, badSuffix, options) {
|
|
1920
1938
|
let salvagedCount = 0;
|
|
1921
1939
|
for (const line of badSuffix.split(`
|
|
1922
1940
|
`)) {
|
|
@@ -1927,6 +1945,7 @@ async function quarantineLedgerSuffix(directory, badSuffix) {
|
|
|
1927
1945
|
salvagedCount++;
|
|
1928
1946
|
} catch {}
|
|
1929
1947
|
}
|
|
1948
|
+
let quarantinePath;
|
|
1930
1949
|
try {
|
|
1931
1950
|
assertProjectRoot(directory);
|
|
1932
1951
|
const hash = crypto.createHash("sha256").update(badSuffix, "utf8").digest("hex").slice(0, 12);
|
|
@@ -1940,7 +1959,12 @@ async function quarantineLedgerSuffix(directory, badSuffix) {
|
|
|
1940
1959
|
}
|
|
1941
1960
|
}
|
|
1942
1961
|
} catch {}
|
|
1943
|
-
|
|
1962
|
+
quarantinePath = path2.join(swarmDir, `plan-ledger.quarantine.${Date.now()}.${hash}`);
|
|
1963
|
+
} catch {
|
|
1964
|
+
return { path: null, salvagedCount };
|
|
1965
|
+
}
|
|
1966
|
+
options?.preCommitCheck?.();
|
|
1967
|
+
try {
|
|
1944
1968
|
fs.writeFileSync(quarantinePath, badSuffix, "utf8");
|
|
1945
1969
|
log(`[ledger] Corrupted suffix quarantined to ${path2.relative(directory, quarantinePath)} (salvageable events: ${salvagedCount})`);
|
|
1946
1970
|
return { path: quarantinePath, salvagedCount };
|
|
@@ -23,68 +23,69 @@ import {
|
|
|
23
23
|
resolveFallbackModel,
|
|
24
24
|
resolvePrimaryAgentNames,
|
|
25
25
|
stripSwarmPrefix
|
|
26
|
-
} from "./index-
|
|
27
|
-
import"./index-
|
|
26
|
+
} from "./index-s7bseqza.js";
|
|
27
|
+
import"./index-32vszgv0.js";
|
|
28
28
|
import"./index-hamqvzqn.js";
|
|
29
|
-
import"./index-
|
|
30
|
-
import"./index-
|
|
31
|
-
import"./index-
|
|
32
|
-
import"./index-
|
|
33
|
-
import"./index-
|
|
29
|
+
import"./index-6g664sy8.js";
|
|
30
|
+
import"./index-yk0r42nr.js";
|
|
31
|
+
import"./index-046psajf.js";
|
|
32
|
+
import"./index-7hvy33gc.js";
|
|
33
|
+
import"./index-ya32wfkp.js";
|
|
34
34
|
import"./index-txdagbh7.js";
|
|
35
|
-
import"./index-
|
|
35
|
+
import"./index-7p4ym4q3.js";
|
|
36
36
|
import"./index-6b295cas.js";
|
|
37
|
-
import"./index-
|
|
38
|
-
import"./index-
|
|
39
|
-
import"./index-
|
|
37
|
+
import"./index-n107956q.js";
|
|
38
|
+
import"./index-3skvygca.js";
|
|
39
|
+
import"./index-jkxef52n.js";
|
|
40
40
|
import {
|
|
41
41
|
createExplorerAgent
|
|
42
42
|
} from "./index-rdec0y3z.js";
|
|
43
|
-
import"./index-
|
|
43
|
+
import"./index-ar2gsn6b.js";
|
|
44
44
|
import"./index-cjapb4hy.js";
|
|
45
45
|
import"./index-zsrtt42s.js";
|
|
46
|
-
import"./index-
|
|
47
|
-
import"./index-
|
|
48
|
-
import"./index-
|
|
46
|
+
import"./index-5ppx86w1.js";
|
|
47
|
+
import"./index-131ay7x1.js";
|
|
48
|
+
import"./index-3n5zsp31.js";
|
|
49
49
|
import"./index-pt7h91zc.js";
|
|
50
50
|
import"./index-q7sjgr1y.js";
|
|
51
|
-
import"./index-
|
|
52
|
-
import"./index-
|
|
53
|
-
import"./index-
|
|
54
|
-
import"./index-
|
|
55
|
-
import"./index-
|
|
56
|
-
import"./index-
|
|
51
|
+
import"./index-76abqm8d.js";
|
|
52
|
+
import"./index-depfky1j.js";
|
|
53
|
+
import"./index-2c91cxdv.js";
|
|
54
|
+
import"./index-57swfxyp.js";
|
|
55
|
+
import"./index-qczxr0wh.js";
|
|
56
|
+
import"./index-wy3zpwjy.js";
|
|
57
57
|
import"./index-2s7dvzff.js";
|
|
58
|
-
import"./index-
|
|
59
|
-
import"./index-
|
|
58
|
+
import"./index-gsgy1psq.js";
|
|
59
|
+
import"./index-earq3mda.js";
|
|
60
60
|
import"./index-rtry5xyf.js";
|
|
61
|
-
import"./index-
|
|
61
|
+
import"./index-6cvdk98y.js";
|
|
62
62
|
import"./index-frcemc0b.js";
|
|
63
63
|
import"./index-0725jpp7.js";
|
|
64
|
-
import"./index-
|
|
65
|
-
import"./index-
|
|
66
|
-
import"./index-
|
|
67
|
-
import"./index-
|
|
68
|
-
import"./index-
|
|
69
|
-
import"./index-
|
|
64
|
+
import"./index-6b427dy8.js";
|
|
65
|
+
import"./index-wfdx7yw2.js";
|
|
66
|
+
import"./index-jvk95e6y.js";
|
|
67
|
+
import"./index-456awy1p.js";
|
|
68
|
+
import"./index-f0nj3d8z.js";
|
|
69
|
+
import"./index-w9hxzcz4.js";
|
|
70
70
|
import"./index-rdm3px0g.js";
|
|
71
71
|
import"./index-ry16d01s.js";
|
|
72
|
-
import"./index-
|
|
73
|
-
import"./index-
|
|
72
|
+
import"./index-zzvxj02e.js";
|
|
73
|
+
import"./index-jc8pcf0r.js";
|
|
74
74
|
import"./index-vzm6zre7.js";
|
|
75
75
|
import"./index-ae75rja9.js";
|
|
76
|
-
import"./index-
|
|
77
|
-
import"./index-
|
|
78
|
-
import"./index-
|
|
79
|
-
import"./index-
|
|
76
|
+
import"./index-475bkab8.js";
|
|
77
|
+
import"./index-xf69xty9.js";
|
|
78
|
+
import"./index-t7hmqgjy.js";
|
|
79
|
+
import"./index-x1gyqgze.js";
|
|
80
|
+
import"./index-mc72pk74.js";
|
|
80
81
|
import"./index-c1ggtmpm.js";
|
|
81
82
|
import"./index-ejhxgyvm.js";
|
|
82
83
|
import"./index-7g4c7s5r.js";
|
|
83
|
-
import"./index-
|
|
84
|
+
import"./index-k53a69vb.js";
|
|
84
85
|
import"./index-gx2vp8gx.js";
|
|
85
|
-
import"./index-
|
|
86
|
+
import"./index-49ptc9xx.js";
|
|
86
87
|
import"./index-zxdawwc7.js";
|
|
87
|
-
import"./index-
|
|
88
|
+
import"./index-0874kghs.js";
|
|
88
89
|
import"./index-wzec3c4g.js";
|
|
89
90
|
import"./index-bk5tah7q.js";
|
|
90
91
|
import"./index-gknz3bv1.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
sameProjectRoot
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-mc72pk74.js";
|
|
5
5
|
import {
|
|
6
6
|
exports_external,
|
|
7
7
|
init_zod
|
|
@@ -236,7 +236,7 @@ var CATALOG_SOURCE = [
|
|
|
236
236
|
category: "delegation",
|
|
237
237
|
severity: "info",
|
|
238
238
|
privacyClass: "pseudonymous",
|
|
239
|
-
producer: "src/index.ts:
|
|
239
|
+
producer: "src/index.ts:940",
|
|
240
240
|
consumers: CONSUMER_COST_CORRECTION,
|
|
241
241
|
retentionOwnerIssue: ISSUE_COST_RETENTION,
|
|
242
242
|
requiredWorkflowIds: REQUIRE_SESSION_AND_TASK,
|
|
@@ -249,7 +249,7 @@ var CATALOG_SOURCE = [
|
|
|
249
249
|
category: "delegation",
|
|
250
250
|
severity: "info",
|
|
251
251
|
privacyClass: "pseudonymous",
|
|
252
|
-
producer: "src/index.ts:
|
|
252
|
+
producer: "src/index.ts:2060",
|
|
253
253
|
consumers: NO_CONSUMERS,
|
|
254
254
|
futureOwnerIssue: ISSUE_SINK,
|
|
255
255
|
retentionOwnerIssue: ISSUE_COST_RETENTION,
|
|
@@ -263,7 +263,7 @@ var CATALOG_SOURCE = [
|
|
|
263
263
|
category: "delegation",
|
|
264
264
|
severity: "notice",
|
|
265
265
|
privacyClass: "pseudonymous",
|
|
266
|
-
producer: "src/index.ts:
|
|
266
|
+
producer: "src/index.ts:2080",
|
|
267
267
|
consumers: CONSUMER_COST_JOIN,
|
|
268
268
|
retentionOwnerIssue: ISSUE_COST_RETENTION,
|
|
269
269
|
requiredWorkflowIds: REQUIRE_SESSION,
|
|
@@ -735,7 +735,7 @@ var CATALOG_SOURCE = [
|
|
|
735
735
|
category: "plan",
|
|
736
736
|
severity: "notice",
|
|
737
737
|
privacyClass: "operational",
|
|
738
|
-
producer: "src/plan/manager.ts:
|
|
738
|
+
producer: "src/plan/manager.ts:376",
|
|
739
739
|
consumers: NO_CONSUMERS,
|
|
740
740
|
futureOwnerIssue: ISSUE_SINK,
|
|
741
741
|
retentionOwnerIssue: ISSUE_PLAN_EVIDENCE_RETENTION,
|
|
@@ -748,7 +748,7 @@ var CATALOG_SOURCE = [
|
|
|
748
748
|
category: "plan",
|
|
749
749
|
severity: "warning",
|
|
750
750
|
privacyClass: "sensitive",
|
|
751
|
-
producer: "src/plan/manager.ts:
|
|
751
|
+
producer: "src/plan/manager.ts:2195",
|
|
752
752
|
consumers: NO_CONSUMERS,
|
|
753
753
|
futureOwnerIssue: ISSUE_SINK,
|
|
754
754
|
retentionOwnerIssue: ISSUE_PLAN_EVIDENCE_RETENTION,
|
|
@@ -761,7 +761,7 @@ var CATALOG_SOURCE = [
|
|
|
761
761
|
category: "plan",
|
|
762
762
|
severity: "error",
|
|
763
763
|
privacyClass: "sensitive",
|
|
764
|
-
producer: "src/plan/ledger.ts:
|
|
764
|
+
producer: "src/plan/ledger.ts:1620",
|
|
765
765
|
consumers: NO_CONSUMERS,
|
|
766
766
|
futureOwnerIssue: ISSUE_SINK,
|
|
767
767
|
retentionOwnerIssue: ISSUE_PLAN_EVIDENCE_RETENTION,
|