@tiinex/core 0.17.0 → 0.18.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 +6 -5
- package/src/tooling/portable/adapters/cli/cli.common-author.js +29 -5
- package/src/tooling/portable/adapters/cli/cli.common-output.js +31 -3
- package/src/tooling/portable/adapters/cli/cli.run.js +4 -0
- package/src/tooling/portable/adapters/node/handoff.manufacture.js +21 -11
- package/src/tooling/portable/adapters/node/handoff.manufacture.packageParent.js +43 -0
- package/src/tooling/portable/grounding/grounding.capsule.js +14 -2
- package/src/tooling/portable/grounding/grounding.orchestrationReadiness.js +33 -0
- package/src/tooling/portable/grounding/grounding.participantContext.js +58 -0
- package/src/tooling/portable/grounding/grounding.processApplicability.js +38 -0
- package/src/tooling/portable/grounding/grounding.readiness.authority.js +48 -3
- package/src/tooling/portable/grounding/grounding.readiness.js +3 -0
- package/src/tooling/portable/grounding/grounding.readiness.support.js +4 -0
- package/src/tooling/portable/grounding/grounding.sourceEvidence.js +151 -9
- package/src/tooling/portable/handoff/carrierProjection.routeQualification.js +12 -1
- package/src/tooling/portable/handoff/coldStartQualification.materials.js +11 -1
- package/src/tooling/portable/handoff/contextAudit.js +1 -1
- package/src/tooling/portable/handoff/recoveryAcceptanceAudit.js +5 -3
- package/src/tooling/portable/schema/contract.field-domain.js +43 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiinex/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Shared host-neutral Tiinex implementation core for artifacts, schemas, validation, lineage, grounding, Handoffs, provenance and deterministic workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": true,
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"./tooling/portable/engine.facade.js": "./src/tooling/portable/engine.facade.js",
|
|
79
79
|
"./tooling/portable/grounding/grounding.capsule.js": "./src/tooling/portable/grounding/grounding.capsule.js",
|
|
80
80
|
"./tooling/portable/grounding/grounding.participantAuthority.js": "./src/tooling/portable/grounding/grounding.participantAuthority.js",
|
|
81
|
+
"./tooling/portable/grounding/grounding.processApplicability.js": "./src/tooling/portable/grounding/grounding.processApplicability.js",
|
|
81
82
|
"./tooling/portable/grounding/grounding.readiness.js": "./src/tooling/portable/grounding/grounding.readiness.js",
|
|
82
83
|
"./tooling/portable/grounding/grounding.workProvenance.js": "./src/tooling/portable/grounding/grounding.workProvenance.js",
|
|
83
84
|
"./tooling/portable/handoff/carrierLineage.js": "./src/tooling/portable/handoff/carrierLineage.js",
|
|
@@ -169,12 +170,12 @@
|
|
|
169
170
|
"type": "git",
|
|
170
171
|
"url": "git+https://github.com/Tiinex/core.git"
|
|
171
172
|
},
|
|
172
|
-
"gitHead": "
|
|
173
|
+
"gitHead": "12321ec2a8d09722b464ef7977afa2dcdc924718",
|
|
173
174
|
"tiinexRelease": {
|
|
174
175
|
"policy": "tiinex.master-npm-release.v1",
|
|
175
|
-
"sourceCommit": "
|
|
176
|
-
"sourceTree": "
|
|
176
|
+
"sourceCommit": "12321ec2a8d09722b464ef7977afa2dcdc924718",
|
|
177
|
+
"sourceTree": "eba0d10ad8f5fc20cc1c98ee88c328fbd4dafa4c",
|
|
177
178
|
"repository": "Tiinex/core",
|
|
178
|
-
"previousVersion": "0.
|
|
179
|
+
"previousVersion": "0.17.0"
|
|
179
180
|
}
|
|
180
181
|
}
|
|
@@ -31,8 +31,8 @@ export async function runCommonAuthorCli(parsed = {}, runtime = {}) {
|
|
|
31
31
|
|
|
32
32
|
const parentReference = resolveParentReference(flags, state);
|
|
33
33
|
const parentSource = String(flags['parent-source'] || flags['parent-file'] || '').trim();
|
|
34
|
-
if (isWorkspaceQualifiedReference(parentReference) && !parentSource) throw new Error(
|
|
35
|
-
if (parentSource && !parentReference) throw new Error('portable.cli.author.parent.required');
|
|
34
|
+
if (isWorkspaceQualifiedReference(parentReference) && !parentSource) throw new Error(`portable.cli.author.parent-source.required: --parent ${parentReference} names an explicit cross-Workspace Parent. Supply --parent-source <local-file> containing the exact qualified Parent bytes; Tooling will not discover or fetch that Parent automatically.`);
|
|
35
|
+
if (parentSource && !parentReference) throw new Error('portable.cli.author.parent.required: --parent-source supplies Parent bytes but no semantic Parent reference. Supply --parent <workspace::path|relative-path> explicitly; Tooling will not infer Parent identity from the source file.');
|
|
36
36
|
if (isWorkspaceQualifiedReference(parentReference) && !requestedArtifactRelativePath && !targetDirectory) throw new Error('portable.cli.author.cross-workspace-parent.target-required');
|
|
37
37
|
const parentPath = parentReference ? (parentSource ? path.resolve(parentSource) : safeWorkspaceTarget(workspaceRoot, parentReference)) : '';
|
|
38
38
|
const artifactRelativePath = requestedArtifactRelativePath || await allocateArtifactRelativePath({ workspaceRoot, targetDirectory, parentRelativePath: parentReference, schemaId, title });
|
|
@@ -80,6 +80,7 @@ export async function runCommonAuthorCli(parsed = {}, runtime = {}) {
|
|
|
80
80
|
}, {});
|
|
81
81
|
const blocking = Number(audit?.findingSummary?.counts?.error || 0) + Number(stage?.findingSummary?.counts?.error || 0);
|
|
82
82
|
if (blocking) {
|
|
83
|
+
const actionableFindings = projectAuthorActionableFindings(audit, stage);
|
|
83
84
|
await rm(artifactPath, { force: true });
|
|
84
85
|
wrote = false;
|
|
85
86
|
return Object.freeze({
|
|
@@ -90,7 +91,8 @@ export async function runCommonAuthorCli(parsed = {}, runtime = {}) {
|
|
|
90
91
|
audit,
|
|
91
92
|
stage,
|
|
92
93
|
findingSummary: mergeFindingSummaries(audit?.findingSummary, stage?.findingSummary),
|
|
93
|
-
|
|
94
|
+
actionableFindings,
|
|
95
|
+
nextAction: actionableFindings[0]?.nextAction || 'Resolve the reported schema/continuity finding, then rerun the same author command. No invalid durable artifact was retained.',
|
|
94
96
|
boundary: 'Common-path authoring composes the shared renderer, c14n-v2 sealing, runtime audit, and staging qualification. It may write only the requested local Workspace artifact and runtime-only .tiinex continuation state; it performs no remote mutation.'
|
|
95
97
|
});
|
|
96
98
|
}
|
|
@@ -125,12 +127,12 @@ async function parentRecordFromArtifact(parentPath, parentRelativePath, context
|
|
|
125
127
|
const schemaId = String(current.schema?.id || '').trim();
|
|
126
128
|
const schemaTarget = String(current.schema?.target || '').trim();
|
|
127
129
|
const self = canonicalC14nV2SelfState(markdown);
|
|
128
|
-
if (!schemaId) throw new Error('portable.cli.author.parent.schema-authority.required');
|
|
130
|
+
if (!schemaId) throw new Error('portable.cli.author.parent.schema-authority.required: the supplied Parent does not declare a Current Schema. Supply exact qualified Parent bytes with an explicit Current Schema reference; Tooling will not infer Parent schema authority from path or filename.');
|
|
129
131
|
if (self.state !== 'verified') throw new Error(`portable.cli.author.parent.integrity.${self.reason || self.state}`);
|
|
130
132
|
const schemaReferenceAuthority = schemaTarget
|
|
131
133
|
? exactDeclaredSchemaReferenceAuthority(schemaId, schemaTarget)
|
|
132
134
|
: await recoverQualifiedRuntimeSchemaReferenceAuthority(schemaId, context.runtime || {});
|
|
133
|
-
if (!schemaReferenceAuthority) throw new Error(
|
|
135
|
+
if (!schemaReferenceAuthority) throw new Error(`portable.cli.author.parent.schema-authority.required: Parent schema ${schemaId} lacks an exact qualified schema-reference authority. Supply Parent bytes with an exact Current Schema target or qualified runtime canonical schema material; Tooling will not invent the schema target.`);
|
|
134
136
|
return Object.freeze({
|
|
135
137
|
id: parentRelativePath,
|
|
136
138
|
path: parentRelativePath,
|
|
@@ -144,6 +146,28 @@ async function parentRecordFromArtifact(parentPath, parentRelativePath, context
|
|
|
144
146
|
});
|
|
145
147
|
}
|
|
146
148
|
|
|
149
|
+
function projectAuthorActionableFindings(audit = {}, stage = {}) {
|
|
150
|
+
const findings = [
|
|
151
|
+
...(audit.findings || audit.actionableFindings || []),
|
|
152
|
+
...(stage.findings || stage.actionableFindings || [])
|
|
153
|
+
].filter((item) => item && (item.severity === 'error' || item.severity === 'warning'));
|
|
154
|
+
const seen = new Set();
|
|
155
|
+
const out = [];
|
|
156
|
+
for (const item of findings) {
|
|
157
|
+
const code = String(item.code || '');
|
|
158
|
+
const key = `${code}\u0000${String(item.message || '')}`;
|
|
159
|
+
if (seen.has(key)) continue;
|
|
160
|
+
seen.add(key);
|
|
161
|
+
out.push(Object.freeze({
|
|
162
|
+
code,
|
|
163
|
+
message: String(item.message || ''),
|
|
164
|
+
...(item.contractGuidance ? { contractGuidance: Object.freeze({ ...item.contractGuidance }) } : {}),
|
|
165
|
+
nextAction: String(item.contractGuidance?.nextAction || 'Resolve this exact finding using its cited authority/evidence, then rerun the same author command. No invalid durable artifact was retained.')
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
return Object.freeze(out.slice(0, 20));
|
|
169
|
+
}
|
|
170
|
+
|
|
147
171
|
export function parentRecoveryMode(reference = '') {
|
|
148
172
|
const classification = classifyParentRecoveryReference(reference);
|
|
149
173
|
if (classification.kind === 'workspace-qualified') return 'workspace-qualified';
|
|
@@ -103,6 +103,7 @@ function projectGroundDefault(result = {}, parsed = {}) {
|
|
|
103
103
|
status: result.status,
|
|
104
104
|
readiness: compactReadiness(result.readiness),
|
|
105
105
|
authority: compactGroundAuthority(result.authority),
|
|
106
|
+
orchestrationReadiness: compactOrchestrationReadiness(result.orchestrationReadiness),
|
|
106
107
|
requiredContext: Object.freeze({
|
|
107
108
|
declared: Number(required.declared || 0),
|
|
108
109
|
matchedInWorkspaceSnapshots: Number(required.matchedInWorkspaceSnapshots || 0),
|
|
@@ -254,13 +255,18 @@ function compactGroundAuthority(authority = {}) {
|
|
|
254
255
|
route: Object.freeze({
|
|
255
256
|
id: String(route.id || ''),
|
|
256
257
|
pointerPath: String(route.pointerPath || ''),
|
|
257
|
-
workspaceId: String(route.workspaceId || '')
|
|
258
|
+
workspaceId: String(route.workspaceId || ''),
|
|
259
|
+
workspaceRelativePath: String(route.workspaceRelativePath || ''),
|
|
260
|
+
sha256: String(route.sha256 || ''),
|
|
261
|
+
provenance: route.provenance ? Object.freeze({ ...route.provenance }) : null
|
|
258
262
|
}),
|
|
259
263
|
handoff: Object.freeze({
|
|
260
264
|
purpose: String(handoff.purpose || ''),
|
|
261
265
|
from: String(handoff.from || ''),
|
|
262
266
|
to: String(handoff.to || ''),
|
|
263
|
-
completionExpectation: handoff.completionExpectation || null
|
|
267
|
+
completionExpectation: handoff.completionExpectation || null,
|
|
268
|
+
transfers: Object.freeze((handoff.transfers || []).map((item) => Object.freeze({ ...item }))),
|
|
269
|
+
provenance: handoff.provenance ? Object.freeze({ ...handoff.provenance }) : null
|
|
264
270
|
}),
|
|
265
271
|
role: Object.freeze({
|
|
266
272
|
state: String(role.state || ''),
|
|
@@ -275,7 +281,8 @@ function compactGroundAuthority(authority = {}) {
|
|
|
275
281
|
recipientCompatibility: String(holderBinding.recipientCompatibility || ''),
|
|
276
282
|
source: String(holderBinding.source || ''),
|
|
277
283
|
explicit: Boolean(holderBinding.explicit),
|
|
278
|
-
inferredFromTransport: Boolean(holderBinding.inferredFromTransport)
|
|
284
|
+
inferredFromTransport: Boolean(holderBinding.inferredFromTransport),
|
|
285
|
+
provenance: holderBinding.provenance ? Object.freeze({ ...holderBinding.provenance }) : null
|
|
279
286
|
}),
|
|
280
287
|
operationBoundary: Object.freeze({
|
|
281
288
|
sourceMutation: Boolean(operationBoundary.sourceMutation),
|
|
@@ -286,14 +293,35 @@ function compactGroundAuthority(authority = {}) {
|
|
|
286
293
|
});
|
|
287
294
|
}
|
|
288
295
|
|
|
296
|
+
function compactOrchestrationReadiness(value = {}) {
|
|
297
|
+
if (!value || typeof value !== 'object') return null;
|
|
298
|
+
const wider = value.widerOrchestration || {};
|
|
299
|
+
return Object.freeze({
|
|
300
|
+
state: String(value.state || ''),
|
|
301
|
+
boundedActionReadiness: String(value.boundedActionReadiness || ''),
|
|
302
|
+
widerOrchestration: Object.freeze({
|
|
303
|
+
state: String(wider.state || ''),
|
|
304
|
+
blockers: Object.freeze((wider.blockers || []).slice(0, 8).map((item) => Object.freeze({ ...item })))
|
|
305
|
+
}),
|
|
306
|
+
participantMap: String(value.participantMap || ''),
|
|
307
|
+
sourceScope: String(value.sourceScope || ''),
|
|
308
|
+
processApplicability: value.processApplicability ? Object.freeze({ ...value.processApplicability, unresolved: Object.freeze([...(value.processApplicability.unresolved || [])].map((item) => Object.freeze({ ...item }))) }) : null,
|
|
309
|
+
boundary: String(value.boundary || '')
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
289
313
|
function projectRequiredContextItem(item = {}) {
|
|
290
314
|
const contentProjected = Boolean(item.contentProjected && typeof item.content === 'string');
|
|
291
315
|
return Object.freeze({
|
|
292
316
|
requirementId: String(item.requirementId || ''),
|
|
293
317
|
name: String(item.name || ''),
|
|
318
|
+
material: String(item.material || ''),
|
|
319
|
+
purpose: String(item.purpose || ''),
|
|
320
|
+
declaredAvailability: String(item.declaredAvailability || ''),
|
|
294
321
|
state: String(item.state || ''),
|
|
295
322
|
workspaceId: String(item.workspaceId || ''),
|
|
296
323
|
innerPath: String(item.innerPath || ''),
|
|
324
|
+
provenance: item.provenance ? Object.freeze({ ...item.provenance }) : null,
|
|
297
325
|
contentProjected,
|
|
298
326
|
...(contentProjected ? { content: item.content } : {})
|
|
299
327
|
});
|
|
@@ -134,6 +134,9 @@ function cliColdStartQualificationSummary(result = {}, flags = {}) {
|
|
|
134
134
|
return Object.freeze({
|
|
135
135
|
requirementId: item.requirementId,
|
|
136
136
|
name: item.name,
|
|
137
|
+
material: item.material,
|
|
138
|
+
purpose: item.purpose,
|
|
139
|
+
declaredAvailability: item.declaredAvailability,
|
|
137
140
|
state: item.state,
|
|
138
141
|
referenceTarget: item.referenceTarget,
|
|
139
142
|
kind: item.kind,
|
|
@@ -147,6 +150,7 @@ function cliColdStartQualificationSummary(result = {}, flags = {}) {
|
|
|
147
150
|
actualBytes: item.actualBytes,
|
|
148
151
|
actualSha256: item.actualSha256,
|
|
149
152
|
contentState: item.contentState,
|
|
153
|
+
provenance: item.provenance,
|
|
150
154
|
contentProjected,
|
|
151
155
|
...(contentProjected ? { content: item.content } : {})
|
|
152
156
|
});
|
|
@@ -6,7 +6,7 @@ import { qualifyToolingRuntimeSourceAlignment } from './handoff.manufacture.runt
|
|
|
6
6
|
import { normalizeHandoffCarrierLineage } from '../../handoff/carrierLineage.js';
|
|
7
7
|
import { normalizeHandoffCarrierProfile } from '../../handoff/carrierProfile.js';
|
|
8
8
|
import { enumerateNodeWorkspace, PORTABLE_NODE_WORKSPACE_ENUMERATION_SCHEMA_ID } from './handoff.manufacture.enumeration.js';
|
|
9
|
-
import { preparePackageParentWorkspaceReuse } from './handoff.manufacture.packageParent.js';
|
|
9
|
+
import { preparePackageParentWorkspaceReuse, projectRequiredContextWorkspaceSelectionPreflight } from './handoff.manufacture.packageParent.js';
|
|
10
10
|
import { qualifyPortableSourceReconciliationProofForManufacture } from '../../comparison/sourceFrontierReconciliationProof.js';
|
|
11
11
|
import { qualifyPortableManufactureSchemaReferenceCandidate } from '../../handoff/schemaReferencePreflight.js';
|
|
12
12
|
import { qualifyDelegationReturnReservation } from '../../handoff/delegationReturnReservation.js';
|
|
@@ -46,14 +46,6 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
|
|
|
46
46
|
(value) => Object.freeze({ value, error: null }),
|
|
47
47
|
(error) => Object.freeze({ value: null, error })
|
|
48
48
|
);
|
|
49
|
-
const enumerationPromise = enumerateNodeWorkspace(workspaceRoot, {
|
|
50
|
-
workspaceId,
|
|
51
|
-
workspaceTitle: requestedWorkspaceTitle,
|
|
52
|
-
sourceMetadata: input.workspaceSource || input.sourceMetadata || {},
|
|
53
|
-
excludeDirectories: input.excludeDirectories || options.excludeDirectories,
|
|
54
|
-
excludeRelativePaths: input.excludeRelativePaths || options.excludeRelativePaths,
|
|
55
|
-
maxFiles: input.maxFiles || options.maxFiles
|
|
56
|
-
});
|
|
57
49
|
const additionalWorkspaceDescriptors = normalizeAdditionalWorkspaceDescriptors(input.additionalWorkspaces || input.workspaceRoots || input.workspaceDescriptors || []);
|
|
58
50
|
const seenWorkspaceIds = new Set([workspaceId]);
|
|
59
51
|
const additionalWorkspaceInputs = additionalWorkspaceDescriptors.map((descriptor) => {
|
|
@@ -77,6 +69,23 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
|
|
|
77
69
|
workspaceIds: input.packageParentWorkspaceIds || input.reusePackageParentWorkspaceIds || [],
|
|
78
70
|
workspaceAliases: input.packageParentWorkspaceAliases || input.workspaceAliases || {}
|
|
79
71
|
});
|
|
72
|
+
const handoffMarkdown = await handoffMarkdownPromise;
|
|
73
|
+
const requiredContextWorkspaceSelectionPreflight = projectRequiredContextWorkspaceSelectionPreflight({
|
|
74
|
+
handoffMarkdown,
|
|
75
|
+
currentWorkspaceIds: [...seenWorkspaceIds],
|
|
76
|
+
packageParentReuse
|
|
77
|
+
});
|
|
78
|
+
if (requiredContextWorkspaceSelectionPreflight.state === 'action-required') {
|
|
79
|
+
throw new Error(`portable.handoff-manufacture.required-context.workspace-selection.required: ${requiredContextWorkspaceSelectionPreflight.nextAction} Missing Workspace ids: ${requiredContextWorkspaceSelectionPreflight.missingWorkspaceIds.join(',')}. Tooling will not auto-select package-parent Workspace source from carrier lineage.`);
|
|
80
|
+
}
|
|
81
|
+
const enumerationPromise = enumerateNodeWorkspace(workspaceRoot, {
|
|
82
|
+
workspaceId,
|
|
83
|
+
workspaceTitle: requestedWorkspaceTitle,
|
|
84
|
+
sourceMetadata: input.workspaceSource || input.sourceMetadata || {},
|
|
85
|
+
excludeDirectories: input.excludeDirectories || options.excludeDirectories,
|
|
86
|
+
excludeRelativePaths: input.excludeRelativePaths || options.excludeRelativePaths,
|
|
87
|
+
maxFiles: input.maxFiles || options.maxFiles
|
|
88
|
+
});
|
|
80
89
|
const additionalEnumerationsPromise = Promise.all(additionalWorkspaceInputs.map(async ({ descriptor, id, root, requestedTitle }) => {
|
|
81
90
|
const enumerated = await enumerateNodeWorkspace(root, {
|
|
82
91
|
workspaceId: id,
|
|
@@ -90,8 +99,7 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
|
|
|
90
99
|
return Object.freeze({ descriptor, id, root, requestedTitle, enumerated });
|
|
91
100
|
}));
|
|
92
101
|
|
|
93
|
-
const [
|
|
94
|
-
handoffMarkdownPromise,
|
|
102
|
+
const [enumeration, additionalEnumerations] = await Promise.all([
|
|
95
103
|
enumerationPromise,
|
|
96
104
|
additionalEnumerationsPromise
|
|
97
105
|
]);
|
|
@@ -217,10 +225,12 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
|
|
|
217
225
|
selectionMode: String(packageParentReuse.selectionMode || ''),
|
|
218
226
|
requestedWorkspaceIds: Object.freeze([...(packageParentReuse.requestedWorkspaceIds || [])].map(String)),
|
|
219
227
|
providerWorkspaceIds: Object.freeze([...(packageParentReuse.providerWorkspaceIds || [])].map(String)),
|
|
228
|
+
providerWorkspaceTargets: Object.freeze([...(packageParentReuse.providerWorkspaceTargets || [])].map((item) => Object.freeze({ ...item }))),
|
|
220
229
|
inheritedWorkspaceIds: Object.freeze((packageParentReuse.inherited || []).map((item) => String(item.id || ''))),
|
|
221
230
|
workspaceAliases: Object.freeze([...(packageParentReuse.workspaceAliases || [])].map((item) => Object.freeze({ ...item }))),
|
|
222
231
|
boundary: String(packageParentReuse.boundary || '')
|
|
223
232
|
}),
|
|
233
|
+
requiredContextWorkspaceSelectionPreflight,
|
|
224
234
|
carrierProjection: Object.freeze({ requestedRoutes: transportRoutes.length || 1, carrierLineage: normalizeHandoffCarrierLineage(input.carrierLineage || null), carrierProfile: normalizeHandoffCarrierProfile(input.carrierProfile || null), boundary: 'Routes are qualified later against packaged workspace bytes; adapter text is not authority.' })
|
|
225
235
|
}),
|
|
226
236
|
verifyRoundtrip: input.verifyRoundtrip !== false
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { packageFileBytes, sha256Hex } from '../../../../export/package.bytes.js';
|
|
2
2
|
import { inspectRecipientFacingV2Topology } from '../../handoff/recipientV2.inspect.js';
|
|
3
3
|
import { parseHandoffPackageV1, RECIPIENT_V2_PACKAGE_V1_ROOT_PATH } from '../../handoff/recipientV2.packageV1.js';
|
|
4
|
+
import { projectHandoffMaterialRequirements } from '../../handoff/materialClosure.requirements.js';
|
|
5
|
+
import { parseWorkspaceQualifiedReference } from '../../handoff/workspaceQualifiedReference.js';
|
|
4
6
|
|
|
5
7
|
export function preparePackageParentWorkspaceReuse(input = {}) {
|
|
6
8
|
const bundle = input.bundle || null;
|
|
@@ -63,6 +65,7 @@ export function preparePackageParentWorkspaceReuse(input = {}) {
|
|
|
63
65
|
providers: Object.freeze(providers),
|
|
64
66
|
providerState: 'qualified',
|
|
65
67
|
providerWorkspaceIds: Object.freeze(providers.map((item) => normalizeId(item.id))),
|
|
68
|
+
providerWorkspaceTargets: Object.freeze([...providerTargetById.entries()].map(([workspaceId, targetPath]) => Object.freeze({ workspaceId, path: targetPath }))),
|
|
66
69
|
inherited: Object.freeze(inherited),
|
|
67
70
|
workspaceTargets: Object.freeze(workspaceTargets),
|
|
68
71
|
inspectionStatus: inspection.status,
|
|
@@ -74,6 +77,44 @@ export function preparePackageParentWorkspaceReuse(input = {}) {
|
|
|
74
77
|
});
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
export function projectRequiredContextWorkspaceSelectionPreflight(input = {}) {
|
|
81
|
+
const reuse = input.packageParentReuse || input.reuse || {};
|
|
82
|
+
const currentWorkspaceIds = new Set([...(input.currentWorkspaceIds || [])].map(normalizeId).filter(Boolean));
|
|
83
|
+
const inheritedWorkspaceIds = new Set((reuse.inherited || []).map((item) => normalizeId(item.id || item.enumeration?.materialization?.id || '')).filter(Boolean));
|
|
84
|
+
const providerTargets = new Map((reuse.providerWorkspaceTargets || []).map((item) => [normalizeId(item.workspaceId), normalizeWorkspacePath(item.path)]));
|
|
85
|
+
const requirements = projectHandoffMaterialRequirements({ markdown: String(input.handoffMarkdown || '') }).required || [];
|
|
86
|
+
const missing = [];
|
|
87
|
+
for (const requirement of requirements) {
|
|
88
|
+
const target = parseWorkspaceQualifiedReference(String(requirement.reference?.target || requirement.materialReference || ''));
|
|
89
|
+
if (!target) continue;
|
|
90
|
+
const workspaceId = normalizeId(target.workspaceId);
|
|
91
|
+
if (!workspaceId || currentWorkspaceIds.has(workspaceId) || inheritedWorkspaceIds.has(workspaceId)) continue;
|
|
92
|
+
const providerTarget = providerTargets.get(workspaceId) || '';
|
|
93
|
+
if (!providerTarget || providerTarget !== normalizeWorkspacePath(target.path)) continue;
|
|
94
|
+
if (!/\bworkspace\b/i.test(String(requirement.material || ''))) continue;
|
|
95
|
+
missing.push(Object.freeze({
|
|
96
|
+
requirementId: String(requirement.id || ''),
|
|
97
|
+
name: String(requirement.name || ''),
|
|
98
|
+
workspaceId,
|
|
99
|
+
material: String(requirement.material || ''),
|
|
100
|
+
purpose: String(requirement.purpose || ''),
|
|
101
|
+
referenceTarget: String(requirement.reference?.target || requirement.materialReference || ''),
|
|
102
|
+
providerWorkspaceTarget: providerTarget,
|
|
103
|
+
basis: 'explicit-required-context-workspace-material-matches-qualified-package-parent-workspace-target'
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
const missingWorkspaceIds = Object.freeze([...new Set(missing.map((item) => item.workspaceId))].sort());
|
|
107
|
+
return Object.freeze({
|
|
108
|
+
state: missingWorkspaceIds.length ? 'action-required' : 'ready',
|
|
109
|
+
missingWorkspaceIds,
|
|
110
|
+
requirements: Object.freeze(missing),
|
|
111
|
+
nextAction: missingWorkspaceIds.length
|
|
112
|
+
? `Re-run manufacture with --package-parent-workspaces ${missingWorkspaceIds.join(',')} to carry the explicitly required Workspace material from the qualified package parent.`
|
|
113
|
+
: 'No mechanically required package-parent Workspace carriage selection is missing.',
|
|
114
|
+
boundary: 'This preflight fires only when exact Handoff Required Context explicitly describes Workspace material and its workspace-qualified Material Reference exactly matches a qualified package-parent Workspace target. It never auto-selects source, infers Workspace intent from filenames alone, or treats carrier lineage as source authority.'
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
77
118
|
export function normalizePackageParentWorkspaceSelection(value = []) {
|
|
78
119
|
const raw = Array.isArray(value) ? value : [value];
|
|
79
120
|
const tokens = raw.flatMap((item) => String(item || '').split(',')).map((item) => String(item || '').trim()).filter(Boolean);
|
|
@@ -205,6 +246,7 @@ function emptyReuse(state, options = {}) {
|
|
|
205
246
|
providers: Object.freeze([]),
|
|
206
247
|
providerState: String(options.providerState || 'unavailable'),
|
|
207
248
|
providerWorkspaceIds: Object.freeze([]),
|
|
249
|
+
providerWorkspaceTargets: Object.freeze([]),
|
|
208
250
|
inherited: Object.freeze([]),
|
|
209
251
|
workspaceTargets: Object.freeze([]),
|
|
210
252
|
inspectionStatus: String(options.inspectionStatus || ''),
|
|
@@ -218,6 +260,7 @@ function emptyReuse(state, options = {}) {
|
|
|
218
260
|
});
|
|
219
261
|
}
|
|
220
262
|
function normalizeId(value = '') { return String(value || '').trim().toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, ''); }
|
|
263
|
+
function normalizeWorkspacePath(value = '') { return String(value || '').trim().replace(/\\/g, '/').replace(/^\/+/, ''); }
|
|
221
264
|
function mediaTypeForPath(value = '') { const lower = String(value || '').toLowerCase(); if (lower.endsWith('.md')) return 'text/markdown'; if (lower.endsWith('.json')) return 'application/json'; if (/\.(?:m?js|cjs)$/.test(lower)) return 'text/javascript'; if (lower.endsWith('.ts')) return 'text/typescript'; if (lower.endsWith('.css')) return 'text/css'; if (lower.endsWith('.html')) return 'text/html'; if (/\.(?:yml|yaml)$/.test(lower)) return 'text/yaml'; if (lower.endsWith('.txt')) return 'text/plain'; return 'application/octet-stream'; }
|
|
222
265
|
function stableJson(value) { return JSON.stringify(sortJson(value)); }
|
|
223
266
|
function sortJson(value) { if (Array.isArray(value)) return value.map(sortJson); if (!value || typeof value !== 'object') return value; return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortJson(value[key])])); }
|
|
@@ -2,6 +2,8 @@ import { projectParticipantAuthority } from './grounding.participantAuthority.js
|
|
|
2
2
|
import { projectWorkProvenance } from './grounding.workProvenance.js';
|
|
3
3
|
import { projectGroundingSourceEvidence } from './grounding.sourceEvidence.js';
|
|
4
4
|
import { projectGroundingPlanningContext } from './grounding.planningContext.js';
|
|
5
|
+
import { projectGroundingParticipantContext } from './grounding.participantContext.js';
|
|
6
|
+
import { projectGroundingProcessApplicability } from './grounding.processApplicability.js';
|
|
5
7
|
|
|
6
8
|
export const PORTABLE_GROUNDING_CAPSULE_SCHEMA_ID = 'tiinex.portable.grounding-capsule.v1';
|
|
7
9
|
|
|
@@ -12,12 +14,15 @@ export function projectGroundingCapsule({ authority = null, continuation = null,
|
|
|
12
14
|
const routeRecords = selectedRouteRecords(authority, records);
|
|
13
15
|
const workProvenance = projectWorkProvenance({ records, topology });
|
|
14
16
|
const participantAuthority = projectParticipantAuthority(authority);
|
|
17
|
+
const participantContext = projectGroundingParticipantContext(authority);
|
|
18
|
+
const processApplicability = projectGroundingProcessApplicability(authority);
|
|
19
|
+
const sourceEvidence = projectGroundingSourceEvidence({ records, contextAudit, continuation, requiredContext });
|
|
15
20
|
return Object.freeze({
|
|
16
21
|
schema: PORTABLE_GROUNDING_CAPSULE_SCHEMA_ID,
|
|
17
22
|
semanticReductions: Object.freeze(requiredContext.slice(0, MAX_CONTEXT).map(reduceRequiredContext)),
|
|
18
23
|
frontier: projectFrontier(topology, blockers),
|
|
19
24
|
exclusions: Object.freeze(routeRecords.flatMap((record) => parseExclusions(record.markdown || '')).slice(0, MAX_EXCLUSIONS)),
|
|
20
|
-
sourceEvidence
|
|
25
|
+
sourceEvidence,
|
|
21
26
|
planningContext: projectGroundingPlanningContext(requiredContext),
|
|
22
27
|
roleState: Object.freeze({
|
|
23
28
|
recipient: String(authority?.role?.endpoint?.label || authority?.handoff?.to || ''),
|
|
@@ -27,8 +32,15 @@ export function projectGroundingCapsule({ authority = null, continuation = null,
|
|
|
27
32
|
compatibility: String(authority?.holderBinding?.recipientCompatibility || 'unresolved')
|
|
28
33
|
}),
|
|
29
34
|
participantAuthority,
|
|
35
|
+
participantContext,
|
|
36
|
+
processApplicability,
|
|
30
37
|
workProvenance,
|
|
31
|
-
unresolved: Object.freeze([
|
|
38
|
+
unresolved: Object.freeze([
|
|
39
|
+
...workProvenance.unresolved,
|
|
40
|
+
...participantContext.unresolved,
|
|
41
|
+
...processApplicability.unresolved,
|
|
42
|
+
...sourceEvidence.blockers.map((item) => ({ code: item.code, detail: item.request }))
|
|
43
|
+
]),
|
|
32
44
|
boundary: 'Full Required Context bodies remain selector-gated.'
|
|
33
45
|
});
|
|
34
46
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function projectGroundingOrchestrationReadiness({ readinessState = '', participantContext = null, processApplicability = null, sourceEvidence = null, topology = {} } = {}) {
|
|
2
|
+
const boundedAction = String(readinessState || '');
|
|
3
|
+
const participantMap = String(participantContext?.participantMapState || 'not-established');
|
|
4
|
+
const unavailableSources = sourceEvidence?.blockers || [];
|
|
5
|
+
const sourceScope = sourceScopeState(sourceEvidence);
|
|
6
|
+
const processState = String(processApplicability?.state || 'not-established');
|
|
7
|
+
const blockers = [];
|
|
8
|
+
if (participantMap !== 'explicit-bounded-map') blockers.push(Object.freeze({ code: 'participant-capability-map-not-established', detail: 'Current route grounding does not establish a semantic participant/capability map. Grounding-only Role pointers and endpoint labels are insufficient.' }));
|
|
9
|
+
if (unavailableSources.length) blockers.push(...unavailableSources.map((item) => Object.freeze({ code: item.code || 'authoritative-material-unavailable', detail: item.request || item.name || item.referenceTarget || '' })));
|
|
10
|
+
if (sourceScope !== 'explicit-multi-source') blockers.push(Object.freeze({ code: 'source-authority-scope-bounded', detail: 'Source evidence is bounded to exact carried/current-route material and does not establish whole-program source authority.' }));
|
|
11
|
+
if (processState !== 'explicit-qualified-authority') blockers.push(Object.freeze({
|
|
12
|
+
code: 'process-applicability-semantic-authority-not-established',
|
|
13
|
+
detail: String(processApplicability?.unresolved?.[0]?.detail || 'Current grounding does not contain an explicit upstream-qualified process-applicability projection; process inventory and Role carriage are not substitutes.')
|
|
14
|
+
}));
|
|
15
|
+
if (!(topology.currentFrontier || []).length) blockers.push(Object.freeze({ code: 'current-work-frontier-unresolved', detail: 'No exact current Task frontier is resolved for orchestration.' }));
|
|
16
|
+
return Object.freeze({
|
|
17
|
+
state: blockers.length ? 'bounded-route-only' : 'sufficiently-grounded-for-current-orchestration-scope',
|
|
18
|
+
boundedActionReadiness: boundedAction,
|
|
19
|
+
widerOrchestration: Object.freeze({ state: blockers.length ? 'not-established' : 'bounded-established', blockers: Object.freeze(blockers.slice(0, 8)) }),
|
|
20
|
+
participantMap,
|
|
21
|
+
sourceScope,
|
|
22
|
+
processApplicability: processApplicability || Object.freeze({ state: processState, unresolved: Object.freeze([]) }),
|
|
23
|
+
boundary: 'Diagnostic projection only; this is not a new lifecycle state and does not weaken or broaden grounded-to-act. Route authorization is not treated as whole-program understanding.'
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function sourceScopeState(sourceEvidence = {}) {
|
|
28
|
+
const workspaces = sourceEvidence?.workspaces || [];
|
|
29
|
+
const qualified = workspaces.filter((item) => ['qualified', 'explicit-profile'].includes(String(item.state || '')));
|
|
30
|
+
if (qualified.length > 1 && qualified.every((item) => item.sources?.length || item.repository || item.rootPath)) return 'explicit-multi-source';
|
|
31
|
+
if (qualified.length) return 'bounded-current-route';
|
|
32
|
+
return 'unresolved';
|
|
33
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const MAX_PARTICIPANTS = 8;
|
|
2
|
+
const MAX_ROLES = 8;
|
|
3
|
+
|
|
4
|
+
export function projectGroundingParticipantContext(authority = null) {
|
|
5
|
+
const participation = authority?.participation || {};
|
|
6
|
+
const semanticParticipants = (participation.participants || []).slice(0, MAX_PARTICIPANTS).map((item) => Object.freeze({
|
|
7
|
+
id: String(item.id || ''),
|
|
8
|
+
label: String(item.label || ''),
|
|
9
|
+
roles: Object.freeze([...(item.roles || [])].map(String)),
|
|
10
|
+
verification: String(item.verification || 'declared'),
|
|
11
|
+
semanticParticipant: true,
|
|
12
|
+
basis: 'explicit-participant-declaration',
|
|
13
|
+
provenance: Object.freeze({
|
|
14
|
+
basis: 'explicit-qualified-participation-input',
|
|
15
|
+
source: String(item.source || item.provenance?.source || ''),
|
|
16
|
+
boundary: 'Only explicit semantic participant authority is projected as participation.'
|
|
17
|
+
})
|
|
18
|
+
}));
|
|
19
|
+
const roleGrounding = (participation.packageRoleGrounding || participation.packageRoleParticipants || []).slice(0, MAX_ROLES).map((item) => Object.freeze({
|
|
20
|
+
label: String(item.label || item.roleArtifact?.roleLabel || ''),
|
|
21
|
+
pointerPath: String(item.pointerPath || ''),
|
|
22
|
+
roleArtifact: Object.freeze({ ...(item.roleArtifact || {}) }),
|
|
23
|
+
groundingOnly: true,
|
|
24
|
+
semanticParticipant: false,
|
|
25
|
+
basis: 'explicit-package-role-grounding-pointer',
|
|
26
|
+
provenance: Object.freeze({
|
|
27
|
+
basis: 'package-role-grounding-pointer',
|
|
28
|
+
pointerPath: String(item.pointerPath || ''),
|
|
29
|
+
boundary: 'This proves only package-local Role grounding availability, not semantic participation.'
|
|
30
|
+
})
|
|
31
|
+
}));
|
|
32
|
+
const endpoints = (participation.handoffCapacities || []).slice(0, 2).map((item) => Object.freeze({
|
|
33
|
+
direction: String(item.direction || ''),
|
|
34
|
+
label: String(item.label || ''),
|
|
35
|
+
kind: String(item.kind || ''),
|
|
36
|
+
semanticClass: 'handoff-capacity',
|
|
37
|
+
semanticParticipant: false,
|
|
38
|
+
provenance: Object.freeze({
|
|
39
|
+
basis: 'selected-handoff-endpoint',
|
|
40
|
+
boundary: 'Handoff endpoint capacity is not a participant declaration.'
|
|
41
|
+
})
|
|
42
|
+
}));
|
|
43
|
+
const mapState = semanticParticipants.length ? 'explicit-bounded-map' : 'not-established';
|
|
44
|
+
return Object.freeze({
|
|
45
|
+
state: semanticParticipants.length ? 'explicit-semantic-participants' : roleGrounding.length ? 'qualified-role-grounding-only' : 'unresolved',
|
|
46
|
+
participantMapState: mapState,
|
|
47
|
+
semanticParticipants: Object.freeze(semanticParticipants),
|
|
48
|
+
roleGrounding: Object.freeze(roleGrounding),
|
|
49
|
+
endpoints: Object.freeze(endpoints),
|
|
50
|
+
unresolved: Object.freeze(semanticParticipants.length ? [] : [{
|
|
51
|
+
code: 'participant-map-not-established',
|
|
52
|
+
detail: 'No explicit semantic participant declaration or authoritative participant Relation is present in the current grounding input. Carried Role pointers remain grounding-only.',
|
|
53
|
+
basis: 'absence-of-explicit-semantic-participant-authority',
|
|
54
|
+
nextAuthorityNeeded: 'Provide an explicit qualified participant declaration/projection from semantic authority; do not infer it from Roles or Handoff endpoints.'
|
|
55
|
+
}]),
|
|
56
|
+
boundary: 'Only explicit semantic participant declarations count as participants here. Package Role grounding pointers and Handoff endpoints are projected separately and never infer participation, holder identity, delegation, or relevance from Role inventory, filenames, transport, chat position, or package adjacency.'
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const MAX_FACTS = 12;
|
|
2
|
+
|
|
3
|
+
export function projectGroundingProcessApplicability(authority = null) {
|
|
4
|
+
const supplied = authority?.processApplicability || null;
|
|
5
|
+
const explicitlyQualified = Boolean(
|
|
6
|
+
supplied
|
|
7
|
+
&& supplied.explicit === true
|
|
8
|
+
&& String(supplied.qualification || supplied.state || '') === 'qualified'
|
|
9
|
+
);
|
|
10
|
+
if (!explicitlyQualified) return Object.freeze({
|
|
11
|
+
state: 'not-established',
|
|
12
|
+
facts: Object.freeze([]),
|
|
13
|
+
provenance: Object.freeze({
|
|
14
|
+
basis: 'no-upstream-qualified-explicit-process-applicability-projection',
|
|
15
|
+
source: '',
|
|
16
|
+
boundary: 'Core does not discover process inventory or define the semantic declaration pattern. It consumes only an upstream projection already marked explicit and qualified by semantic authority.'
|
|
17
|
+
}),
|
|
18
|
+
unresolved: Object.freeze([Object.freeze({
|
|
19
|
+
code: 'process-applicability-semantic-authority-not-established',
|
|
20
|
+
detail: 'Current qualified grounding authority contains no explicit, upstream-qualified process-applicability projection. Supply semantic-owner-qualified applicability authority; do not infer applicability from carried Roles, Handoff endpoints, filenames, folders, process inventory, or repository adjacency.'
|
|
21
|
+
})]),
|
|
22
|
+
boundary: 'Semantics-neutral pass-through only. Absence stays unresolved; carriage and inventory never become applicability.'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const facts = Array.isArray(supplied.facts) ? supplied.facts : Array.isArray(supplied.items) ? supplied.items : [];
|
|
26
|
+
return Object.freeze({
|
|
27
|
+
state: 'explicit-qualified-authority',
|
|
28
|
+
facts: Object.freeze(facts.slice(0, MAX_FACTS).map((item) => Object.freeze({ ...(item || {}) }))),
|
|
29
|
+
provenance: Object.freeze({
|
|
30
|
+
basis: 'upstream-qualified-explicit-process-applicability-projection',
|
|
31
|
+
source: String(supplied.source || supplied.provenance?.source || ''),
|
|
32
|
+
upstreamProvenance: supplied.provenance ? Object.freeze({ ...(supplied.provenance || {}) }) : null,
|
|
33
|
+
boundary: 'Facts are passed through without Core interpreting process inventory or inventing process-to-participant semantics.'
|
|
34
|
+
}),
|
|
35
|
+
unresolved: Object.freeze([]),
|
|
36
|
+
boundary: 'Semantics-neutral pass-through only. Core does not define or expand the declaration pattern that established these facts.'
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
export function projectGroundingAuthority(authority, mode) {
|
|
2
2
|
if (!authority || mode !== 'routed-handoff-package') return Object.freeze({ state: 'not-supplied', route: null, handoff: null, role: null, holderBinding: null, operationBoundary: null });
|
|
3
3
|
const mutationBoundary = authority.mutationBoundary || null;
|
|
4
|
+
const selectedRoute = authority.selectedRoute || null;
|
|
5
|
+
const handoff = authority.handoff || null;
|
|
4
6
|
return Object.freeze({
|
|
5
7
|
state: String(authority.status || ''),
|
|
6
|
-
route:
|
|
7
|
-
|
|
8
|
+
route: selectedRoute ? Object.freeze({
|
|
9
|
+
id: selectedRoute.id || '',
|
|
10
|
+
pointerPath: selectedRoute.pointerPath || '',
|
|
11
|
+
workspaceId: selectedRoute.workspaceId || '',
|
|
12
|
+
workspaceRelativePath: selectedRoute.workspaceRelativeHandoffPath || selectedRoute.workspaceRelativePath || '',
|
|
13
|
+
sha256: selectedRoute.sha256 || '',
|
|
14
|
+
provenance: Object.freeze({
|
|
15
|
+
basis: 'explicit-qualified-route-selection',
|
|
16
|
+
pointerPath: selectedRoute.pointerPath || '',
|
|
17
|
+
workspaceId: selectedRoute.workspaceId || '',
|
|
18
|
+
workspaceRelativePath: selectedRoute.workspaceRelativeHandoffPath || selectedRoute.workspaceRelativePath || '',
|
|
19
|
+
boundary: 'Route authority is bounded to the exact qualified selected route; nearby package routes and filenames are not substituted.'
|
|
20
|
+
})
|
|
21
|
+
}) : null,
|
|
22
|
+
handoff: handoff ? Object.freeze({
|
|
23
|
+
purpose: handoff.purpose || '',
|
|
24
|
+
from: handoff.from || '',
|
|
25
|
+
to: handoff.to || '',
|
|
26
|
+
transfers: Object.freeze((handoff.transfers || []).map((item) => Object.freeze({ ...item }))),
|
|
27
|
+
completionExpectation: handoff.completionExpectation || null,
|
|
28
|
+
provenance: Object.freeze({
|
|
29
|
+
basis: 'exact-selected-handoff-bytes',
|
|
30
|
+
routeId: handoff.routeId || selectedRoute?.id || '',
|
|
31
|
+
workspaceId: handoff.workspaceId || selectedRoute?.workspaceId || '',
|
|
32
|
+
workspaceRelativePath: handoff.workspaceRelativePath || selectedRoute?.workspaceRelativeHandoffPath || '',
|
|
33
|
+
packagePath: handoff.packagePath || selectedRoute?.packagePath || '',
|
|
34
|
+
sha256: handoff.sha256 || selectedRoute?.sha256 || '',
|
|
35
|
+
boundary: handoff.boundary || 'Exact selected Handoff bytes are semantic authority for Handoff parties, purpose, transfers and completion expectation.'
|
|
36
|
+
})
|
|
37
|
+
}) : null,
|
|
8
38
|
role: authority.role ? Object.freeze({ state: authority.role.state || '', label: authority.role.endpoint?.label || '', kind: authority.role.endpoint?.kind || '' }) : null,
|
|
9
|
-
holderBinding: authority.holderBinding ? Object.freeze({
|
|
39
|
+
holderBinding: authority.holderBinding ? Object.freeze({
|
|
40
|
+
state: authority.holderBinding.state || '',
|
|
41
|
+
holderId: authority.holderBinding.holderId || '',
|
|
42
|
+
roleLabel: authority.holderBinding.roleLabel || '',
|
|
43
|
+
recipientRoleLabel: authority.holderBinding.recipientRoleLabel || '',
|
|
44
|
+
recipientCompatibility: authority.holderBinding.recipientCompatibility || '',
|
|
45
|
+
source: authority.holderBinding.source || '',
|
|
46
|
+
explicit: Boolean(authority.holderBinding.explicit),
|
|
47
|
+
inferredFromTransport: Boolean(authority.holderBinding.inferredFromTransport),
|
|
48
|
+
provenance: Object.freeze({
|
|
49
|
+
basis: authority.holderBinding.explicit ? 'explicit-consuming-session-holder-binding' : 'unresolved-or-non-explicit-holder-binding',
|
|
50
|
+
source: authority.holderBinding.source || '',
|
|
51
|
+
boundary: authority.holderBinding.boundary || 'Consuming-session holder identity is never inferred from route transport or recipient position.'
|
|
52
|
+
}),
|
|
53
|
+
boundary: authority.holderBinding.boundary || ''
|
|
54
|
+
}) : null,
|
|
10
55
|
operationBoundary: mutationBoundary ? Object.freeze({
|
|
11
56
|
...mutationBoundary,
|
|
12
57
|
scope: 'current-grounding-operation-only',
|
|
@@ -9,6 +9,7 @@ import { auditHandoffPackageContextCarriage } from '../handoff/contextAudit.js';
|
|
|
9
9
|
import { acceptedRecoveryMaterial, projectColdStartContinuity } from './grounding.continuity.js';
|
|
10
10
|
import { projectGroundingAuthority } from './grounding.readiness.authority.js';
|
|
11
11
|
import { projectGroundingCapsule } from './grounding.capsule.js';
|
|
12
|
+
import { projectGroundingOrchestrationReadiness } from './grounding.orchestrationReadiness.js';
|
|
12
13
|
|
|
13
14
|
export const PORTABLE_GROUNDING_READINESS_SCHEMA_ID = 'tiinex.portable.grounding-readiness.v1';
|
|
14
15
|
|
|
@@ -190,6 +191,7 @@ export function composeGroundingReadiness({ mode = 'loaded-material', authority
|
|
|
190
191
|
if (missingEvidence.length) state = 'insufficient-grounding';
|
|
191
192
|
else if (!handoffMode || !holderBindingActReady || !topology.currentFrontier.length || humanOnly.length) state = 'grounded-to-discuss';
|
|
192
193
|
if (state === 'grounded-to-act') reasons.push(reason('bounded-act-ready', 'Selected Handoff authority, explicit consuming-session holder Role binding, Required Context, carried Workspace coverage, cold-start continuity to a qualified semantic root, the selected-route Parent-lineage leaf, and declared current-work frontier evidence are all resolved enough for the next bounded action.'));
|
|
194
|
+
const orchestrationReadiness = projectGroundingOrchestrationReadiness({ readinessState: state, participantContext: capsule.participantContext, processApplicability: capsule.processApplicability, sourceEvidence: capsule.sourceEvidence, topology });
|
|
193
195
|
|
|
194
196
|
return Object.freeze({
|
|
195
197
|
schema: PORTABLE_GROUNDING_READINESS_SCHEMA_ID,
|
|
@@ -240,6 +242,7 @@ export function composeGroundingReadiness({ mode = 'loaded-material', authority
|
|
|
240
242
|
boundary: 'Leaf/root roles are derived only from loaded declared Parent edges produced by the shared lineage resolver. Filename numbering, carrier dimensions, directory depth, branch names, and Task lifecycle labels are never substituted for Parent topology.'
|
|
241
243
|
}),
|
|
242
244
|
continuity,
|
|
245
|
+
orchestrationReadiness,
|
|
243
246
|
capsule,
|
|
244
247
|
currentWork: Object.freeze({
|
|
245
248
|
state: topology.currentFrontier.length ? 'current-frontier-resolved' : topology.currentTasks.length ? 'current-candidates-without-frontier' : 'unresolved',
|
|
@@ -122,12 +122,16 @@ export function projectRequiredContext(requiredContext = [], selectors = []) {
|
|
|
122
122
|
return Object.freeze({
|
|
123
123
|
requirementId: entry.requirementId || '',
|
|
124
124
|
name: entry.name || '',
|
|
125
|
+
material: entry.material || '',
|
|
126
|
+
purpose: entry.purpose || '',
|
|
127
|
+
declaredAvailability: entry.declaredAvailability || '',
|
|
125
128
|
state: entry.state || '',
|
|
126
129
|
workspaceId: entry.workspaceId || '',
|
|
127
130
|
innerPath: entry.innerPath || entry.workspaceRelativePath || '',
|
|
128
131
|
referenceTarget: entry.referenceTarget || '',
|
|
129
132
|
bytes: Number(entry.bytes || entry.actualBytes || 0),
|
|
130
133
|
sha256: entry.sha256 || entry.actualSha256 || '',
|
|
134
|
+
provenance: entry.provenance ? Object.freeze({ ...entry.provenance }) : null,
|
|
131
135
|
contentProjected,
|
|
132
136
|
...(contentProjected ? { content: entry.content } : {})
|
|
133
137
|
});
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { parseWorkspaceEntrypoints } from '../handoff/workspaceSourceIdentity.js';
|
|
2
2
|
const MAX_WORKSPACES = 8;
|
|
3
3
|
const MAX_SOURCES = 8;
|
|
4
|
+
const MAX_MATERIALS = 12;
|
|
5
|
+
const MAX_BLOCKERS = 8;
|
|
4
6
|
|
|
5
|
-
export function projectGroundingSourceEvidence({ records = [], contextAudit = null, continuation = null, sourceProfiles = [] } = {}) {
|
|
7
|
+
export function projectGroundingSourceEvidence({ records = [], contextAudit = null, continuation = null, requiredContext = [], sourceProfiles = [] } = {}) {
|
|
6
8
|
const byPath = new Map((records || []).map((record) => [String(record.path || ''), record]));
|
|
7
9
|
const profiles = profileIndex(sourceProfiles);
|
|
10
|
+
const coverageByWorkspace = new Map();
|
|
8
11
|
const workspaces = (contextAudit?.workspaceMaterializations || []).slice(0, MAX_WORKSPACES).map((workspace) => {
|
|
9
12
|
const workspaceId = String(workspace.workspaceId || '');
|
|
13
|
+
const coverage = normalizeCoverage(workspace);
|
|
14
|
+
if (workspaceId) coverageByWorkspace.set(workspaceId, coverage);
|
|
10
15
|
const innerPath = normalizePath(workspace.sourceWorkspaceTargetInnerPath || '');
|
|
11
16
|
const exactPath = workspaceId && innerPath ? `${workspaceId}/${innerPath}` : '';
|
|
12
17
|
const record = exactPath ? byPath.get(exactPath) : null;
|
|
@@ -21,10 +26,21 @@ export function projectGroundingSourceEvidence({ records = [], contextAudit = nu
|
|
|
21
26
|
&& record.hasContinuityContext
|
|
22
27
|
&& record.hasIntegrity
|
|
23
28
|
);
|
|
24
|
-
if (!qualifiedArtifact && !explicitProfile.length) return Object.freeze({
|
|
29
|
+
if (!qualifiedArtifact && !explicitProfile.length) return Object.freeze({
|
|
30
|
+
workspace: workspaceId,
|
|
31
|
+
state: 'unresolved',
|
|
32
|
+
coverage,
|
|
33
|
+
carrier: String(workspace.reason || ''),
|
|
34
|
+
provenance: Object.freeze({
|
|
35
|
+
basis: 'carried-workspace-materialization-without-qualified-source-declaration',
|
|
36
|
+
sourceArtifactPath: exactPath,
|
|
37
|
+
boundary: 'Workspace carriage alone does not establish repository/source identity.'
|
|
38
|
+
})
|
|
39
|
+
});
|
|
25
40
|
return Object.freeze({
|
|
26
41
|
workspace: workspaceId,
|
|
27
42
|
state: qualifiedArtifact ? 'qualified' : 'explicit-profile',
|
|
43
|
+
coverage,
|
|
28
44
|
carrier: String(workspace.reason || 'qualified-workspace-snapshot'),
|
|
29
45
|
sourceArtifactPath: exactPath,
|
|
30
46
|
sourceArtifactSha256: String(workspace.sourceWorkspaceTargetSha256 || ''),
|
|
@@ -32,20 +48,150 @@ export function projectGroundingSourceEvidence({ records = [], contextAudit = nu
|
|
|
32
48
|
ref: String(unique?.ref || ''),
|
|
33
49
|
rootPath: String(unique?.rootPath || ''),
|
|
34
50
|
remoteState: String(unique?.remoteState || 'not-checked'),
|
|
35
|
-
sources: Object.freeze(sources.slice(0, MAX_SOURCES))
|
|
51
|
+
sources: Object.freeze(sources.slice(0, MAX_SOURCES)),
|
|
52
|
+
provenance: Object.freeze({
|
|
53
|
+
basis: qualifiedArtifact ? 'exact-qualified-workspace-source-artifact' : 'explicit-source-profile',
|
|
54
|
+
sourceArtifactPath: exactPath,
|
|
55
|
+
sourceArtifactSha256: String(workspace.sourceWorkspaceTargetSha256 || ''),
|
|
56
|
+
coverageBasis: String(workspace.reason || ''),
|
|
57
|
+
boundary: qualifiedArtifact
|
|
58
|
+
? 'Source identity is projected only from the exact qualified Workspace artifact carried for this Workspace.'
|
|
59
|
+
: 'Source identity is projected only from an explicitly supplied source profile; no repository discovery is implied.'
|
|
60
|
+
})
|
|
36
61
|
});
|
|
37
62
|
});
|
|
63
|
+
|
|
64
|
+
const requirements = (requiredContext || []).slice(0, MAX_MATERIALS).map((entry) => projectRequirement(entry, coverageByWorkspace));
|
|
65
|
+
const unavailable = requirements.filter((entry) => entry.availability === 'unavailable');
|
|
66
|
+
const blockers = unavailable.slice(0, MAX_BLOCKERS).map((entry) => Object.freeze({
|
|
67
|
+
code: 'authoritative-material-unavailable',
|
|
68
|
+
requirementId: entry.requirementId,
|
|
69
|
+
name: entry.name,
|
|
70
|
+
requiredMaterial: Object.freeze({
|
|
71
|
+
material: entry.material,
|
|
72
|
+
referenceTarget: entry.referenceTarget,
|
|
73
|
+
workspace: entry.workspace,
|
|
74
|
+
path: entry.path
|
|
75
|
+
}),
|
|
76
|
+
owner: Object.freeze({
|
|
77
|
+
kind: 'selected-handoff-required-context',
|
|
78
|
+
requirementId: entry.requirementId,
|
|
79
|
+
name: entry.name,
|
|
80
|
+
purpose: entry.purpose
|
|
81
|
+
}),
|
|
82
|
+
basis: Object.freeze({
|
|
83
|
+
state: entry.state,
|
|
84
|
+
availability: entry.availability,
|
|
85
|
+
materialClass: entry.materialClass,
|
|
86
|
+
workspaceCoverage: entry.workspaceCoverage,
|
|
87
|
+
providerMode: entry.providerMode,
|
|
88
|
+
kind: entry.kind,
|
|
89
|
+
provenance: entry.provenance
|
|
90
|
+
}),
|
|
91
|
+
blockingReason: 'The exact declared Required Context material is not qualified in current carried/explicit material, so Tooling cannot claim that authority is available.',
|
|
92
|
+
workspace: entry.workspace,
|
|
93
|
+
path: entry.path,
|
|
94
|
+
referenceTarget: entry.referenceTarget,
|
|
95
|
+
request: exactMaterialRequest(entry)
|
|
96
|
+
}));
|
|
97
|
+
const boundedOrCache = requirements.filter((entry) => entry.availability === 'qualified' && ['bounded-workspace', 'cache'].includes(entry.materialClass));
|
|
98
|
+
const contextMaterials = [
|
|
99
|
+
...(contextAudit?.materialCarriers || []).map((item) => projectAuditMaterial(item, 'requirement-material')),
|
|
100
|
+
...(contextAudit?.explicitDetachedMaterial || []).map((item) => projectAuditMaterial(item, 'bounded-or-cache-material')),
|
|
101
|
+
...(contextAudit?.lineageMaterializations || []).map((item) => projectAuditMaterial(item, 'lineage-cache-material'))
|
|
102
|
+
].slice(0, MAX_MATERIALS);
|
|
103
|
+
|
|
38
104
|
return Object.freeze({
|
|
39
105
|
carrier: Object.freeze({
|
|
40
106
|
state: String(contextAudit?.coverage?.state || contextAudit?.status || 'unresolved'),
|
|
41
107
|
workspaceCount: Number(contextAudit?.workspaceMaterializations?.length || 0),
|
|
42
|
-
packageSourcePath: String(continuation?.packageSourcePath || '')
|
|
108
|
+
packageSourcePath: String(continuation?.packageSourcePath || ''),
|
|
109
|
+
completeWorkspaceCount: workspaces.filter((item) => item.coverage === 'complete').length,
|
|
110
|
+
boundedWorkspaceCount: workspaces.filter((item) => item.coverage === 'bounded').length
|
|
43
111
|
}),
|
|
44
112
|
workspaces: Object.freeze(workspaces),
|
|
45
|
-
|
|
113
|
+
requirements: Object.freeze(requirements),
|
|
114
|
+
boundedOrCache: Object.freeze(boundedOrCache),
|
|
115
|
+
carriedMaterial: Object.freeze(contextMaterials),
|
|
116
|
+
blockers: Object.freeze(blockers),
|
|
117
|
+
boundary: 'Exact selected Workspace/source declarations and exact qualified Required Context material only. Complete Workspace carriage, bounded Workspace/cache material, explicit requirements, and unavailable authoritative material remain distinct. Missing material never authorizes repository, connector, or network discovery.'
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function projectRequirement(entry = {}, coverageByWorkspace = new Map()) {
|
|
122
|
+
const state = String(entry.state || 'unresolved');
|
|
123
|
+
const providerMode = String(entry.providerMode || '');
|
|
124
|
+
const workspace = String(entry.workspaceId || '');
|
|
125
|
+
const workspaceCoverage = coverageByWorkspace.get(workspace) || 'unresolved';
|
|
126
|
+
let materialClass = 'explicit-requirement';
|
|
127
|
+
if (state === 'qualified') {
|
|
128
|
+
if (providerMode === 'cache' || String(entry.kind || '') === 'workspace-cache-entry') materialClass = 'cache';
|
|
129
|
+
else if (providerMode === 'archive' && workspaceCoverage === 'bounded') materialClass = 'bounded-workspace';
|
|
130
|
+
else if (providerMode === 'archive' && workspaceCoverage === 'complete') materialClass = 'complete-workspace';
|
|
131
|
+
else if (providerMode === 'archive') materialClass = 'workspace-material';
|
|
132
|
+
else materialClass = 'qualified-material';
|
|
133
|
+
}
|
|
134
|
+
return Object.freeze({
|
|
135
|
+
requirementId: String(entry.requirementId || ''),
|
|
136
|
+
name: String(entry.name || ''),
|
|
137
|
+
material: String(entry.material || ''),
|
|
138
|
+
purpose: String(entry.purpose || ''),
|
|
139
|
+
declaredAvailability: String(entry.declaredAvailability || ''),
|
|
140
|
+
state,
|
|
141
|
+
availability: state === 'qualified' ? 'qualified' : 'unavailable',
|
|
142
|
+
materialClass,
|
|
143
|
+
workspace,
|
|
144
|
+
workspaceCoverage,
|
|
145
|
+
path: String(entry.innerPath || entry.workspaceRelativePath || ''),
|
|
146
|
+
packagePath: String(entry.packagePath || entry.archivePackagePath || ''),
|
|
147
|
+
providerMode,
|
|
148
|
+
kind: String(entry.kind || ''),
|
|
149
|
+
referenceTarget: String(entry.referenceTarget || ''),
|
|
150
|
+
bytes: Number(entry.bytes || 0),
|
|
151
|
+
sha256: String(entry.sha256 || ''),
|
|
152
|
+
provenance: Object.freeze({
|
|
153
|
+
basis: String(entry.provenance?.basis || 'selected-handoff-required-context-and-route-closure'),
|
|
154
|
+
declarationSource: entry.provenance?.declarationSource ? Object.freeze({ ...(entry.provenance.declarationSource || {}) }) : null,
|
|
155
|
+
resolutionKind: String(entry.provenance?.resolutionKind || entry.kind || ''),
|
|
156
|
+
providerMode: String(entry.provenance?.providerMode || providerMode),
|
|
157
|
+
boundary: String(entry.provenance?.boundary || 'Requirement identity comes from the selected Handoff declaration; qualification/material class comes from exact route closure and carried source state.')
|
|
158
|
+
})
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function projectAuditMaterial(item = {}, classification = '') {
|
|
163
|
+
return Object.freeze({
|
|
164
|
+
classification,
|
|
165
|
+
requirementId: String(item.requirementId || item.requirement?.id || ''),
|
|
166
|
+
name: String(item.requirement?.name || ''),
|
|
167
|
+
workspace: String(item.workspaceId || item.targetWorkspaceId || item.selectedProvider?.workspaceId || ''),
|
|
168
|
+
path: String(item.workspaceRelativePath || item.targetPath || item.originalPath || item.selectedProvider?.workspaceRelativePath || ''),
|
|
169
|
+
packagePath: String(item.path || item.archivePackagePath || ''),
|
|
170
|
+
bytes: Number(item.bytes || item.actualBytes || 0),
|
|
171
|
+
sha256: String(item.sha256 || item.actualSha256 || ''),
|
|
172
|
+
authority: Object.freeze({ ...(item.authority || {}) }),
|
|
173
|
+
provenance: Object.freeze({
|
|
174
|
+
basis: classification,
|
|
175
|
+
carrierPath: String(item.path || item.archivePackagePath || ''),
|
|
176
|
+
boundary: 'Diagnostic carriage evidence only; presence does not create semantic authority beyond the requirement/material it exactly resolves.'
|
|
177
|
+
})
|
|
46
178
|
});
|
|
47
179
|
}
|
|
48
180
|
|
|
181
|
+
function exactMaterialRequest(entry = {}) {
|
|
182
|
+
const target = entry.referenceTarget || [entry.workspace, entry.path].filter(Boolean).join('::') || entry.name || entry.requirementId || 'the declared Required Context material';
|
|
183
|
+
return `Provide exact qualified material for ${target}, or an explicitly qualified bounded Workspace/cache carrier that resolves this declared requirement. Do not substitute GitHub, a connector, a repository checkout, or network discovery without separate authority.`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function normalizeCoverage(workspace = {}) {
|
|
187
|
+
const explicit = String(workspace.coverage || '').trim().toLowerCase();
|
|
188
|
+
if (explicit === 'complete' || explicit === 'bounded') return explicit;
|
|
189
|
+
const reason = String(workspace.reason || '').toLowerCase();
|
|
190
|
+
if (reason.includes('bounded') || reason.includes('partial')) return 'bounded';
|
|
191
|
+
if (reason.includes('complete')) return 'complete';
|
|
192
|
+
return 'unresolved';
|
|
193
|
+
}
|
|
194
|
+
|
|
49
195
|
function profileIndex(value = []) {
|
|
50
196
|
const map = new Map();
|
|
51
197
|
if (!value) return map;
|
|
@@ -64,8 +210,4 @@ function profileIndex(value = []) {
|
|
|
64
210
|
}
|
|
65
211
|
function normalizeProfileList(value) { return (Array.isArray(value) ? value : [value]).filter(Boolean).map(normalizeProfile); }
|
|
66
212
|
function normalizeProfile(value = {}) { return Object.freeze({ label: String(value.label || ''), sourceKind: String(value.sourceKind || value.kind || ''), repository: String(value.repository || ''), ref: String(value.ref || ''), rootPath: String(value.rootPath || ''), remoteState: String(value.remoteState || 'not-checked'), basis: 'explicit-source-profile' }); }
|
|
67
|
-
function section(markdown = '', heading = '') { const escaped = escape(heading); return String(markdown || '').match(new RegExp(`(?:^|\\n)##\\s+${escaped}\\s*\\r?\\n([\\s\\S]*?)(?=\\n##\\s+|\\n#\\s+Continuity Integrity|$)`, 'i'))?.[1]?.trim() || ''; }
|
|
68
|
-
function field(markdown = '', label = '') { const escaped = escape(label); return strip(String(markdown || '').match(new RegExp(`^\\s*-\\s+${escaped}:\\s*(.+)$`, 'mi'))?.[1] || ''); }
|
|
69
213
|
function normalizePath(value = '') { return String(value || '').replace(/\\/g, '/').replace(/^\/+/, ''); }
|
|
70
|
-
function strip(value = '') { return String(value || '').replace(/^\[([^\]]+)\]\([^)]+\)$/, '$1').replace(/[`*_]/g, '').trim(); }
|
|
71
|
-
function escape(value = '') { return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
|
|
@@ -76,7 +76,18 @@ function qualifyRequiredRequirement(bundle, descriptor, byteProvider, workspace,
|
|
|
76
76
|
if (!resolution&&!reasons.length) resolution=resolveDescriptorMaterial(bundle,descriptor,byteProvider,target,requirementId,workspace.id,routePath);
|
|
77
77
|
if (!resolution&&!reasons.length) reasons.push('required-material-not-carried');
|
|
78
78
|
if (resolution?.state!=='qualified'&&resolution?.reason) reasons.push(resolution.reason);
|
|
79
|
-
return deepFreeze({
|
|
79
|
+
return deepFreeze({
|
|
80
|
+
requirementId:String(requirement.id||''),
|
|
81
|
+
name:String(requirement.name||''),
|
|
82
|
+
material:String(requirement.material||''),
|
|
83
|
+
purpose:String(requirement.purpose||''),
|
|
84
|
+
declaredAvailability:String(requirement.availability||''),
|
|
85
|
+
referenceTarget:target,
|
|
86
|
+
declarationSource:requirement.source||null,
|
|
87
|
+
state:!reasons.length&&resolution?.state==='qualified'?'qualified':'blocked',
|
|
88
|
+
resolution:resolution?.state==='qualified'?resolution:null,
|
|
89
|
+
reasons:Object.freeze([...new Set(reasons)])
|
|
90
|
+
});
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
function resolveWorkspaceRequiredMaterial(byteProvider, workspace, resolvedPath) {
|
|
@@ -232,6 +232,9 @@ function hydrateRequiredContextEntry(bundle = {}, entry = {}, context = null) {
|
|
|
232
232
|
const base = {
|
|
233
233
|
requirementId: String(entry.requirementId || ''),
|
|
234
234
|
name: String(entry.name || ''),
|
|
235
|
+
material: String(entry.material || ''),
|
|
236
|
+
purpose: String(entry.purpose || ''),
|
|
237
|
+
declaredAvailability: String(entry.declaredAvailability || ''),
|
|
235
238
|
state: String(entry.state || resolution.state || 'unresolved'),
|
|
236
239
|
referenceTarget: String(entry.referenceTarget || ''),
|
|
237
240
|
kind: String(resolution.kind || ''),
|
|
@@ -241,7 +244,14 @@ function hydrateRequiredContextEntry(bundle = {}, entry = {}, context = null) {
|
|
|
241
244
|
packagePath: String(resolution.packagePath || ''),
|
|
242
245
|
providerMode: String(resolution.providerMode || ''),
|
|
243
246
|
bytes: Number(resolution.bytes || 0),
|
|
244
|
-
sha256: String(resolution.sha256 || '')
|
|
247
|
+
sha256: String(resolution.sha256 || ''),
|
|
248
|
+
provenance: Object.freeze({
|
|
249
|
+
basis: 'selected-handoff-required-context-declaration',
|
|
250
|
+
declarationSource: entry.declarationSource ? Object.freeze({ ...(entry.declarationSource || {}) }) : null,
|
|
251
|
+
resolutionKind: String(resolution.kind || ''),
|
|
252
|
+
providerMode: String(resolution.providerMode || ''),
|
|
253
|
+
boundary: 'Material/Purpose/Availability are copied from the exact selected Handoff Required Context declaration; qualification and bytes come from exact route closure resolution.'
|
|
254
|
+
})
|
|
245
255
|
};
|
|
246
256
|
if (base.state !== 'qualified') return Object.freeze({ ...base, contentState: 'unavailable', content: '' });
|
|
247
257
|
const hydrated = resolveQualifiedMaterialBytes(bundle, resolution, context);
|
|
@@ -184,7 +184,7 @@ function auditRecipientV2(bundle = {}) {
|
|
|
184
184
|
sha256: String(material.sha256 || '')
|
|
185
185
|
})))
|
|
186
186
|
: [];
|
|
187
|
-
return deepFreeze({ schema: PORTABLE_HANDOFF_CONTEXT_AUDIT_SCHEMA_ID, status: inspection.status === 'valid' && !unexplained ? 'ready' : 'blocked', coverage: Object.freeze({ nonControlCarrierCount: files.length, classifiedCarrierCount: classified, unexplainedCarrierCount: unexplained, state: unexplained ? 'incomplete' : 'qualified' }), workspaceMaterializations: Object.freeze((inspection.workspaces || []).map((item) => Object.freeze({ workspaceId: item.workspaceId, reason: 'complete-workspace-archive-representation', qualification: 'qualified', carrierMode: 'archive', workspaceTargetPackagePath: item.workspaceArtifactPath, archivePackagePath: item.workspaceArchivePath, sourceWorkspaceTargetInnerPath: item.sourceWorkspaceTargetInnerPath, sourceWorkspaceTargetSha256: item.sourceWorkspaceTargetSha256 }))), lineageMaterializations: Object.freeze(lineageMaterializations), materialCarriers: Object.freeze([]), generatedEntrypoints: Object.freeze([String(inspection.rootArtifact?.path || ''), RECIPIENT_V2_READ_PATH, ...(inspection.endpointRoles || []).map((item) => item.pointerPath), ...(inspection.participantRoles || []).map((item) => item.pointerPath), ...(inspection.routes || []).map((item) => item.pointerPath)].filter(Boolean)), namedPackageRequirements: Object.freeze([]), explicitDetachedMaterial: Object.freeze(cacheMaterials), unexplainedCarriers: Object.freeze([]), duplicateByteSummary: Object.freeze({ materialCarriersAlsoPresentInWorkspace: 0, totalMaterialCarriers: cacheMaterials.length, interpretation: 'Exact Workspace-scoped recipient cache material is permitted only when not satisfied by a qualified Workspace archive.' }), routeGrounding: Object.freeze((inspection.carrierProjection?.routes || []).map((route) => Object.freeze({ routeId: route.id, workspaceId: route.workspaceId, handoffPackagePath: route.packagePath, required: route.requiredClosure?.requirements || [] }))), inspections: Object.freeze({ recipientV2: inspection.status, parentBoundaryGrounding: parentBoundaryGroundingEligible ? 'qualified-package-v1' : 'not-projected' }), findings: Object.freeze(dedupeFindings(findings)), boundary: 'Recipient-facing v2 carriage audit over qualified visible Tiinex artifacts and exact payload bytes. Complete Workspace snapshots and independently qualified package-v1 detached Parent-boundary lineage are projected separately; detached lineage never implies whole-Workspace carriage or membership.' });
|
|
187
|
+
return deepFreeze({ schema: PORTABLE_HANDOFF_CONTEXT_AUDIT_SCHEMA_ID, status: inspection.status === 'valid' && !unexplained ? 'ready' : 'blocked', coverage: Object.freeze({ nonControlCarrierCount: files.length, classifiedCarrierCount: classified, unexplainedCarrierCount: unexplained, state: unexplained ? 'incomplete' : 'qualified' }), workspaceMaterializations: Object.freeze((inspection.workspaces || []).map((item) => Object.freeze({ workspaceId: item.workspaceId, coverage: String(item.coverage || 'unresolved'), reason: String(item.coverage || '') === 'complete' ? 'complete-workspace-archive-representation' : String(item.coverage || '') === 'bounded' ? 'bounded-workspace-archive-representation' : 'workspace-archive-representation', qualification: 'qualified', carrierMode: 'archive', workspaceTargetPackagePath: item.workspaceArtifactPath, archivePackagePath: item.workspaceArchivePath, sourceWorkspaceTargetInnerPath: item.sourceWorkspaceTargetInnerPath, sourceWorkspaceTargetSha256: item.sourceWorkspaceTargetSha256 }))), lineageMaterializations: Object.freeze(lineageMaterializations), materialCarriers: Object.freeze([]), generatedEntrypoints: Object.freeze([String(inspection.rootArtifact?.path || ''), RECIPIENT_V2_READ_PATH, ...(inspection.endpointRoles || []).map((item) => item.pointerPath), ...(inspection.participantRoles || []).map((item) => item.pointerPath), ...(inspection.routes || []).map((item) => item.pointerPath)].filter(Boolean)), namedPackageRequirements: Object.freeze([]), explicitDetachedMaterial: Object.freeze(cacheMaterials), unexplainedCarriers: Object.freeze([]), duplicateByteSummary: Object.freeze({ materialCarriersAlsoPresentInWorkspace: 0, totalMaterialCarriers: cacheMaterials.length, interpretation: 'Exact Workspace-scoped recipient cache material is permitted only when not satisfied by a qualified Workspace archive.' }), routeGrounding: Object.freeze((inspection.carrierProjection?.routes || []).map((route) => Object.freeze({ routeId: route.id, workspaceId: route.workspaceId, handoffPackagePath: route.packagePath, required: route.requiredClosure?.requirements || [] }))), inspections: Object.freeze({ recipientV2: inspection.status, parentBoundaryGrounding: parentBoundaryGroundingEligible ? 'qualified-package-v1' : 'not-projected' }), findings: Object.freeze(dedupeFindings(findings)), boundary: 'Recipient-facing v2 carriage audit over qualified visible Tiinex artifacts and exact payload bytes. Complete Workspace snapshots and independently qualified package-v1 detached Parent-boundary lineage are projected separately; detached lineage never implies whole-Workspace carriage or membership.' });
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
function indexWorkspaceEntries(workspaces = []) {
|
|
@@ -8,8 +8,8 @@ export function auditPortableRecoveryAcceptance(input = {}) {
|
|
|
8
8
|
const basisInspection = inspectRecipientFacingV2Topology(input.basis?.bundle || input.basis || {});
|
|
9
9
|
const candidateInspection = inspectRecipientFacingV2Topology(input.candidate?.bundle || input.candidate || {});
|
|
10
10
|
const findings = [];
|
|
11
|
-
if (String(basisInspection.status || '') !== 'valid') findings.push(finding('error', 'portable.recovery-acceptance.basis-unqualified', 'Recovery acceptance audit requires one independently qualified accepted-basis Handoff
|
|
12
|
-
if (String(candidateInspection.status || '') !== 'valid') findings.push(finding('error', 'portable.recovery-acceptance.candidate-unqualified', 'Recovery acceptance audit requires one independently qualified candidate
|
|
11
|
+
if (String(basisInspection.status || '') !== 'valid') findings.push(finding('error', 'portable.recovery-acceptance.basis-unqualified', 'Recovery acceptance audit requires one independently qualified accepted-basis recipient-facing carrier. A qualified pointerless Workspace package is permitted; Handoff routing is not required for the accepted basis.'));
|
|
12
|
+
if (String(candidateInspection.status || '') !== 'valid') findings.push(finding('error', 'portable.recovery-acceptance.candidate-unqualified', 'Recovery acceptance audit requires one independently qualified candidate recipient-facing carrier. Candidate restart suitability still requires complete selected Workspace coverage.'));
|
|
13
13
|
if (findings.some((item) => item.severity === 'error')) return auditResult('blocked', [], findings, basisInspection, candidateInspection, input);
|
|
14
14
|
|
|
15
15
|
const candidateIds = [...new Set((candidateInspection.workspaces || []).map((item) => normalizeId(item.workspaceId)).filter(Boolean))].sort();
|
|
@@ -92,7 +92,9 @@ function auditResult(status, workspaces, findings, basisInspection, candidateIns
|
|
|
92
92
|
status,
|
|
93
93
|
state: status === 'ready' && allReady ? 'acceptance-audit-ready' : 'acceptance-audit-blocked',
|
|
94
94
|
basisQualification: String(basisInspection.status || 'invalid'),
|
|
95
|
+
basisCarrierRole: String(basisInspection.packageContract?.packageRole || ''),
|
|
95
96
|
candidateQualification: String(candidateInspection.status || 'invalid'),
|
|
97
|
+
candidateCarrierRole: String(candidateInspection.packageContract?.packageRole || ''),
|
|
96
98
|
selectionMode: (input.workspaceIds || input.selectedWorkspaceIds || []).length ? 'explicit-workspace-set' : 'all-candidate-workspaces',
|
|
97
99
|
workspaces: freeze(workspaces),
|
|
98
100
|
counts: freeze({ workspaces: workspaces.length, readyWorkspaces: workspaces.filter((item) => item.state === 'ready').length, completeWorkspaces: completeWorkspaceCount, unexplainedRemovals: unexplainedRemovalCount }),
|
|
@@ -106,7 +108,7 @@ function auditResult(status, workspaces, findings, basisInspection, candidateIns
|
|
|
106
108
|
semanticAcceptanceGranted: false
|
|
107
109
|
}),
|
|
108
110
|
findings: freeze(findings),
|
|
109
|
-
boundary: 'Coarse Recovery acceptance audit over already-qualified carrier bytes. It decodes the exact candidate Workspace representations, compares them to one explicit accepted basis, and fails on unexplained source removals or incomplete coverage. It does not inspect a live checkout, prove Git cleanliness/committability, decide semantic correctness, authorize deletion, or grant Master Recovery acceptance; target landing still requires the separate exact source preflight.'
|
|
111
|
+
boundary: 'Coarse Recovery acceptance audit over already-qualified recipient-facing carrier bytes. The accepted basis may be a routed Handoff carrier or a qualified pointerless Workspace carrier; route authority is not required merely to establish exact basis bytes. It decodes the exact candidate Workspace representations, compares them to one explicit accepted basis, and fails on unexplained source removals or incomplete candidate coverage. It does not inspect a live checkout, prove Git cleanliness/committability, decide semantic correctness, authorize deletion, or grant Master Recovery acceptance; target landing still requires the separate exact source preflight.'
|
|
110
112
|
});
|
|
111
113
|
}
|
|
112
114
|
|
|
@@ -52,12 +52,13 @@ export function validatePortableFieldDomains(input = {}) {
|
|
|
52
52
|
}));
|
|
53
53
|
|
|
54
54
|
if (qualification === 'invalid') {
|
|
55
|
+
const contractGuidance = fieldDomainContractGuidance(results);
|
|
55
56
|
findings.push(fieldDomainFinding(
|
|
56
57
|
'error',
|
|
57
58
|
'portable.contract.field-domain.value.invalid',
|
|
58
|
-
|
|
59
|
+
invalidFieldDomainMessage(bucket.group, bucket.field, occurrence.value, contractGuidance),
|
|
59
60
|
'structurally-invalid',
|
|
60
|
-
{ group: bucket.group, field: bucket.field, value: occurrence.value, owner: occurrence.owner, contributions: results }
|
|
61
|
+
{ group: bucket.group, field: bucket.field, value: occurrence.value, owner: occurrence.owner, contributions: results, contractGuidance }
|
|
61
62
|
));
|
|
62
63
|
} else if (qualification === 'extension-candidate') {
|
|
63
64
|
findings.push(fieldDomainFinding(
|
|
@@ -242,6 +243,46 @@ function fieldDomainFinding(severity, code, message, state, extra = {}) {
|
|
|
242
243
|
return portableFinding(severity, code, message, { ...extra, state });
|
|
243
244
|
}
|
|
244
245
|
|
|
246
|
+
function fieldDomainContractGuidance(results = []) {
|
|
247
|
+
const contributions = (results || []).map((item) => Object.freeze({
|
|
248
|
+
sourceSchemaId: String(item.sourceSchemaId || ''),
|
|
249
|
+
sourceGroup: String(item.sourceGroup || ''),
|
|
250
|
+
field: String(item.field || ''),
|
|
251
|
+
allowedValues: Object.freeze([...(item.allowedValues || [])].map(String)),
|
|
252
|
+
allowedShapes: Object.freeze([...(item.allowedShapes || [])].map(String)),
|
|
253
|
+
domainPolicy: String(item.domainPolicy || ''),
|
|
254
|
+
declarationLine: Number(item.declarationLine || 0),
|
|
255
|
+
contractPath: [
|
|
256
|
+
String(item.sourceSchemaId || ''),
|
|
257
|
+
String(item.sourceGroup || ''),
|
|
258
|
+
'Field Value Constraints',
|
|
259
|
+
String(item.field || '')
|
|
260
|
+
].filter(Boolean).join(' :: ')
|
|
261
|
+
}));
|
|
262
|
+
return Object.freeze({
|
|
263
|
+
contributions: Object.freeze(contributions),
|
|
264
|
+
nextAction: contributions.length === 1
|
|
265
|
+
? `Use one value/shape allowed by ${contributions[0].contractPath || 'the cited field-domain contract'}; do not invent an extension unless the declared domain policy authorizes one.`
|
|
266
|
+
: 'Satisfy every contributing field-domain authority. Review each exact contractPath below; do not treat values from separate contributions as a union unless the contracts themselves establish that.'
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function invalidFieldDomainMessage(group, field, value, guidance = {}) {
|
|
271
|
+
const contributions = guidance.contributions || [];
|
|
272
|
+
if (contributions.length === 1) {
|
|
273
|
+
const item = contributions[0];
|
|
274
|
+
const allowed = item.allowedValues || [];
|
|
275
|
+
const shapes = item.allowedShapes || [];
|
|
276
|
+
const domain = [
|
|
277
|
+
allowed.length ? `Allowed values: ${allowed.join(', ')}` : '',
|
|
278
|
+
shapes.length ? `Allowed shapes: ${shapes.join(', ')}` : ''
|
|
279
|
+
].filter(Boolean).join('; ');
|
|
280
|
+
const path = item.contractPath ? ` Contract: ${item.contractPath}${item.declarationLine ? ` (line ${item.declarationLine})` : ''}.` : '';
|
|
281
|
+
return `Value is outside the allowed field domain for ${group}.${field}: ${value}.${domain ? ` ${domain}.` : ''}${path}`;
|
|
282
|
+
}
|
|
283
|
+
return `Value is outside the allowed field domain for ${group}.${field}: ${value}. Multiple field-domain authorities apply; see contractGuidance for each exact contract path and allowed values/shapes.`;
|
|
284
|
+
}
|
|
285
|
+
|
|
245
286
|
function exact(value = '') {
|
|
246
287
|
return String(value || '').trim();
|
|
247
288
|
}
|