@mmnto/totem 1.14.10 → 1.14.11
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/compile-lesson.d.ts +19 -0
- package/dist/compile-lesson.d.ts.map +1 -1
- package/dist/compile-lesson.js +193 -43
- package/dist/compile-lesson.js.map +1 -1
- package/dist/compile-lesson.test.js +277 -1
- package/dist/compile-lesson.test.js.map +1 -1
- package/dist/compiler-schema.d.ts +31 -0
- package/dist/compiler-schema.d.ts.map +1 -1
- package/dist/compiler-schema.js +7 -0
- package/dist/compiler-schema.js.map +1 -1
- package/dist/config-schema.d.ts +41 -0
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config-schema.js +33 -0
- package/dist/config-schema.js.map +1 -1
- package/dist/config-schema.test.js +87 -0
- package/dist/config-schema.test.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/ledger.d.ts +10 -0
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +8 -0
- package/dist/ledger.js.map +1 -1
- package/dist/lesson-pattern.d.ts.map +1 -1
- package/dist/lesson-pattern.js +6 -9
- package/dist/lesson-pattern.js.map +1 -1
- package/dist/pack-merge.d.ts +73 -0
- package/dist/pack-merge.d.ts.map +1 -0
- package/dist/pack-merge.js +117 -0
- package/dist/pack-merge.js.map +1 -0
- package/dist/pack-merge.test.d.ts +2 -0
- package/dist/pack-merge.test.d.ts.map +1 -0
- package/dist/pack-merge.test.js +238 -0
- package/dist/pack-merge.test.js.map +1 -0
- package/dist/regex-utils.d.ts +5 -0
- package/dist/regex-utils.d.ts.map +1 -1
- package/dist/regex-utils.js +6 -1
- package/dist/regex-utils.js.map +1 -1
- package/dist/regex-utils.test.js +15 -2
- package/dist/regex-utils.test.js.map +1 -1
- package/dist/rule-engine.d.ts.map +1 -1
- package/dist/rule-engine.js +3 -0
- package/dist/rule-engine.js.map +1 -1
- package/dist/rule-engine.test.js +29 -0
- package/dist/rule-engine.test.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/ledger.d.ts
CHANGED
|
@@ -14,6 +14,14 @@ export declare const LedgerEventSchema: z.ZodObject<{
|
|
|
14
14
|
justification: z.ZodDefault<z.ZodString>;
|
|
15
15
|
/** Source of the event */
|
|
16
16
|
source: z.ZodEnum<["lint", "shield", "bot"]>;
|
|
17
|
+
/**
|
|
18
|
+
* True when the bypassed rule was shipped by a pack with
|
|
19
|
+
* `immutable: true`. Audit consumers can filter
|
|
20
|
+
* `events.ndjson | jq 'select(.immutable == true)'` to surface every
|
|
21
|
+
* attempt to silence an enforced security rule (ADR-089,
|
|
22
|
+
* mmnto-ai/totem#1485). Absent on events from non-immutable rules.
|
|
23
|
+
*/
|
|
24
|
+
immutable: z.ZodOptional<z.ZodBoolean>;
|
|
17
25
|
}, "strip", z.ZodTypeAny, {
|
|
18
26
|
type: "suppress" | "override" | "exemption";
|
|
19
27
|
file: string;
|
|
@@ -21,6 +29,7 @@ export declare const LedgerEventSchema: z.ZodObject<{
|
|
|
21
29
|
source: "lint" | "shield" | "bot";
|
|
22
30
|
timestamp: string;
|
|
23
31
|
ruleId: string;
|
|
32
|
+
immutable?: boolean | undefined;
|
|
24
33
|
line?: number | undefined;
|
|
25
34
|
}, {
|
|
26
35
|
type: "suppress" | "override" | "exemption";
|
|
@@ -28,6 +37,7 @@ export declare const LedgerEventSchema: z.ZodObject<{
|
|
|
28
37
|
source: "lint" | "shield" | "bot";
|
|
29
38
|
timestamp: string;
|
|
30
39
|
ruleId: string;
|
|
40
|
+
immutable?: boolean | undefined;
|
|
31
41
|
line?: number | undefined;
|
|
32
42
|
justification?: string | undefined;
|
|
33
43
|
}>;
|
package/dist/ledger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,iBAAiB;IAC5B,yBAAyB;;IAEzB,uHAAuH;;IAEvH,0DAA0D;;IAE1D,mDAAmD;;IAEnD,8BAA8B;;IAE9B,gHAAgH;;IAEhH,0BAA0B
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,iBAAiB;IAC5B,yBAAyB;;IAEzB,uHAAuH;;IAEvH,0DAA0D;;IAE1D,mDAAmD;;IAEnD,8BAA8B;;IAE9B,gHAAgH;;IAEhH,0BAA0B;;IAE1B;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAS5D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC7B,IAAI,CAaN;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,WAAW,EAAE,CAwBhG"}
|
package/dist/ledger.js
CHANGED
|
@@ -17,6 +17,14 @@ export const LedgerEventSchema = z.object({
|
|
|
17
17
|
justification: z.string().default(''),
|
|
18
18
|
/** Source of the event */
|
|
19
19
|
source: z.enum(['lint', 'shield', 'bot']),
|
|
20
|
+
/**
|
|
21
|
+
* True when the bypassed rule was shipped by a pack with
|
|
22
|
+
* `immutable: true`. Audit consumers can filter
|
|
23
|
+
* `events.ndjson | jq 'select(.immutable == true)'` to surface every
|
|
24
|
+
* attempt to silence an enforced security rule (ADR-089,
|
|
25
|
+
* mmnto-ai/totem#1485). Absent on events from non-immutable rules.
|
|
26
|
+
*/
|
|
27
|
+
immutable: z.boolean().optional(),
|
|
20
28
|
});
|
|
21
29
|
// ─── Constants ──────────────────────────────────────
|
|
22
30
|
const LEDGER_DIR = 'ledger';
|
package/dist/ledger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,uDAAuD;AAEvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,yBAAyB;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,uHAAuH;IACvH,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACnD,0DAA0D;IAC1D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,mDAAmD;IACnD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,8BAA8B;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5C,gHAAgH;IAChH,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,0BAA0B;IAC1B,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson-pattern.d.ts","sourceRoot":"","sources":["../src/lesson-pattern.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"lesson-pattern.d.ts","sourceRoot":"","sources":["../src/lesson-pattern.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA0B5E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA6CrF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAclE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA6DhC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAsDvE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAItE;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAKrE;AAID,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAyBD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAK3E"}
|
package/dist/lesson-pattern.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import YAML from 'yaml';
|
|
13
13
|
import { TotemParseError } from './errors.js';
|
|
14
|
+
import { escapeRegex } from './regex-utils.js';
|
|
14
15
|
export function extractField(body, field) {
|
|
15
16
|
// Match all common bold/colon variants (#1282 — caught by Shield AI as a
|
|
16
17
|
// partial-fix consequence of extending extractMultilineField):
|
|
@@ -31,7 +32,7 @@ export function extractField(body, field) {
|
|
|
31
32
|
// silently rejecting `**Pattern:**foo` (no space) and `**Pattern:**` (empty value).
|
|
32
33
|
// Caught by gemini-code-assist on PR #1282 as another instance of the
|
|
33
34
|
// cross-helper-consistency cascade pattern documented in lesson-400fed87.
|
|
34
|
-
const safeField = field
|
|
35
|
+
const safeField = escapeRegex(field);
|
|
35
36
|
const re = new RegExp(`^(?:\\*{2})?${safeField}(?:\\*{2})?:(?:\\*{2})?[ \\t]*(.*)$`, 'im');
|
|
36
37
|
const match = body.match(re);
|
|
37
38
|
// Trim and treat empty as "no value" so callers' `if (!value)` checks fire correctly.
|
|
@@ -54,7 +55,7 @@ export function extractField(body, field) {
|
|
|
54
55
|
* Returns the trimmed value, or `undefined` if the field is absent.
|
|
55
56
|
*/
|
|
56
57
|
export function extractMultilineField(body, field) {
|
|
57
|
-
const safeField = field
|
|
58
|
+
const safeField = escapeRegex(field);
|
|
58
59
|
// Match the field's first line. Supports four common forms:
|
|
59
60
|
// **Field:** ← canonical totem (asterisks both sides of colon)
|
|
60
61
|
// **Field**: ← alternative markdown convention (asterisks before colon)
|
|
@@ -153,11 +154,7 @@ export function extractBadExample(body) {
|
|
|
153
154
|
* rules ahead of the 1.15.0 Pack Distribution milestone.
|
|
154
155
|
*/
|
|
155
156
|
export function extractYamlRuleAfterField(body, field) {
|
|
156
|
-
|
|
157
|
-
// expanding to the matched char is exactly the intent, but the function
|
|
158
|
-
// form is the safer idiom in substitution-sensitive contexts (matches the
|
|
159
|
-
// broader repo convention, GCA catch on mmnto/totem#1454).
|
|
160
|
-
const safeField = field.replace(/[.*+?^${}()|[\]\\]/g, (ch) => '\\' + ch);
|
|
157
|
+
const safeField = escapeRegex(field);
|
|
161
158
|
const startRe = new RegExp(`^(?:\\*{2})?${safeField}(?:\\*{2})?:(?:\\*{2})?.*$`, 'i');
|
|
162
159
|
// Section terminator — any bold field marker OR any markdown heading stops
|
|
163
160
|
// the YAML scan. CR catch on mmnto/totem#1454: without the heading guard,
|
|
@@ -277,7 +274,7 @@ export function extractManualPattern(body) {
|
|
|
277
274
|
* `**Field**:`, `**Field:`, and plain `Field:`.
|
|
278
275
|
*/
|
|
279
276
|
export function extractAllFields(body, field) {
|
|
280
|
-
const safeField = field
|
|
277
|
+
const safeField = escapeRegex(field);
|
|
281
278
|
const re = new RegExp(`^(?:\\*{2})?${safeField}(?:\\*{2})?:(?:\\*{2})?[ \\t]*(.*)$`, 'gim');
|
|
282
279
|
return Array.from(body.matchAll(re), (m) => m[1].trim());
|
|
283
280
|
}
|
|
@@ -301,7 +298,7 @@ export function extractRuleExamples(body) {
|
|
|
301
298
|
* Used internally by extractBadGoodSnippets.
|
|
302
299
|
*/
|
|
303
300
|
function extractCodeBlock(body, field) {
|
|
304
|
-
const safeField = field
|
|
301
|
+
const safeField = escapeRegex(field);
|
|
305
302
|
// Try fenced code block after **Field:** or **Field**: (colon required, inside or outside bold)
|
|
306
303
|
const fencedRe = new RegExp(`(?:^|\\n)\\*{0,2}${safeField}\\*{0,2}\\s*:[^\\n]*\\n(?:\\s*\\n)*(\`\`\`|~~~)[^\\n]*\\n([\\s\\S]*?)\\1`, 'i');
|
|
307
304
|
const fencedMatch = body.match(fencedRe);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson-pattern.js","sourceRoot":"","sources":["../src/lesson-pattern.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"lesson-pattern.js","sourceRoot":"","sources":["../src/lesson-pattern.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pack rule merge primitive (ADR-085 + ADR-089, mmnto-ai/totem#1485).
|
|
3
|
+
*
|
|
4
|
+
* The default pack-merge semantic from ADR-085 Resolved Decision 3 is
|
|
5
|
+
* "Local Supreme Authority": when a repo's local `compiled-rules.json`
|
|
6
|
+
* declares the same `lessonHash` as an inherited pack rule, the local
|
|
7
|
+
* entry wins. This preserves the "my repo, my rules" principle.
|
|
8
|
+
*
|
|
9
|
+
* ADR-089 carves out a narrow exception: rules shipped by a pack with
|
|
10
|
+
* `immutable: true` AND `severity: 'error'` cannot be locally downgraded
|
|
11
|
+
* or archived. Security packs like `@totem/pack-agent-security` rely on
|
|
12
|
+
* this contract to guarantee that enforcement cannot be silently weakened
|
|
13
|
+
* by a motivated local override.
|
|
14
|
+
*
|
|
15
|
+
* This module is the pure primitive that encodes both rules. It does
|
|
16
|
+
* NOT know about pack install paths, config resolution, or the filesystem —
|
|
17
|
+
* callers hand it two arrays and receive the merged array back. Phase C
|
|
18
|
+
* will wire a consumer (`totem install` + pack-config resolution) around
|
|
19
|
+
* this primitive. Until then the logic is fully unit-tested in memory so
|
|
20
|
+
* the enforcement contract is ready the day pack distribution lands.
|
|
21
|
+
*/
|
|
22
|
+
import type { CompiledRule } from './compiler-schema.js';
|
|
23
|
+
/**
|
|
24
|
+
* Explains why a local override was refused. Accumulated into the merge
|
|
25
|
+
* result so callers can surface every blocked attempt without swallowing
|
|
26
|
+
* the detail. Useful for `totem install` diagnostics and for the Trap
|
|
27
|
+
* Ledger snapshot a future pack-build flow may capture.
|
|
28
|
+
*/
|
|
29
|
+
export interface ImmutableOverrideBlock {
|
|
30
|
+
/** The lessonHash of the immutable pack rule whose local override was rejected. */
|
|
31
|
+
lessonHash: string;
|
|
32
|
+
/** Human-readable name for log output. */
|
|
33
|
+
lessonHeading: string;
|
|
34
|
+
/** Which aspect of the local rule the merge refused to honor. */
|
|
35
|
+
attemptedChange: 'severity-downgrade' | 'archive' | 'both';
|
|
36
|
+
/** The severity the local rule tried to set. Absent for archive-only overrides. */
|
|
37
|
+
attemptedSeverity?: 'warning' | 'error';
|
|
38
|
+
/** The severity the pack enforces. Always 'error' — immutable is currently error-only. */
|
|
39
|
+
enforcedSeverity: 'error';
|
|
40
|
+
}
|
|
41
|
+
export interface MergeRulesResult {
|
|
42
|
+
/** The merged rule array. One entry per unique `lessonHash`. */
|
|
43
|
+
rules: CompiledRule[];
|
|
44
|
+
/**
|
|
45
|
+
* Immutable overrides the merge blocked. Empty when no local rule tried
|
|
46
|
+
* to downgrade or archive an immutable pack rule. Callers that want a
|
|
47
|
+
* hard error on any blocked override can check `blocks.length > 0`.
|
|
48
|
+
*/
|
|
49
|
+
blocks: ImmutableOverrideBlock[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Merge local and pack rule arrays according to ADR-085 + ADR-089 semantics.
|
|
53
|
+
*
|
|
54
|
+
* Precedence:
|
|
55
|
+
* - When a `lessonHash` appears in both arrays, local wins (ADR-085
|
|
56
|
+
* Local Supreme Authority)
|
|
57
|
+
* - EXCEPT when the pack rule carries `immutable: true` AND
|
|
58
|
+
* `severity: 'error'`: the pack's severity is preserved and any local
|
|
59
|
+
* `status: 'archived'` is cleared back to active. The rest of the
|
|
60
|
+
* local rule's shape (pattern, message, fileGlobs, badExample) is
|
|
61
|
+
* still honored — immutable protects the enforcement knob, not the
|
|
62
|
+
* rule body. A pack author that needs to freeze the pattern as well
|
|
63
|
+
* should simply ship the rule without a matching local entry.
|
|
64
|
+
*
|
|
65
|
+
* Non-immutable pack rules follow pure local precedence: the local entry
|
|
66
|
+
* replaces the pack entry byte-for-byte.
|
|
67
|
+
*
|
|
68
|
+
* Rules that appear only in `packRules` are appended as-is. Rules that
|
|
69
|
+
* appear only in `localRules` are emitted as-is. Pure function — does
|
|
70
|
+
* not mutate its inputs.
|
|
71
|
+
*/
|
|
72
|
+
export declare function mergeRules(localRules: readonly CompiledRule[], packRules: readonly CompiledRule[]): MergeRulesResult;
|
|
73
|
+
//# sourceMappingURL=pack-merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-merge.d.ts","sourceRoot":"","sources":["../src/pack-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,eAAe,EAAE,oBAAoB,GAAG,SAAS,GAAG,MAAM,CAAC;IAC3D,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACxC,0FAA0F;IAC1F,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB;;;;OAIG;IACH,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,SAAS,YAAY,EAAE,EACnC,SAAS,EAAE,SAAS,YAAY,EAAE,GACjC,gBAAgB,CAoFlB"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pack rule merge primitive (ADR-085 + ADR-089, mmnto-ai/totem#1485).
|
|
3
|
+
*
|
|
4
|
+
* The default pack-merge semantic from ADR-085 Resolved Decision 3 is
|
|
5
|
+
* "Local Supreme Authority": when a repo's local `compiled-rules.json`
|
|
6
|
+
* declares the same `lessonHash` as an inherited pack rule, the local
|
|
7
|
+
* entry wins. This preserves the "my repo, my rules" principle.
|
|
8
|
+
*
|
|
9
|
+
* ADR-089 carves out a narrow exception: rules shipped by a pack with
|
|
10
|
+
* `immutable: true` AND `severity: 'error'` cannot be locally downgraded
|
|
11
|
+
* or archived. Security packs like `@totem/pack-agent-security` rely on
|
|
12
|
+
* this contract to guarantee that enforcement cannot be silently weakened
|
|
13
|
+
* by a motivated local override.
|
|
14
|
+
*
|
|
15
|
+
* This module is the pure primitive that encodes both rules. It does
|
|
16
|
+
* NOT know about pack install paths, config resolution, or the filesystem —
|
|
17
|
+
* callers hand it two arrays and receive the merged array back. Phase C
|
|
18
|
+
* will wire a consumer (`totem install` + pack-config resolution) around
|
|
19
|
+
* this primitive. Until then the logic is fully unit-tested in memory so
|
|
20
|
+
* the enforcement contract is ready the day pack distribution lands.
|
|
21
|
+
*/
|
|
22
|
+
// ─── Merge ──────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Merge local and pack rule arrays according to ADR-085 + ADR-089 semantics.
|
|
25
|
+
*
|
|
26
|
+
* Precedence:
|
|
27
|
+
* - When a `lessonHash` appears in both arrays, local wins (ADR-085
|
|
28
|
+
* Local Supreme Authority)
|
|
29
|
+
* - EXCEPT when the pack rule carries `immutable: true` AND
|
|
30
|
+
* `severity: 'error'`: the pack's severity is preserved and any local
|
|
31
|
+
* `status: 'archived'` is cleared back to active. The rest of the
|
|
32
|
+
* local rule's shape (pattern, message, fileGlobs, badExample) is
|
|
33
|
+
* still honored — immutable protects the enforcement knob, not the
|
|
34
|
+
* rule body. A pack author that needs to freeze the pattern as well
|
|
35
|
+
* should simply ship the rule without a matching local entry.
|
|
36
|
+
*
|
|
37
|
+
* Non-immutable pack rules follow pure local precedence: the local entry
|
|
38
|
+
* replaces the pack entry byte-for-byte.
|
|
39
|
+
*
|
|
40
|
+
* Rules that appear only in `packRules` are appended as-is. Rules that
|
|
41
|
+
* appear only in `localRules` are emitted as-is. Pure function — does
|
|
42
|
+
* not mutate its inputs.
|
|
43
|
+
*/
|
|
44
|
+
export function mergeRules(localRules, packRules) {
|
|
45
|
+
const localByHash = new Map();
|
|
46
|
+
for (const rule of localRules) {
|
|
47
|
+
localByHash.set(rule.lessonHash, rule);
|
|
48
|
+
}
|
|
49
|
+
const merged = [];
|
|
50
|
+
const blocks = [];
|
|
51
|
+
const consumedLocalHashes = new Set();
|
|
52
|
+
for (const packRule of packRules) {
|
|
53
|
+
const localRule = localByHash.get(packRule.lessonHash);
|
|
54
|
+
if (!localRule) {
|
|
55
|
+
// No local override — pack rule lands as-is.
|
|
56
|
+
merged.push(packRule);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
consumedLocalHashes.add(packRule.lessonHash);
|
|
60
|
+
const isEnforcedImmutable = packRule.immutable === true && (packRule.severity ?? 'warning') === 'error';
|
|
61
|
+
if (!isEnforcedImmutable) {
|
|
62
|
+
// ADR-085 default: local overrides pack byte-for-byte.
|
|
63
|
+
merged.push(localRule);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Immutable carve-out (ADR-089). Start from the local rule, then
|
|
67
|
+
// force severity and clear archive status if the local attempted
|
|
68
|
+
// either of those. An omitted `localRule.severity` is NOT treated as
|
|
69
|
+
// a downgrade attempt — the local override is opting out of
|
|
70
|
+
// opinionating on severity, not declaring a lower one. Only an
|
|
71
|
+
// explicit `'warning'` counts. (Runtime severity defaults vary
|
|
72
|
+
// across consumers; finding.ts defaults to 'error' while
|
|
73
|
+
// compile-lesson.ts defaults to 'warning', so inferring a downgrade
|
|
74
|
+
// from absence would produce bogus blocks.)
|
|
75
|
+
const attemptedSeverityDowngrade = localRule.severity === 'warning';
|
|
76
|
+
const attemptedArchive = localRule.status === 'archived';
|
|
77
|
+
if (attemptedSeverityDowngrade || attemptedArchive) {
|
|
78
|
+
const attemptedChange = attemptedSeverityDowngrade && attemptedArchive
|
|
79
|
+
? 'both'
|
|
80
|
+
: attemptedSeverityDowngrade
|
|
81
|
+
? 'severity-downgrade'
|
|
82
|
+
: 'archive';
|
|
83
|
+
const block = {
|
|
84
|
+
lessonHash: packRule.lessonHash,
|
|
85
|
+
lessonHeading: packRule.lessonHeading,
|
|
86
|
+
attemptedChange,
|
|
87
|
+
enforcedSeverity: 'error',
|
|
88
|
+
};
|
|
89
|
+
if (attemptedSeverityDowngrade) {
|
|
90
|
+
block.attemptedSeverity = 'warning';
|
|
91
|
+
}
|
|
92
|
+
blocks.push(block);
|
|
93
|
+
}
|
|
94
|
+
// Build the enforced rule. Preserve the local rule's pattern / body
|
|
95
|
+
// (immutable protects severity, not code content), but force the
|
|
96
|
+
// pack's severity and clear any archive flag. Preserve local
|
|
97
|
+
// `archivedReason` removal by not copying the field forward.
|
|
98
|
+
const enforced = {
|
|
99
|
+
...localRule,
|
|
100
|
+
severity: 'error',
|
|
101
|
+
immutable: true,
|
|
102
|
+
};
|
|
103
|
+
if (enforced.status === 'archived') {
|
|
104
|
+
enforced.status = 'active';
|
|
105
|
+
delete enforced.archivedReason;
|
|
106
|
+
}
|
|
107
|
+
merged.push(enforced);
|
|
108
|
+
}
|
|
109
|
+
// Emit local-only rules that no pack rule claimed.
|
|
110
|
+
for (const rule of localRules) {
|
|
111
|
+
if (!consumedLocalHashes.has(rule.lessonHash)) {
|
|
112
|
+
merged.push(rule);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { rules: merged, blocks };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=pack-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-merge.js","sourceRoot":"","sources":["../src/pack-merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-merge.test.d.ts","sourceRoot":"","sources":["../src/pack-merge.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeRules } from './pack-merge.js';
|
|
3
|
+
// ─── Helpers ────────────────────────────────────────
|
|
4
|
+
const baseRule = (overrides) => ({
|
|
5
|
+
lessonHeading: 'test-rule',
|
|
6
|
+
message: 'test message',
|
|
7
|
+
pattern: 'pattern-x',
|
|
8
|
+
engine: 'regex',
|
|
9
|
+
compiledAt: '2026-04-17T00:00:00Z',
|
|
10
|
+
...overrides,
|
|
11
|
+
});
|
|
12
|
+
// ─── Tests ──────────────────────────────────────────
|
|
13
|
+
describe('mergeRules', () => {
|
|
14
|
+
it('emits pack-only rules unchanged', () => {
|
|
15
|
+
const packRule = baseRule({ lessonHash: 'pack-only' });
|
|
16
|
+
const { rules, blocks } = mergeRules([], [packRule]);
|
|
17
|
+
expect(rules).toEqual([packRule]);
|
|
18
|
+
expect(blocks).toEqual([]);
|
|
19
|
+
});
|
|
20
|
+
it('emits local-only rules unchanged', () => {
|
|
21
|
+
const localRule = baseRule({ lessonHash: 'local-only' });
|
|
22
|
+
const { rules, blocks } = mergeRules([localRule], []);
|
|
23
|
+
expect(rules).toEqual([localRule]);
|
|
24
|
+
expect(blocks).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
it('returns empty result on empty inputs', () => {
|
|
27
|
+
const { rules, blocks } = mergeRules([], []);
|
|
28
|
+
expect(rules).toEqual([]);
|
|
29
|
+
expect(blocks).toEqual([]);
|
|
30
|
+
});
|
|
31
|
+
it('local rule overrides pack rule when pack is not immutable (ADR-085 default)', () => {
|
|
32
|
+
const packRule = baseRule({
|
|
33
|
+
lessonHash: 'shared',
|
|
34
|
+
severity: 'error',
|
|
35
|
+
message: 'pack message',
|
|
36
|
+
});
|
|
37
|
+
const localRule = baseRule({
|
|
38
|
+
lessonHash: 'shared',
|
|
39
|
+
severity: 'warning',
|
|
40
|
+
message: 'local message',
|
|
41
|
+
});
|
|
42
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
43
|
+
expect(rules).toEqual([localRule]);
|
|
44
|
+
expect(blocks).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
it('forces pack severity when local downgrades an immutable+error pack rule', () => {
|
|
47
|
+
const packRule = baseRule({
|
|
48
|
+
lessonHash: 'immut',
|
|
49
|
+
immutable: true,
|
|
50
|
+
severity: 'error',
|
|
51
|
+
message: 'pack enforcement',
|
|
52
|
+
});
|
|
53
|
+
const localRule = baseRule({
|
|
54
|
+
lessonHash: 'immut',
|
|
55
|
+
severity: 'warning',
|
|
56
|
+
message: 'local tries to downgrade',
|
|
57
|
+
});
|
|
58
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
59
|
+
expect(rules).toHaveLength(1);
|
|
60
|
+
expect(rules[0].severity).toBe('error');
|
|
61
|
+
expect(rules[0].immutable).toBe(true);
|
|
62
|
+
// Pattern / message bodies come from the local rule — immutable
|
|
63
|
+
// protects the enforcement knob, not the rule content.
|
|
64
|
+
expect(rules[0].message).toBe('local tries to downgrade');
|
|
65
|
+
expect(blocks).toEqual([
|
|
66
|
+
{
|
|
67
|
+
lessonHash: 'immut',
|
|
68
|
+
lessonHeading: 'test-rule',
|
|
69
|
+
attemptedChange: 'severity-downgrade',
|
|
70
|
+
attemptedSeverity: 'warning',
|
|
71
|
+
enforcedSeverity: 'error',
|
|
72
|
+
},
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
it('blocks archive attempt on an immutable+error pack rule and restores active status', () => {
|
|
76
|
+
const packRule = baseRule({
|
|
77
|
+
lessonHash: 'immut-archive',
|
|
78
|
+
immutable: true,
|
|
79
|
+
severity: 'error',
|
|
80
|
+
});
|
|
81
|
+
const localRule = baseRule({
|
|
82
|
+
lessonHash: 'immut-archive',
|
|
83
|
+
severity: 'error',
|
|
84
|
+
status: 'archived',
|
|
85
|
+
archivedReason: 'local tried to archive a security rule',
|
|
86
|
+
});
|
|
87
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
88
|
+
expect(rules).toHaveLength(1);
|
|
89
|
+
expect(rules[0].severity).toBe('error');
|
|
90
|
+
expect(rules[0].status).toBe('active');
|
|
91
|
+
expect(rules[0].archivedReason).toBeUndefined();
|
|
92
|
+
expect(blocks).toEqual([
|
|
93
|
+
{
|
|
94
|
+
lessonHash: 'immut-archive',
|
|
95
|
+
lessonHeading: 'test-rule',
|
|
96
|
+
attemptedChange: 'archive',
|
|
97
|
+
enforcedSeverity: 'error',
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
it('blocks combined downgrade + archive attempt with attemptedChange: both', () => {
|
|
102
|
+
const packRule = baseRule({
|
|
103
|
+
lessonHash: 'immut-both',
|
|
104
|
+
immutable: true,
|
|
105
|
+
severity: 'error',
|
|
106
|
+
});
|
|
107
|
+
const localRule = baseRule({
|
|
108
|
+
lessonHash: 'immut-both',
|
|
109
|
+
severity: 'warning',
|
|
110
|
+
status: 'archived',
|
|
111
|
+
archivedReason: 'double override attempt',
|
|
112
|
+
});
|
|
113
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
114
|
+
expect(rules).toHaveLength(1);
|
|
115
|
+
expect(rules[0].severity).toBe('error');
|
|
116
|
+
expect(rules[0].status).toBe('active');
|
|
117
|
+
expect(rules[0].archivedReason).toBeUndefined();
|
|
118
|
+
expect(blocks).toHaveLength(1);
|
|
119
|
+
expect(blocks[0].attemptedChange).toBe('both');
|
|
120
|
+
expect(blocks[0].attemptedSeverity).toBe('warning');
|
|
121
|
+
});
|
|
122
|
+
it('does not force severity when pack is immutable but severity is not error', () => {
|
|
123
|
+
// Immutable currently protects error-level rules only. A pack that
|
|
124
|
+
// declares immutable: true + severity: 'warning' communicates intent
|
|
125
|
+
// but the merge falls back to local precedence — no block reported.
|
|
126
|
+
const packRule = baseRule({
|
|
127
|
+
lessonHash: 'immut-warn',
|
|
128
|
+
immutable: true,
|
|
129
|
+
severity: 'warning',
|
|
130
|
+
});
|
|
131
|
+
const localRule = baseRule({
|
|
132
|
+
lessonHash: 'immut-warn',
|
|
133
|
+
severity: 'warning',
|
|
134
|
+
status: 'archived',
|
|
135
|
+
});
|
|
136
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
137
|
+
expect(rules).toEqual([localRule]);
|
|
138
|
+
expect(blocks).toEqual([]);
|
|
139
|
+
});
|
|
140
|
+
it('does not treat an omitted local severity as a downgrade attempt', () => {
|
|
141
|
+
// CR finding on #1515: defaulting omitted localRule.severity to
|
|
142
|
+
// 'warning' records bogus blocks for local overrides that simply
|
|
143
|
+
// don't opine on severity. Runtime consumers disagree on the default
|
|
144
|
+
// (finding.ts uses 'error', compile-lesson.ts uses 'warning'), so
|
|
145
|
+
// absence is ambiguous — only an explicit 'warning' counts as a
|
|
146
|
+
// downgrade. The merged rule still gets the pack's 'error' forced.
|
|
147
|
+
const packRule = baseRule({
|
|
148
|
+
lessonHash: 'immut-implicit',
|
|
149
|
+
immutable: true,
|
|
150
|
+
severity: 'error',
|
|
151
|
+
});
|
|
152
|
+
const localRule = baseRule({
|
|
153
|
+
lessonHash: 'immut-implicit',
|
|
154
|
+
// severity intentionally omitted — local has no opinion
|
|
155
|
+
message: 'local refines message only',
|
|
156
|
+
});
|
|
157
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
158
|
+
expect(rules).toHaveLength(1);
|
|
159
|
+
expect(rules[0].severity).toBe('error');
|
|
160
|
+
expect(rules[0].immutable).toBe(true);
|
|
161
|
+
expect(rules[0].message).toBe('local refines message only');
|
|
162
|
+
expect(blocks).toEqual([]);
|
|
163
|
+
});
|
|
164
|
+
it('emits no block when the local rule does not attempt to downgrade or archive', () => {
|
|
165
|
+
const packRule = baseRule({
|
|
166
|
+
lessonHash: 'immut-noop',
|
|
167
|
+
immutable: true,
|
|
168
|
+
severity: 'error',
|
|
169
|
+
});
|
|
170
|
+
const localRule = baseRule({
|
|
171
|
+
lessonHash: 'immut-noop',
|
|
172
|
+
severity: 'error',
|
|
173
|
+
message: 'local refines message but keeps severity',
|
|
174
|
+
});
|
|
175
|
+
const { rules, blocks } = mergeRules([localRule], [packRule]);
|
|
176
|
+
expect(rules).toHaveLength(1);
|
|
177
|
+
expect(rules[0].severity).toBe('error');
|
|
178
|
+
expect(rules[0].message).toBe('local refines message but keeps severity');
|
|
179
|
+
expect(rules[0].immutable).toBe(true);
|
|
180
|
+
expect(blocks).toEqual([]);
|
|
181
|
+
});
|
|
182
|
+
it('preserves deterministic ordering: pack rules first, then local-only rules', () => {
|
|
183
|
+
const pack1 = baseRule({ lessonHash: 'p1' });
|
|
184
|
+
const pack2 = baseRule({ lessonHash: 'p2' });
|
|
185
|
+
const localOverlap = baseRule({ lessonHash: 'p1', message: 'overrides pack1' });
|
|
186
|
+
const localOnly1 = baseRule({ lessonHash: 'l1' });
|
|
187
|
+
const localOnly2 = baseRule({ lessonHash: 'l2' });
|
|
188
|
+
const { rules } = mergeRules([localOverlap, localOnly1, localOnly2], [pack1, pack2]);
|
|
189
|
+
const hashes = rules.map((r) => r.lessonHash);
|
|
190
|
+
expect(hashes).toEqual(['p1', 'p2', 'l1', 'l2']);
|
|
191
|
+
expect(rules[0].message).toBe('overrides pack1');
|
|
192
|
+
});
|
|
193
|
+
it('is a pure function — inputs are not mutated', () => {
|
|
194
|
+
const packRule = baseRule({
|
|
195
|
+
lessonHash: 'immut',
|
|
196
|
+
immutable: true,
|
|
197
|
+
severity: 'error',
|
|
198
|
+
});
|
|
199
|
+
const localRule = baseRule({
|
|
200
|
+
lessonHash: 'immut',
|
|
201
|
+
severity: 'warning',
|
|
202
|
+
status: 'archived',
|
|
203
|
+
archivedReason: 'audit',
|
|
204
|
+
});
|
|
205
|
+
const packSnapshot = JSON.stringify(packRule);
|
|
206
|
+
const localSnapshot = JSON.stringify(localRule);
|
|
207
|
+
mergeRules([localRule], [packRule]);
|
|
208
|
+
expect(JSON.stringify(packRule)).toBe(packSnapshot);
|
|
209
|
+
expect(JSON.stringify(localRule)).toBe(localSnapshot);
|
|
210
|
+
});
|
|
211
|
+
it('handles multiple immutable pack rules with mixed override attempts', () => {
|
|
212
|
+
const p1 = baseRule({
|
|
213
|
+
lessonHash: 'p1',
|
|
214
|
+
immutable: true,
|
|
215
|
+
severity: 'error',
|
|
216
|
+
});
|
|
217
|
+
const p2 = baseRule({
|
|
218
|
+
lessonHash: 'p2',
|
|
219
|
+
immutable: true,
|
|
220
|
+
severity: 'error',
|
|
221
|
+
});
|
|
222
|
+
const p3 = baseRule({
|
|
223
|
+
lessonHash: 'p3',
|
|
224
|
+
immutable: true,
|
|
225
|
+
severity: 'error',
|
|
226
|
+
});
|
|
227
|
+
const l1 = baseRule({ lessonHash: 'p1', severity: 'warning' });
|
|
228
|
+
const l2 = baseRule({ lessonHash: 'p2', status: 'archived' });
|
|
229
|
+
// p3 has no local override — no block, emits pack rule as-is.
|
|
230
|
+
const { rules, blocks } = mergeRules([l1, l2], [p1, p2, p3]);
|
|
231
|
+
expect(rules).toHaveLength(3);
|
|
232
|
+
expect(rules.every((r) => r.severity === 'error')).toBe(true);
|
|
233
|
+
expect(rules.every((r) => r.status !== 'archived')).toBe(true);
|
|
234
|
+
expect(blocks).toHaveLength(2);
|
|
235
|
+
expect(blocks.map((b) => b.lessonHash).sort()).toEqual(['p1', 'p2']);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
//# sourceMappingURL=pack-merge.test.js.map
|