@micelio/eslint-config 0.1.2 → 0.2.1
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/standard.d.ts +11 -2
- package/dist/standard.js +50 -3
- package/package.json +3 -3
- package/standard-hashes.json +13 -1
package/dist/standard.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare const STANDARD_PATH = "docs/engineering-standard.md";
|
|
3
3
|
/** The SHA-256 of each released version of the standard, by `major.minor`. */
|
|
4
4
|
export type StandardHashes = Record<string, string>;
|
|
5
|
+
/** The SHA-256 of each synced file (agent prompts, skills, pull request template), by path in the repository. */
|
|
6
|
+
export type FileHashes = Record<string, string>;
|
|
5
7
|
/** What `lintStandard` found. */
|
|
6
8
|
export interface StandardResult {
|
|
7
9
|
/** True when the local copy is the one published for the pinned version. */
|
|
@@ -21,14 +23,21 @@ export declare function readPin(agents: string): string | null;
|
|
|
21
23
|
export declare function setPin(agents: string, version: string): string | null;
|
|
22
24
|
/** Reads the version a copy of the standard says it is, or `null` when its header is missing. */
|
|
23
25
|
export declare function standardVersion(standard: string): string | null;
|
|
24
|
-
/** Loads the
|
|
26
|
+
/** Loads the hash of each released version of the standard bundled in this package. */
|
|
25
27
|
export declare function loadHashes(): StandardHashes;
|
|
28
|
+
/** Loads the hash of each file the sync carries next to the standard, by path in the repository. */
|
|
29
|
+
export declare function loadFileHashes(): FileHashes;
|
|
26
30
|
/**
|
|
27
31
|
* Checks that the copy of the standard in `root` is the one published for the version its
|
|
28
32
|
* `AGENTS.md` pins (standard, section 16). A repository may pin an older version on purpose:
|
|
29
33
|
* the pinned one is checked, not the latest.
|
|
30
34
|
*
|
|
31
35
|
* @param root - The repository root.
|
|
36
|
+
* It also checks the synced files the repository has (`.claude/agents/*.md`, the skills, the pull
|
|
37
|
+
* request template) against `fileHashes`, but only when the pin is the newest version this package
|
|
38
|
+
* knows: a repository that stays on an older version on purpose keeps the older files too.
|
|
39
|
+
*
|
|
32
40
|
* @param hashes - The published hashes; the ones bundled in this package by default.
|
|
41
|
+
* @param fileHashes - The published hashes of the synced files; the bundled ones by default.
|
|
33
42
|
*/
|
|
34
|
-
export declare function lintStandard(root: string, hashes?: StandardHashes): StandardResult;
|
|
43
|
+
export declare function lintStandard(root: string, hashes?: StandardHashes, fileHashes?: FileHashes): StandardResult;
|
package/dist/standard.js
CHANGED
|
@@ -31,20 +31,53 @@ export function setPin(agents, version) {
|
|
|
31
31
|
export function standardVersion(standard) {
|
|
32
32
|
return HEADER.exec(standard)?.[1] ?? null;
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
34
|
+
/** Reads `standard-hashes.json`, bundled in this package. */
|
|
35
|
+
function readHashesFile() {
|
|
36
36
|
const file = new URL('../standard-hashes.json', import.meta.url);
|
|
37
37
|
return JSON.parse(readFileSync(file, 'utf8'));
|
|
38
38
|
}
|
|
39
|
+
/** Loads the hash of each released version of the standard bundled in this package. */
|
|
40
|
+
export function loadHashes() {
|
|
41
|
+
const hashes = {};
|
|
42
|
+
for (const [key, value] of Object.entries(readHashesFile())) {
|
|
43
|
+
if (typeof value === 'string')
|
|
44
|
+
hashes[key] = value;
|
|
45
|
+
}
|
|
46
|
+
return hashes;
|
|
47
|
+
}
|
|
48
|
+
/** Loads the hash of each file the sync carries next to the standard, by path in the repository. */
|
|
49
|
+
export function loadFileHashes() {
|
|
50
|
+
const files = {};
|
|
51
|
+
for (const [path, value] of Object.entries(readHashesFile().files ?? {})) {
|
|
52
|
+
if (typeof value === 'string')
|
|
53
|
+
files[path] = value;
|
|
54
|
+
}
|
|
55
|
+
return files;
|
|
56
|
+
}
|
|
57
|
+
/** The newest version in `hashes`, compared as numbers. */
|
|
58
|
+
function latestVersion(hashes) {
|
|
59
|
+
const order = (version) => version.split('.').map(Number);
|
|
60
|
+
const [latest] = Object.keys(hashes).sort((a, b) => {
|
|
61
|
+
const [ax = 0, ay = 0] = order(a);
|
|
62
|
+
const [bx = 0, by = 0] = order(b);
|
|
63
|
+
return bx - ax || by - ay;
|
|
64
|
+
});
|
|
65
|
+
return latest ?? null;
|
|
66
|
+
}
|
|
39
67
|
/**
|
|
40
68
|
* Checks that the copy of the standard in `root` is the one published for the version its
|
|
41
69
|
* `AGENTS.md` pins (standard, section 16). A repository may pin an older version on purpose:
|
|
42
70
|
* the pinned one is checked, not the latest.
|
|
43
71
|
*
|
|
44
72
|
* @param root - The repository root.
|
|
73
|
+
* It also checks the synced files the repository has (`.claude/agents/*.md`, the skills, the pull
|
|
74
|
+
* request template) against `fileHashes`, but only when the pin is the newest version this package
|
|
75
|
+
* knows: a repository that stays on an older version on purpose keeps the older files too.
|
|
76
|
+
*
|
|
45
77
|
* @param hashes - The published hashes; the ones bundled in this package by default.
|
|
78
|
+
* @param fileHashes - The published hashes of the synced files; the bundled ones by default.
|
|
46
79
|
*/
|
|
47
|
-
export function lintStandard(root, hashes = loadHashes()) {
|
|
80
|
+
export function lintStandard(root, hashes = loadHashes(), fileHashes = loadFileHashes()) {
|
|
48
81
|
const agentsPath = join(root, 'AGENTS.md');
|
|
49
82
|
if (!existsSync(agentsPath)) {
|
|
50
83
|
return {
|
|
@@ -78,5 +111,19 @@ export function lintStandard(root, hashes = loadHashes()) {
|
|
|
78
111
|
message: `${STANDARD_PATH} does not match standard ${pin}, the version AGENTS.md pins (sha256 ${actual}, published ${expected}). Restore it, or sync it from bogd3v/micelio-engineering.`,
|
|
79
112
|
};
|
|
80
113
|
}
|
|
114
|
+
const stale = pin === latestVersion(hashes)
|
|
115
|
+
? Object.entries(fileHashes)
|
|
116
|
+
.filter(([path, hash]) => {
|
|
117
|
+
const file = join(root, path);
|
|
118
|
+
return existsSync(file) && hashOf(readFileSync(file)) !== hash;
|
|
119
|
+
})
|
|
120
|
+
.map(([path]) => path)
|
|
121
|
+
: [];
|
|
122
|
+
if (stale.length > 0) {
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
message: `${stale.join(', ')} ${stale.length === 1 ? 'does' : 'do'} not match the published copy of standard ${pin}. Restore ${stale.length === 1 ? 'it' : 'them'} if edited by hand, or, in a sync pull request, upgrade @micelio/eslint-config to the release that publishes the new hashes.`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
81
128
|
return { ok: true, message: `Standard ${pin}: ${STANDARD_PATH} matches the published copy.` };
|
|
82
129
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@micelio/eslint-config",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "The ESLint flat config of the Micelio repositories, the licence allowlist behind lint:licenses and lint:standard.",
|
|
5
5
|
"license": "MIT-0",
|
|
6
6
|
"repository": {
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"eslint-config-prettier": "^10.1.8",
|
|
35
|
-
"eslint-plugin-jsdoc": "^65.
|
|
35
|
+
"eslint-plugin-jsdoc": "^65.4.2",
|
|
36
36
|
"eslint-plugin-tsdoc": "0.5.4",
|
|
37
|
-
"typescript-eslint": "^8.
|
|
37
|
+
"typescript-eslint": "^8.72.1"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"eslint": "^10.12.0",
|
package/standard-hashes.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"1.4": "0f1202bbd02a83f216313b84be4744d66ccbee60bc01b39bfc7f67cefd30e139",
|
|
3
|
-
"1.5": "c3ee8aa9a13945e073dedeecbb7ba3a9587ec0ef6878e426eb4be7a0398d93a1"
|
|
3
|
+
"1.5": "c3ee8aa9a13945e073dedeecbb7ba3a9587ec0ef6878e426eb4be7a0398d93a1",
|
|
4
|
+
"1.6": "ea74875d30586378a64d90feb59ce197d3efa7f07e867108f3849f5308cc1f92",
|
|
5
|
+
"files": {
|
|
6
|
+
".claude/agents/master.md": "ee982318762bccb42a8a68dfaf51628087dcd7d4563be5b8a08b1ffabea7adbd",
|
|
7
|
+
".claude/agents/planner.md": "b71c815c78875252c9574b74e581115c9814903bc05c11a992689d8af979f7e8",
|
|
8
|
+
".claude/agents/reviewer.md": "62b9addeab36c5166b674dd1b1cdae92c382b00a563ccbd2b652227932b7ef52",
|
|
9
|
+
".claude/agents/verifier.md": "9d42abc7329774c51f63f1079182e42720b052f1f3ef5b05019c9729aa394958",
|
|
10
|
+
".claude/agents/worker.md": "8390a223c983ec5ea7254e1f7fd1de79cfd1bb4c73936a133ddfb6ffd7f25d45",
|
|
11
|
+
".claude/skills/ship-pr/SKILL.md": "c6267ca9022252dbd48a90c19940d70f7515857792b5df5d2e6a8320f2ecfb51",
|
|
12
|
+
".claude/skills/blind-review/SKILL.md": "914d96d06ff3d34b711702c2a77315a387b3529e672eeead48fc830875a1f4ae",
|
|
13
|
+
".claude/skills/verify-pr/SKILL.md": "8a6c66d9b8933af550038f58587868665daa90c7ac631fc648d92b366bd7e516",
|
|
14
|
+
".github/pull_request_template.md": "3ae627043b11a7f26283ee90f68ac8ba6b6b2fb6a24a97f23637ae8ef9dd23e0"
|
|
15
|
+
}
|
|
4
16
|
}
|