@csark0812/skeleton 1.1.3 → 1.5.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/README.md +5 -1
- package/dist/cli.js +2070 -909
- package/dist/hooks/customize-on-skill-read.js +27 -2
- package/dist/plugin-types.d.ts +117 -0
- package/dist/plugin-types.js +41 -0
- package/package.json +14 -2
- package/schemas/config.schema.json +7 -2
- package/schemas/policy-file.schema.json +41 -0
- package/templates/skeleton-init/config.yaml +4 -0
|
@@ -13241,7 +13241,13 @@ import { readFileSync as readFileSync4 } from "node:fs";
|
|
|
13241
13241
|
var REGISTRY_REL_PATH = ".skeleton/registry.md";
|
|
13242
13242
|
var REGISTRY_DIR_REL = ".skeleton";
|
|
13243
13243
|
function normalizeRelPath(p) {
|
|
13244
|
-
|
|
13244
|
+
let out = p.replace(/\\/g, "/");
|
|
13245
|
+
if (out.startsWith("/"))
|
|
13246
|
+
return out;
|
|
13247
|
+
while (out.startsWith("./")) {
|
|
13248
|
+
out = out.slice(2);
|
|
13249
|
+
}
|
|
13250
|
+
return out;
|
|
13245
13251
|
}
|
|
13246
13252
|
|
|
13247
13253
|
// src/audit/core/skill-roots.ts
|
|
@@ -13354,6 +13360,23 @@ var $stringify = publicApi.stringify;
|
|
|
13354
13360
|
var $visit = visit.visit;
|
|
13355
13361
|
var $visitAsync = visit.visitAsync;
|
|
13356
13362
|
|
|
13363
|
+
// src/audit/core/draft.ts
|
|
13364
|
+
function normalizeDraftPrefix(prefix) {
|
|
13365
|
+
const normalized = normalizeRelPath(prefix);
|
|
13366
|
+
const withSlash = normalized.endsWith("/") ? normalized : `${normalized}/`;
|
|
13367
|
+
if (withSlash === "/" || withSlash === "./") {
|
|
13368
|
+
throw new Error(`Invalid draftPathPrefixes entry ${JSON.stringify(prefix)}: must be a repo-relative directory (e.g. drafts/), not ${JSON.stringify(prefix)}`);
|
|
13369
|
+
}
|
|
13370
|
+
return withSlash;
|
|
13371
|
+
}
|
|
13372
|
+
function validateDraftPathPrefixes(prefixes) {
|
|
13373
|
+
if (!prefixes)
|
|
13374
|
+
return;
|
|
13375
|
+
for (const prefix of prefixes) {
|
|
13376
|
+
normalizeDraftPrefix(prefix);
|
|
13377
|
+
}
|
|
13378
|
+
}
|
|
13379
|
+
|
|
13357
13380
|
// src/audit/config/load.ts
|
|
13358
13381
|
var SCHEMA_CANDIDATES = [
|
|
13359
13382
|
join2(dirname(fileURLToPath(import.meta.url)), "../../../schemas/config.schema.json"),
|
|
@@ -13394,7 +13417,9 @@ function validateConfig(raw) {
|
|
|
13394
13417
|
const detail = validate.errors?.map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ");
|
|
13395
13418
|
throw new Error(`Invalid .skeleton/config.yaml: ${detail ?? "schema validation failed"}`);
|
|
13396
13419
|
}
|
|
13397
|
-
|
|
13420
|
+
const config = raw;
|
|
13421
|
+
validateDraftPathPrefixes(config.draftPathPrefixes);
|
|
13422
|
+
return config;
|
|
13398
13423
|
}
|
|
13399
13424
|
function loadConfig(root) {
|
|
13400
13425
|
const configPath = join2(root, ".skeleton", "config.yaml");
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for `@csark0812/skeleton/plugin-types`.
|
|
3
|
+
* Kept hand-written so publishes stay independent of `.ts` extension emit quirks.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type Severity = "error" | "warning";
|
|
7
|
+
|
|
8
|
+
export interface Issue {
|
|
9
|
+
rule: string;
|
|
10
|
+
file: string;
|
|
11
|
+
link?: string;
|
|
12
|
+
message: string;
|
|
13
|
+
severity: Severity;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export declare function issue(
|
|
17
|
+
rule: string,
|
|
18
|
+
file: string,
|
|
19
|
+
message: string,
|
|
20
|
+
opts?: { link?: string; severity?: Severity },
|
|
21
|
+
): Issue;
|
|
22
|
+
|
|
23
|
+
export type AuditSuite = "docs" | "skills";
|
|
24
|
+
|
|
25
|
+
export interface AuditRule {
|
|
26
|
+
id: string;
|
|
27
|
+
global?: boolean;
|
|
28
|
+
suites?: AuditSuite[];
|
|
29
|
+
run: (ctx: AuditContext) => Issue[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type PolicyEntry =
|
|
33
|
+
| {
|
|
34
|
+
id: string;
|
|
35
|
+
message: string;
|
|
36
|
+
mode?: "pattern";
|
|
37
|
+
pattern: string;
|
|
38
|
+
scope?: string;
|
|
39
|
+
severity?: Severity;
|
|
40
|
+
canonical?: string;
|
|
41
|
+
}
|
|
42
|
+
| {
|
|
43
|
+
id: string;
|
|
44
|
+
message: string;
|
|
45
|
+
mode: "fingerprint";
|
|
46
|
+
pattern?: string;
|
|
47
|
+
scope?: string;
|
|
48
|
+
severity?: Severity;
|
|
49
|
+
canonical?: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export interface CompiledPolicyEntry {
|
|
53
|
+
id: string;
|
|
54
|
+
message: string;
|
|
55
|
+
mode: "pattern" | "fingerprint";
|
|
56
|
+
pattern?: string;
|
|
57
|
+
scope?: string;
|
|
58
|
+
severity?: Severity;
|
|
59
|
+
canonical?: string;
|
|
60
|
+
regex: RegExp | null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface PolicyFile {
|
|
64
|
+
name: string;
|
|
65
|
+
entries: CompiledPolicyEntry[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface PolicyFileYaml {
|
|
69
|
+
name: string;
|
|
70
|
+
entries: PolicyEntry[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type MatchedPolicyEntry = CompiledPolicyEntry & { policyName: string };
|
|
74
|
+
|
|
75
|
+
export interface ScanConfig {
|
|
76
|
+
include: string[];
|
|
77
|
+
exclude: string[];
|
|
78
|
+
banned: string[];
|
|
79
|
+
retiredSkills?: string[];
|
|
80
|
+
nonPublicSkills?: string[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface CustomizeConfig {
|
|
84
|
+
alwaysInclude?: string[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface SkeletonConfig {
|
|
88
|
+
scan: ScanConfig;
|
|
89
|
+
daysUntilStale: number;
|
|
90
|
+
customize?: CustomizeConfig;
|
|
91
|
+
plugins?: string[];
|
|
92
|
+
draftPathPrefixes?: string[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface SkillRoot {
|
|
96
|
+
kind: "nested" | "flat";
|
|
97
|
+
relPath: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface SkillIndex {
|
|
101
|
+
roots: SkillRoot[];
|
|
102
|
+
slugs: string[];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface AuditContext {
|
|
106
|
+
root: string;
|
|
107
|
+
config: SkeletonConfig;
|
|
108
|
+
files: string[];
|
|
109
|
+
docMetaPaths: string[];
|
|
110
|
+
registryPaths: string[];
|
|
111
|
+
registryHasTableHeader: boolean;
|
|
112
|
+
retiredSkills: Set<string>;
|
|
113
|
+
skillIndex: SkillIndex;
|
|
114
|
+
policies: PolicyFile[];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export declare function matchesGlobScope(relPath: string, scope: string | undefined): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/audit/core/report.ts
|
|
2
|
+
function issue(rule, file, message, opts) {
|
|
3
|
+
return {
|
|
4
|
+
rule,
|
|
5
|
+
file,
|
|
6
|
+
link: opts?.link,
|
|
7
|
+
message,
|
|
8
|
+
severity: opts?.severity ?? "error"
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
// src/audit/core/shared.ts
|
|
12
|
+
function normalizeRelPath(p) {
|
|
13
|
+
let out = p.replace(/\\/g, "/");
|
|
14
|
+
if (out.startsWith("/"))
|
|
15
|
+
return out;
|
|
16
|
+
while (out.startsWith("./")) {
|
|
17
|
+
out = out.slice(2);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
function escapeRegexLiteral(s) {
|
|
22
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23
|
+
}
|
|
24
|
+
function globToRegex(glob) {
|
|
25
|
+
let pattern = glob.replace(/\\/g, "/");
|
|
26
|
+
pattern = pattern.replace(/\{([^}]+)\}/g, (_, inner) => {
|
|
27
|
+
const parts = inner.split(",").map((p) => escapeRegexLiteral(p.trim()));
|
|
28
|
+
return `(${parts.join("|")})`;
|
|
29
|
+
});
|
|
30
|
+
pattern = pattern.replace(/\*\*/g, "§§").replace(/\*/g, "[^/]*").replace(/§§/g, ".*").replace(/\?/g, "[^/]");
|
|
31
|
+
return new RegExp(`^${pattern}$`);
|
|
32
|
+
}
|
|
33
|
+
function matchesGlobScope(relPath, scope) {
|
|
34
|
+
if (!scope)
|
|
35
|
+
return true;
|
|
36
|
+
return globToRegex(scope).test(normalizeRelPath(relPath));
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
matchesGlobScope,
|
|
40
|
+
issue
|
|
41
|
+
};
|
package/package.json
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csark0812/skeleton",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "SSOT audit CLI for agent harness repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"skeleton": "./dist/cli.js"
|
|
8
8
|
},
|
|
9
|
+
"exports": {
|
|
10
|
+
"./plugin-types": {
|
|
11
|
+
"types": "./dist/plugin-types.d.ts",
|
|
12
|
+
"default": "./dist/plugin-types.js"
|
|
13
|
+
},
|
|
14
|
+
"./schemas/config.schema.json": "./schemas/config.schema.json",
|
|
15
|
+
"./schemas/policy-file.schema.json": "./schemas/policy-file.schema.json"
|
|
16
|
+
},
|
|
9
17
|
"files": [
|
|
10
18
|
"dist",
|
|
11
19
|
"templates",
|
|
12
20
|
"schemas"
|
|
13
21
|
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/csark0812/skeleton.git"
|
|
25
|
+
},
|
|
14
26
|
"license": "MIT",
|
|
15
27
|
"engines": {
|
|
16
28
|
"node": ">=22"
|
|
17
29
|
},
|
|
18
30
|
"packageManager": "bun@1.2.21",
|
|
19
31
|
"scripts": {
|
|
20
|
-
"build": "bun build src/cli.ts --target=node --outfile=dist/cli.js && bun build src/hooks/customize-on-skill-read.ts --target=node --outfile=dist/hooks/customize-on-skill-read.js",
|
|
32
|
+
"build": "bun build src/cli.ts --target=node --outfile=dist/cli.js && bun build src/hooks/customize-on-skill-read.ts --target=node --outfile=dist/hooks/customize-on-skill-read.js && bun build src/plugin-types.ts --target=node --format=esm --outfile=dist/plugin-types.js --packages=external && cp types/plugin-types.d.ts dist/plugin-types.d.ts",
|
|
21
33
|
"test": "bun test",
|
|
22
34
|
"test:audit": "bun test src/audit/__tests__",
|
|
23
35
|
"test:cli": "bun test src/__tests__/cli",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"type": "array",
|
|
25
25
|
"items": { "type": "string" }
|
|
26
26
|
},
|
|
27
|
-
|
|
27
|
+
"retiredSkills": {
|
|
28
28
|
"type": "array",
|
|
29
29
|
"items": { "type": "string", "pattern": "^[a-z0-9-]+$" }
|
|
30
30
|
},
|
|
@@ -58,7 +58,12 @@
|
|
|
58
58
|
"plugins": {
|
|
59
59
|
"type": "array",
|
|
60
60
|
"items": { "type": "string", "minLength": 1 },
|
|
61
|
-
"description": "Plugin entry paths relative to .skeleton
|
|
61
|
+
"description": "Plugin entry paths relative to .skeleton/; each entry must have a built sibling .mjs (run skeleton build-plugin)"
|
|
62
|
+
},
|
|
63
|
+
"draftPathPrefixes": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"items": { "type": "string", "minLength": 1 },
|
|
66
|
+
"description": "Allow-list directory prefixes for draft-marker prose-policy placement (plus _draft-*.md filenames). Trailing / is implied. Repo-relative only (e.g. drafts/) — not ., ./, or /. Not scan.exclude."
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
69
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/csark0812/skeleton/schemas/policy-file.schema.json",
|
|
4
|
+
"title": "Policy File",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["name", "entries"],
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Policy set id (matches filename stem)"
|
|
12
|
+
},
|
|
13
|
+
"entries": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"minItems": 1,
|
|
16
|
+
"items": { "$ref": "#/$defs/policyEntry" }
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"$defs": {
|
|
20
|
+
"policyEntry": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"required": ["id", "message"],
|
|
23
|
+
"additionalProperties": false,
|
|
24
|
+
"properties": {
|
|
25
|
+
"id": { "type": "string" },
|
|
26
|
+
"mode": { "enum": ["pattern", "fingerprint"] },
|
|
27
|
+
"pattern": { "type": "string" },
|
|
28
|
+
"message": { "type": "string" },
|
|
29
|
+
"scope": { "type": "string" },
|
|
30
|
+
"severity": { "enum": ["error", "warning"] },
|
|
31
|
+
"canonical": { "type": "string" }
|
|
32
|
+
},
|
|
33
|
+
"if": {
|
|
34
|
+
"properties": { "mode": { "const": "fingerprint" } },
|
|
35
|
+
"required": ["mode"]
|
|
36
|
+
},
|
|
37
|
+
"then": true,
|
|
38
|
+
"else": { "required": ["pattern"] }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -18,3 +18,7 @@ daysUntilStale: 180
|
|
|
18
18
|
# alwaysInclude:
|
|
19
19
|
# - shared-agent-references.md
|
|
20
20
|
|
|
21
|
+
# Optional: plugin `.ts` entries relative to .skeleton/ (built sibling `.mjs` required)
|
|
22
|
+
# plugins: []
|
|
23
|
+
# Optional: draft-marker allow-list prefixes (plus `_draft-*.md` filenames)
|
|
24
|
+
# draftPathPrefixes: []
|