@tiinex/core 0.6.0 → 0.8.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiinex/core",
3
- "version": "0.6.0",
3
+ "version": "0.8.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,
@@ -167,12 +167,12 @@
167
167
  "type": "git",
168
168
  "url": "git+https://github.com/Tiinex/core.git"
169
169
  },
170
- "gitHead": "0020f40134cd3d1978c929343cb77d3051852d22",
170
+ "gitHead": "6a139559c7cb3d809b2ecf0482d0ae42243aa609",
171
171
  "tiinexRelease": {
172
172
  "policy": "tiinex.master-npm-release.v1",
173
- "sourceCommit": "0020f40134cd3d1978c929343cb77d3051852d22",
174
- "sourceTree": "8818bf936b8128159a3cf1a0913b7405a4bd669c",
173
+ "sourceCommit": "6a139559c7cb3d809b2ecf0482d0ae42243aa609",
174
+ "sourceTree": "ec876301e7b78eaf85e8cbf9aba91dba873c2b3b",
175
175
  "repository": "Tiinex/core",
176
- "previousVersion": "0.5.0"
176
+ "previousVersion": "0.7.0"
177
177
  }
178
178
  }
@@ -172,6 +172,7 @@ async function prepareWorkspaceCarrierCliCommand(flags = {}, workspaceRoot = '.'
172
172
  const additionalWorkspaces = [...splitFlag(flags['additional-workspaces']), ...descriptorArray(workspaceDescriptorValue, 'workspaces')];
173
173
  const verifyRoundtrip = !flags['no-roundtrip'];
174
174
  const carrierProfile = selectCarrierProfile({ operator: operatorCarrierProfile, runtime: runtime.defaultCarrierProfile || null });
175
+ const projectedFilename = String(flags['projected-filename'] || flags.projectedFilename || '').trim();
175
176
  const input = await prepareNodeWorkspaceCarrierManufacturingInput({
176
177
  workspaceRoot,
177
178
  additionalWorkspaces,
@@ -185,6 +186,7 @@ async function prepareWorkspaceCarrierCliCommand(flags = {}, workspaceRoot = '.'
185
186
  bootstrapMaxFiles: flags['bootstrap-max-files'],
186
187
  verifyRoundtrip,
187
188
  createdAt: flags['built-at'] || undefined,
189
+ projectedFilename,
188
190
  carrierLineage: Object.freeze({ ...initialHandoffCarrierLineage(), checkpointKind: 'progression', majorReason: '' }),
189
191
  carrierProfile
190
192
  }, runtime);
@@ -195,8 +197,13 @@ function projectWorkspaceCarrierHumanOutput(result = {}, flags = {}) {
195
197
  const projection = result.carrierProjection || {};
196
198
  const ready = result.status === 'ready' && projection.status === 'ready' && projection.mode === 'workspace' && (projection.routes || []).length === 0;
197
199
  const dimension = String(projection.lineage?.dimension || '001');
198
- const projectedFilename = String(flags['projected-filename'] || '').trim();
200
+ const projectedFilename = String(flags['projected-filename'] || flags.projectedFilename || result?.input?.projectedFilename || '').trim();
199
201
  const filename = projectedFilename || `tiinex-${dimension}.handoff-package.zip`;
202
+ // This is a basename-only presentation label; it does not define carrier lineage.
203
+ if (filename !== filename.trim() || !filename.endsWith('.handoff-package.zip') ||
204
+ /[<>:"/\\|?*\x00-\x1f\x7f]/.test(filename) || /[. ]$/.test(filename) ||
205
+ /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(filename) ||
206
+ new TextEncoder().encode(filename).byteLength > 255) throw new Error('portable.cli.workspace-carrier.filename.invalid');
200
207
  return Object.freeze({
201
208
  schema: 'tiinex.portable.handoff-human-output.v1',
202
209
  status: ready ? 'ready' : 'blocked',
@@ -4,13 +4,15 @@ import { sha256Hex } from '../../../../export/package.bytes.js';
4
4
  import { safeWorkspaceToken, serializableMetadata } from './handoff.manufacture.multiRoot.js';
5
5
 
6
6
  export const PORTABLE_NODE_WORKSPACE_ENUMERATION_SCHEMA_ID = 'tiinex.portable.node-workspace-enumeration.v1';
7
- export const DEFAULT_HANDOFF_MANUFACTURE_EXCLUDED_DIRECTORIES = Object.freeze(['.git', '.tiinex', 'node_modules', '.site-publish']);
7
+ export const DEFAULT_HANDOFF_MANUFACTURE_EXCLUDED_DIRECTORIES = Object.freeze(['.git', '.tiinex', 'node_modules', '.site-publish', '.release', '.outgoing-handoff-packages']);
8
+ export const DEFAULT_HANDOFF_MANUFACTURE_EXCLUDED_RELATIVE_PATHS = Object.freeze(['.vscode/link']);
8
9
  const DEFAULT_MAX_FILES = 10000;
9
10
 
10
11
  export async function enumerateNodeWorkspace(rootInput = '.', options = {}) {
11
12
  const root = path.resolve(String(rootInput || '.'));
12
13
  const maxFiles = positiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
13
14
  const excluded = new Set([...(options.excludeDirectories || DEFAULT_HANDOFF_MANUFACTURE_EXCLUDED_DIRECTORIES)].map(String));
15
+ const excludedPaths = new Set(options.excludeRelativePaths || DEFAULT_HANDOFF_MANUFACTURE_EXCLUDED_RELATIVE_PATHS);
14
16
  const queue = [root];
15
17
  const absoluteFiles = [];
16
18
  const skippedSymlinks = [];
@@ -21,6 +23,7 @@ export async function enumerateNodeWorkspace(rootInput = '.', options = {}) {
21
23
  for (const entry of entries) {
22
24
  if (entry.isDirectory() && excluded.has(entry.name)) continue;
23
25
  const absolute = path.join(current, entry.name);
26
+ if (excludedPaths.has(normalizeRelativePath(path.relative(root, absolute)))) continue;
24
27
  if (entry.isSymbolicLink()) { skippedSymlinks.push(normalizeRelativePath(path.relative(root, absolute))); continue; }
25
28
  if (entry.isDirectory()) queue.push(absolute);
26
29
  else if (entry.isFile()) absoluteFiles.push(absolute);
@@ -59,7 +62,7 @@ export async function enumerateNodeWorkspace(rootInput = '.', options = {}) {
59
62
  workspaceId,
60
63
  entryCount: includedEntries.length,
61
64
  totalBytes,
62
- exclusions: Object.freeze({ directories: Object.freeze([...excluded].sort()), symbolicLinks: 'excluded-and-reported' }),
65
+ exclusions: Object.freeze({ directories: Object.freeze([...excluded].sort()), relativePaths: Object.freeze([...excludedPaths].sort()), symbolicLinks: 'excluded-and-reported' }),
63
66
  skippedSymlinks: Object.freeze(skippedSymlinks.sort()),
64
67
  entriesFingerprint: sha256Text(stableJson(includedEntries))
65
68
  });