@tiangong-ai/cli 0.0.36 → 0.0.37
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/AGENTS.md +2 -2
- package/README.md +38 -2
- package/dist/research/orchestration.js +36 -1
- package/dist/research/orchestration.js.map +1 -1
- package/dist/research/workspace/acquisition-routes.d.ts +14 -0
- package/dist/research/workspace/acquisition-routes.js +45 -0
- package/dist/research/workspace/acquisition-routes.js.map +1 -0
- package/dist/research/workspace/broker.js +54 -10
- package/dist/research/workspace/broker.js.map +1 -1
- package/dist/research/workspace/downloads.d.ts +6 -0
- package/dist/research/workspace/downloads.js +32 -8
- package/dist/research/workspace/downloads.js.map +1 -1
- package/dist/research/workspace/evidence-exhaustion.d.ts +45 -0
- package/dist/research/workspace/evidence-exhaustion.js +365 -0
- package/dist/research/workspace/evidence-exhaustion.js.map +1 -0
- package/dist/research/workspace/native-activity.d.ts +6 -0
- package/dist/research/workspace/native-activity.js +24 -7
- package/dist/research/workspace/native-activity.js.map +1 -1
- package/dist/research/workspace/preflight.js +18 -2
- package/dist/research/workspace/preflight.js.map +1 -1
- package/dist/research/workspace/projects.js +52 -0
- package/dist/research/workspace/projects.js.map +1 -1
- package/dist/research/workspace/runtime.d.ts +151 -3
- package/dist/research/workspace/runtime.js +176 -5
- package/dist/research/workspace/runtime.js.map +1 -1
- package/dist/research/workspace/scientific-design.d.ts +23 -0
- package/dist/research/workspace/scientific-design.js +176 -0
- package/dist/research/workspace/scientific-design.js.map +1 -1
- package/dist/research/workspace/setup-catalog.js +2 -2
- package/dist/research/workspace/types.d.ts +27 -0
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ScientificDesignContract } from "./scientific-design.js";
|
|
2
|
+
import type { ProjectState, ResearchAccessRequest, ResearchEvidenceExhaustion } from "./types.js";
|
|
3
|
+
type TerminalClassification = "completed-insufficient" | "access-blocked" | "deterministic-unavailable";
|
|
4
|
+
interface TerminalRouteEvent {
|
|
5
|
+
hash: string;
|
|
6
|
+
type: string;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
classification: TerminalClassification;
|
|
9
|
+
journal: "workspace" | "evidence-ledger";
|
|
10
|
+
}
|
|
11
|
+
export interface EvidenceAccessRouteStatus {
|
|
12
|
+
id: string;
|
|
13
|
+
evidenceRoleIds: string[];
|
|
14
|
+
routeClass: ScientificDesignContract["acquisitionPlan"]["routes"][number]["routeClass"];
|
|
15
|
+
executor: ScientificDesignContract["acquisitionPlan"]["routes"][number]["executor"];
|
|
16
|
+
required: boolean;
|
|
17
|
+
accessMode: ScientificDesignContract["acquisitionPlan"]["routes"][number]["accessMode"];
|
|
18
|
+
terminalEventHashes: string[];
|
|
19
|
+
terminalEvents: TerminalRouteEvent[];
|
|
20
|
+
exhausted: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface EvidenceAccessStatus {
|
|
23
|
+
schemaVersion: 1;
|
|
24
|
+
projectId: string;
|
|
25
|
+
designSha256: string;
|
|
26
|
+
requiredEvidenceRoleIds: string[];
|
|
27
|
+
routes: EvidenceAccessRouteStatus[];
|
|
28
|
+
untriedRequiredAgentRouteIds: string[];
|
|
29
|
+
allRequiredAgentRoutesExhausted: boolean;
|
|
30
|
+
recommendedAction: "continue-plan-bound-agent-routes" | "assess-required-evidence-role-coverage";
|
|
31
|
+
ifEvidenceStillInsufficient: "request-reviewed-access-handoff" | "scope-pivot-required" | null;
|
|
32
|
+
}
|
|
33
|
+
export interface ParsedEvidenceExhaustionHandoff {
|
|
34
|
+
exhaustion: ResearchEvidenceExhaustion;
|
|
35
|
+
accessRequests: ResearchAccessRequest[];
|
|
36
|
+
}
|
|
37
|
+
export declare function inspectEvidenceAccessStatus(root: string, projectId: string): Promise<EvidenceAccessStatus>;
|
|
38
|
+
export declare function parseEvidenceExhaustionHandoff(exhaustionValue: unknown, accessRequestsValue: unknown): ParsedEvidenceExhaustionHandoff;
|
|
39
|
+
export declare function validateEvidenceExhaustionHandoff(input: {
|
|
40
|
+
root: string;
|
|
41
|
+
project: ProjectState;
|
|
42
|
+
state: "user-action-required" | "external-response-required";
|
|
43
|
+
value: ParsedEvidenceExhaustionHandoff;
|
|
44
|
+
}): Promise<ParsedEvidenceExhaustionHandoff>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { CliError } from "../../errors.js";
|
|
2
|
+
import { loadBoundAcquisitionDesign } from "./acquisition-routes.js";
|
|
3
|
+
import { evidenceLedgerPath, verifyEvidenceLedger } from "./evidence-ledger.js";
|
|
4
|
+
import { readJournal, verifyJournal } from "./journal.js";
|
|
5
|
+
import { loadProject } from "./projects.js";
|
|
6
|
+
import { isObject, workspacePaths } from "./storage.js";
|
|
7
|
+
const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
8
|
+
const SHA256 = /^[a-f0-9]{64}$/;
|
|
9
|
+
const SENSITIVE_QUERY_KEY = /^(?:access[_-]?token|api[_-]?key|apikey|auth|authorization|awsaccesskeyid|code|cookie|credential|key|password|secret|session(?:[_-]?id)?|sig|signature|token|x[_-]amz[_-](?:credential|security[_-]?token|signature)|x[_-]goog[_-](?:credential|signature))$/i;
|
|
10
|
+
const TRACKING_QUERY_KEY = /^(?:utm_[a-z0-9_]+|fbclid|gclid|mc_cid|mc_eid|ref|source)$/i;
|
|
11
|
+
export async function inspectEvidenceAccessStatus(root, projectId) {
|
|
12
|
+
const project = await loadProject(root, projectId);
|
|
13
|
+
const design = await loadBoundAcquisitionDesign(root, project);
|
|
14
|
+
const paths = workspacePaths(root);
|
|
15
|
+
const ledgerPath = evidenceLedgerPath(root, project.id);
|
|
16
|
+
await Promise.all([verifyJournal(paths.journal), verifyEvidenceLedger(root, project.id)]);
|
|
17
|
+
const [workspaceEvents, ledgerEvents] = await Promise.all([
|
|
18
|
+
readJournal(paths.journal),
|
|
19
|
+
readJournal(ledgerPath),
|
|
20
|
+
]);
|
|
21
|
+
const routes = design.acquisitionPlan.routes.map((route) => {
|
|
22
|
+
const terminalEvents = terminalEventsForRoute(project.id, route, workspaceEvents, ledgerEvents);
|
|
23
|
+
return {
|
|
24
|
+
id: route.id,
|
|
25
|
+
evidenceRoleIds: [...route.evidenceRoleIds],
|
|
26
|
+
routeClass: route.routeClass,
|
|
27
|
+
executor: route.executor,
|
|
28
|
+
required: route.required,
|
|
29
|
+
accessMode: route.accessMode,
|
|
30
|
+
terminalEventHashes: terminalEvents.map((event) => event.hash),
|
|
31
|
+
terminalEvents,
|
|
32
|
+
exhausted: terminalEvents.length > 0,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
const untriedRequiredAgentRouteIds = routes
|
|
36
|
+
.filter((route) => route.required && route.executor === "agent" && !route.exhausted)
|
|
37
|
+
.map((route) => route.id);
|
|
38
|
+
const nonAgentRoutes = routes.filter((route) => route.required && route.executor !== "agent");
|
|
39
|
+
return {
|
|
40
|
+
schemaVersion: 1,
|
|
41
|
+
projectId: project.id,
|
|
42
|
+
designSha256: project.scientificDesign.designSha256,
|
|
43
|
+
requiredEvidenceRoleIds: design.evidenceRoles
|
|
44
|
+
.filter((role) => role.required)
|
|
45
|
+
.map((role) => role.id),
|
|
46
|
+
routes,
|
|
47
|
+
untriedRequiredAgentRouteIds,
|
|
48
|
+
allRequiredAgentRoutesExhausted: untriedRequiredAgentRouteIds.length === 0,
|
|
49
|
+
recommendedAction: untriedRequiredAgentRouteIds.length > 0
|
|
50
|
+
? "continue-plan-bound-agent-routes"
|
|
51
|
+
: "assess-required-evidence-role-coverage",
|
|
52
|
+
ifEvidenceStillInsufficient: untriedRequiredAgentRouteIds.length > 0
|
|
53
|
+
? null
|
|
54
|
+
: nonAgentRoutes.length > 0
|
|
55
|
+
? "request-reviewed-access-handoff"
|
|
56
|
+
: "scope-pivot-required",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function parseEvidenceExhaustionHandoff(exhaustionValue, accessRequestsValue) {
|
|
60
|
+
if (!isObject(exhaustionValue))
|
|
61
|
+
throw invalidHandoff();
|
|
62
|
+
assertExactKeys(exhaustionValue, [
|
|
63
|
+
"missingEvidenceRoleIds",
|
|
64
|
+
"routeAttempts",
|
|
65
|
+
"remainingRouteIds",
|
|
66
|
+
]);
|
|
67
|
+
const missingEvidenceRoleIds = stringSet(exhaustionValue.missingEvidenceRoleIds, 1, 100, IDENTIFIER);
|
|
68
|
+
const remainingRouteIds = stringSet(exhaustionValue.remainingRouteIds, 0, 100, IDENTIFIER);
|
|
69
|
+
if (!Array.isArray(exhaustionValue.routeAttempts) || exhaustionValue.routeAttempts.length < 1) {
|
|
70
|
+
throw invalidHandoff();
|
|
71
|
+
}
|
|
72
|
+
const routeAttempts = exhaustionValue.routeAttempts.map((attempt) => {
|
|
73
|
+
if (!isObject(attempt))
|
|
74
|
+
throw invalidHandoff();
|
|
75
|
+
assertExactKeys(attempt, ["routeId", "terminalEventHashes", "outcome"]);
|
|
76
|
+
if (typeof attempt.routeId !== "string" ||
|
|
77
|
+
!IDENTIFIER.test(attempt.routeId) ||
|
|
78
|
+
!["completed-insufficient", "access-blocked", "deterministic-unavailable"].includes(String(attempt.outcome))) {
|
|
79
|
+
throw invalidHandoff();
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
routeId: attempt.routeId,
|
|
83
|
+
terminalEventHashes: stringSet(attempt.terminalEventHashes, 1, 100, SHA256),
|
|
84
|
+
outcome: attempt.outcome,
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
if (new Set(routeAttempts.map((attempt) => attempt.routeId)).size !== routeAttempts.length) {
|
|
88
|
+
throw invalidHandoff();
|
|
89
|
+
}
|
|
90
|
+
if (!Array.isArray(accessRequestsValue) || accessRequestsValue.length > 100) {
|
|
91
|
+
throw invalidHandoff();
|
|
92
|
+
}
|
|
93
|
+
const accessRequests = accessRequestsValue.map(parseAccessRequest);
|
|
94
|
+
if (new Set(accessRequests.map((request) => request.id)).size !== accessRequests.length) {
|
|
95
|
+
throw invalidHandoff();
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
exhaustion: { missingEvidenceRoleIds, routeAttempts, remainingRouteIds },
|
|
99
|
+
accessRequests,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export async function validateEvidenceExhaustionHandoff(input) {
|
|
103
|
+
const status = await inspectEvidenceAccessStatus(input.root, input.project.id);
|
|
104
|
+
const routeById = new Map(status.routes.map((route) => [route.id, route]));
|
|
105
|
+
const requiredRoles = new Set(status.requiredEvidenceRoleIds);
|
|
106
|
+
const missingRoles = new Set(input.value.exhaustion.missingEvidenceRoleIds);
|
|
107
|
+
if ([...missingRoles].some((roleId) => !requiredRoles.has(roleId)))
|
|
108
|
+
throw unproven();
|
|
109
|
+
const relevantAgentRoutes = status.routes.filter((route) => route.required &&
|
|
110
|
+
route.executor === "agent" &&
|
|
111
|
+
route.evidenceRoleIds.some((roleId) => missingRoles.has(roleId)));
|
|
112
|
+
const attemptByRoute = new Map(input.value.exhaustion.routeAttempts.map((attempt) => [attempt.routeId, attempt]));
|
|
113
|
+
if (attemptByRoute.size !== relevantAgentRoutes.length ||
|
|
114
|
+
relevantAgentRoutes.some((route) => !attemptByRoute.has(route.id))) {
|
|
115
|
+
throw unproven();
|
|
116
|
+
}
|
|
117
|
+
for (const route of relevantAgentRoutes) {
|
|
118
|
+
const attempt = attemptByRoute.get(route.id);
|
|
119
|
+
const terminalByHash = new Map(route.terminalEvents.map((event) => [event.hash, event]));
|
|
120
|
+
if (attempt.terminalEventHashes.some((hash) => terminalByHash.get(hash)?.classification !== attempt.outcome)) {
|
|
121
|
+
throw unproven();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const relevantNonAgentRoutes = status.routes.filter((route) => route.required &&
|
|
125
|
+
route.executor !== "agent" &&
|
|
126
|
+
route.evidenceRoleIds.some((roleId) => missingRoles.has(roleId)));
|
|
127
|
+
const remainingRoutes = input.value.exhaustion.remainingRouteIds.map((routeId) => routeById.get(routeId));
|
|
128
|
+
const expectedExecutor = input.state === "user-action-required" ? "user" : "external-party";
|
|
129
|
+
if (remainingRoutes.some((route) => !route ||
|
|
130
|
+
!route.required ||
|
|
131
|
+
route.executor !== expectedExecutor ||
|
|
132
|
+
!route.evidenceRoleIds.some((roleId) => missingRoles.has(roleId))) ||
|
|
133
|
+
(remainingRoutes.length === 0
|
|
134
|
+
? relevantNonAgentRoutes.length > 0 || input.state !== "user-action-required"
|
|
135
|
+
: [...missingRoles].some((roleId) => !remainingRoutes.some((route) => route?.evidenceRoleIds.includes(roleId))))) {
|
|
136
|
+
throw unproven();
|
|
137
|
+
}
|
|
138
|
+
const requestByRoute = new Map(input.value.accessRequests.map((request) => [request.routeId, request]));
|
|
139
|
+
if (requestByRoute.size !== remainingRoutes.length ||
|
|
140
|
+
input.value.exhaustion.remainingRouteIds.some((routeId) => !requestByRoute.has(routeId))) {
|
|
141
|
+
throw invalidHandoff();
|
|
142
|
+
}
|
|
143
|
+
const triedRouteIds = new Set(input.value.exhaustion.routeAttempts.map((attempt) => attempt.routeId));
|
|
144
|
+
const coveredRoles = new Set();
|
|
145
|
+
for (const route of remainingRoutes) {
|
|
146
|
+
const request = requestByRoute.get(route.id);
|
|
147
|
+
if (request.evidenceRoleIds.some((roleId) => !missingRoles.has(roleId) || !route.evidenceRoleIds.includes(roleId)) ||
|
|
148
|
+
request.alternativesTriedRouteIds.length !== triedRouteIds.size ||
|
|
149
|
+
request.alternativesTriedRouteIds.some((routeId) => !triedRouteIds.has(routeId)) ||
|
|
150
|
+
!resourceTypeMatchesRoute(request.resourceType, route.routeClass)) {
|
|
151
|
+
throw invalidHandoff();
|
|
152
|
+
}
|
|
153
|
+
request.evidenceRoleIds.forEach((roleId) => coveredRoles.add(roleId));
|
|
154
|
+
}
|
|
155
|
+
if (remainingRoutes.length > 0 && [...missingRoles].some((roleId) => !coveredRoles.has(roleId))) {
|
|
156
|
+
throw invalidHandoff();
|
|
157
|
+
}
|
|
158
|
+
return input.value;
|
|
159
|
+
}
|
|
160
|
+
function terminalEventsForRoute(projectId, route, workspaceEvents, ledgerEvents) {
|
|
161
|
+
const events = [];
|
|
162
|
+
for (const event of workspaceEvents) {
|
|
163
|
+
if (event.scope !== projectId || event.payload.projectId !== projectId)
|
|
164
|
+
continue;
|
|
165
|
+
const classification = workspaceTerminalClassification(route, event);
|
|
166
|
+
if (classification) {
|
|
167
|
+
events.push({
|
|
168
|
+
hash: event.hash,
|
|
169
|
+
type: event.type,
|
|
170
|
+
timestamp: event.timestamp,
|
|
171
|
+
classification,
|
|
172
|
+
journal: "workspace",
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
for (const event of ledgerEvents) {
|
|
177
|
+
if (event.scope !== projectId || event.payload.projectId !== projectId)
|
|
178
|
+
continue;
|
|
179
|
+
const classification = ledgerTerminalClassification(route, event);
|
|
180
|
+
if (classification) {
|
|
181
|
+
events.push({
|
|
182
|
+
hash: event.hash,
|
|
183
|
+
type: event.type,
|
|
184
|
+
timestamp: event.timestamp,
|
|
185
|
+
classification,
|
|
186
|
+
journal: "evidence-ledger",
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return events.sort((left, right) => left.timestamp.localeCompare(right.timestamp) || left.hash.localeCompare(right.hash));
|
|
191
|
+
}
|
|
192
|
+
function workspaceTerminalClassification(route, event) {
|
|
193
|
+
if (route.routeClass !== "broker-capability" ||
|
|
194
|
+
event.payload.acquisitionRouteId !== route.id ||
|
|
195
|
+
event.payload.capabilityId !== route.capabilityId) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
if (["capability.fetch.completed", "capability.fetch.reused"].includes(event.type)) {
|
|
199
|
+
return "completed-insufficient";
|
|
200
|
+
}
|
|
201
|
+
if (event.type !== "capability.fetch.failed")
|
|
202
|
+
return null;
|
|
203
|
+
const failureKind = String(event.payload.failureKind);
|
|
204
|
+
if (failureKind === "authentication")
|
|
205
|
+
return "access-blocked";
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
function ledgerTerminalClassification(route, event) {
|
|
209
|
+
if (route.routeClass === "native-discovery") {
|
|
210
|
+
if (event.type !== "activity.recorded" ||
|
|
211
|
+
event.payload.acquisitionRouteId !== route.id ||
|
|
212
|
+
event.payload.kind !== route.activityKind ||
|
|
213
|
+
event.payload.channel !== route.activityChannel) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
if (event.payload.status === "completed")
|
|
217
|
+
return "completed-insufficient";
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
if (!["open-access-download", "authorized-browser"].includes(route.routeClass))
|
|
221
|
+
return null;
|
|
222
|
+
if (event.payload.acquisitionRouteId !== route.id)
|
|
223
|
+
return null;
|
|
224
|
+
const backend = event.payload.backend;
|
|
225
|
+
if (!route.downloadBackends.includes(backend))
|
|
226
|
+
return null;
|
|
227
|
+
if (event.type === "download.bound")
|
|
228
|
+
return "completed-insufficient";
|
|
229
|
+
if (event.type !== "download.failed" || event.payload.status === "cancelled")
|
|
230
|
+
return null;
|
|
231
|
+
const failureCode = String(event.payload.failureCode ?? "");
|
|
232
|
+
if (/not-found|unsupported|invalid-content|no-open-access|oa-exhausted|unavailable/i.test(failureCode)) {
|
|
233
|
+
return "deterministic-unavailable";
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
function parseAccessRequest(value) {
|
|
238
|
+
if (!isObject(value))
|
|
239
|
+
throw invalidHandoff();
|
|
240
|
+
assertExactKeys(value, [
|
|
241
|
+
"id",
|
|
242
|
+
"routeId",
|
|
243
|
+
"resourceType",
|
|
244
|
+
"resourceName",
|
|
245
|
+
"officialLocator",
|
|
246
|
+
"evidenceRoleIds",
|
|
247
|
+
"rationale",
|
|
248
|
+
"alternativesTriedRouteIds",
|
|
249
|
+
"requestedAction",
|
|
250
|
+
"resumeCriteria",
|
|
251
|
+
"costStatus",
|
|
252
|
+
]);
|
|
253
|
+
const resourceTypes = [
|
|
254
|
+
"database-subscription",
|
|
255
|
+
"article-purchase",
|
|
256
|
+
"institutional-access",
|
|
257
|
+
"licensed-dataset",
|
|
258
|
+
"owner-provided-material",
|
|
259
|
+
"external-data-request",
|
|
260
|
+
"field-data-collection",
|
|
261
|
+
];
|
|
262
|
+
if (typeof value.id !== "string" ||
|
|
263
|
+
!IDENTIFIER.test(value.id) ||
|
|
264
|
+
typeof value.routeId !== "string" ||
|
|
265
|
+
!IDENTIFIER.test(value.routeId) ||
|
|
266
|
+
!resourceTypes.includes(value.resourceType) ||
|
|
267
|
+
!boundedString(value.resourceName, 3, 500) ||
|
|
268
|
+
!boundedString(value.rationale, 8, 2_000) ||
|
|
269
|
+
!boundedString(value.requestedAction, 8, 1_000) ||
|
|
270
|
+
!boundedString(value.resumeCriteria, 8, 1_000) ||
|
|
271
|
+
!["unknown", "provider-quote-required"].includes(String(value.costStatus))) {
|
|
272
|
+
throw invalidHandoff();
|
|
273
|
+
}
|
|
274
|
+
const resourceType = value.resourceType;
|
|
275
|
+
const officialLocator = safeOfficialLocator(value.officialLocator);
|
|
276
|
+
if ([
|
|
277
|
+
"database-subscription",
|
|
278
|
+
"article-purchase",
|
|
279
|
+
"institutional-access",
|
|
280
|
+
"licensed-dataset",
|
|
281
|
+
].includes(resourceType) &&
|
|
282
|
+
!officialLocator) {
|
|
283
|
+
throw invalidHandoff();
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
id: value.id,
|
|
287
|
+
routeId: value.routeId,
|
|
288
|
+
resourceType,
|
|
289
|
+
resourceName: value.resourceName.trim(),
|
|
290
|
+
officialLocator,
|
|
291
|
+
evidenceRoleIds: stringSet(value.evidenceRoleIds, 1, 100, IDENTIFIER),
|
|
292
|
+
rationale: value.rationale.trim(),
|
|
293
|
+
alternativesTriedRouteIds: stringSet(value.alternativesTriedRouteIds, 1, 100, IDENTIFIER),
|
|
294
|
+
requestedAction: value.requestedAction.trim(),
|
|
295
|
+
resumeCriteria: value.resumeCriteria.trim(),
|
|
296
|
+
costStatus: value.costStatus,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function safeOfficialLocator(value) {
|
|
300
|
+
if (value === null)
|
|
301
|
+
return null;
|
|
302
|
+
if (typeof value !== "string" || value.length > 2_000)
|
|
303
|
+
throw invalidHandoff();
|
|
304
|
+
let url;
|
|
305
|
+
try {
|
|
306
|
+
url = new URL(value);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
throw invalidHandoff();
|
|
310
|
+
}
|
|
311
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash)
|
|
312
|
+
throw invalidHandoff();
|
|
313
|
+
if ([...url.searchParams.keys()].some((key) => SENSITIVE_QUERY_KEY.test(key))) {
|
|
314
|
+
throw invalidHandoff();
|
|
315
|
+
}
|
|
316
|
+
for (const key of [...url.searchParams.keys()]) {
|
|
317
|
+
if (TRACKING_QUERY_KEY.test(key))
|
|
318
|
+
url.searchParams.delete(key);
|
|
319
|
+
}
|
|
320
|
+
url.searchParams.sort();
|
|
321
|
+
return url.toString();
|
|
322
|
+
}
|
|
323
|
+
function resourceTypeMatchesRoute(resourceType, routeClass) {
|
|
324
|
+
if (routeClass === "licensed-resource") {
|
|
325
|
+
return [
|
|
326
|
+
"database-subscription",
|
|
327
|
+
"article-purchase",
|
|
328
|
+
"institutional-access",
|
|
329
|
+
"licensed-dataset",
|
|
330
|
+
].includes(resourceType);
|
|
331
|
+
}
|
|
332
|
+
if (routeClass === "owner-provided-resource")
|
|
333
|
+
return resourceType === "owner-provided-material";
|
|
334
|
+
if (routeClass === "external-data-request")
|
|
335
|
+
return resourceType === "external-data-request";
|
|
336
|
+
return routeClass === "field-data-collection" && resourceType === "field-data-collection";
|
|
337
|
+
}
|
|
338
|
+
function stringSet(value, minimum, maximum, pattern) {
|
|
339
|
+
if (!Array.isArray(value) ||
|
|
340
|
+
value.length < minimum ||
|
|
341
|
+
value.length > maximum ||
|
|
342
|
+
value.some((item) => typeof item !== "string" || !pattern.test(item)) ||
|
|
343
|
+
new Set(value).size !== value.length) {
|
|
344
|
+
throw invalidHandoff();
|
|
345
|
+
}
|
|
346
|
+
return value;
|
|
347
|
+
}
|
|
348
|
+
function assertExactKeys(value, keys) {
|
|
349
|
+
const expected = new Set(keys);
|
|
350
|
+
if (Object.keys(value).some((key) => !expected.has(key)))
|
|
351
|
+
throw invalidHandoff();
|
|
352
|
+
}
|
|
353
|
+
function boundedString(value, minimum, maximum) {
|
|
354
|
+
return typeof value === "string" && value.trim().length >= minimum && value.length <= maximum;
|
|
355
|
+
}
|
|
356
|
+
function invalidHandoff() {
|
|
357
|
+
return new CliError("Handoff request failed validation.", {
|
|
358
|
+
code: "RESEARCH_PROJECT_HANDOFF_INVALID",
|
|
359
|
+
exitCode: 2,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
function unproven() {
|
|
363
|
+
return new CliError("Evidence exhaustion is not proven by every required plan-bound terminal event.", { code: "RESEARCH_EVIDENCE_EXHAUSTION_UNPROVEN", exitCode: 3 });
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=evidence-exhaustion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-exhaustion.js","sourceRoot":"","sources":["../../../src/research/workspace/evidence-exhaustion.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,11 @@ export declare const nativeActivityRecordSchema: {
|
|
|
8
8
|
readonly type: "integer";
|
|
9
9
|
readonly const: 1;
|
|
10
10
|
};
|
|
11
|
+
readonly acquisitionRouteId: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$";
|
|
14
|
+
readonly description: "Required for a project with a frozen scientific design; binds this event to one exact planned agent route.";
|
|
15
|
+
};
|
|
11
16
|
readonly kind: {
|
|
12
17
|
readonly type: "string";
|
|
13
18
|
readonly enum: readonly ["web-search", "database-search", "browser-navigation", "download", "file-inspection"];
|
|
@@ -48,6 +53,7 @@ export declare const nativeActivityRecordSchema: {
|
|
|
48
53
|
export interface NativeActivityReceipt {
|
|
49
54
|
activityId: string;
|
|
50
55
|
projectId: string;
|
|
56
|
+
acquisitionRouteId: string | null;
|
|
51
57
|
stage: "discover" | "acquire";
|
|
52
58
|
kind: string;
|
|
53
59
|
channel: string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveAgentAcquisitionRoute } from "./acquisition-routes.js";
|
|
3
3
|
import { appendEvidenceLedgerEvent, listEvidenceCandidates } from "./evidence-ledger.js";
|
|
4
|
+
import { loadProject } from "./projects.js";
|
|
4
5
|
import { sanitizeResearchValue } from "./sanitization.js";
|
|
5
|
-
import { canonicalJson, isObject,
|
|
6
|
+
import { canonicalJson, isObject, sha256Text } from "./storage.js";
|
|
6
7
|
import { StructuredOutputError } from "./schemas.js";
|
|
7
8
|
const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
8
9
|
export const nativeActivityRecordSchema = {
|
|
@@ -21,6 +22,11 @@ export const nativeActivityRecordSchema = {
|
|
|
21
22
|
],
|
|
22
23
|
properties: {
|
|
23
24
|
schemaVersion: { type: "integer", const: 1 },
|
|
25
|
+
acquisitionRouteId: {
|
|
26
|
+
type: "string",
|
|
27
|
+
pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
|
|
28
|
+
description: "Required for a project with a frozen scientific design; binds this event to one exact planned agent route.",
|
|
29
|
+
},
|
|
24
30
|
kind: {
|
|
25
31
|
type: "string",
|
|
26
32
|
enum: ["web-search", "database-search", "browser-navigation", "download", "file-inspection"],
|
|
@@ -61,6 +67,7 @@ export async function recordNativeResearchActivity(input) {
|
|
|
61
67
|
throw activityError("Native activity record must be a JSON object.");
|
|
62
68
|
const allowed = new Set([
|
|
63
69
|
"schemaVersion",
|
|
70
|
+
"acquisitionRouteId",
|
|
64
71
|
"kind",
|
|
65
72
|
"channel",
|
|
66
73
|
"input",
|
|
@@ -72,6 +79,9 @@ export async function recordNativeResearchActivity(input) {
|
|
|
72
79
|
const unknown = Object.keys(value).filter((key) => !allowed.has(key));
|
|
73
80
|
if (unknown.length ||
|
|
74
81
|
value.schemaVersion !== 1 ||
|
|
82
|
+
(value.acquisitionRouteId !== undefined &&
|
|
83
|
+
(typeof value.acquisitionRouteId !== "string" ||
|
|
84
|
+
!IDENTIFIER.test(value.acquisitionRouteId))) ||
|
|
75
85
|
![
|
|
76
86
|
"web-search",
|
|
77
87
|
"database-search",
|
|
@@ -106,13 +116,11 @@ export async function recordNativeResearchActivity(input) {
|
|
|
106
116
|
if (value.challenge !== "none" && value.status !== "blocked") {
|
|
107
117
|
throw activityError("A native challenge must be recorded with blocked status.");
|
|
108
118
|
}
|
|
109
|
-
const project = await
|
|
110
|
-
const
|
|
111
|
-
const active = packages.find((workPackage) => isObject(workPackage) &&
|
|
112
|
-
(workPackage.stage === "discover" || workPackage.stage === "acquire") &&
|
|
119
|
+
const project = await loadProject(input.root, input.projectId);
|
|
120
|
+
const active = project.packages.find((workPackage) => (workPackage.stage === "discover" || workPackage.stage === "acquire") &&
|
|
113
121
|
workPackage.status === "running" &&
|
|
114
122
|
workPackage.executor === "producer");
|
|
115
|
-
if (!
|
|
123
|
+
if (!active || (active.stage !== "discover" && active.stage !== "acquire")) {
|
|
116
124
|
throw activityError("Native activity may be recorded only during an active discover or acquire stage.");
|
|
117
125
|
}
|
|
118
126
|
const stage = active.stage;
|
|
@@ -121,6 +129,14 @@ export async function recordNativeResearchActivity(input) {
|
|
|
121
129
|
(stage === "acquire" && ["web-search", "database-search"].includes(kind))) {
|
|
122
130
|
throw activityError(`Native ${kind} activity is not valid during ${stage}.`);
|
|
123
131
|
}
|
|
132
|
+
const route = await resolveAgentAcquisitionRoute({
|
|
133
|
+
root: input.root,
|
|
134
|
+
project,
|
|
135
|
+
routeId: value.acquisitionRouteId,
|
|
136
|
+
routeClasses: ["native-discovery"],
|
|
137
|
+
activityKind: value.kind,
|
|
138
|
+
activityChannel: value.channel,
|
|
139
|
+
});
|
|
124
140
|
const candidateIds = value.candidateIds;
|
|
125
141
|
const known = new Set((await listEvidenceCandidates(input.root, input.projectId)).map((candidate) => candidate.id));
|
|
126
142
|
const missing = candidateIds.filter((candidateId) => !known.has(candidateId));
|
|
@@ -131,6 +147,7 @@ export async function recordNativeResearchActivity(input) {
|
|
|
131
147
|
const receipt = {
|
|
132
148
|
activityId: `activity-${randomUUID()}`,
|
|
133
149
|
projectId: input.projectId,
|
|
150
|
+
acquisitionRouteId: route?.id ?? null,
|
|
134
151
|
stage,
|
|
135
152
|
kind,
|
|
136
153
|
channel: value.channel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-activity.js","sourceRoot":"","sources":["../../../src/research/workspace/native-activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"native-activity.js","sourceRoot":"","sources":["../../../src/research/workspace/native-activity.ts"],"names":[],"mappings":"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"}
|
|
@@ -97,7 +97,7 @@ export async function evaluateProjectPreflight(root, question, requirements, inp
|
|
|
97
97
|
gaps.push(...designEvaluation.issueCodes.map((code) => `scientific-design:${code}`));
|
|
98
98
|
}
|
|
99
99
|
if (options.publicationPolicy && options.scientificDesign) {
|
|
100
|
-
appendScientificDesignContractGaps(gaps, options.scientificDesign.contract, options.publicationPolicy, requirements);
|
|
100
|
+
appendScientificDesignContractGaps(gaps, options.scientificDesign.contract, options.publicationPolicy, requirements, new Set(networkCapabilities.map((capability) => capability.id)));
|
|
101
101
|
}
|
|
102
102
|
if (config.mode === "production-research" && !requirements) {
|
|
103
103
|
gaps.push("explicit-evidence-requirements-missing");
|
|
@@ -465,7 +465,7 @@ function appendEvidencePlanGaps(gaps, coverageGaps, requirements, inputPlan, net
|
|
|
465
465
|
gaps.push(`evidence-plan-dated-sources-insufficient:${plannedDatedCount}/${requirements.minDatedSources}`);
|
|
466
466
|
}
|
|
467
467
|
}
|
|
468
|
-
function appendScientificDesignContractGaps(gaps, design, policy, requirements) {
|
|
468
|
+
function appendScientificDesignContractGaps(gaps, design, policy, requirements, availableCapabilityIds) {
|
|
469
469
|
const prefix = "scientific-design-contract:";
|
|
470
470
|
gaps.push(...scientificDesignPolicyGaps(design, policy).map((gap) => `${prefix}${gap}`));
|
|
471
471
|
if (policy.targetJournal) {
|
|
@@ -477,7 +477,23 @@ function appendScientificDesignContractGaps(gaps, design, policy, requirements)
|
|
|
477
477
|
gaps.push(`${prefix}policy-journal-approval-unbound`);
|
|
478
478
|
}
|
|
479
479
|
const requiredRoles = design.evidenceRoles.filter((role) => role.required);
|
|
480
|
+
const requiredRoleIds = new Set(requiredRoles.map((role) => role.id));
|
|
481
|
+
const requiredBrokerRoutes = design.acquisitionPlan.routes.filter((route) => route.required &&
|
|
482
|
+
route.executor === "agent" &&
|
|
483
|
+
route.routeClass === "broker-capability" &&
|
|
484
|
+
route.evidenceRoleIds.some((roleId) => requiredRoleIds.has(roleId)));
|
|
485
|
+
for (const route of requiredBrokerRoutes) {
|
|
486
|
+
if (route.capabilityId && !availableCapabilityIds.has(route.capabilityId)) {
|
|
487
|
+
gaps.push(`${prefix}acquisition-capability-unavailable:${route.id}:${route.capabilityId}`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
480
490
|
if (requirements) {
|
|
491
|
+
const mappedCapabilityIds = new Set(requiredBrokerRoutes.flatMap((route) => (route.capabilityId ? [route.capabilityId] : [])));
|
|
492
|
+
for (const capabilityId of requirements.requiredCapabilityIds ?? []) {
|
|
493
|
+
if (!mappedCapabilityIds.has(capabilityId)) {
|
|
494
|
+
gaps.push(`${prefix}required-capability-route-unmapped:${capabilityId}`);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
481
497
|
const mappedDimensions = new Set(requiredRoles.flatMap((role) => role.coverageDimensionIds));
|
|
482
498
|
const mappedSourceTypes = new Set(requiredRoles.flatMap((role) => role.sourceTypeRequirements));
|
|
483
499
|
for (const dimension of requirements.dimensions) {
|