@tiinex/core 0.7.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.7.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": "c08cb2e85827e3b8565225208284933d97256d5f",
170
+ "gitHead": "6a139559c7cb3d809b2ecf0482d0ae42243aa609",
171
171
  "tiinexRelease": {
172
172
  "policy": "tiinex.master-npm-release.v1",
173
- "sourceCommit": "c08cb2e85827e3b8565225208284933d97256d5f",
174
- "sourceTree": "3cca44f889324a87400993c4e727c840e7cdc07e",
173
+ "sourceCommit": "6a139559c7cb3d809b2ecf0482d0ae42243aa609",
174
+ "sourceTree": "ec876301e7b78eaf85e8cbf9aba91dba873c2b3b",
175
175
  "repository": "Tiinex/core",
176
- "previousVersion": "0.6.0"
176
+ "previousVersion": "0.7.0"
177
177
  }
178
178
  }
@@ -199,6 +199,11 @@ function projectWorkspaceCarrierHumanOutput(result = {}, flags = {}) {
199
199
  const dimension = String(projection.lineage?.dimension || '001');
200
200
  const projectedFilename = String(flags['projected-filename'] || flags.projectedFilename || result?.input?.projectedFilename || '').trim();
201
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');
202
207
  return Object.freeze({
203
208
  schema: 'tiinex.portable.handoff-human-output.v1',
204
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
  });