@tiinex/core 0.17.0 → 0.19.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.
Files changed (31) hide show
  1. package/package.json +7 -5
  2. package/src/tooling/portable/adapters/cli/cli.command-input.js +8 -1
  3. package/src/tooling/portable/adapters/cli/cli.common-author.js +29 -5
  4. package/src/tooling/portable/adapters/cli/cli.common-output.js +38 -3
  5. package/src/tooling/portable/adapters/cli/cli.handoff-manufacture.js +33 -17
  6. package/src/tooling/portable/adapters/cli/cli.handoff-sibling-allocation.js +139 -2
  7. package/src/tooling/portable/adapters/cli/cli.help.js +1 -1
  8. package/src/tooling/portable/adapters/cli/cli.run.js +4 -0
  9. package/src/tooling/portable/adapters/node/handoff.manufacture.js +25 -12
  10. package/src/tooling/portable/adapters/node/handoff.manufacture.packageParent.js +43 -0
  11. package/src/tooling/portable/grounding/grounding.capsule.js +22 -3
  12. package/src/tooling/portable/grounding/grounding.holderBindingAuthorization.js +81 -0
  13. package/src/tooling/portable/grounding/grounding.implementationSourceAuthority.js +109 -0
  14. package/src/tooling/portable/grounding/grounding.orchestrationReadiness.js +33 -0
  15. package/src/tooling/portable/grounding/grounding.participantAuthority.js +1 -1
  16. package/src/tooling/portable/grounding/grounding.participantContext.js +58 -0
  17. package/src/tooling/portable/grounding/grounding.processApplicability.js +38 -0
  18. package/src/tooling/portable/grounding/grounding.readiness.authority.js +63 -3
  19. package/src/tooling/portable/grounding/grounding.readiness.js +72 -12
  20. package/src/tooling/portable/grounding/grounding.readiness.support.js +5 -1
  21. package/src/tooling/portable/grounding/grounding.sourceEvidence.js +151 -9
  22. package/src/tooling/portable/handoff/carrierProjection.routeQualification.js +12 -1
  23. package/src/tooling/portable/handoff/coldStartQualification.grounding.js +62 -3
  24. package/src/tooling/portable/handoff/coldStartQualification.materials.js +19 -1
  25. package/src/tooling/portable/handoff/contextAudit.js +1 -1
  26. package/src/tooling/portable/handoff/delegationReturnReservation.js +4 -2
  27. package/src/tooling/portable/handoff/manufacture.js +1 -0
  28. package/src/tooling/portable/handoff/recipientV2.inspect.projection.js +3 -0
  29. package/src/tooling/portable/handoff/recipientV2.packageV1.inspect.js +1 -1
  30. package/src/tooling/portable/handoff/recoveryAcceptanceAudit.js +5 -3
  31. 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.17.0",
3
+ "version": "0.19.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,8 @@
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",
82
+ "./tooling/portable/grounding/grounding.implementationSourceAuthority.js": "./src/tooling/portable/grounding/grounding.implementationSourceAuthority.js",
81
83
  "./tooling/portable/grounding/grounding.readiness.js": "./src/tooling/portable/grounding/grounding.readiness.js",
82
84
  "./tooling/portable/grounding/grounding.workProvenance.js": "./src/tooling/portable/grounding/grounding.workProvenance.js",
83
85
  "./tooling/portable/handoff/carrierLineage.js": "./src/tooling/portable/handoff/carrierLineage.js",
@@ -169,12 +171,12 @@
169
171
  "type": "git",
170
172
  "url": "git+https://github.com/Tiinex/core.git"
171
173
  },
172
- "gitHead": "2986187f3e95582d13c784060272e111931c6a1b",
174
+ "gitHead": "fe01706aecacbf28c66e2ac052e4f639170dfe73",
173
175
  "tiinexRelease": {
174
176
  "policy": "tiinex.master-npm-release.v1",
175
- "sourceCommit": "2986187f3e95582d13c784060272e111931c6a1b",
176
- "sourceTree": "0c65ff04241c756ae67978d777d1bee8ac1befc9",
177
+ "sourceCommit": "fe01706aecacbf28c66e2ac052e4f639170dfe73",
178
+ "sourceTree": "b4e5dbb825a1504fef53f1e5281d4bd6fd3c87ff",
177
179
  "repository": "Tiinex/core",
178
- "previousVersion": "0.16.0"
180
+ "previousVersion": "0.18.0"
179
181
  }
180
182
  }
@@ -117,7 +117,7 @@ export async function commandInput(parsed, runtime = {}) {
117
117
  packageSourcePath: packagePath,
118
118
  includeLegacyTopics: Boolean(flags['include-legacy-topics']),
119
119
  includeRequiredContext: flags['include-required-context'] || '',
120
- holderBinding: { roleLabel: flags['holder-role'] || '', holderId: flags['holder-id'] || '' },
120
+ holderBinding: { roleLabel: flags['holder-role'] || '', holderId: flags['holder-id'] || '', sourceLocator: holderBindingCliSource(flags) },
121
121
  host,
122
122
  recoveryAcceptance
123
123
  },
@@ -471,4 +471,11 @@ function mergeLoadedMaterial(primary = {}, secondary = {}) {
471
471
  }
472
472
 
473
473
  function normalizeRuntimePaths(value) { const paths = Array.isArray(value) ? value : value ? [value] : []; return paths.map((entry) => String(entry || '').trim()).filter(Boolean); }
474
+ function holderBindingCliSource(flags = {}) {
475
+ const fields = [];
476
+ if (Object.prototype.hasOwnProperty.call(flags, 'holder-role')) fields.push('--holder-role');
477
+ if (Object.prototype.hasOwnProperty.call(flags, 'holder-id')) fields.push('--holder-id');
478
+ return fields.length ? `cli:${fields.join(',')}` : '';
479
+ }
480
+
474
481
  function splitFlag(value) { return !value || value === true ? [] : String(value).split(',').map((item) => item.trim()).filter(Boolean); }
@@ -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('portable.cli.author.parent-source.required');
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
- nextAction: 'Resolve the reported schema/continuity finding, then rerun the same author command. No invalid durable artifact was retained.',
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('portable.cli.author.parent.schema-authority.required');
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),
@@ -162,6 +163,7 @@ function projectHandoffDefault(result = {}, parsed = {}) {
162
163
  status: String(carrier.status || ''),
163
164
  mode: String(carrier.mode || ''),
164
165
  lineage: carrier.lineage ? compactCarrierLineage(carrier.lineage) : null,
166
+ allocation: result.carrierAllocation ? Object.freeze({ ...result.carrierAllocation }) : null,
165
167
  route: Object.freeze({
166
168
  id: String(route.id || ''),
167
169
  state: String(route.state || ''),
@@ -254,13 +256,18 @@ function compactGroundAuthority(authority = {}) {
254
256
  route: Object.freeze({
255
257
  id: String(route.id || ''),
256
258
  pointerPath: String(route.pointerPath || ''),
257
- workspaceId: String(route.workspaceId || '')
259
+ workspaceId: String(route.workspaceId || ''),
260
+ workspaceRelativePath: String(route.workspaceRelativePath || ''),
261
+ sha256: String(route.sha256 || ''),
262
+ provenance: route.provenance ? Object.freeze({ ...route.provenance }) : null
258
263
  }),
259
264
  handoff: Object.freeze({
260
265
  purpose: String(handoff.purpose || ''),
261
266
  from: String(handoff.from || ''),
262
267
  to: String(handoff.to || ''),
263
- completionExpectation: handoff.completionExpectation || null
268
+ completionExpectation: handoff.completionExpectation || null,
269
+ transfers: Object.freeze((handoff.transfers || []).map((item) => Object.freeze({ ...item }))),
270
+ provenance: handoff.provenance ? Object.freeze({ ...handoff.provenance }) : null
264
271
  }),
265
272
  role: Object.freeze({
266
273
  state: String(role.state || ''),
@@ -269,13 +276,20 @@ function compactGroundAuthority(authority = {}) {
269
276
  }),
270
277
  holderBinding: Object.freeze({
271
278
  state: String(holderBinding.state || ''),
279
+ bindingPresent: Boolean(holderBinding.bindingPresent),
280
+ declarationPresent: Boolean(holderBinding.declarationPresent),
272
281
  holderId: String(holderBinding.holderId || ''),
273
282
  roleLabel: String(holderBinding.roleLabel || ''),
274
283
  recipientRoleLabel: String(holderBinding.recipientRoleLabel || ''),
275
284
  recipientCompatibility: String(holderBinding.recipientCompatibility || ''),
276
285
  source: String(holderBinding.source || ''),
286
+ sourceDetail: holderBinding.sourceDetail ? Object.freeze({ ...holderBinding.sourceDetail }) : null,
287
+ authorization: holderBinding.authorization ? Object.freeze({ ...holderBinding.authorization, provenance: holderBinding.authorization.provenance ? Object.freeze({ ...holderBinding.authorization.provenance }) : null }) : null,
288
+ durableIdentity: holderBinding.durableIdentity ? Object.freeze({ ...holderBinding.durableIdentity }) : Object.freeze({ state: 'not-established' }),
289
+ semanticAuthorityState: String(holderBinding.semanticAuthorityState || 'not-established'),
277
290
  explicit: Boolean(holderBinding.explicit),
278
- inferredFromTransport: Boolean(holderBinding.inferredFromTransport)
291
+ inferredFromTransport: Boolean(holderBinding.inferredFromTransport),
292
+ provenance: holderBinding.provenance ? Object.freeze({ ...holderBinding.provenance }) : null
279
293
  }),
280
294
  operationBoundary: Object.freeze({
281
295
  sourceMutation: Boolean(operationBoundary.sourceMutation),
@@ -286,14 +300,35 @@ function compactGroundAuthority(authority = {}) {
286
300
  });
287
301
  }
288
302
 
303
+ function compactOrchestrationReadiness(value = {}) {
304
+ if (!value || typeof value !== 'object') return null;
305
+ const wider = value.widerOrchestration || {};
306
+ return Object.freeze({
307
+ state: String(value.state || ''),
308
+ boundedActionReadiness: String(value.boundedActionReadiness || ''),
309
+ widerOrchestration: Object.freeze({
310
+ state: String(wider.state || ''),
311
+ blockers: Object.freeze((wider.blockers || []).slice(0, 8).map((item) => Object.freeze({ ...item })))
312
+ }),
313
+ participantMap: String(value.participantMap || ''),
314
+ sourceScope: String(value.sourceScope || ''),
315
+ processApplicability: value.processApplicability ? Object.freeze({ ...value.processApplicability, unresolved: Object.freeze([...(value.processApplicability.unresolved || [])].map((item) => Object.freeze({ ...item }))) }) : null,
316
+ boundary: String(value.boundary || '')
317
+ });
318
+ }
319
+
289
320
  function projectRequiredContextItem(item = {}) {
290
321
  const contentProjected = Boolean(item.contentProjected && typeof item.content === 'string');
291
322
  return Object.freeze({
292
323
  requirementId: String(item.requirementId || ''),
293
324
  name: String(item.name || ''),
325
+ material: String(item.material || ''),
326
+ purpose: String(item.purpose || ''),
327
+ declaredAvailability: String(item.declaredAvailability || ''),
294
328
  state: String(item.state || ''),
295
329
  workspaceId: String(item.workspaceId || ''),
296
330
  innerPath: String(item.innerPath || ''),
331
+ provenance: item.provenance ? Object.freeze({ ...item.provenance }) : null,
297
332
  contentProjected,
298
333
  ...(contentProjected ? { content: item.content } : {})
299
334
  });
@@ -10,7 +10,7 @@ import { projectRecipientV2HumanOutput } from '../../handoff/recipientV2.humanOu
10
10
  import { inspectRecipientFacingV2Topology } from '../../handoff/recipientV2.inspect.js';
11
11
  import { carrierLineageFromCliParent, initialHandoffCarrierLineage, parentHandoffCarrierLineageFromBundle, parentHandoffCarrierProfileFromBundle } from '../../handoff/carrierLineage.js';
12
12
  import { loadNodePortableInput } from '../../input/node.input.js';
13
- import { reserveHandoffSiblingIndex } from './cli.handoff-sibling-allocation.js';
13
+ import { resolveHandoffSiblingAllocation } from './cli.handoff-sibling-allocation.js';
14
14
  import { normalizeHandoffCarrierProfile } from '../../handoff/carrierProfile.js';
15
15
 
16
16
  export async function prepareHandoffManufactureCliCommand(parsed = {}, runtime = {}) {
@@ -26,7 +26,6 @@ export async function prepareHandoffManufactureCliCommand(parsed = {}, runtime =
26
26
  const handoffPath = flags.handoff || parsed.positionals?.[1] || continuationState.returnHandoffPath || '';
27
27
  if (!flags['workspace-id'] && continuationState.workspaceId) flags['workspace-id'] = continuationState.workspaceId;
28
28
  if (!flags['workspace-target'] && continuationState.workspaceTarget) flags['workspace-target'] = continuationState.workspaceTarget;
29
- if (!flags['package-sibling-index'] && continuationState.returnPackageSiblingIndex) flags['package-sibling-index'] = continuationState.returnPackageSiblingIndex;
30
29
  if (!flags['package-parent'] && continuationState.packageParentPath) flags['package-parent'] = continuationState.packageParentPath;
31
30
  if (!flags.route && handoffPath) flags.route = handoffPath;
32
31
  if (!flags.output && !flags['output-dir'] && parsed.surfaceCommand === 'handoff' && continuationState.returnOutputDir) flags['output-dir'] = continuationState.returnOutputDir;
@@ -55,6 +54,7 @@ export async function prepareHandoffManufactureCliCommand(parsed = {}, runtime =
55
54
  let packageParentSha256 = '';
56
55
  let carrierLineage = initialHandoffCarrierLineage();
57
56
  let inheritedCarrierProfile = normalizeHandoffCarrierProfile(null);
57
+ let carrierAllocation = Object.freeze({ state: 'root', allocationMode: 'initial-root', siblingIndex: null, provenance: Object.freeze({ basis: 'initial-carrier-root' }) });
58
58
  if (parentPackagePath) {
59
59
  const resolvedParent = path.resolve(parentPackagePath);
60
60
  const parentBytes = new Uint8Array(await readFile(resolvedParent));
@@ -86,21 +86,35 @@ export async function prepareHandoffManufactureCliCommand(parsed = {}, runtime =
86
86
  major: Boolean(flags['package-major']),
87
87
  majorReason: flags['major-reason'] || ''
88
88
  });
89
- const siblingAllocation = await reserveHandoffSiblingIndex({
90
- parentPackagePath: resolvedParent,
91
- parentPackageSha256: provisionalLineage.parentPackageSha256,
92
- parentDimension: provisionalLineage.parentDimension,
93
- enabled: !flags['package-major'] && Boolean(flags.output || flags['output-dir']),
94
- siblingIndex: flags['package-sibling-index']
95
- });
96
- carrierLineage = flags['package-major'] ? provisionalLineage : carrierLineageFromCliParent({
97
- bundle: parentBundle,
98
- parentPath: resolvedParent,
99
- parentBytes,
100
- routeDimensions,
101
- qualifiedParentLineage: parentLineage,
102
- siblingIndex: siblingAllocation.siblingIndex
103
- });
89
+ if (flags['package-major']) {
90
+ carrierLineage = provisionalLineage;
91
+ carrierAllocation = Object.freeze({
92
+ state: 'qualified', allocationMode: 'explicit-major', siblingIndex: null,
93
+ provenance: Object.freeze({ basis: 'explicit-major-request', parentPackagePath: resolvedParent, parentPackageSha256: provisionalLineage.parentPackageSha256, parentDimension: provisionalLineage.parentDimension }),
94
+ boundary: 'Carrier Major creation remains explicit and separate from non-Major pointer-order allocation.'
95
+ });
96
+ } else {
97
+ const parentInspection = inspectRecipientFacingV2Topology(parentBundle);
98
+ const siblingAllocation = await resolveHandoffSiblingAllocation({
99
+ parentInspection,
100
+ parentPackagePath: resolvedParent,
101
+ parentPackageSha256: provisionalLineage.parentPackageSha256,
102
+ parentDimension: provisionalLineage.parentDimension,
103
+ selectedRoutePointer: continuationState.selectedRoutePointer || flags['package-parent-route-pointer'] || '',
104
+ selectedRouteId: continuationState.selectedRouteId || flags['package-parent-route-id'] || '',
105
+ explicitSiblingIndex: flags['package-sibling-index'],
106
+ enabled: Boolean(flags.output || flags['output-dir'])
107
+ });
108
+ carrierAllocation = siblingAllocation;
109
+ carrierLineage = carrierLineageFromCliParent({
110
+ bundle: parentBundle,
111
+ parentPath: resolvedParent,
112
+ parentBytes,
113
+ routeDimensions,
114
+ qualifiedParentLineage: parentLineage,
115
+ siblingIndex: siblingAllocation.siblingIndex
116
+ });
117
+ }
104
118
  packageParentSha256 = String(carrierLineage.parentPackageSha256 || '');
105
119
  } else if (flags['package-major']) {
106
120
  throw new Error('portable.cli.handoff-carrier.package-major.parent-required');
@@ -129,6 +143,7 @@ export async function prepareHandoffManufactureCliCommand(parsed = {}, runtime =
129
143
  verifyRoundtrip,
130
144
  recipientRouteSelector: flags.route || '',
131
145
  carrierLineage,
146
+ carrierAllocation,
132
147
  carrierProfile,
133
148
  packageParentBundle,
134
149
  packageParentPath: parentPackagePath ? path.resolve(parentPackagePath) : '',
@@ -329,6 +344,7 @@ export function summarizeHandoffManufactureCliOutput(result = {}, writeReceipt =
329
344
  }) : null,
330
345
  toolingBootstrap: result.toolingBootstrap || null,
331
346
  carrierLineage: result.carrierLineage || projection.lineage || null,
347
+ carrierAllocation: result.carrierAllocation || result.manufacturingEvidence?.carrierAllocation || null,
332
348
  majorReadiness: result.majorReadiness || null,
333
349
  operationBoundary: result.operationBoundary ? Object.freeze({ ...result.operationBoundary }) : null,
334
350
  manufacturingEvidence: result.manufacturingEvidence || null,
@@ -2,6 +2,125 @@ import { mkdir, open, readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
 
4
4
  const MAX_SIBLING_INDEX = 9999;
5
+ const POINTER_PATH_RE = /^(\d{3}(?:-\d+)*)-handoff-pointer\.trace\.md$/;
6
+
7
+ export function deriveHandoffSiblingAllocation({ parentInspection = null, selectedRoutePointer = '', selectedRouteId = '', explicitSiblingIndex = null, parentPackagePath = '', parentPackageSha256 = '', parentDimension = '' } = {}) {
8
+ const explicit = normalizeSiblingIndex(explicitSiblingIndex);
9
+ const inspection = parentInspection && typeof parentInspection === 'object' ? parentInspection : null;
10
+ if (!inspection || inspection.detected === false) return freeze({
11
+ state: 'unavailable',
12
+ siblingIndex: explicit || null,
13
+ allocationMode: explicit ? 'explicit-override-only' : 'unavailable',
14
+ reasonCode: 'qualified-parent-route-topology-unavailable',
15
+ provenance: provenanceBase({ parentPackagePath, parentPackageSha256, parentDimension, explicitSiblingIndex: explicit }),
16
+ boundary: allocationBoundary()
17
+ });
18
+ if (String(inspection.status || '') !== 'valid') return freeze({
19
+ state: 'blocked',
20
+ siblingIndex: null,
21
+ allocationMode: 'blocked',
22
+ reasonCode: 'qualified-parent-route-topology-invalid',
23
+ provenance: provenanceBase({ parentPackagePath, parentPackageSha256, parentDimension, explicitSiblingIndex: explicit }),
24
+ boundary: allocationBoundary()
25
+ });
26
+
27
+ const routes = [...(inspection.routes || [])].map((route) => ({
28
+ pointerPath: String(route.pointerPath || '').trim(),
29
+ routeId: String(route.routeId || '').trim(),
30
+ workspaceId: String(route.workspaceId || '').trim(),
31
+ workspaceRelativeHandoffPath: String(route.workspaceRelativeHandoffPath || '').trim()
32
+ }));
33
+ if (!routes.length) return blocked('qualified-parent-route-topology-empty');
34
+
35
+ const qualified = [];
36
+ const seenDimensions = new Set();
37
+ for (const route of routes) {
38
+ const match = route.pointerPath.match(POINTER_PATH_RE);
39
+ if (!match) return blocked('qualified-parent-route-pointer-order-unresolved');
40
+ const dimension = match[1];
41
+ if (seenDimensions.has(dimension)) return blocked('qualified-parent-route-pointer-order-ambiguous');
42
+ seenDimensions.add(dimension);
43
+ qualified.push({ ...route, pointerDimension: dimension, pointerSegments: dimension.split('-').map((value) => Number.parseInt(value, 10)) });
44
+ }
45
+ qualified.sort(comparePointerOrder);
46
+
47
+ const pointerSelector = String(selectedRoutePointer || '').trim();
48
+ const routeIdSelector = String(selectedRouteId || '').trim();
49
+ let selected = null;
50
+ if (pointerSelector) {
51
+ const matches = qualified.filter((route) => route.pointerPath === pointerSelector);
52
+ if (matches.length !== 1) return blocked(matches.length ? 'selected-parent-route-pointer-ambiguous' : 'selected-parent-route-pointer-unqualified');
53
+ selected = matches[0];
54
+ }
55
+ if (routeIdSelector) {
56
+ const matches = qualified.filter((route) => route.routeId === routeIdSelector);
57
+ if (matches.length !== 1) return blocked(matches.length ? 'selected-parent-route-id-ambiguous' : 'selected-parent-route-id-unqualified');
58
+ if (selected && selected.pointerPath !== matches[0].pointerPath) return blocked('selected-parent-route-selector-conflict');
59
+ selected = matches[0];
60
+ }
61
+ if (!selected) {
62
+ if (qualified.length !== 1) return blocked('selected-parent-route-required-for-parallel-topology');
63
+ selected = qualified[0];
64
+ }
65
+
66
+ const siblingIndex = qualified.findIndex((route) => route.pointerPath === selected.pointerPath) + 1;
67
+ if (!Number.isInteger(siblingIndex) || siblingIndex < 1 || siblingIndex > MAX_SIBLING_INDEX) return blocked('derived-sibling-index-out-of-range');
68
+ if (explicit && explicit !== siblingIndex) return blocked('explicit-sibling-index-conflicts-with-qualified-topology', { expectedSiblingIndex: siblingIndex });
69
+
70
+ return freeze({
71
+ state: 'qualified',
72
+ siblingIndex,
73
+ childDimension: parentDimension ? `${String(parentDimension).trim()}-${siblingIndex}` : '',
74
+ allocationMode: 'qualified-parent-route-pointer-ordinal',
75
+ explicitOverride: explicit ? 'matched-derived-value' : 'not-supplied',
76
+ reasonCode: '',
77
+ provenance: {
78
+ ...provenanceBase({ parentPackagePath, parentPackageSha256, parentDimension, explicitSiblingIndex: explicit }),
79
+ basis: 'qualified-parent-route-pointer-ordinal',
80
+ selectedRoutePointer: selected.pointerPath,
81
+ selectedRouteId: selected.routeId,
82
+ selectedWorkspaceId: selected.workspaceId,
83
+ selectedWorkspaceRelativeHandoffPath: selected.workspaceRelativeHandoffPath,
84
+ routeOrdinal: siblingIndex,
85
+ qualifiedRouteCount: qualified.length,
86
+ pointerOrder: qualified.map((route, index) => Object.freeze({ ordinal: index + 1, pointerPath: route.pointerPath, routeId: route.routeId }))
87
+ },
88
+ boundary: allocationBoundary()
89
+ });
90
+
91
+ function blocked(reasonCode, extra = {}) {
92
+ return freeze({
93
+ state: 'blocked', siblingIndex: null, allocationMode: 'blocked', reasonCode, ...extra,
94
+ provenance: provenanceBase({ parentPackagePath, parentPackageSha256, parentDimension, explicitSiblingIndex: explicit }),
95
+ boundary: allocationBoundary()
96
+ });
97
+ }
98
+ }
99
+
100
+ export async function resolveHandoffSiblingAllocation(input = {}) {
101
+ const derived = deriveHandoffSiblingAllocation(input);
102
+ if (derived.state === 'qualified') return derived;
103
+ if (derived.state === 'blocked') throw new Error(`portable.cli.handoff-carrier.sibling-allocation.${derived.reasonCode}`);
104
+ const explicit = normalizeSiblingIndex(input.explicitSiblingIndex ?? input.siblingIndex);
105
+ if (!explicit) throw new Error('portable.cli.handoff-carrier.sibling-allocation.explicit-index-required-when-topology-unavailable');
106
+ const legacy = await reserveHandoffSiblingIndex({
107
+ parentPackagePath: input.parentPackagePath,
108
+ parentPackageSha256: input.parentPackageSha256,
109
+ parentDimension: input.parentDimension,
110
+ enabled: input.enabled !== false,
111
+ siblingIndex: explicit
112
+ });
113
+ return freeze({
114
+ ...legacy,
115
+ allocationMode: 'explicit-advanced-override',
116
+ explicitOverride: 'required-because-qualified-topology-unavailable',
117
+ provenance: {
118
+ ...provenanceBase({ ...input, explicitSiblingIndex: explicit }),
119
+ basis: 'explicit-advanced-override-without-qualified-route-topology'
120
+ },
121
+ boundary: allocationBoundary()
122
+ });
123
+ }
5
124
 
6
125
  export async function reserveHandoffSiblingIndex({ parentPackagePath = '', parentPackageSha256 = '', parentDimension = '', enabled = true, siblingIndex = null } = {}) {
7
126
  const requestedSiblingIndex = normalizeSiblingIndex(siblingIndex);
@@ -35,21 +154,39 @@ export async function reserveHandoffSiblingIndex({ parentPackagePath = '', paren
35
154
  }
36
155
  }
37
156
 
157
+ function comparePointerOrder(left, right) {
158
+ const a = left.pointerSegments || [], b = right.pointerSegments || [];
159
+ for (let index = 0; index < Math.max(a.length, b.length); index += 1) {
160
+ if (a[index] === undefined) return -1;
161
+ if (b[index] === undefined) return 1;
162
+ if (a[index] !== b[index]) return a[index] - b[index];
163
+ }
164
+ return left.pointerPath.localeCompare(right.pointerPath);
165
+ }
166
+
167
+ function provenanceBase({ parentPackagePath = '', parentPackageSha256 = '', parentDimension = '', explicitSiblingIndex = null } = {}) {
168
+ return {
169
+ parentPackagePath: String(parentPackagePath || ''),
170
+ parentPackageSha256: String(parentPackageSha256 || '').trim().toLowerCase(),
171
+ parentDimension: String(parentDimension || '').trim(),
172
+ explicitSiblingIndex: explicitSiblingIndex ? normalizeSiblingIndex(explicitSiblingIndex) : null
173
+ };
174
+ }
175
+ function allocationBoundary() { return 'Transport-only carrier allocation. A non-Major sibling ordinal may come only from exact qualified package-local Handoff Pointer order for the selected parent route, or from an explicit advanced override when such topology is unavailable. Allocation never creates semantic Parent, Workspace, Role, acceptance, completion, participant, process, or source authority; different carrier prefixes are not coordinated.'; }
38
176
  function normalizeSiblingIndex(value) {
39
177
  if (value === null || value === undefined || value === '') return 0;
40
178
  const parsed = Number(value);
41
179
  if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_SIBLING_INDEX) throw new Error('portable.cli.handoff-carrier.sibling-allocation.index-invalid');
42
180
  return parsed;
43
181
  }
44
-
45
182
  async function readAllocation(allocationPath) {
46
183
  try { return JSON.parse(await readFile(allocationPath, 'utf8')); }
47
184
  catch { throw new Error('portable.cli.handoff-carrier.sibling-allocation.existing-reservation-invalid'); }
48
185
  }
49
-
50
186
  function sameAllocation(left = {}, right = {}) {
51
187
  return String(left.parentPackageSha256 || '') === String(right.parentPackageSha256 || '')
52
188
  && String(left.parentDimension || '') === String(right.parentDimension || '')
53
189
  && Number(left.siblingIndex || 0) === Number(right.siblingIndex || 0)
54
190
  && String(left.childDimension || '') === String(right.childDimension || '');
55
191
  }
192
+ function freeze(value) { if (Array.isArray(value)) return Object.freeze(value.map(freeze)); if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value; return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, freeze(item)]))); }
@@ -83,7 +83,7 @@ function commonCommandHelp(command, surfaceCommand) {
83
83
  '',
84
84
  `${command} handoff <workspace-dir>`,
85
85
  '',
86
- 'Infers the latest qualified authored Handoff, selected Workspace identity/target, received package parent as carrier-lineage evidence, canonical projected filename, and return output directory. When the outgoing Handoff declares `Signal Kind: return`, delegation manufacture is transport-not-ready unless the delegator supplies `--return-package-sibling-index <1..9999>` for the expected non-Major return, or explicitly declares `--return-package-major`; the qualified reservation is carried in the route pointer and later continuation state. A non-major continuation that writes a carrier must supply an explicitly coordinated `--package-sibling-index <1..9999>`; Tooling will not silently discover the next sibling because isolated runtimes cannot prove a globally unique reservation. Distinct explicit sibling indexes preserve same-Major parallelism, while byte-identical duplicate transport at one exact output path is idempotent and divergent bytes fail closed. It does not implicitly carry sibling Workspaces from the received package; advanced manufacture must select exact reusable parent snapshots with `--package-parent-workspaces <id,...|all>`. Recovery/integration manufacture can bind the reconciled byte proof with `--require-reconciliation-proof --reconciliation-proof <full-reconcile-receipt.json>`; missing, non-ready, edited, or source-stale proof blocks package output. The default receipt keeps output identity, routing text, closure/workspace qualification, verification, and actionable findings compact; add `--full` for the complete manufacture receipt. Normal operator completion is exactly one Handoff package plus the adjacent exact routing text. In markdown-capable hosts render that routing in a fenced code block; do not emit canonical Workspace Evidence/Handoff markdown as additional loose transport files. Runtime-only `.tiinex` state is excluded from canonical manufacture.',
86
+ 'Infers the latest qualified authored Handoff, selected Workspace identity/target, received package parent as carrier-lineage evidence, canonical projected filename, and return output directory. Ordinary non-Major continuation derives its sibling ordinal from the exact qualified selected Handoff Pointer order in the received parent carrier, so common-path `handoff` does not require `--package-sibling-index` or `--return-package-sibling-index`. A single selected Pointer derives `-1`; parallel qualified Pointers derive dense local ordinals in Pointer order, and each returned branch continues from its own carrier. `--package-sibling-index` remains an advanced compatibility override only when qualified route topology is unavailable, and must match when topology already proves the value; conflicting or ambiguous topology fails closed. `--return-package-major` remains the explicit Major-return declaration. Different carrier prefixes are never globally coordinated. Byte-identical duplicate transport at one exact output path is idempotent and divergent bytes fail closed. It does not implicitly carry sibling Workspaces from the received package; advanced manufacture must select exact reusable parent snapshots with `--package-parent-workspaces <id,...|all>`. Recovery/integration manufacture can bind the reconciled byte proof with `--require-reconciliation-proof --reconciliation-proof <full-reconcile-receipt.json>`; missing, non-ready, edited, or source-stale proof blocks package output. The default receipt keeps output identity, routing text, closure/workspace qualification, verification, and actionable findings compact; add `--full` for the complete manufacture receipt. Normal operator completion is exactly one Handoff package plus the adjacent exact routing text. In markdown-capable hosts render that routing in a fenced code block; do not emit canonical Workspace Evidence/Handoff markdown as additional loose transport files. Runtime-only `.tiinex` state is excluded from canonical manufacture.',
87
87
  '',
88
88
  `Advanced/internal catalog: ${command} operations`
89
89
  ];
@@ -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 [handoffMarkdown, enumeration, additionalEnumerations] = await Promise.all([
94
- handoffMarkdownPromise,
102
+ const [enumeration, additionalEnumerations] = await Promise.all([
95
103
  enumerationPromise,
96
104
  additionalEnumerationsPromise
97
105
  ]);
@@ -132,7 +140,8 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
132
140
  }
133
141
  const suppliedTransportRoutes = [...(input.transportRoutes || input.handoffRoutes || [])].map((route) => normalizeTransportRoute(route, workspaceId)).filter(Boolean);
134
142
  const reservationProjection = returnCarrierReservationPreflight.state === 'qualified' && returnCarrierReservationPreflight.returnExpected
135
- ? Object.freeze({ carrierKind: returnCarrierReservationPreflight.carrierKind, siblingIndex: returnCarrierReservationPreflight.siblingIndex })
143
+ && (returnCarrierReservationPreflight.carrierKind === 'major' || Number.isInteger(returnCarrierReservationPreflight.siblingIndex))
144
+ ? Object.freeze({ carrierKind: returnCarrierReservationPreflight.carrierKind, ...(Number.isInteger(returnCarrierReservationPreflight.siblingIndex) ? { siblingIndex: returnCarrierReservationPreflight.siblingIndex } : {}) })
136
145
  : null;
137
146
  const transportRoutes = Object.freeze((suppliedTransportRoutes.length ? suppliedTransportRoutes : [Object.freeze({ workspaceId, path: handoffPath })]).map((route) => Object.freeze({ ...route, ...(route.path === handoffPath && String(route.workspaceId || '') === workspaceId && reservationProjection ? { returnCarrierReservation: reservationProjection } : {}) })));
138
147
  const workspaceTargets = mergeWorkspaceTargetBindings(normalizeWorkspaceTargetBindings({
@@ -197,6 +206,7 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
197
206
  transportRoutes,
198
207
  workspaceTargets,
199
208
  carrierLineage: normalizeHandoffCarrierLineage(input.carrierLineage || null),
209
+ carrierAllocation: input.carrierAllocation ? Object.freeze({ ...input.carrierAllocation }) : null,
200
210
  carrierProfile: normalizeHandoffCarrierProfile(input.carrierProfile || null),
201
211
  toolingBootstrap: toolingBootstrap.summary,
202
212
  reconciliationProofQualification,
@@ -210,6 +220,7 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
210
220
  reconciliationProof: reconciliationProofQualification,
211
221
  schemaReferencePreflight,
212
222
  returnCarrierReservationPreflight,
223
+ carrierAllocation: input.carrierAllocation ? Object.freeze({ ...input.carrierAllocation }) : null,
213
224
  packageParentWorkspaceReuse: Object.freeze({
214
225
  state: String(packageParentReuse.state || ''),
215
226
  providerState: String(packageParentReuse.providerState || ''),
@@ -217,10 +228,12 @@ export async function prepareNodeHandoffManufacturingInput(input = {}, options =
217
228
  selectionMode: String(packageParentReuse.selectionMode || ''),
218
229
  requestedWorkspaceIds: Object.freeze([...(packageParentReuse.requestedWorkspaceIds || [])].map(String)),
219
230
  providerWorkspaceIds: Object.freeze([...(packageParentReuse.providerWorkspaceIds || [])].map(String)),
231
+ providerWorkspaceTargets: Object.freeze([...(packageParentReuse.providerWorkspaceTargets || [])].map((item) => Object.freeze({ ...item }))),
220
232
  inheritedWorkspaceIds: Object.freeze((packageParentReuse.inherited || []).map((item) => String(item.id || ''))),
221
233
  workspaceAliases: Object.freeze([...(packageParentReuse.workspaceAliases || [])].map((item) => Object.freeze({ ...item }))),
222
234
  boundary: String(packageParentReuse.boundary || '')
223
235
  }),
236
+ requiredContextWorkspaceSelectionPreflight,
224
237
  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
238
  }),
226
239
  verifyRoundtrip: input.verifyRoundtrip !== false