@orkestrel/study 0.0.2 → 0.0.3

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.
@@ -8,8 +8,8 @@ let _orkestrel_abort = require("@orkestrel/abort");
8
8
  * Keys the own self-identity every study error stamps on itself.
9
9
  * @remarks
10
10
  * The global symbol registry lets every package, ESM, CommonJS and captured copy read the same
11
- * key. The registry makes the key discoverable; it is a recognition mechanism, not an
12
- * unforgeable provenance marker.
11
+ * key. The registry makes the key discoverable; it recognizes the contract without proving
12
+ * its origin.
13
13
  */
14
14
  var STUDY_ERROR_BRAND = Symbol.for("@orkestrel/study.error");
15
15
  /** Caps a declared trial population before schedule allocation. */
@@ -24,6 +24,7 @@ var STUDY_ROLES = Object.freeze([
24
24
  "judge",
25
25
  "summary",
26
26
  "metadata",
27
+ "maintenance",
27
28
  "tool"
28
29
  ]);
29
30
  /** Lists every ceiling a run can stop at in report order. */
@@ -67,16 +68,18 @@ function omitStudyAbsent(value) {
67
68
  * ```
68
69
  */
69
70
  function normalizeStudyProfile(profile) {
70
- const { provider, qualification, settings, room, ...required } = profile;
71
+ const { provider, qualification, settings, record, room, ...required } = profile;
71
72
  return {
72
73
  ...required,
73
74
  room: omitStudyAbsent(room),
74
75
  ...provider === void 0 ? {} : { provider: {
75
76
  ...omitStudyAbsent(provider),
76
- digest: omitStudyAbsent(provider.digest)
77
+ digest: omitStudyAbsent(provider.digest),
78
+ ...provider.daemon === void 0 ? {} : { daemon: omitStudyAbsent(provider.daemon) }
77
79
  } },
78
80
  ...qualification === void 0 ? {} : { qualification },
79
- ...settings === void 0 ? {} : { settings }
81
+ ...settings === void 0 ? {} : { settings },
82
+ ...record === void 0 ? {} : { record }
80
83
  };
81
84
  }
82
85
  /**
@@ -418,15 +421,46 @@ function isStudyProvider(value) {
418
421
  "url",
419
422
  "model",
420
423
  "digest"
421
- ], ["judge"]) || ![
424
+ ], ["judge", "daemon"]) || ![
422
425
  "entry",
423
426
  "url",
424
427
  "model"
425
428
  ].every((key) => (0, _orkestrel_contract.isNonEmptyString)(value[key])) || typeof value.url !== "string" || !(0, _orkestrel_contract.isRecord)(value.digest) || !matchesStudyKeys(value.digest, ["model"], ["judge"]) || !isStudyDigest(value.digest.model) || value.judge === void 0 !== (value.digest.judge === void 0) || value.judge !== void 0 && (!(0, _orkestrel_contract.isNonEmptyString)(value.judge) || !isStudyDigest(value.digest.judge))) return false;
426
429
  const url = new URL(value.url);
430
+ if (value.daemon !== void 0) {
431
+ if (!isStudyDaemon(value.daemon) || !/^http:\/\/127\.0\.0\.1:[0-9]+\/?$/.test(value.url) || Number(url.port) <= 0 || Number(url.port) === 11434) return false;
432
+ const daemon = value.daemon;
433
+ const digest = value.digest;
434
+ if (!daemon.models.every((model) => model.name === value.model && model.digest === digest.model || value.judge !== void 0 && model.name === value.judge && model.digest === digest.judge) || !daemon.models.some((model) => model.name === value.model && model.digest === digest.model) || value.judge !== void 0 && !daemon.models.some((model) => model.name === value.judge && model.digest === digest.judge)) return false;
435
+ }
427
436
  return ["http:", "https:"].includes(url.protocol) && url.username === "" && url.password === "" && url.search === "" && url.hash === "" && url.pathname === "/";
428
437
  });
429
438
  }
439
+ /** Checks whether an owned daemon declaration pins an absolute executable and distinct models.
440
+ * @param value - The candidate declaration.
441
+ * @returns True if executable, version, environment, and model identities are valid; false otherwise.
442
+ * @example
443
+ * ```ts
444
+ * isStudyDaemon({ executable: 'ollama' }) // false
445
+ * ```
446
+ */
447
+ function isStudyDaemon(value) {
448
+ return (0, _orkestrel_contract.holds)(() => {
449
+ if (!(0, _orkestrel_contract.isRecord)(value) || !matchesStudyKeys(value, [
450
+ "executable",
451
+ "digest",
452
+ "version",
453
+ "models"
454
+ ], ["environment"]) || typeof value.executable !== "string" || !/^(?:[A-Za-z]:[\\/]|\/(?!\/)|\\\\[^\\]+\\[^\\]+\\)/.test(value.executable) || value.executable.includes("\0") || value.executable.split(/[\\/]/).some((part) => part === "." || part === "..") || !isStudyDigest(value.digest) || !(0, _orkestrel_contract.isNonEmptyString)(value.version) || value.version.trim().length === 0 || value.version.includes("\0") || !(0, _orkestrel_contract.isArray)(value.models) || value.models.length === 0 || !value.models.every((model) => (0, _orkestrel_contract.isRecord)(model) && matchesStudyKeys(model, ["name", "digest"]) && (0, _orkestrel_contract.isNonEmptyString)(model.name) && model.name.trim().length > 0 && !model.name.includes("\0") && isStudyDigest(model.digest))) return false;
455
+ if (new Set(value.models.map((model) => (0, _orkestrel_contract.isRecord)(model) ? model.name : void 0)).size !== value.models.length) return false;
456
+ if (value.environment !== void 0) {
457
+ if (!(0, _orkestrel_contract.isRecord)(value.environment) || !matchesStudyKeys(value.environment, [], Object.keys(value.environment))) return false;
458
+ const entries = Object.entries(value.environment);
459
+ if (new Set(entries.map(([name]) => name.toLowerCase())).size !== entries.length || entries.some(([name, entry]) => name.length === 0 || /[=\0]/.test(name) || typeof entry !== "string" || entry.includes("\0"))) return false;
460
+ }
461
+ return true;
462
+ });
463
+ }
430
464
  /**
431
465
  * Checks whether a profile carries finite bounds and an optional explicit provider.
432
466
  * @param value - The candidate profile
@@ -448,10 +482,18 @@ function isStudyProfile(value) {
448
482
  ], [
449
483
  "provider",
450
484
  "qualification",
451
- "settings"
452
- ]) && isStudyName(value.name) && (0, _orkestrel_contract.isNonEmptyString)(value.agent) && (0, _orkestrel_contract.isArray)(value.roots) && (0, _orkestrel_contract.isJSONValue)(value.roots) && value.roots.length > 0 && value.roots.every((root) => typeof root === "string" && root.trim().length > 0) && new Set(value.roots).size === value.roots.length && (0, _orkestrel_contract.isNonEmptyString)(value.subject) && isStudyBounds(value.bounds) && isStudyRoom(value.room) && (value.provider === void 0 || isStudyProvider(value.provider)) && (value.qualification === void 0 || (0, _orkestrel_contract.isNonEmptyString)(value.qualification)) && (value.settings === void 0 || (0, _orkestrel_contract.isRecord)(value.settings) && (0, _orkestrel_contract.isJSONValue)(value.settings));
485
+ "settings",
486
+ "record"
487
+ ]) && isStudyName(value.name) && (0, _orkestrel_contract.isNonEmptyString)(value.agent) && (0, _orkestrel_contract.isArray)(value.roots) && (0, _orkestrel_contract.isJSONValue)(value.roots) && value.roots.length > 0 && value.roots.every((root) => typeof root === "string" && root.trim().length > 0) && new Set(value.roots).size === value.roots.length && (0, _orkestrel_contract.isNonEmptyString)(value.subject) && isStudyBounds(value.bounds) && isStudyRoom(value.room) && (value.provider === void 0 || isStudyProvider(value.provider)) && (value.record === void 0 || isStudyRecord(value.record)) && (value.qualification === void 0 || (0, _orkestrel_contract.isNonEmptyString)(value.qualification)) && (value.settings === void 0 || (0, _orkestrel_contract.isRecord)(value.settings) && (0, _orkestrel_contract.isJSONValue)(value.settings));
453
488
  });
454
489
  }
490
+ /** Checks whether a recording declaration bounds every serialized sidecar byte.
491
+ * @param value - The candidate declaration.
492
+ * @returns True if its byte allowance is a positive safe integer; false otherwise.
493
+ */
494
+ function isStudyRecord(value) {
495
+ return (0, _orkestrel_contract.holds)(() => (0, _orkestrel_contract.isRecord)(value) && matchesStudyKeys(value, ["bytes"]) && typeof value.bytes === "number" && Number.isSafeInteger(value.bytes) && value.bytes > 0);
496
+ }
455
497
  /**
456
498
  * Checks whether a byte identity is a lowercase SHA-256 digest.
457
499
  * @param value - The candidate identity
@@ -650,9 +692,9 @@ var StudyError = class extends Error {
650
692
  * valid optional failure members, and an own {@link STUDY_ERROR_BRAND} descriptor whose value is
651
693
  * the error itself. Subclasses can replace the name.
652
694
  * The global key is recognized across package, ESM, CommonJS and captured module copies; it is
653
- * not unforgeable provenance. A transparent proxy is refused because its forwarded descriptor
695
+ * not proof of origin. A transparent proxy is refused because its forwarded descriptor
654
696
  * stores the target, and an unbranded copy, an inherited brand, or a property-only lookalike
655
- * stays outside the type. Hostile property access returns false instead of throwing.
697
+ * stays outside the type. Throwing property access returns false instead of throwing.
656
698
  * @param value - The caught value
657
699
  * @returns True if the value is a study error; false otherwise
658
700
  * @example
@@ -662,11 +704,12 @@ var StudyError = class extends Error {
662
704
  */
663
705
  function isStudyError(value) {
664
706
  return (0, _orkestrel_contract.holds)(() => {
665
- if (!(0, _orkestrel_contract.isError)(value) || _orkestrel_contract.INTRINSICS.prototype(value) === _orkestrel_contract.INTRINSICS.error.prototype) return false;
707
+ if (!(value instanceof _orkestrel_contract.INTRINSICS.error) || _orkestrel_contract.INTRINSICS.prototype(value) === _orkestrel_contract.INTRINSICS.error.prototype) return false;
666
708
  const brand = _orkestrel_contract.INTRINSICS.describe(value, STUDY_ERROR_BRAND)?.value;
667
709
  const code = _orkestrel_contract.INTRINSICS.reflect.read(value, "code");
668
710
  const failure = _orkestrel_contract.INTRINSICS.reflect.read(value, "failure");
669
- if (brand !== value || !isStudyErrorCode(code) || typeof _orkestrel_contract.INTRINSICS.reflect.read(value, "name") !== "string" || typeof _orkestrel_contract.INTRINSICS.reflect.read(value, "message") !== "string") return false;
711
+ const stack = _orkestrel_contract.INTRINSICS.reflect.read(value, "stack");
712
+ if (brand !== value || !isStudyErrorCode(code) || typeof _orkestrel_contract.INTRINSICS.reflect.read(value, "name") !== "string" || typeof _orkestrel_contract.INTRINSICS.reflect.read(value, "message") !== "string" || stack !== void 0 && typeof stack !== "string") return false;
670
713
  if (failure === void 0) return true;
671
714
  if (!(0, _orkestrel_contract.isObject)(failure)) return false;
672
715
  const cause = _orkestrel_contract.INTRINSICS.reflect.read(failure, "cause");
@@ -680,7 +723,7 @@ function isStudyError(value) {
680
723
  const id = _orkestrel_contract.INTRINSICS.reflect.read(stop, "id");
681
724
  const max = _orkestrel_contract.INTRINSICS.reflect.read(stop, "max");
682
725
  const consumed = _orkestrel_contract.INTRINSICS.reflect.read(stop, "consumed");
683
- return isStudyLayer(layer) && typeof id === "string" && (max === void 0 || (0, _orkestrel_contract.isFiniteNumber)(max)) && (consumed === void 0 || (0, _orkestrel_contract.isFiniteNumber)(consumed));
726
+ return isStudyLayer(layer) && typeof id === "string" && (max === void 0 || (0, _orkestrel_contract.isNumber)(max)) && (consumed === void 0 || (0, _orkestrel_contract.isNumber)(consumed));
684
727
  });
685
728
  }
686
729
  //#endregion
@@ -945,8 +988,8 @@ function computeStudyOutputStop(bytes, limit, outputs) {
945
988
  };
946
989
  }
947
990
  /**
948
- * Records an error that escaped admitted work as the failure of its ticket.
949
- * @param ticket - The admitted request whose work escaped
991
+ * Records an error thrown by admitted work as the failure of its ticket.
992
+ * @param ticket - The admitted request whose work threw
950
993
  * @param error - The caught value, read through `readStudyFailure`
951
994
  * @param role - The responsibility that replaces any role the reading carries; Default: the carried role, else the ticket's admitted role
952
995
  * @remarks
@@ -955,7 +998,7 @@ function computeStudyOutputStop(bytes, limit, outputs) {
955
998
  * so the parent's ownership is respected rather than inferred as local settlement. A refusal
956
999
  * thrown by the ticket's own settlement propagates.
957
1000
  * @throws Thrown when the ticket's settlement refuses the failure.
958
- * @example Fail an escaped request
1001
+ * @example Fail an admitted request
959
1002
  * ```ts
960
1003
  * import type { StudyTicket } from '@orkestrel/study'
961
1004
  * import { failStudyTicket } from '@orkestrel/study'
@@ -2065,6 +2108,7 @@ exports.isStudyAgentRuntime = isStudyAgentRuntime;
2065
2108
  exports.isStudyBounds = isStudyBounds;
2066
2109
  exports.isStudyCause = isStudyCause;
2067
2110
  exports.isStudyCriterion = isStudyCriterion;
2111
+ exports.isStudyDaemon = isStudyDaemon;
2068
2112
  exports.isStudyDefinition = isStudyDefinition;
2069
2113
  exports.isStudyDigest = isStudyDigest;
2070
2114
  exports.isStudyError = isStudyError;
@@ -2079,6 +2123,7 @@ exports.isStudyName = isStudyName;
2079
2123
  exports.isStudyProduct = isStudyProduct;
2080
2124
  exports.isStudyProfile = isStudyProfile;
2081
2125
  exports.isStudyProvider = isStudyProvider;
2126
+ exports.isStudyRecord = isStudyRecord;
2082
2127
  exports.isStudyRole = isStudyRole;
2083
2128
  exports.isStudyRoom = isStudyRoom;
2084
2129
  exports.isStudyRubric = isStudyRubric;