@tiinex/core 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -6
- package/src/schemas/creation.contracts.js +1 -1
- package/src/schemas/party/role/tiinex.party.role.v1.schema.js +5 -0
- package/src/schemas/party/role/tiinex.party.role.v1.schema.json +2 -2
- package/src/schemas/party/role/tiinex.party.role.v1.schema.md +313 -0
- package/src/schemas/party/role/tiinex.party.role.v1.schema.runtime.json +18 -6
- package/src/schemas/party/role/tiinex.party.role.v1.validate.js +36 -0
- package/src/schemas/schema.reference.js +29 -0
- package/src/tooling/portable/adapters/cli/cli.common-author.js +117 -6
- package/src/tooling/portable/adapters/cli/cli.common-output.js +19 -0
- package/src/tooling/portable/adapters/node/handoff.manufacture.js +26 -4
- package/src/tooling/portable/adapters/node/handoff.manufacture.packageParent.js +123 -0
- package/src/tooling/portable/audit/audit.capability.js +10 -4
- package/src/tooling/portable/grounding/grounding.capsule.js +26 -2
- package/src/tooling/portable/grounding/grounding.delegationArtifactAuthority.js +314 -0
- package/src/tooling/portable/grounding/grounding.delegationReadiness.js +241 -0
- package/src/tooling/portable/grounding/grounding.holderAssignmentModes.js +125 -0
- package/src/tooling/portable/grounding/grounding.holderBindingAuthorization.js +49 -50
- package/src/tooling/portable/grounding/grounding.readiness.js +19 -3
- package/src/tooling/portable/grounding/grounding.readiness.support.js +1 -1
- package/src/tooling/portable/handoff/carrierProjection.routeQualification.js +20 -4
- package/src/tooling/portable/handoff/coldStartQualification.grounding.js +67 -4
- package/src/tooling/portable/handoff/coldStartQualification.materials.js +84 -10
- package/src/tooling/portable/handoff/recipientV2.endpointRolePointers.js +1 -1
- package/src/tooling/portable/handoff/recipientV2.inspect.projection.js +5 -2
- package/src/tooling/portable/handoff/recipientV2.packageV1.build.js +2 -2
- package/src/tooling/portable/handoff/recipientV2.topology.js +5 -3
- package/src/tooling/portable/handoff/recipientV2.topology.materials.js +0 -0
|
@@ -3,6 +3,7 @@ import { packageFileBytes, sha256Hex } from '../../../export/package.bytes.js';
|
|
|
3
3
|
import { portableFinding } from '../findings.js';
|
|
4
4
|
import { inspectStoredWorkspaceArchive } from './workspaceByteProvider.js';
|
|
5
5
|
import { recipientV2FactsIndex } from './recipientV2.transportManifest.js';
|
|
6
|
+
import { deriveRecipientV2ArtifactFirstPhase1Facts } from './recipientV2.artifactFirst.materials.js';
|
|
6
7
|
import { parseNamedDeclarationSection } from '../schema/named.declarations.js';
|
|
7
8
|
import { resolveColdStartRolePointerMaterial } from './coldStartRolePointers.js';
|
|
8
9
|
import {
|
|
@@ -58,7 +59,12 @@ export function collectPackageRoleMaterials(bundle = {}) {
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
export function resolveReferencedRoleMaterial(bundle = {}, handoff = {}, orientation = null, selectedRoute = null, findings = [], context = null) {
|
|
61
|
-
|
|
62
|
+
return resolveReferencedEndpointRoleMaterial(bundle, handoff, orientation, selectedRoute, findings, context, 'to');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function resolveReferencedEndpointRoleMaterial(bundle = {}, handoff = {}, orientation = null, selectedRoute = null, findings = [], context = null, endpointParty = 'to') {
|
|
66
|
+
const party = String(endpointParty || 'to').trim().toLowerCase() === 'from' ? 'from' : 'to';
|
|
67
|
+
const reference = String(party === 'from' ? handoff.fromReference : handoff.toReference || '').trim();
|
|
62
68
|
if (!reference) return null;
|
|
63
69
|
if (!isExternalReference(reference)) {
|
|
64
70
|
const workspaceZip = findFile(bundle, String(handoff.packagePath || ''));
|
|
@@ -71,7 +77,7 @@ export function resolveReferencedRoleMaterial(bundle = {}, handoff = {}, orienta
|
|
|
71
77
|
const markdown = decodeUtf8(matches[0].data || new Uint8Array());
|
|
72
78
|
if (markdown) return Object.freeze({ path: `${workspaceZip.path}::${resolvedPath}`, markdown, explicit: false, exactReference: reference });
|
|
73
79
|
}
|
|
74
|
-
if (matches.length > 1) findings.push(portableFinding('error', 'portable.cold-start.role.reference-material.ambiguous', 'Handoff
|
|
80
|
+
if (matches.length > 1) findings.push(portableFinding('error', 'portable.cold-start.role.reference-material.ambiguous', 'Handoff endpoint Reference resolves to multiple entries in the selected Workspace archive.', { reference, resolvedPath }));
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
}
|
|
@@ -85,14 +91,14 @@ export function resolveReferencedRoleMaterial(bundle = {}, handoff = {}, orienta
|
|
|
85
91
|
: projectedFacts
|
|
86
92
|
? { role: 'endpoint-role', ...projectedFacts }
|
|
87
93
|
: {};
|
|
88
|
-
if (facts.role !== 'endpoint-role' || String(facts.endpointParty || '').toLowerCase() !==
|
|
94
|
+
if (facts.role !== 'endpoint-role' || String(facts.endpointParty || '').toLowerCase() !== party) continue;
|
|
89
95
|
if (facts.referenceTarget && String(facts.referenceTarget) !== reference) continue;
|
|
90
96
|
const material = resolveColdStartRolePointerMaterial(bundle, facts, findings, String(pointerPath || ''), 'endpoint-role');
|
|
91
97
|
if (material) endpointPointerMatches.push(Object.freeze({ ...material, exactReference: reference }));
|
|
92
98
|
}
|
|
93
99
|
if (endpointPointerMatches.length === 1) return endpointPointerMatches[0];
|
|
94
100
|
if (endpointPointerMatches.length > 1) {
|
|
95
|
-
findings.push(portableFinding('error', 'portable.cold-start.role.reference-material.ambiguous', 'Handoff
|
|
101
|
+
findings.push(portableFinding('error', 'portable.cold-start.role.reference-material.ambiguous', 'Handoff endpoint Reference resolves through multiple qualified endpoint Role Pointers.', { reference, count: endpointPointerMatches.length }));
|
|
96
102
|
return null;
|
|
97
103
|
}
|
|
98
104
|
const cacheMatches = [];
|
|
@@ -114,7 +120,7 @@ export function resolveReferencedRoleMaterial(bundle = {}, handoff = {}, orienta
|
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
if (cacheMatches.length === 1) return cacheMatches[0];
|
|
117
|
-
if (cacheMatches.length > 1) findings.push(portableFinding('error', 'portable.cold-start.role.reference-material.ambiguous', 'Handoff
|
|
123
|
+
if (cacheMatches.length > 1) findings.push(portableFinding('error', 'portable.cold-start.role.reference-material.ambiguous', 'Handoff endpoint Reference resolves to multiple cached exact byte carriers.', { reference, count: cacheMatches.length }));
|
|
118
124
|
return null;
|
|
119
125
|
}
|
|
120
126
|
|
|
@@ -172,9 +178,16 @@ export function parseRoleMaterial(entry) {
|
|
|
172
178
|
label,
|
|
173
179
|
roleKind: sectionField(roleSection, 'Role Kind'),
|
|
174
180
|
boundary: Object.freeze({ inScope: sectionField(boundarySection, 'In Scope'), outOfScope: sectionField(boundarySection, 'Out Of Scope'), context: sectionField(boundarySection, 'Context') }),
|
|
175
|
-
authorityBoundary: Object.freeze({
|
|
181
|
+
authorityBoundary: Object.freeze({
|
|
182
|
+
mayDo: sectionField(authoritySection, 'May Do'),
|
|
183
|
+
doesNotAuthorize: sectionField(authoritySection, 'Does Not Authorize'),
|
|
184
|
+
requiredInstrument: sectionField(authoritySection, 'Required Instrument'),
|
|
185
|
+
delegation: sectionField(authoritySection, 'Delegation'),
|
|
186
|
+
reviewBoundary: sectionField(authoritySection, 'Review Boundary')
|
|
187
|
+
}),
|
|
176
188
|
holderRelationship: Object.freeze({
|
|
177
189
|
holderState: sectionField(holderSection, 'Holder State'),
|
|
190
|
+
assignmentModes: sectionField(holderSection, 'Assignment Modes'),
|
|
178
191
|
currentHolder: sectionField(holderSection, 'Current Holder'),
|
|
179
192
|
possibleHolder: sectionField(holderSection, 'Possible Holder'),
|
|
180
193
|
unknownHolder: sectionField(holderSection, 'Unknown Holder'),
|
|
@@ -262,7 +275,7 @@ function hydrateRequiredContextEntry(bundle = {}, entry = {}, context = null) {
|
|
|
262
275
|
})
|
|
263
276
|
};
|
|
264
277
|
if (base.state !== 'qualified') return Object.freeze({ ...base, contentState: 'unavailable', content: '' });
|
|
265
|
-
const hydrated = resolveQualifiedMaterialBytes(bundle, resolution, context);
|
|
278
|
+
const hydrated = resolveQualifiedMaterialBytes(bundle, resolution, context, base);
|
|
266
279
|
if (!hydrated.bytes) return Object.freeze({ ...base, state: 'unresolved', contentState: 'unavailable', content: '' });
|
|
267
280
|
const actualSha256 = sha256Hex(hydrated.bytes);
|
|
268
281
|
const identityQualified = (!base.bytes || hydrated.bytes.byteLength === base.bytes) && (!base.sha256 || actualSha256 === base.sha256);
|
|
@@ -270,14 +283,21 @@ function hydrateRequiredContextEntry(bundle = {}, entry = {}, context = null) {
|
|
|
270
283
|
return Object.freeze({
|
|
271
284
|
...base,
|
|
272
285
|
state: identityQualified ? 'qualified' : 'identity-mismatch',
|
|
286
|
+
workspaceId: String(hydrated.workspaceId || base.workspaceId || ''),
|
|
287
|
+
archivePackagePath: String(hydrated.archivePackagePath || base.archivePackagePath || ''),
|
|
288
|
+
innerPath: String(hydrated.innerPath || base.innerPath || ''),
|
|
289
|
+
packagePath: String(hydrated.packagePath || base.packagePath || ''),
|
|
290
|
+
providerMode: String(hydrated.providerMode || base.providerMode || ''),
|
|
291
|
+
kind: String(hydrated.kind || base.kind || ''),
|
|
273
292
|
actualBytes: hydrated.bytes.byteLength,
|
|
274
293
|
actualSha256,
|
|
294
|
+
provenance: Object.freeze({ ...(base.provenance || {}), providerMode: String(hydrated.providerMode || base.providerMode || ''), resolutionKind: String(hydrated.kind || base.kind || '') }),
|
|
275
295
|
contentState: text ? 'hydrated-text' : identityQualified ? 'qualified-locator-only' : 'unavailable',
|
|
276
296
|
content: text
|
|
277
297
|
});
|
|
278
298
|
}
|
|
279
299
|
|
|
280
|
-
function resolveQualifiedMaterialBytes(bundle = {}, resolution = {}, context = null) {
|
|
300
|
+
function resolveQualifiedMaterialBytes(bundle = {}, resolution = {}, context = null, requirement = {}) {
|
|
281
301
|
const kind = String(resolution.kind || '');
|
|
282
302
|
if (kind === 'workspace-archive-entry' || kind === 'workspace-cache-entry') {
|
|
283
303
|
const archivePath = String(resolution.archivePackagePath || resolution.packagePath || '');
|
|
@@ -293,17 +313,64 @@ function resolveQualifiedMaterialBytes(bundle = {}, resolution = {}, context = n
|
|
|
293
313
|
}
|
|
294
314
|
const packagePath = String(resolution.packagePath || '');
|
|
295
315
|
const file = packagePath ? findFile(bundle, packagePath) : null;
|
|
296
|
-
return Object.freeze({ bytes:
|
|
316
|
+
if (file) return Object.freeze({ bytes: packageFileBytes(file), packagePath });
|
|
317
|
+
if (kind === 'materialized-required-material') {
|
|
318
|
+
const requirementId = String(requirement.requirementId || '');
|
|
319
|
+
const referenceTarget = String(requirement.referenceTarget || '');
|
|
320
|
+
const matches = [];
|
|
321
|
+
const factsIndex = recipientFactsIndexForColdStart(bundle, context).map;
|
|
322
|
+
const visibleFactsIndex = deriveRecipientV2ArtifactFirstPhase1Facts(bundle.files || []);
|
|
323
|
+
for (const candidateFile of bundle.files || []) {
|
|
324
|
+
const candidatePath = String(candidateFile.path || '');
|
|
325
|
+
const facts = factsIndex.get(candidatePath) || visibleFactsIndex.get(candidatePath) || null;
|
|
326
|
+
if (facts?.role !== 'workspace-dependency-cache' && !/dependency cache/i.test(String(facts?.role || ''))) continue;
|
|
327
|
+
for (const material of facts.materials || []) {
|
|
328
|
+
if (requirementId && String(material.requirementId || '') !== requirementId) continue;
|
|
329
|
+
if (referenceTarget && String(material.referenceTarget || '') !== referenceTarget) continue;
|
|
330
|
+
const archivePath = String(facts.archivePath || '');
|
|
331
|
+
const archiveFile = findFile(bundle, archivePath);
|
|
332
|
+
if (!archiveFile) continue;
|
|
333
|
+
const archive = inspectWorkspaceArchiveForColdStart(archiveFile, context);
|
|
334
|
+
if (archive.state !== 'qualified') continue;
|
|
335
|
+
const entries = (archive.entries || []).filter((entry) => String(entry.path || '') === String(material.archiveEntry || ''));
|
|
336
|
+
if (entries.length !== 1) continue;
|
|
337
|
+
const entry = entries[0];
|
|
338
|
+
const data = packageFileBytes({ data: entry.data });
|
|
339
|
+
const actualSha = sha256Hex(data);
|
|
340
|
+
if (Number(material.bytes || 0) && Number(material.bytes || 0) !== data.byteLength) continue;
|
|
341
|
+
if (String(material.sha256 || '') && String(material.sha256 || '') !== actualSha) continue;
|
|
342
|
+
if (Number(resolution.bytes || 0) && Number(resolution.bytes || 0) !== data.byteLength) continue;
|
|
343
|
+
if (String(resolution.sha256 || '') && String(resolution.sha256 || '') !== actualSha) continue;
|
|
344
|
+
matches.push(Object.freeze({
|
|
345
|
+
bytes: data, providerMode: 'cache', kind: 'workspace-cache-entry',
|
|
346
|
+
workspaceId: String(material.targetWorkspaceId || material.sourceWorkspaceId || facts.workspaceId || ''),
|
|
347
|
+
innerPath: String(material.targetPath || material.originalPath || ''),
|
|
348
|
+
archivePackagePath: archivePath, packagePath: archivePath
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (matches.length === 1) return matches[0];
|
|
353
|
+
}
|
|
354
|
+
return Object.freeze({ bytes: null });
|
|
297
355
|
}
|
|
298
356
|
|
|
299
357
|
export function parseHandoffGrounding(markdown, route) {
|
|
300
358
|
const parties = sectionText(markdown, 'Handoff Parties');
|
|
301
359
|
const transferSection = parseNamedDeclarationSection(markdown, '## Transfers');
|
|
360
|
+
const retainedSection = parseNamedDeclarationSection(markdown, '## Retained Responsibilities');
|
|
302
361
|
const completion = sectionText(markdown, 'Completion Expectation');
|
|
303
362
|
const transfers = Object.freeze((transferSection.entries || []).filter((entry) => String(entry.name || '').trim().toLowerCase() !== 'none').map((entry) => Object.freeze({
|
|
304
363
|
id: String(entry.name || ''),
|
|
305
364
|
transferKind: String(entry.fields?.['Transfer Kind'] || ''),
|
|
306
365
|
description: String(entry.fields?.Description || ''),
|
|
366
|
+
controllingArtifact: String(entry.fields?.['Controlling Artifact'] || ''),
|
|
367
|
+
controllingArtifactTarget: markdownReferenceTarget(entry.fields?.['Controlling Artifact'] || ''),
|
|
368
|
+
boundary: String(entry.fields?.Boundary || '')
|
|
369
|
+
})));
|
|
370
|
+
const retainedResponsibilities = Object.freeze((retainedSection.entries || []).filter((entry) => String(entry.name || '').trim().toLowerCase() !== 'none').map((entry) => Object.freeze({
|
|
371
|
+
id: String(entry.name || ''),
|
|
372
|
+
retainedBy: String(entry.fields?.['Retained By'] || ''),
|
|
373
|
+
responsibility: String(entry.fields?.Responsibility || ''),
|
|
307
374
|
boundary: String(entry.fields?.Boundary || '')
|
|
308
375
|
})));
|
|
309
376
|
return deepFreeze({
|
|
@@ -316,6 +383,7 @@ export function parseHandoffGrounding(markdown, route) {
|
|
|
316
383
|
fromReference: sectionReferenceTarget(parties, 'From Reference'),
|
|
317
384
|
toReference: sectionReferenceTarget(parties, 'To Reference'),
|
|
318
385
|
transfers,
|
|
386
|
+
retainedResponsibilities,
|
|
319
387
|
completionExpectation: Object.freeze({
|
|
320
388
|
signalKind: sectionField(completion, 'Signal Kind'),
|
|
321
389
|
signalMeaning: sectionField(completion, 'Signal Meaning'),
|
|
@@ -330,8 +398,14 @@ export function parseHandoffGrounding(markdown, route) {
|
|
|
330
398
|
});
|
|
331
399
|
}
|
|
332
400
|
|
|
401
|
+
function markdownReferenceTarget(value = '') {
|
|
402
|
+
const text = String(value || '').trim();
|
|
403
|
+
const match = text.match(/\[[^\]]*\]\(([^)]+)\)/);
|
|
404
|
+
return match ? String(match[1] || '').trim() : '';
|
|
405
|
+
}
|
|
406
|
+
|
|
333
407
|
export function emptyHandoffGrounding() {
|
|
334
|
-
return deepFreeze({ schemaId: '', purpose: '', from: '', fromKind: '', fromReference: '', to: '', toKind: '', toReference: '', transfers: Object.freeze([]), completionExpectation: Object.freeze({ signalKind: '', signalMeaning: '', returnTo: '' }), routeId: '', workspaceId: '', workspaceRelativePath: '', packagePath: '', sha256: '', boundary: 'No Handoff material supplied.' });
|
|
408
|
+
return deepFreeze({ schemaId: '', purpose: '', from: '', fromKind: '', fromReference: '', to: '', toKind: '', toReference: '', transfers: Object.freeze([]), retainedResponsibilities: Object.freeze([]), completionExpectation: Object.freeze({ signalKind: '', signalMeaning: '', returnTo: '' }), routeId: '', workspaceId: '', workspaceRelativePath: '', packagePath: '', sha256: '', boundary: 'No Handoff material supplied.' });
|
|
335
409
|
}
|
|
336
410
|
|
|
337
411
|
export function resolveGroundingRouteMarkdown(bundle = {}, selectedRoute = {}, findings = [], context = null) {
|
|
@@ -136,7 +136,7 @@ export function buildParticipantRolePointerChain(input = {}) {
|
|
|
136
136
|
prose: 'This Pointer is recipient discovery/grounding only. It does not declare semantic participation, change Handoff From/To, prove a human holder, or create Role authority; participation meaning remains owned by authoritative Handoff/Relation/context authority.',
|
|
137
137
|
currentRead: [
|
|
138
138
|
{ label: 'Route Id', value: `\`${String(input.route?.id || '')}\`` },
|
|
139
|
-
{ label: '
|
|
139
|
+
{ label: 'Participant Requirement Id', value: `\`${String(requirement.id || '')}\`` },
|
|
140
140
|
...(roleFacts.roleLabelHint ? [{ label: 'Role Label Hint', value: roleFacts.roleLabelHint }] : []),
|
|
141
141
|
{ label: 'Role Reference', value: roleFacts.referenceTarget ? `\`${roleFacts.referenceTarget}\`` : 'exact carried target' },
|
|
142
142
|
{ label: 'Target Carrier Kind', value: target.carrierKind },
|
|
@@ -38,14 +38,17 @@ export function projectRecipientV2EndpointRoles(pointers = []) {
|
|
|
38
38
|
export function projectRecipientV2ParticipantRoles(pointers = []) {
|
|
39
39
|
return Object.freeze(pointers.map((item) => Object.freeze({
|
|
40
40
|
pointerPath: item.path,
|
|
41
|
-
routeId: String(item.facts?.routeId || qualified?.id || ''),
|
|
42
|
-
workspaceId: String(item.facts?.workspaceId || ''),
|
|
43
41
|
routeId: String(item.facts?.routeId || ''),
|
|
42
|
+
workspaceId: String(item.facts?.workspaceId || ''),
|
|
43
|
+
requirementId: String(item.facts?.participantRequirementId || ''),
|
|
44
44
|
roleLabelHint: String(item.facts?.roleLabelHint || ''),
|
|
45
45
|
referenceTarget: String(item.facts?.referenceTarget || ''),
|
|
46
46
|
targetCarrierKind: String(item.facts?.targetCarrierKind || ''),
|
|
47
47
|
targetWorkspaceId: String(item.facts?.targetWorkspaceId || ''),
|
|
48
|
+
archivePath: String(item.facts?.archivePath || ''),
|
|
48
49
|
targetInnerPath: String(item.facts?.targetInnerPath || item.facts?.targetArchiveEntry || ''),
|
|
50
|
+
targetArchiveEntry: String(item.facts?.targetArchiveEntry || ''),
|
|
51
|
+
targetBytes: Number(item.facts?.targetBytes || 0),
|
|
49
52
|
targetSha256: String(item.facts?.targetSha256 || '')
|
|
50
53
|
})));
|
|
51
54
|
}
|
|
@@ -9,7 +9,7 @@ import { RECIPIENT_V2_ROUTE_SELECTION_AUTHORITY, RECIPIENT_V2_SIBLING_ROUTE_INFE
|
|
|
9
9
|
import { recipientV2TransportFacts } from './recipientV2.transportManifest.js';
|
|
10
10
|
import { buildRecipientV2BootstrapCarrier, buildRecipientV2WorkspaceCarriers, recipientV2ParentAuthority } from './recipientV2.topology.workspaces.js';
|
|
11
11
|
import { buildEndpointRolePointerChain, buildParticipantRolePointerChain } from './recipientV2.endpointRolePointers.js';
|
|
12
|
-
import { bindingForWorkspace, boundedWorkspaceClaimsDetachedRecovery, detachedMaterial, duplicates, finding, roleMaterialTarget, routeClaimsDetachedMaterial, safeToken, uniqueFileIndex } from './recipientV2.topology.materials.js';
|
|
12
|
+
import { bindingForWorkspace, boundedWorkspaceClaimsDetachedRecovery, coalesceDetachedCacheMaterials, detachedMaterial, duplicates, finding, roleMaterialTarget, routeClaimsDetachedMaterial, safeToken, uniqueFileIndex } from './recipientV2.topology.materials.js';
|
|
13
13
|
import { RECIPIENT_V2_PACKAGE_V1_FORMAT_ID, RECIPIENT_V2_PACKAGE_V1_ROOT_PATH, RECIPIENT_V2_PACKAGE_V1_SCHEMA_ID, RECIPIENT_V2_PACKAGE_V1_SCHEMA_TARGET } from './recipientV2.packageV1.constants.js';
|
|
14
14
|
import { renderHandoffPackageV1 } from './recipientV2.packageV1.contract.js';
|
|
15
15
|
import { inspectRecipientFacingV2PackageV1 } from './recipientV2.packageV1.inspect.js';
|
|
@@ -136,7 +136,7 @@ function buildRecipientFacingV2PackageV1Prepared(input = {}, sealedByWorkspaceId
|
|
|
136
136
|
const workspace = workspaceById.get(plan.workspaceId);
|
|
137
137
|
if (!workspace) continue;
|
|
138
138
|
const binding = bindingForWorkspace(descriptor, workspace.workspaceId);
|
|
139
|
-
const materials = detached.filter((item) => (workspace.workspaceId === String(route.workspaceId || '') && routeClaimsDetachedMaterial(route, item)) || boundedWorkspaceClaimsDetachedRecovery(binding, item));
|
|
139
|
+
const materials = coalesceDetachedCacheMaterials(detached.filter((item) => (workspace.workspaceId === String(route.workspaceId || '') && routeClaimsDetachedMaterial(route, item)) || boundedWorkspaceClaimsDetachedRecovery(binding, item)));
|
|
140
140
|
if (!materials.length) continue;
|
|
141
141
|
const artifactPath = `${plan.prefix}-1-cache.trace.md`;
|
|
142
142
|
const archivePath = `${plan.prefix}-1-cache.zip`;
|
|
@@ -16,6 +16,8 @@ import { buildEndpointRolePointerChain, buildParticipantRolePointerChain } from
|
|
|
16
16
|
import {
|
|
17
17
|
bindingForWorkspace,
|
|
18
18
|
boundedWorkspaceClaimsDetachedRecovery,
|
|
19
|
+
coalesceDetachedCacheMaterials,
|
|
20
|
+
detachedCacheRepresentationKey,
|
|
19
21
|
deepFreeze,
|
|
20
22
|
detachedMaterial,
|
|
21
23
|
duplicates,
|
|
@@ -144,7 +146,7 @@ function buildRecipientFacingV2TopologyLegacy(input = {}) {
|
|
|
144
146
|
if (!workspace) continue;
|
|
145
147
|
const workspaceRoutes = routePlans.filter((plan) => plan.workspace.workspaceId === workspace.workspaceId);
|
|
146
148
|
const binding = bindingForWorkspace(descriptor, workspace.workspaceId);
|
|
147
|
-
const materials = detached.filter((item) => workspaceRoutes.some((plan) => routeClaimsDetachedMaterial(plan.route, item)) || boundedWorkspaceClaimsDetachedRecovery(binding, item));
|
|
149
|
+
const materials = coalesceDetachedCacheMaterials(detached.filter((item) => workspaceRoutes.some((plan) => routeClaimsDetachedMaterial(plan.route, item)) || boundedWorkspaceClaimsDetachedRecovery(binding, item)));
|
|
148
150
|
if (!materials.length) continue;
|
|
149
151
|
const artifactPath = `001-${workspacePlan.ordinal}-1-cache.trace.md`;
|
|
150
152
|
const archivePath = `001-${workspacePlan.ordinal}-1-cache.zip`;
|
|
@@ -166,9 +168,9 @@ function buildRecipientFacingV2TopologyLegacy(input = {}) {
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
const claimedDetached = new Set();
|
|
169
|
-
for (const cache of topology.caches) for (const material of cache.materials || []) claimedDetached.add(
|
|
171
|
+
for (const cache of topology.caches) for (const material of cache.materials || []) claimedDetached.add(detachedCacheRepresentationKey(material));
|
|
170
172
|
for (const item of detached) {
|
|
171
|
-
const key =
|
|
173
|
+
const key = detachedCacheRepresentationKey(item);
|
|
172
174
|
if (!claimedDetached.has(key)) findings.push(finding('error', 'portable.handoff-v2-surface.cache.material-unowned', 'Detached dependency bytes are not claimed by any Workspace-scoped Handoff route cache.', { requirementId: item.requirementId || '', referenceTarget: item.referenceTarget || '' }));
|
|
173
175
|
}
|
|
174
176
|
|
|
Binary file
|