@traits-dev/core 0.3.0 → 0.4.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/dist/{index-CFhdB_nQ.d.cts → index-Ct4kuPk7.d.cts} +11 -4
- package/dist/{index-CFhdB_nQ.d.ts → index-Ct4kuPk7.d.ts} +11 -4
- package/dist/index.cjs +271 -71
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +271 -71
- package/dist/internal.cjs +272 -72
- package/dist/internal.d.cts +2 -2
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +272 -72
- package/package.json +1 -1
package/dist/internal.cjs
CHANGED
|
@@ -116,6 +116,37 @@ function isClaudeModel(model) {
|
|
|
116
116
|
function isGptModel(model) {
|
|
117
117
|
return /gpt/i.test(String(model ?? ""));
|
|
118
118
|
}
|
|
119
|
+
function isLockedRule(value) {
|
|
120
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
121
|
+
const candidate = value;
|
|
122
|
+
if (typeof candidate.rule !== "string" || candidate.rule.trim().length === 0) return false;
|
|
123
|
+
if (candidate.locked != null && typeof candidate.locked !== "boolean") return false;
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
function ruleConstraintText(entry) {
|
|
127
|
+
if (typeof entry === "string") {
|
|
128
|
+
const text = entry.trim();
|
|
129
|
+
return text.length > 0 ? text : null;
|
|
130
|
+
}
|
|
131
|
+
if (isLockedRule(entry)) {
|
|
132
|
+
return entry.rule.trim();
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
function normalizeRuleConstraints(value) {
|
|
137
|
+
const out = [];
|
|
138
|
+
for (const entry of asArray(value)) {
|
|
139
|
+
if (typeof entry === "string") {
|
|
140
|
+
const text = entry.trim();
|
|
141
|
+
if (!text) continue;
|
|
142
|
+
out.push({ rule: text, locked: false });
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (!isLockedRule(entry)) continue;
|
|
146
|
+
out.push({ rule: entry.rule.trim(), locked: Boolean(entry.locked) });
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
119
150
|
|
|
120
151
|
// src/profile/merge.ts
|
|
121
152
|
var PASS_THROUGH_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -131,17 +162,6 @@ var PASS_THROUGH_FIELDS = /* @__PURE__ */ new Set([
|
|
|
131
162
|
"behavioral_rules_remove",
|
|
132
163
|
"context_adaptations_remove"
|
|
133
164
|
]);
|
|
134
|
-
function dedupExact(items) {
|
|
135
|
-
const seen = /* @__PURE__ */ new Set();
|
|
136
|
-
const out = [];
|
|
137
|
-
for (const item of items) {
|
|
138
|
-
const key = String(item);
|
|
139
|
-
if (seen.has(key)) continue;
|
|
140
|
-
seen.add(key);
|
|
141
|
-
out.push(item);
|
|
142
|
-
}
|
|
143
|
-
return out;
|
|
144
|
-
}
|
|
145
165
|
function dedupCaseInsensitive(items) {
|
|
146
166
|
const seen = /* @__PURE__ */ new Set();
|
|
147
167
|
const out = [];
|
|
@@ -184,8 +204,29 @@ function mergeVocabulary(parentVocab = {}, childVocab = {}) {
|
|
|
184
204
|
if (mergedForbidden.length) merged.forbidden_terms = mergedForbidden;
|
|
185
205
|
return merged;
|
|
186
206
|
}
|
|
207
|
+
function mergeRuleConstraints(parentRules = [], childRules = [], options) {
|
|
208
|
+
const out = [];
|
|
209
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
210
|
+
const combined = [
|
|
211
|
+
...normalizeRuleConstraints(parentRules),
|
|
212
|
+
...normalizeRuleConstraints(childRules)
|
|
213
|
+
];
|
|
214
|
+
for (const entry of combined) {
|
|
215
|
+
const key = options.caseInsensitive ? entry.rule.toLowerCase() : entry.rule;
|
|
216
|
+
const existingIndex = byKey.get(key);
|
|
217
|
+
if (existingIndex == null) {
|
|
218
|
+
byKey.set(key, out.length);
|
|
219
|
+
out.push({ rule: entry.rule, locked: entry.locked });
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
out[existingIndex].locked = out[existingIndex].locked || entry.locked;
|
|
223
|
+
}
|
|
224
|
+
return out.map(
|
|
225
|
+
(entry) => entry.locked ? { rule: entry.rule, locked: true } : entry.rule
|
|
226
|
+
);
|
|
227
|
+
}
|
|
187
228
|
function mergeBehavioralRules(parentRules = [], childRules = []) {
|
|
188
|
-
return
|
|
229
|
+
return mergeRuleConstraints(parentRules, childRules, { caseInsensitive: false });
|
|
189
230
|
}
|
|
190
231
|
function mergeContextAdaptations(parentAdaptations = [], childAdaptations = []) {
|
|
191
232
|
const base = asArray(parentAdaptations).map((item) => clone(item));
|
|
@@ -217,13 +258,13 @@ function mergeCapabilities(parentCapabilities, childCapabilities) {
|
|
|
217
258
|
...asArray(parentCapabilities.tools),
|
|
218
259
|
...asArray(childCapabilities.tools)
|
|
219
260
|
]);
|
|
220
|
-
const mergedConstraints = dedupCaseInsensitive([
|
|
221
|
-
...asArray(parentCapabilities.constraints),
|
|
222
|
-
...asArray(childCapabilities.constraints)
|
|
223
|
-
]);
|
|
224
261
|
return {
|
|
225
262
|
tools: mergedTools,
|
|
226
|
-
constraints:
|
|
263
|
+
constraints: mergeRuleConstraints(
|
|
264
|
+
parentCapabilities.constraints,
|
|
265
|
+
childCapabilities.constraints,
|
|
266
|
+
{ caseInsensitive: true }
|
|
267
|
+
),
|
|
227
268
|
handoff: {
|
|
228
269
|
trigger: childCapabilities.handoff?.trigger ?? parentCapabilities.handoff?.trigger ?? "",
|
|
229
270
|
action: childCapabilities.handoff?.action ?? parentCapabilities.handoff?.action ?? ""
|
|
@@ -246,9 +287,15 @@ function applyExplicitRemovals(childProfile, mergedProfile) {
|
|
|
246
287
|
);
|
|
247
288
|
const childAdaptationRemovals = asArray(childProfile.context_adaptations_remove);
|
|
248
289
|
if (childBehavioralRemovals.length) {
|
|
249
|
-
mergedProfile.behavioral_rules = asArray(
|
|
250
|
-
|
|
251
|
-
)
|
|
290
|
+
mergedProfile.behavioral_rules = asArray(
|
|
291
|
+
mergedProfile.behavioral_rules
|
|
292
|
+
).filter((ruleEntry) => {
|
|
293
|
+
const ruleText = ruleConstraintText(ruleEntry);
|
|
294
|
+
if (!ruleText) return false;
|
|
295
|
+
if (!childBehavioralRemovals.includes(ruleText)) return true;
|
|
296
|
+
if (typeof ruleEntry === "object" && ruleEntry.locked === true) return true;
|
|
297
|
+
return false;
|
|
298
|
+
});
|
|
252
299
|
}
|
|
253
300
|
if (childForbiddenRemovals.length) {
|
|
254
301
|
const nextForbidden = removeCaseInsensitive(
|
|
@@ -303,37 +350,89 @@ function mergeProfiles(parentProfile, childProfile) {
|
|
|
303
350
|
}
|
|
304
351
|
|
|
305
352
|
// src/profile/extends.ts
|
|
353
|
+
function normalizeExtendsTargets(value) {
|
|
354
|
+
if (value == null) return [];
|
|
355
|
+
if (typeof value === "string") {
|
|
356
|
+
return value.trim().length > 0 ? [value] : null;
|
|
357
|
+
}
|
|
358
|
+
if (!Array.isArray(value) || value.length === 0) return null;
|
|
359
|
+
const targets = [];
|
|
360
|
+
for (const item of value) {
|
|
361
|
+
if (typeof item !== "string" || item.trim().length === 0) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
targets.push(item);
|
|
365
|
+
}
|
|
366
|
+
return targets;
|
|
367
|
+
}
|
|
306
368
|
function resolveExtends(profilePath, options = {}) {
|
|
307
369
|
const diagnostics = { warnings: [], errors: [] };
|
|
308
370
|
const childProfile = loadProfileFile(profilePath);
|
|
309
|
-
|
|
371
|
+
const extendsTargets = normalizeExtendsTargets(childProfile?.extends);
|
|
372
|
+
if (!extendsTargets || extendsTargets.length === 0) {
|
|
310
373
|
return {
|
|
311
374
|
profile: childProfile,
|
|
312
375
|
parentPath: null,
|
|
376
|
+
parentPaths: [],
|
|
377
|
+
parentProfile: null,
|
|
313
378
|
diagnostics
|
|
314
379
|
};
|
|
315
380
|
}
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
381
|
+
const parentPaths = [];
|
|
382
|
+
let mergedParent = null;
|
|
383
|
+
for (const extendsName of extendsTargets) {
|
|
384
|
+
const parentPath = resolveParentPath(profilePath, extendsName, options);
|
|
385
|
+
if (!parentPath) {
|
|
386
|
+
diagnostics.errors.push({
|
|
387
|
+
code: "E_RESOLVE_EXTENDS",
|
|
388
|
+
severity: "error",
|
|
389
|
+
message: `Unable to resolve parent profile "${extendsName}".`
|
|
390
|
+
});
|
|
391
|
+
return {
|
|
392
|
+
profile: childProfile,
|
|
393
|
+
parentPath: parentPaths[0] ?? null,
|
|
394
|
+
parentPaths,
|
|
395
|
+
parentProfile: null,
|
|
396
|
+
diagnostics
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
const parentProfile2 = loadProfileFile(parentPath);
|
|
400
|
+
if (parentProfile2?.extends) {
|
|
401
|
+
diagnostics.errors.push({
|
|
402
|
+
code: "E_EXTENDS_CHAIN",
|
|
403
|
+
severity: "error",
|
|
404
|
+
message: "extends chains are not supported in MVP."
|
|
405
|
+
});
|
|
406
|
+
return {
|
|
407
|
+
profile: childProfile,
|
|
408
|
+
parentPath: parentPaths[0] ?? parentPath,
|
|
409
|
+
parentPaths: [...parentPaths, parentPath],
|
|
410
|
+
parentProfile: null,
|
|
411
|
+
diagnostics
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
parentPaths.push(parentPath);
|
|
415
|
+
mergedParent = mergedParent ? mergeProfiles(mergedParent, parentProfile2) : parentProfile2;
|
|
416
|
+
}
|
|
417
|
+
const parentProfile = mergedParent;
|
|
418
|
+
if (!parentProfile) {
|
|
419
|
+
return {
|
|
420
|
+
profile: childProfile,
|
|
421
|
+
parentPath: null,
|
|
422
|
+
parentPaths: [],
|
|
423
|
+
parentProfile: null,
|
|
424
|
+
diagnostics
|
|
425
|
+
};
|
|
333
426
|
}
|
|
334
427
|
const merged = mergeProfiles(parentProfile, childProfile);
|
|
335
428
|
delete merged.extends;
|
|
336
|
-
return {
|
|
429
|
+
return {
|
|
430
|
+
profile: merged,
|
|
431
|
+
parentPath: parentPaths[0] ?? null,
|
|
432
|
+
parentPaths,
|
|
433
|
+
parentProfile,
|
|
434
|
+
diagnostics
|
|
435
|
+
};
|
|
337
436
|
}
|
|
338
437
|
|
|
339
438
|
// src/profile/normalize.ts
|
|
@@ -378,7 +477,7 @@ function resolveActiveContext(profile, context = {}) {
|
|
|
378
477
|
|
|
379
478
|
// src/validator/overspec.ts
|
|
380
479
|
function computeConstraintCount(profile) {
|
|
381
|
-
const behavioralRules =
|
|
480
|
+
const behavioralRules = normalizeRuleConstraints(profile?.behavioral_rules).length;
|
|
382
481
|
const preferredTerms = asArray(profile?.vocabulary?.preferred_terms).length;
|
|
383
482
|
const forbiddenTerms = asArray(profile?.vocabulary?.forbidden_terms).length;
|
|
384
483
|
const contextAdaptations = asArray(profile?.context_adaptations).length;
|
|
@@ -420,7 +519,7 @@ function checkOverspec(profile) {
|
|
|
420
519
|
|
|
421
520
|
// src/validator/schema.ts
|
|
422
521
|
var HUMOR_STYLES = ["none", "dry", "subtle-wit", "playful"];
|
|
423
|
-
var SUPPORTED_SCHEMAS = /* @__PURE__ */ new Set(["v1.4", "v1.5"]);
|
|
522
|
+
var SUPPORTED_SCHEMAS = /* @__PURE__ */ new Set(["v1.4", "v1.5", "v1.6"]);
|
|
424
523
|
var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
425
524
|
"schema",
|
|
426
525
|
"meta",
|
|
@@ -452,6 +551,9 @@ function isString(value) {
|
|
|
452
551
|
function isStringArray(value) {
|
|
453
552
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
454
553
|
}
|
|
554
|
+
function isNonEmptyStringArray(value) {
|
|
555
|
+
return Array.isArray(value) && value.length > 0 && value.every((item) => typeof item === "string" && item.trim().length > 0);
|
|
556
|
+
}
|
|
455
557
|
function pushDiagnostic(target, code, message, location) {
|
|
456
558
|
target.push({
|
|
457
559
|
code,
|
|
@@ -477,6 +579,66 @@ function validateScalarField(parent, key, location, diagnostics) {
|
|
|
477
579
|
);
|
|
478
580
|
}
|
|
479
581
|
}
|
|
582
|
+
function validateRuleConstraintArray(value, field, diagnostics, options) {
|
|
583
|
+
if (!Array.isArray(value)) {
|
|
584
|
+
pushDiagnostic(
|
|
585
|
+
diagnostics,
|
|
586
|
+
"V001",
|
|
587
|
+
`Expected "${field}" to be an array`,
|
|
588
|
+
field
|
|
589
|
+
);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
value.forEach((entry, idx) => {
|
|
593
|
+
const location = `${field}[${idx}]`;
|
|
594
|
+
if (typeof entry === "string") return;
|
|
595
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
596
|
+
pushDiagnostic(
|
|
597
|
+
diagnostics,
|
|
598
|
+
"V001",
|
|
599
|
+
`Expected "${location}" to be a string or { rule, locked? } object`,
|
|
600
|
+
location
|
|
601
|
+
);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (!options.allowObjects) {
|
|
605
|
+
pushDiagnostic(
|
|
606
|
+
diagnostics,
|
|
607
|
+
"V001",
|
|
608
|
+
`Object rule entries in "${field}" require schema version "v1.6"`,
|
|
609
|
+
location
|
|
610
|
+
);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const ruleObject = entry;
|
|
614
|
+
for (const key of Object.keys(ruleObject)) {
|
|
615
|
+
if (key !== "rule" && key !== "locked") {
|
|
616
|
+
pushDiagnostic(
|
|
617
|
+
diagnostics,
|
|
618
|
+
"V001",
|
|
619
|
+
`Unknown key "${key}" in ${location}`,
|
|
620
|
+
`${location}.${key}`
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
if (!isString(ruleObject.rule)) {
|
|
625
|
+
pushDiagnostic(
|
|
626
|
+
diagnostics,
|
|
627
|
+
"V001",
|
|
628
|
+
`Expected "${location}.rule" to be a non-empty string`,
|
|
629
|
+
`${location}.rule`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
if (ruleObject.locked != null && typeof ruleObject.locked !== "boolean") {
|
|
633
|
+
pushDiagnostic(
|
|
634
|
+
diagnostics,
|
|
635
|
+
"V001",
|
|
636
|
+
`Expected "${location}.locked" to be a boolean`,
|
|
637
|
+
`${location}.locked`
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
}
|
|
480
642
|
function validateDimensionValue(value, dimension, location, dimensionsDiagnostics, rangeDiagnostics) {
|
|
481
643
|
if (typeof value === "string") {
|
|
482
644
|
if (!LEVEL_INDEX.has(value)) {
|
|
@@ -627,13 +789,25 @@ function validateSchema(profile) {
|
|
|
627
789
|
"schema"
|
|
628
790
|
);
|
|
629
791
|
}
|
|
630
|
-
if (profile.extends != null
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
792
|
+
if (profile.extends != null) {
|
|
793
|
+
const isStringExtends = isString(profile.extends);
|
|
794
|
+
const isArrayExtends = isNonEmptyStringArray(profile.extends);
|
|
795
|
+
if (!isStringExtends && !isArrayExtends) {
|
|
796
|
+
pushDiagnostic(
|
|
797
|
+
structureDiagnostics,
|
|
798
|
+
"V001",
|
|
799
|
+
`Expected "extends" to be a non-empty string or non-empty array of non-empty strings`,
|
|
800
|
+
"extends"
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
if (Array.isArray(profile.extends) && profile.schema !== "v1.6") {
|
|
804
|
+
pushDiagnostic(
|
|
805
|
+
structureDiagnostics,
|
|
806
|
+
"V001",
|
|
807
|
+
`Array "extends" requires schema version "v1.6"`,
|
|
808
|
+
"extends"
|
|
809
|
+
);
|
|
810
|
+
}
|
|
637
811
|
}
|
|
638
812
|
if (!isObject(profile.meta)) {
|
|
639
813
|
pushDiagnostic(structureDiagnostics, "V001", `Missing required "meta" section`, "meta");
|
|
@@ -759,20 +933,17 @@ function validateSchema(profile) {
|
|
|
759
933
|
}
|
|
760
934
|
}
|
|
761
935
|
}
|
|
762
|
-
if (profile.behavioral_rules != null
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
`Expected "behavioral_rules" to be an array of strings`,
|
|
767
|
-
"behavioral_rules"
|
|
768
|
-
);
|
|
936
|
+
if (profile.behavioral_rules != null) {
|
|
937
|
+
validateRuleConstraintArray(profile.behavioral_rules, "behavioral_rules", structureDiagnostics, {
|
|
938
|
+
allowObjects: profile.schema === "v1.6"
|
|
939
|
+
});
|
|
769
940
|
}
|
|
770
941
|
if (profile.capabilities != null) {
|
|
771
|
-
if (profile.schema !== "v1.5") {
|
|
942
|
+
if (profile.schema !== "v1.5" && profile.schema !== "v1.6") {
|
|
772
943
|
pushDiagnostic(
|
|
773
944
|
structureDiagnostics,
|
|
774
945
|
"V001",
|
|
775
|
-
`The "capabilities" section requires schema version "v1.5"`,
|
|
946
|
+
`The "capabilities" section requires schema version "v1.5" or "v1.6"`,
|
|
776
947
|
"capabilities"
|
|
777
948
|
);
|
|
778
949
|
}
|
|
@@ -802,13 +973,20 @@ function validateSchema(profile) {
|
|
|
802
973
|
"capabilities.tools"
|
|
803
974
|
);
|
|
804
975
|
}
|
|
805
|
-
if (
|
|
976
|
+
if (profile.capabilities.constraints == null) {
|
|
806
977
|
pushDiagnostic(
|
|
807
978
|
structureDiagnostics,
|
|
808
979
|
"V001",
|
|
809
|
-
`Expected "capabilities.constraints" to be an array
|
|
980
|
+
`Expected "capabilities.constraints" to be an array`,
|
|
810
981
|
"capabilities.constraints"
|
|
811
982
|
);
|
|
983
|
+
} else {
|
|
984
|
+
validateRuleConstraintArray(
|
|
985
|
+
profile.capabilities.constraints,
|
|
986
|
+
"capabilities.constraints",
|
|
987
|
+
structureDiagnostics,
|
|
988
|
+
{ allowObjects: profile.schema === "v1.6" }
|
|
989
|
+
);
|
|
812
990
|
}
|
|
813
991
|
if (!isObject(profile.capabilities.handoff)) {
|
|
814
992
|
pushDiagnostic(
|
|
@@ -1105,7 +1283,9 @@ function collectS001Candidates(profile) {
|
|
|
1105
1283
|
text: normalizeText(profile.identity.backstory)
|
|
1106
1284
|
});
|
|
1107
1285
|
}
|
|
1108
|
-
asArray(profile?.behavioral_rules).forEach((
|
|
1286
|
+
asArray(profile?.behavioral_rules).forEach((ruleEntry, idx) => {
|
|
1287
|
+
const rule = ruleConstraintText(ruleEntry);
|
|
1288
|
+
if (!rule) return;
|
|
1109
1289
|
candidates.push({
|
|
1110
1290
|
location: `behavioral_rules[${idx}]`,
|
|
1111
1291
|
text: normalizeText(rule)
|
|
@@ -1125,7 +1305,9 @@ function collectS001Candidates(profile) {
|
|
|
1125
1305
|
}
|
|
1126
1306
|
function collectS005Candidates(profile) {
|
|
1127
1307
|
const candidates = [];
|
|
1128
|
-
asArray(profile?.behavioral_rules).forEach((
|
|
1308
|
+
asArray(profile?.behavioral_rules).forEach((ruleEntry, idx) => {
|
|
1309
|
+
const rule = ruleConstraintText(ruleEntry);
|
|
1310
|
+
if (!rule) return;
|
|
1129
1311
|
candidates.push({
|
|
1130
1312
|
location: `behavioral_rules[${idx}]`,
|
|
1131
1313
|
text: normalizeText(rule)
|
|
@@ -1157,7 +1339,9 @@ function collectS005Candidates(profile) {
|
|
|
1157
1339
|
}
|
|
1158
1340
|
function collectS008Candidates(profile) {
|
|
1159
1341
|
const candidates = [];
|
|
1160
|
-
asArray(profile?.behavioral_rules).forEach((
|
|
1342
|
+
asArray(profile?.behavioral_rules).forEach((ruleEntry, idx) => {
|
|
1343
|
+
const rule = ruleConstraintText(ruleEntry);
|
|
1344
|
+
if (!rule) return;
|
|
1161
1345
|
candidates.push({
|
|
1162
1346
|
location: `behavioral_rules[${idx}]`,
|
|
1163
1347
|
text: normalizeText(rule)
|
|
@@ -1301,6 +1485,19 @@ function checkS006(parentProfile, childProfile, mergedProfile) {
|
|
|
1301
1485
|
severity: "warning",
|
|
1302
1486
|
message: "Explicit behavioral_rules_remove detected. Behavioral rules are safety-relevant."
|
|
1303
1487
|
});
|
|
1488
|
+
const lockedParentRules = new Set(
|
|
1489
|
+
normalizeRuleConstraints(parentProfile.behavioral_rules).filter((rule) => rule.locked).map((rule) => rule.rule)
|
|
1490
|
+
);
|
|
1491
|
+
const lockedRemovals = childBehavioralRemovals.filter(
|
|
1492
|
+
(rule) => lockedParentRules.has(rule)
|
|
1493
|
+
);
|
|
1494
|
+
if (lockedRemovals.length > 0) {
|
|
1495
|
+
diagnostics.push({
|
|
1496
|
+
code: "S006",
|
|
1497
|
+
severity: "error",
|
|
1498
|
+
message: `behavioral_rules_remove attempted to remove locked inherited rules: ${lockedRemovals.join("; ")}`
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1304
1501
|
}
|
|
1305
1502
|
if (childForbiddenRemovals.length) {
|
|
1306
1503
|
diagnostics.push({
|
|
@@ -1309,9 +1506,9 @@ function checkS006(parentProfile, childProfile, mergedProfile) {
|
|
|
1309
1506
|
message: "Explicit vocabulary.forbidden_terms_remove detected. Forbidden terms are safety-relevant."
|
|
1310
1507
|
});
|
|
1311
1508
|
}
|
|
1312
|
-
const parentBehavioralCount =
|
|
1509
|
+
const parentBehavioralCount = normalizeRuleConstraints(parentProfile.behavioral_rules).length;
|
|
1313
1510
|
const parentForbiddenCount = asArray(parentProfile?.vocabulary?.forbidden_terms).length;
|
|
1314
|
-
const mergedBehavioralCount =
|
|
1511
|
+
const mergedBehavioralCount = normalizeRuleConstraints(mergedProfile.behavioral_rules).length;
|
|
1315
1512
|
const mergedForbiddenCount = asArray(mergedProfile?.vocabulary?.forbidden_terms).length;
|
|
1316
1513
|
if (mergedBehavioralCount < parentBehavioralCount || mergedForbiddenCount < parentForbiddenCount) {
|
|
1317
1514
|
diagnostics.push({
|
|
@@ -1481,11 +1678,10 @@ function validateProfile(profilePath, options = {}) {
|
|
|
1481
1678
|
(diagnostic) => normalizeDiagnosticSeverity(diagnostic, "error")
|
|
1482
1679
|
);
|
|
1483
1680
|
let s006Diagnostics = [];
|
|
1484
|
-
if (resolvedErrors.length === 0 && resolved.
|
|
1681
|
+
if (resolvedErrors.length === 0 && resolved.parentProfile) {
|
|
1485
1682
|
try {
|
|
1486
1683
|
const childProfile = loadProfileFile(profilePath);
|
|
1487
|
-
|
|
1488
|
-
s006Diagnostics = checkS006(parentProfile, childProfile, resolved.profile);
|
|
1684
|
+
s006Diagnostics = checkS006(resolved.parentProfile, childProfile, resolved.profile);
|
|
1489
1685
|
} catch (error) {
|
|
1490
1686
|
s006Diagnostics = [
|
|
1491
1687
|
{
|
|
@@ -1847,7 +2043,7 @@ function renderPersonalityText(profile, model, contextResolution, compileOptions
|
|
|
1847
2043
|
lines.push(`Protected refusal terms (always available): ${PROTECTED_REFUSAL_TERMS.join("; ")}`);
|
|
1848
2044
|
lines.push("");
|
|
1849
2045
|
lines.push("[BEHAVIORAL RULES]");
|
|
1850
|
-
const rules =
|
|
2046
|
+
const rules = normalizeRuleConstraints(profile.behavioral_rules).map((entry) => entry.rule);
|
|
1851
2047
|
if (rules.length === 0) {
|
|
1852
2048
|
lines.push("- (none)");
|
|
1853
2049
|
} else {
|
|
@@ -1855,10 +2051,12 @@ function renderPersonalityText(profile, model, contextResolution, compileOptions
|
|
|
1855
2051
|
lines.push(`- ${rule}`);
|
|
1856
2052
|
}
|
|
1857
2053
|
}
|
|
1858
|
-
if (profile.schema === "v1.5" && profile.capabilities) {
|
|
2054
|
+
if ((profile.schema === "v1.5" || profile.schema === "v1.6") && profile.capabilities) {
|
|
1859
2055
|
const capabilities = profile.capabilities;
|
|
1860
2056
|
const tools = asArray(capabilities.tools);
|
|
1861
|
-
const constraints =
|
|
2057
|
+
const constraints = normalizeRuleConstraints(capabilities.constraints).map(
|
|
2058
|
+
(entry) => entry.rule
|
|
2059
|
+
);
|
|
1862
2060
|
lines.push("");
|
|
1863
2061
|
lines.push("[CAPABILITY BOUNDARIES]");
|
|
1864
2062
|
lines.push(
|
|
@@ -2152,7 +2350,7 @@ function evaluateTier1Response(profile, responseText, options = {}) {
|
|
|
2152
2350
|
forbidden_matched: forbiddenMatches,
|
|
2153
2351
|
pass: forbiddenMatches === 0
|
|
2154
2352
|
};
|
|
2155
|
-
const behavioralRules =
|
|
2353
|
+
const behavioralRules = normalizeRuleConstraints(profile?.behavioral_rules);
|
|
2156
2354
|
const structureCheck = {
|
|
2157
2355
|
behavioral_rule_count: behavioralRules.length,
|
|
2158
2356
|
response_non_empty: response.trim().length > 0,
|
|
@@ -2834,7 +3032,9 @@ function buildJudgeUserPrompt(profile, sample) {
|
|
|
2834
3032
|
const targets = collectVoiceTargets(profile);
|
|
2835
3033
|
const preferredTerms = asArray(profile?.vocabulary?.preferred_terms);
|
|
2836
3034
|
const forbiddenTerms = asArray(profile?.vocabulary?.forbidden_terms);
|
|
2837
|
-
const behavioralRules =
|
|
3035
|
+
const behavioralRules = normalizeRuleConstraints(profile?.behavioral_rules).map(
|
|
3036
|
+
(entry) => entry.rule
|
|
3037
|
+
);
|
|
2838
3038
|
return [
|
|
2839
3039
|
`Profile: ${profile?.meta?.name ?? "unknown"}`,
|
|
2840
3040
|
`Role: ${profile?.identity?.role ?? "assistant"}`,
|
package/dist/internal.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { V as ValidationResult, a as ValidationCheckSummary, b as ValidationDiagnostic, P as PersonalityProfile, r as runTier1Evaluation, E as EvalScenario } from './index-
|
|
2
|
-
export { C as CapabilityHandoff, c as CompileOptions, d as CompiledPersonality, e as ContextAdaptation, f as ContextResolution, D as DimensionName, g as DimensionObject, h as DimensionShorthand, i as DimensionValue, j as EvalSample, k as ExtendsDiagnostics, l as ExtendsResult, H as HumorDimensionObject, m as HumorDimensionValue, n as HumorStyle, I as ImportOptions, L as Level, o as ProfileCapabilities, T as Tier1Options,
|
|
1
|
+
import { V as ValidationResult, a as ValidationCheckSummary, b as ValidationDiagnostic, P as PersonalityProfile, r as runTier1Evaluation, E as EvalScenario } from './index-Ct4kuPk7.cjs';
|
|
2
|
+
export { C as CapabilityHandoff, c as CompileOptions, d as CompiledPersonality, e as ContextAdaptation, f as ContextResolution, D as DimensionName, g as DimensionObject, h as DimensionShorthand, i as DimensionValue, j as EvalSample, k as ExtendsDiagnostics, l as ExtendsResult, H as HumorDimensionObject, m as HumorDimensionValue, n as HumorStyle, I as ImportOptions, L as Level, o as LockedRule, p as ProfileCapabilities, R as RuleConstraint, T as Tier1Options, q as Tier2Options, s as Tier3Options, t as VocabularyConstraints, u as compileProfile, v as compileResolvedProfile, w as evaluateTier1Response, x as injectPersonality, y as loadProfileFile, z as mapImportAnalysisToProfile, A as normalizeProfile, B as renderImportedProfileYAML, F as resolveActiveContext, G as resolveExtends, J as runImportAnalysis, K as runTier1EvaluationForProfile, M as runTier2Evaluation, N as runTier2EvaluationForProfile, O as runTier3Evaluation, Q as runTier3EvaluationForProfile, S as validateEvalScenario, U as validateEvalScenarios, W as validateProfile, X as validateResolvedProfile } from './index-Ct4kuPk7.cjs';
|
|
3
3
|
|
|
4
4
|
type ValidationResultObject = {
|
|
5
5
|
profilePath: string | null;
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { V as ValidationResult, a as ValidationCheckSummary, b as ValidationDiagnostic, P as PersonalityProfile, r as runTier1Evaluation, E as EvalScenario } from './index-
|
|
2
|
-
export { C as CapabilityHandoff, c as CompileOptions, d as CompiledPersonality, e as ContextAdaptation, f as ContextResolution, D as DimensionName, g as DimensionObject, h as DimensionShorthand, i as DimensionValue, j as EvalSample, k as ExtendsDiagnostics, l as ExtendsResult, H as HumorDimensionObject, m as HumorDimensionValue, n as HumorStyle, I as ImportOptions, L as Level, o as ProfileCapabilities, T as Tier1Options,
|
|
1
|
+
import { V as ValidationResult, a as ValidationCheckSummary, b as ValidationDiagnostic, P as PersonalityProfile, r as runTier1Evaluation, E as EvalScenario } from './index-Ct4kuPk7.js';
|
|
2
|
+
export { C as CapabilityHandoff, c as CompileOptions, d as CompiledPersonality, e as ContextAdaptation, f as ContextResolution, D as DimensionName, g as DimensionObject, h as DimensionShorthand, i as DimensionValue, j as EvalSample, k as ExtendsDiagnostics, l as ExtendsResult, H as HumorDimensionObject, m as HumorDimensionValue, n as HumorStyle, I as ImportOptions, L as Level, o as LockedRule, p as ProfileCapabilities, R as RuleConstraint, T as Tier1Options, q as Tier2Options, s as Tier3Options, t as VocabularyConstraints, u as compileProfile, v as compileResolvedProfile, w as evaluateTier1Response, x as injectPersonality, y as loadProfileFile, z as mapImportAnalysisToProfile, A as normalizeProfile, B as renderImportedProfileYAML, F as resolveActiveContext, G as resolveExtends, J as runImportAnalysis, K as runTier1EvaluationForProfile, M as runTier2Evaluation, N as runTier2EvaluationForProfile, O as runTier3Evaluation, Q as runTier3EvaluationForProfile, S as validateEvalScenario, U as validateEvalScenarios, W as validateProfile, X as validateResolvedProfile } from './index-Ct4kuPk7.js';
|
|
3
3
|
|
|
4
4
|
type ValidationResultObject = {
|
|
5
5
|
profilePath: string | null;
|