rulereceipt 0.1.22 → 0.1.23
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/checks/classify.js +42 -0
- package/dist/cli.js +3 -1
- package/dist/report/generateHtmlReport.js +12 -5
- package/package.json +1 -1
package/dist/checks/classify.js
CHANGED
|
@@ -31,7 +31,49 @@ const IMPERATIVE_INSTRUCTION = /(?:^|[.;:!?]\s+|^\s*[-*+]\s*|\n\s*[-*+]\s*)(use|
|
|
|
31
31
|
* with no instruction in it has nothing to check compliance against,
|
|
32
32
|
* whatever its punctuation.
|
|
33
33
|
*/
|
|
34
|
+
/**
|
|
35
|
+
* A section whose TITLE announces a record of something that happened —
|
|
36
|
+
* an incident, a postmortem, a retrospective. These are written to
|
|
37
|
+
* explain history, not to instruct the agent.
|
|
38
|
+
*
|
|
39
|
+
* Found by running this tool on a real session (2026-08-31): a section
|
|
40
|
+
* titled "Real incident (2026-08-28): Vercel had the same office/personal
|
|
41
|
+
* mixup" was enforced as a REQUIRE rule whose pattern was an employer
|
|
42
|
+
* name pulled out of the narrative, so the report announced FOLLOWED
|
|
43
|
+
* because that name appeared somewhere in the session. The rule being
|
|
44
|
+
* "satisfied" was a sentence describing a past mistake.
|
|
45
|
+
*
|
|
46
|
+
* The existing directive test cannot catch these, and correctly so: a
|
|
47
|
+
* good incident note ends with the lesson ("Verify with `vercel whoami`
|
|
48
|
+
* before every deploy"), so it genuinely does contain a directive. What
|
|
49
|
+
* the section IS gets announced by its title, which is where this looks.
|
|
50
|
+
*
|
|
51
|
+
* Kept to a small closed class of words that name a record of an event,
|
|
52
|
+
* in the same spirit as DIRECTIVE_LANGUAGE above — a bounded property of
|
|
53
|
+
* language, not an enumeration of document formats. Enumerating formats
|
|
54
|
+
* is the mistake this project already made once and wrote up publicly.
|
|
55
|
+
*/
|
|
56
|
+
const EVENT_RECORD_TITLE = /\b(incident|post-?mortem|retro(spective)?|outage|what went wrong)\b/i;
|
|
57
|
+
/**
|
|
58
|
+
* A title that OPENS with an instruction is a rule, whatever it goes on
|
|
59
|
+
* to mention. "Never repeat the 2026-08-28 incident" is a directive that
|
|
60
|
+
* happens to name an incident; "Real incident (2026-08-28): ..." is a
|
|
61
|
+
* report that happens to contain the word never further along.
|
|
62
|
+
*/
|
|
63
|
+
const TITLE_OPENS_WITH_DIRECTIVE = /^\s*[-*+\d.\s]*(never|always|must|do not|don't|dont|avoid|ensure|prefer|only|make sure|be sure)\b/i;
|
|
64
|
+
function isEventRecord(rule) {
|
|
65
|
+
if (TITLE_OPENS_WITH_DIRECTIVE.test(rule.title))
|
|
66
|
+
return false;
|
|
67
|
+
if (IMPERATIVE_INSTRUCTION.test(rule.title))
|
|
68
|
+
return false;
|
|
69
|
+
return EVENT_RECORD_TITLE.test(rule.title);
|
|
70
|
+
}
|
|
34
71
|
function isNotARule(rule) {
|
|
72
|
+
// Checked before the directive test on purpose: an incident note that
|
|
73
|
+
// ends with its lesson contains a real directive, and would otherwise
|
|
74
|
+
// be enforced as though the history itself were the rule.
|
|
75
|
+
if (isEventRecord(rule))
|
|
76
|
+
return true;
|
|
35
77
|
const combined = `${rule.title} ${rule.text}`;
|
|
36
78
|
if (DIRECTIVE_LANGUAGE.test(combined))
|
|
37
79
|
return false;
|
package/dist/cli.js
CHANGED
|
@@ -123,7 +123,9 @@ function writeHtmlReport(results, meta, cwd, target) {
|
|
|
123
123
|
// name, an office email, and absolute paths. Home paths are redacted
|
|
124
124
|
// automatically; nothing else can be, so say so plainly at the moment
|
|
125
125
|
// the file is created rather than burying it in a policy page.
|
|
126
|
-
console.log("
|
|
126
|
+
console.log("\n⚠ This report includes your rule text and session evidence VERBATIM.\n" +
|
|
127
|
+
" Review it before sharing outside your team — only you know what's in your rules file.\n" +
|
|
128
|
+
" Nothing is auto-redacted: this tool cannot tell which of your own rules are sensitive.");
|
|
127
129
|
}
|
|
128
130
|
catch (err) {
|
|
129
131
|
console.log(`\n(--html: couldn't write ${outPath} — ${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -34,11 +34,18 @@ function stripControlChars(value) {
|
|
|
34
34
|
* directory layout — that is a leak in the one artifact most likely to
|
|
35
35
|
* leave the machine.
|
|
36
36
|
*
|
|
37
|
-
* This is
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
37
|
+
* This is DISPLAY FORMATTING, not a safety mechanism, and the difference
|
|
38
|
+
* matters. It is a fixed, deterministic substitution of one known string
|
|
39
|
+
* — always correct, never guessing — and it makes paths easier to read as
|
|
40
|
+
* a side benefit. It protects nothing.
|
|
41
|
+
*
|
|
42
|
+
* Auto-detecting "sensitive" content and scrubbing it would be a losing
|
|
43
|
+
* game: it can never catch everything, and a partial scrub is worse than
|
|
44
|
+
* none because it invites the user to trust the output. Rule text and
|
|
45
|
+
* evidence are reproduced verbatim on purpose, because that is what makes
|
|
46
|
+
* the report worth sending. The real safeguard is the warning the CLI
|
|
47
|
+
* prints at write time, which puts the responsibility where it belongs —
|
|
48
|
+
* with the person who knows what is in their own rules file.
|
|
42
49
|
*/
|
|
43
50
|
function redactHome(value) {
|
|
44
51
|
const home = homedir();
|