@tiangong-ai/cli 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/AGENTS.md +7 -2
  2. package/README.md +72 -19
  3. package/dist/research/commands.js +58 -1
  4. package/dist/research/commands.js.map +1 -1
  5. package/dist/research/orchestration.js +388 -31
  6. package/dist/research/orchestration.js.map +1 -1
  7. package/dist/research/workspace/acquisition.d.ts +71 -0
  8. package/dist/research/workspace/acquisition.js +593 -0
  9. package/dist/research/workspace/acquisition.js.map +1 -0
  10. package/dist/research/workspace/artifacts.d.ts +43 -0
  11. package/dist/research/workspace/artifacts.js +544 -0
  12. package/dist/research/workspace/artifacts.js.map +1 -0
  13. package/dist/research/workspace/broker.js +265 -56
  14. package/dist/research/workspace/broker.js.map +1 -1
  15. package/dist/research/workspace/constants.d.ts +1 -0
  16. package/dist/research/workspace/constants.js +4 -2
  17. package/dist/research/workspace/constants.js.map +1 -1
  18. package/dist/research/workspace/context.js +106 -11
  19. package/dist/research/workspace/context.js.map +1 -1
  20. package/dist/research/workspace/discovery-planning.d.ts +25 -0
  21. package/dist/research/workspace/discovery-planning.js +106 -0
  22. package/dist/research/workspace/discovery-planning.js.map +1 -0
  23. package/dist/research/workspace/discovery-status.d.ts +46 -0
  24. package/dist/research/workspace/discovery-status.js +183 -0
  25. package/dist/research/workspace/discovery-status.js.map +1 -0
  26. package/dist/research/workspace/discovery.d.ts +25 -0
  27. package/dist/research/workspace/discovery.js +268 -0
  28. package/dist/research/workspace/discovery.js.map +1 -0
  29. package/dist/research/workspace/downloads.d.ts +76 -0
  30. package/dist/research/workspace/downloads.js +274 -0
  31. package/dist/research/workspace/downloads.js.map +1 -0
  32. package/dist/research/workspace/evidence-ledger.d.ts +52 -0
  33. package/dist/research/workspace/evidence-ledger.js +487 -0
  34. package/dist/research/workspace/evidence-ledger.js.map +1 -0
  35. package/dist/research/workspace/evidence.d.ts +1 -0
  36. package/dist/research/workspace/evidence.js +2 -0
  37. package/dist/research/workspace/evidence.js.map +1 -1
  38. package/dist/research/workspace/input-plan.js +4 -0
  39. package/dist/research/workspace/input-plan.js.map +1 -1
  40. package/dist/research/workspace/native-activity.d.ts +65 -0
  41. package/dist/research/workspace/native-activity.js +153 -0
  42. package/dist/research/workspace/native-activity.js.map +1 -0
  43. package/dist/research/workspace/preflight.d.ts +5 -0
  44. package/dist/research/workspace/preflight.js +37 -17
  45. package/dist/research/workspace/preflight.js.map +1 -1
  46. package/dist/research/workspace/projects.d.ts +3 -1
  47. package/dist/research/workspace/projects.js +346 -5
  48. package/dist/research/workspace/projects.js.map +1 -1
  49. package/dist/research/workspace/runtime.d.ts +106 -4
  50. package/dist/research/workspace/runtime.js +947 -80
  51. package/dist/research/workspace/runtime.js.map +1 -1
  52. package/dist/research/workspace/sanitization.js +28 -6
  53. package/dist/research/workspace/sanitization.js.map +1 -1
  54. package/dist/research/workspace/schemas.d.ts +3 -0
  55. package/dist/research/workspace/schemas.js +206 -33
  56. package/dist/research/workspace/schemas.js.map +1 -1
  57. package/dist/research/workspace/setup-catalog.js +5 -5
  58. package/dist/research/workspace/setup-invocation.d.ts +11 -0
  59. package/dist/research/workspace/setup-invocation.js +34 -0
  60. package/dist/research/workspace/setup-invocation.js.map +1 -0
  61. package/dist/research/workspace/setup-wizard.js +10 -4
  62. package/dist/research/workspace/setup-wizard.js.map +1 -1
  63. package/dist/research/workspace/setup.d.ts +55 -7
  64. package/dist/research/workspace/setup.js +603 -32
  65. package/dist/research/workspace/setup.js.map +1 -1
  66. package/dist/research/workspace/types.d.ts +52 -3
  67. package/dist/research/workspace/workspace.js +45 -6
  68. package/dist/research/workspace/workspace.js.map +1 -1
  69. package/package.json +4 -2
@@ -0,0 +1,183 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { loadCapabilityDeclarations } from "./capabilities.js";
4
+ import { deriveDiscoveryPlan } from "./discovery-planning.js";
5
+ import { evidenceLedgerPath, listEvidenceCandidates } from "./evidence-ledger.js";
6
+ import { readJournal } from "./journal.js";
7
+ import { isObject, pathExists, workspacePaths } from "./storage.js";
8
+ import { loadWorkspaceConfig } from "./workspace.js";
9
+ export async function inspectDiscoveryProgress(root, project, suppliedConfig) {
10
+ const [config, declarations, mainEvents, ledgerEvents, candidates] = await Promise.all([
11
+ suppliedConfig ? Promise.resolve(suppliedConfig) : loadWorkspaceConfig(root),
12
+ loadCapabilityDeclarations(root),
13
+ readJournal(workspacePaths(root).journal),
14
+ readJournal(evidenceLedgerPath(root, project.id)),
15
+ listEvidenceCandidates(root, project.id),
16
+ ]);
17
+ const networkCapabilityIds = declarations.capabilities
18
+ .filter((capability) => capability.permissions.includes("brokered-network"))
19
+ .map((capability) => capability.id)
20
+ .sort();
21
+ const plan = deriveDiscoveryPlan(project.evidenceRequirements, config, networkCapabilityIds);
22
+ const projectEvents = mainEvents.filter((event) => event.scope === project.id);
23
+ const requested = projectEvents.filter((event) => event.type === "capability.fetch.requested");
24
+ const attempted = projectEvents.filter((event) => event.type === "capability.fetch.attempted");
25
+ const completed = projectEvents.filter((event) => event.type === "capability.fetch.completed");
26
+ const reused = projectEvents.filter((event) => event.type === "capability.fetch.reused");
27
+ const failed = projectEvents.filter((event) => event.type === "capability.fetch.failed");
28
+ const latestDecisions = new Map();
29
+ for (const event of ledgerEvents) {
30
+ if (event.type === "candidate.assessed" &&
31
+ (event.payload.decision === "admit" || event.payload.decision === "reject")) {
32
+ latestDecisions.set(String(event.payload.candidateId), event.payload.decision === "admit" ? "admitted" : "rejected");
33
+ }
34
+ else if (event.type === "candidate.admitted") {
35
+ latestDecisions.set(String(event.payload.candidateId), "admitted");
36
+ }
37
+ else if (event.type === "candidate.rejected") {
38
+ latestDecisions.set(String(event.payload.candidateId), "rejected");
39
+ }
40
+ }
41
+ const admitted = new Set([...latestDecisions].filter(([, decision]) => decision === "admitted").map(([id]) => id));
42
+ const rejected = new Set([...latestDecisions].filter(([, decision]) => decision === "rejected").map(([id]) => id));
43
+ const duplicateOccurrences = ledgerEvents.filter((event) => event.type === "candidate.duplicate").length;
44
+ const activityEvents = ledgerEvents.filter((event) => event.type === "activity.recorded");
45
+ const activityByKind = {};
46
+ for (const event of activityEvents) {
47
+ const kind = String(event.payload.kind);
48
+ activityByKind[kind] = (activityByKind[kind] ?? 0) + 1;
49
+ }
50
+ const nativeCandidates = candidates.filter((candidate) => candidate.occurrences.some((origin) => origin.kind === "native"));
51
+ const formalizedNativeCandidates = nativeCandidates.filter((candidate) => candidate.occurrences.some((origin) => origin.kind === "broker" || origin.kind === "input"));
52
+ const providers = networkCapabilityIds.map((capabilityId) => {
53
+ const uniqueCandidates = candidates.filter((candidate) => candidate.occurrences.some((origin) => origin.capabilityId === capabilityId)).length;
54
+ return {
55
+ capabilityId,
56
+ requests: requested.filter((event) => event.payload.capabilityId === capabilityId).length,
57
+ networkCalls: attempted.filter((event) => event.payload.capabilityId === capabilityId).length,
58
+ completedReceipts: completed.filter((event) => event.payload.capabilityId === capabilityId)
59
+ .length,
60
+ reuseHits: reused.filter((event) => event.payload.capabilityId === capabilityId).length,
61
+ failures: failed.filter((event) => event.payload.capabilityId === capabilityId).length,
62
+ uniqueCandidates,
63
+ };
64
+ });
65
+ const exercised = new Set(providers
66
+ .filter((provider) => provider.networkCalls > 0 || provider.completedReceipts > 0)
67
+ .map((provider) => provider.capabilityId));
68
+ const missingRequired = plan.requiredFirstPassCapabilityIds.filter((capabilityId) => !exercised.has(capabilityId));
69
+ const callsRemaining = Math.max(0, plan.maxCalls - requested.length);
70
+ const gaps = [...plan.constraintGaps];
71
+ if (missingRequired.length) {
72
+ gaps.push(`required first-pass capabilities not exercised: ${missingRequired.join(", ")}`);
73
+ }
74
+ if (candidates.length < plan.targetUniqueSources) {
75
+ gaps.push(`unique candidate target not met: ${candidates.length}/${plan.targetUniqueSources}`);
76
+ }
77
+ const persistedCoverageGaps = await readPersistedCoverageGaps(root, project.id);
78
+ gaps.push(...persistedCoverageGaps);
79
+ const terminalDiscover = project.packages.find((workPackage) => workPackage.stage === "discover")?.status === "complete";
80
+ let recommendedAction;
81
+ if (terminalDiscover)
82
+ recommendedAction = "continue-pipeline";
83
+ else if (missingRequired.length && callsRemaining > 0) {
84
+ recommendedAction = "exercise-required-first-pass";
85
+ }
86
+ else if (candidates.length - admitted.size - rejected.size > 0) {
87
+ recommendedAction = "assess-unassessed-candidates";
88
+ }
89
+ else if (candidates.length < plan.targetUniqueSources && callsRemaining > 0) {
90
+ recommendedAction = "run-gap-fill-batch";
91
+ }
92
+ else if (callsRemaining === 0 && gaps.length > 0) {
93
+ recommendedAction = "review-call-ceiling-or-stop";
94
+ }
95
+ else {
96
+ recommendedAction = "submit-admission-judgments";
97
+ }
98
+ const nextBatch = nextDiscoveryBatch(plan, missingRequired, exercised, callsRemaining, requested.length, recommendedAction);
99
+ return {
100
+ plan,
101
+ calls: {
102
+ used: requested.length,
103
+ networkUsed: attempted.length,
104
+ reused: reused.length,
105
+ max: plan.maxCalls,
106
+ remaining: callsRemaining,
107
+ hardLimit: plan.hardCallLimit,
108
+ },
109
+ candidates: {
110
+ unique: candidates.length,
111
+ duplicateOccurrences,
112
+ admitted: admitted.size,
113
+ rejected: rejected.size,
114
+ unassessed: Math.max(0, candidates.length - admitted.size - rejected.size),
115
+ },
116
+ nativeActivities: {
117
+ total: activityEvents.length,
118
+ byKind: activityByKind,
119
+ blockedChallenges: activityEvents.filter((event) => event.payload.status === "blocked" && event.payload.challenge !== "none").length,
120
+ nativeCandidates: nativeCandidates.length,
121
+ formalizedNativeCandidates: formalizedNativeCandidates.length,
122
+ unformalizedNativeCandidates: nativeCandidates.length - formalizedNativeCandidates.length,
123
+ },
124
+ providers,
125
+ gaps: [...new Set(gaps)],
126
+ nextBatch,
127
+ recommendedAction,
128
+ };
129
+ }
130
+ function nextDiscoveryBatch(plan, missingRequired, exercised, callsRemaining, callsUsed, action) {
131
+ if (callsRemaining < 1 || action === "continue-pipeline")
132
+ return null;
133
+ if (missingRequired.length) {
134
+ return {
135
+ kind: "required-first-pass",
136
+ capabilityIds: missingRequired,
137
+ maxCalls: Math.min(callsRemaining, missingRequired.length),
138
+ };
139
+ }
140
+ const supplemental = plan.plannedBatches
141
+ .flatMap((batch) => batch.capabilityIds)
142
+ .filter((id) => !exercised.has(id));
143
+ if (supplemental.length) {
144
+ return {
145
+ kind: "supplemental-first-pass",
146
+ capabilityIds: [...new Set(supplemental)],
147
+ maxCalls: Math.min(callsRemaining, supplemental.length),
148
+ };
149
+ }
150
+ const available = [...new Set(plan.plannedBatches.flatMap((batch) => batch.capabilityIds))];
151
+ if (callsUsed < plan.firstPassCalls) {
152
+ return {
153
+ kind: "coverage-first-pass",
154
+ capabilityIds: available,
155
+ maxCalls: Math.min(callsRemaining, plan.firstPassCalls - callsUsed),
156
+ };
157
+ }
158
+ return {
159
+ kind: "gap-fill",
160
+ capabilityIds: available,
161
+ maxCalls: callsRemaining,
162
+ };
163
+ }
164
+ async function readPersistedCoverageGaps(root, projectId) {
165
+ const path = join(workspacePaths(root).projects, projectId, "outputs", "evidence.json");
166
+ if (!(await pathExists(path)))
167
+ return [];
168
+ try {
169
+ const value = JSON.parse(await readFile(path, "utf8"));
170
+ if (!isObject(value) || !isObject(value.coverage))
171
+ return [];
172
+ const mechanical = value.coverage.mechanicalGaps;
173
+ const declared = value.coverage.gaps;
174
+ return [
175
+ ...(Array.isArray(mechanical) ? mechanical : []),
176
+ ...(Array.isArray(declared) ? declared : []),
177
+ ].filter((item) => typeof item === "string");
178
+ }
179
+ catch {
180
+ return ["persisted evidence coverage cannot be read"];
181
+ }
182
+ }
183
+ //# sourceMappingURL=discovery-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-status.js","sourceRoot":"","sources":["../../../src/research/workspace/discovery-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { ProjectState } from "./types.js";
2
+ interface DimensionJudgment {
3
+ id: string;
4
+ status: "covered" | "partial" | "missing";
5
+ }
6
+ export interface DiscoveryCloseoutValue {
7
+ schemaVersion: 2;
8
+ limitations: string[];
9
+ dimensionJudgments: DimensionJudgment[];
10
+ gaps: string[];
11
+ }
12
+ export declare function materializeDiscoveryEvidence(root: string, project: ProjectState, value: Record<string, unknown>): Promise<Record<string, unknown>>;
13
+ export declare function commitDiscoveryDecisions(root: string, projectId: string, value: Record<string, unknown>): Promise<void>;
14
+ export declare function recordDiscoveryAssessmentBatch(input: {
15
+ root: string;
16
+ projectId: string;
17
+ value: Record<string, unknown>;
18
+ }): Promise<{
19
+ recorded: number;
20
+ unchanged: number;
21
+ assessedCandidates: number;
22
+ admittedCandidates: number;
23
+ rejectedCandidates: number;
24
+ }>;
25
+ export {};
@@ -0,0 +1,268 @@
1
+ import { basename, join } from "node:path";
2
+ import { appendEvidenceLedgerEvent, evidenceLedgerPath, listEvidenceCandidates, } from "./evidence-ledger.js";
3
+ import { loadProjectEvidenceReceipts } from "./evidence.js";
4
+ import { readJournal } from "./journal.js";
5
+ import { parseDiscoveryAssessmentBatch, StructuredOutputError } from "./schemas.js";
6
+ import { canonicalJson, isObject, readJsonFile, sha256Text, workspacePaths } from "./storage.js";
7
+ export async function materializeDiscoveryEvidence(root, project, value) {
8
+ const closeout = parseCloseoutValue(value);
9
+ const assessments = await latestDiscoveryAssessments(root, project.id);
10
+ const admissions = assessments.filter(isAdmission);
11
+ const rejections = assessments.filter(isRejection);
12
+ const candidates = new Map((await listEvidenceCandidates(root, project.id)).map((candidate) => [candidate.id, candidate]));
13
+ const receipts = new Map((await loadProjectEvidenceReceipts(root, project.id)).map((receipt) => [
14
+ receipt.attemptId,
15
+ receipt,
16
+ ]));
17
+ const inputs = new Map(project.inputs.map((input) => [input.id, input]));
18
+ const admittedCandidateIds = new Set(admissions.map((item) => item.candidateId));
19
+ const rejectedCandidateIds = new Set(rejections.map((item) => item.candidateId));
20
+ for (const candidateId of [...admittedCandidateIds, ...rejectedCandidateIds]) {
21
+ if (!candidates.has(candidateId)) {
22
+ throw discoveryError(`Discovery decision refers to unknown candidate ${candidateId}.`);
23
+ }
24
+ }
25
+ for (const candidateId of admittedCandidateIds) {
26
+ if (rejectedCandidateIds.has(candidateId)) {
27
+ throw discoveryError(`Candidate ${candidateId} cannot be both admitted and rejected.`);
28
+ }
29
+ }
30
+ const requiredDimensions = new Set(project.evidenceRequirements.dimensions);
31
+ const judgmentIds = new Set(closeout.dimensionJudgments.map((item) => item.id));
32
+ if (judgmentIds.size !== requiredDimensions.size ||
33
+ [...requiredDimensions].some((dimension) => !judgmentIds.has(dimension))) {
34
+ throw discoveryError("Dimension judgments must cover every reviewed evidence dimension exactly once.");
35
+ }
36
+ const sources = admissions.map((admission) => {
37
+ if (admission.coverageDimensions.some((dimension) => !requiredDimensions.has(dimension))) {
38
+ throw discoveryError(`Admission ${admission.sourceId} declares an unreviewed evidence dimension.`);
39
+ }
40
+ const candidate = candidates.get(admission.candidateId);
41
+ const admissibleOrigin = candidate.occurrences.find((origin) => origin.kind === "input" || origin.kind === "broker");
42
+ if (!admissibleOrigin) {
43
+ throw new StructuredOutputError("Native Web or Browser discovery must first be formalized through an immutable broker receipt for the same canonical URL or DOI.", {
44
+ validation: ["native candidates require immutable broker provenance"],
45
+ candidateId: candidate.id,
46
+ });
47
+ }
48
+ const provenance = admissibleOrigin.kind === "broker"
49
+ ? brokerProvenance(admissibleOrigin.receiptId, admissibleOrigin.locator, receipts)
50
+ : inputProvenance(admissibleOrigin.inputId, admissibleOrigin.locator, inputs);
51
+ const input = provenance.kind === "input" ? inputs.get(provenance.id) : undefined;
52
+ return {
53
+ id: admission.sourceId,
54
+ title: candidate.title,
55
+ locator: provenance.locator,
56
+ relevance: admission.relevance,
57
+ provenance: { kind: provenance.kind, id: provenance.id },
58
+ sourceType: admission.sourceType,
59
+ retrievedAt: admissibleOrigin.retrievedAt,
60
+ fullTextAvailable: provenance.kind === "input" ? input?.fullText !== false : false,
61
+ url: candidate.url,
62
+ doi: candidate.doi,
63
+ publicationDate: candidate.publicationDate ?? input?.publicationDate ?? null,
64
+ excerpt: candidate.excerpt,
65
+ jsonPointer: admissibleOrigin.jsonPointer,
66
+ quality: admission.quality,
67
+ applicability: admission.applicability,
68
+ coverageDimensions: admission.coverageDimensions,
69
+ };
70
+ });
71
+ const sourceLimitations = admissions.flatMap((admission) => admission.limitations.map((limitation) => `${admission.sourceId}: ${limitation}`));
72
+ return {
73
+ schemaVersion: 1,
74
+ sources,
75
+ limitations: [...new Set([...closeout.limitations, ...sourceLimitations])],
76
+ coverage: {
77
+ dimensions: closeout.dimensionJudgments.map((item) => ({
78
+ id: item.id,
79
+ status: item.status,
80
+ sourceIds: [],
81
+ })),
82
+ sourceTypes: [],
83
+ fullTextSources: 0,
84
+ datedSources: 0,
85
+ publicationDateRange: { earliest: null, latest: null },
86
+ decision: "pass",
87
+ gaps: closeout.gaps,
88
+ },
89
+ };
90
+ }
91
+ export async function commitDiscoveryDecisions(root, projectId, value) {
92
+ parseCloseoutValue(value);
93
+ const assessments = await latestDiscoveryAssessments(root, projectId);
94
+ const events = await readJournal(evidenceLedgerPath(root, projectId));
95
+ const committed = new Set(events
96
+ .filter((event) => event.type === "candidate.admitted" || event.type === "candidate.rejected")
97
+ .map((event) => `${event.type}:${String(event.payload.judgmentSha256)}`));
98
+ for (const admission of assessments.filter(isAdmission)) {
99
+ const judgmentSha256 = sha256Text(canonicalJson(admission));
100
+ const key = `candidate.admitted:${judgmentSha256}`;
101
+ if (committed.has(key))
102
+ continue;
103
+ await appendEvidenceLedgerEvent(root, projectId, "candidate.admitted", {
104
+ candidateId: admission.candidateId,
105
+ sourceId: admission.sourceId,
106
+ sourceType: admission.sourceType,
107
+ judgmentSha256,
108
+ coverageDimensions: admission.coverageDimensions,
109
+ });
110
+ }
111
+ for (const rejection of assessments.filter(isRejection)) {
112
+ const judgmentSha256 = sha256Text(canonicalJson(rejection));
113
+ const key = `candidate.rejected:${judgmentSha256}`;
114
+ if (committed.has(key))
115
+ continue;
116
+ await appendEvidenceLedgerEvent(root, projectId, "candidate.rejected", {
117
+ candidateId: rejection.candidateId,
118
+ reasonCode: rejection.reasonCode,
119
+ rationale: rejection.rationale,
120
+ judgmentSha256,
121
+ });
122
+ }
123
+ }
124
+ export async function recordDiscoveryAssessmentBatch(input) {
125
+ const parsed = parseDiscoveryAssessmentBatch(input.value);
126
+ const assessments = parsed.assessments;
127
+ const project = await readJsonFile(join(workspacePaths(input.root).projects, input.projectId, "project.json"), `Research project ${input.projectId}`);
128
+ const packages = Array.isArray(project.packages) ? project.packages : [];
129
+ const discover = packages.find((workPackage) => isObject(workPackage) && workPackage.stage === "discover");
130
+ if (!isObject(discover) || discover.status !== "running") {
131
+ throw discoveryError("Discovery assessments may be recorded only during the active discover stage.");
132
+ }
133
+ const requiredDimensions = new Set(isObject(project.evidenceRequirements) && Array.isArray(project.evidenceRequirements.dimensions)
134
+ ? project.evidenceRequirements.dimensions.filter((dimension) => typeof dimension === "string")
135
+ : []);
136
+ const candidates = new Map((await listEvidenceCandidates(input.root, input.projectId)).map((candidate) => [
137
+ candidate.id,
138
+ candidate,
139
+ ]));
140
+ for (const assessment of assessments) {
141
+ const candidate = candidates.get(assessment.candidateId);
142
+ if (!candidate) {
143
+ throw discoveryError(`Discovery assessment refers to unknown candidate ${assessment.candidateId}.`);
144
+ }
145
+ if (assessment.decision === "admit") {
146
+ if (assessment.coverageDimensions.some((dimension) => !requiredDimensions.has(dimension))) {
147
+ throw discoveryError(`Admission ${assessment.sourceId} declares an unreviewed evidence dimension.`);
148
+ }
149
+ if (!candidate.occurrences.some((origin) => origin.kind === "input" || origin.kind === "broker")) {
150
+ throw discoveryError(`Native candidate ${candidate.id} must be formalized by a broker receipt before admission.`);
151
+ }
152
+ }
153
+ }
154
+ const existing = await latestDiscoveryAssessments(input.root, input.projectId);
155
+ const replacementIds = new Set(assessments.map((assessment) => assessment.candidateId));
156
+ const sourceOwners = new Map(existing
157
+ .filter(isAdmission)
158
+ .filter((assessment) => !replacementIds.has(assessment.candidateId))
159
+ .map((assessment) => [assessment.sourceId, assessment.candidateId]));
160
+ for (const assessment of assessments.filter(isAdmission)) {
161
+ const owner = sourceOwners.get(assessment.sourceId);
162
+ if (owner && owner !== assessment.candidateId) {
163
+ throw discoveryError(`Source ID ${assessment.sourceId} is already assigned to ${owner}.`);
164
+ }
165
+ sourceOwners.set(assessment.sourceId, assessment.candidateId);
166
+ }
167
+ const priorHashes = new Set((await readJournal(evidenceLedgerPath(input.root, input.projectId)))
168
+ .filter((event) => event.type === "candidate.assessed")
169
+ .map((event) => String(event.payload.assessmentSha256)));
170
+ let recorded = 0;
171
+ let unchanged = 0;
172
+ for (const assessment of assessments) {
173
+ const assessmentSha256 = sha256Text(canonicalJson(assessment));
174
+ if (priorHashes.has(assessmentSha256)) {
175
+ unchanged += 1;
176
+ continue;
177
+ }
178
+ await appendEvidenceLedgerEvent(input.root, input.projectId, "candidate.assessed", {
179
+ candidateId: assessment.candidateId,
180
+ decision: assessment.decision,
181
+ assessment,
182
+ assessmentSha256,
183
+ });
184
+ priorHashes.add(assessmentSha256);
185
+ recorded += 1;
186
+ }
187
+ const latest = await latestDiscoveryAssessments(input.root, input.projectId);
188
+ return {
189
+ recorded,
190
+ unchanged,
191
+ assessedCandidates: latest.length,
192
+ admittedCandidates: latest.filter(isAdmission).length,
193
+ rejectedCandidates: latest.filter(isRejection).length,
194
+ };
195
+ }
196
+ function brokerProvenance(receiptId, locator, receipts) {
197
+ const receipt = receiptId ? receipts.get(receiptId) : undefined;
198
+ if (!receipt || !locator || receipt.locator !== locator) {
199
+ throw discoveryError("Broker candidate provenance does not match an immutable receipt.");
200
+ }
201
+ return { kind: "broker", id: receipt.attemptId, locator: receipt.locator };
202
+ }
203
+ function inputProvenance(inputId, locator, inputs) {
204
+ const input = inputId ? inputs.get(inputId) : undefined;
205
+ const expectedLocator = input
206
+ ? join("inputs", input.id, basename(input.path)).replaceAll("\\", "/")
207
+ : null;
208
+ if (!input || !locator || locator !== expectedLocator) {
209
+ throw discoveryError("Input candidate provenance does not match a registered immutable input.");
210
+ }
211
+ return { kind: "input", id: input.id, locator: expectedLocator };
212
+ }
213
+ async function latestDiscoveryAssessments(root, projectId) {
214
+ const events = await readJournal(evidenceLedgerPath(root, projectId));
215
+ const latest = new Map();
216
+ for (const event of events) {
217
+ if (event.type !== "candidate.assessed" || !isObject(event.payload.assessment))
218
+ continue;
219
+ const assessment = event.payload.assessment;
220
+ if (!isAdmission(assessment) && !isRejection(assessment)) {
221
+ throw discoveryError("Persisted discovery assessment is malformed.");
222
+ }
223
+ latest.set(assessment.candidateId, assessment);
224
+ }
225
+ return [...latest.values()];
226
+ }
227
+ function parseCloseoutValue(value) {
228
+ if (value.schemaVersion !== 2 ||
229
+ !Array.isArray(value.limitations) ||
230
+ !Array.isArray(value.dimensionJudgments) ||
231
+ !Array.isArray(value.gaps) ||
232
+ value.dimensionJudgments.some((item) => !isDimensionJudgment(item))) {
233
+ throw discoveryError("Discovery closeout value is malformed.");
234
+ }
235
+ return value;
236
+ }
237
+ function isAdmission(value) {
238
+ return (isObject(value) &&
239
+ value.decision === "admit" &&
240
+ typeof value.candidateId === "string" &&
241
+ typeof value.sourceId === "string" &&
242
+ typeof value.sourceType === "string" &&
243
+ typeof value.relevance === "string" &&
244
+ isObject(value.quality) &&
245
+ typeof value.quality.level === "string" &&
246
+ typeof value.quality.rationale === "string" &&
247
+ typeof value.applicability === "string" &&
248
+ Array.isArray(value.coverageDimensions) &&
249
+ value.coverageDimensions.every((item) => typeof item === "string") &&
250
+ Array.isArray(value.limitations) &&
251
+ value.limitations.every((item) => typeof item === "string"));
252
+ }
253
+ function isRejection(value) {
254
+ return (isObject(value) &&
255
+ value.decision === "reject" &&
256
+ typeof value.candidateId === "string" &&
257
+ typeof value.reasonCode === "string" &&
258
+ typeof value.rationale === "string");
259
+ }
260
+ function isDimensionJudgment(value) {
261
+ return (isObject(value) &&
262
+ typeof value.id === "string" &&
263
+ ["covered", "partial", "missing"].includes(String(value.status)));
264
+ }
265
+ function discoveryError(message) {
266
+ return new StructuredOutputError(message, { validation: [message] });
267
+ }
268
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../src/research/workspace/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ export declare const downloadBindingRecordSchema: {
2
+ readonly $id: "https://schemas.tiangong.ai/research/download-binding-input-v1.json";
3
+ readonly type: "object";
4
+ readonly additionalProperties: false;
5
+ readonly required: readonly ["schemaVersion", "backend", "status", "downloadUrl"];
6
+ readonly properties: {
7
+ readonly schemaVersion: {
8
+ readonly type: "integer";
9
+ readonly const: 1;
10
+ };
11
+ readonly backend: {
12
+ readonly type: "string";
13
+ readonly enum: readonly ["native-browser", "chrome", "cloakbrowser", "skill-adapter", "direct-http"];
14
+ };
15
+ readonly status: {
16
+ readonly type: "string";
17
+ readonly enum: readonly ["completed", "failed", "cancelled"];
18
+ };
19
+ readonly path: {
20
+ readonly type: "string";
21
+ };
22
+ readonly downloadUrl: {
23
+ readonly type: "string";
24
+ readonly format: "uri";
25
+ };
26
+ readonly suggestedFilename: {
27
+ readonly type: "string";
28
+ readonly maxLength: 500;
29
+ };
30
+ readonly downloadIdentifier: {
31
+ readonly type: "string";
32
+ readonly maxLength: 1000;
33
+ };
34
+ readonly failureCode: {
35
+ readonly type: "string";
36
+ readonly pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$";
37
+ };
38
+ };
39
+ };
40
+ export interface EvidenceDownloadBinding {
41
+ schemaVersion: 1;
42
+ bindingId: string;
43
+ projectId: string;
44
+ candidateId: string;
45
+ backend: "native-browser" | "chrome" | "cloakbrowser" | "skill-adapter" | "direct-http";
46
+ status: "completed";
47
+ fileSha256: string;
48
+ fileBytes: number;
49
+ filePathSha256: string;
50
+ downloadUrl: string;
51
+ suggestedFilename: string | null;
52
+ downloadIdentifierSha256: string | null;
53
+ boundAt: string;
54
+ bindingSha256: string;
55
+ }
56
+ export declare function bindEvidenceDownload(input: {
57
+ root: string;
58
+ projectId: string;
59
+ candidateId: string;
60
+ value: Record<string, unknown>;
61
+ }): Promise<{
62
+ status: "completed";
63
+ binding: EvidenceDownloadBinding;
64
+ } | {
65
+ status: "failed" | "cancelled";
66
+ binding: null;
67
+ nextAction: string;
68
+ }>;
69
+ export declare function loadAndVerifyDownloadBinding(input: {
70
+ root: string;
71
+ projectId: string;
72
+ candidateId: string;
73
+ bindingId: string;
74
+ path: string;
75
+ }): Promise<EvidenceDownloadBinding>;
76
+ export declare function parseEvidenceDownloadBinding(value: unknown): EvidenceDownloadBinding;