@agentxm/extension-content 0.28.14-preview.1789139351.5cd4595aa

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.
Files changed (133) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +17 -0
  3. package/dist/src/content/agent-skills-standard.d.ts +17 -0
  4. package/dist/src/content/agent-skills-standard.js +24 -0
  5. package/dist/src/content/frontmatter.d.ts +52 -0
  6. package/dist/src/content/frontmatter.js +115 -0
  7. package/dist/src/content/index.d.ts +11 -0
  8. package/dist/src/content/index.js +11 -0
  9. package/dist/src/content/skill-content.d.ts +43 -0
  10. package/dist/src/content/skill-content.js +184 -0
  11. package/dist/src/content/skill-types.d.ts +22 -0
  12. package/dist/src/content/skill-types.js +9 -0
  13. package/dist/src/content/subagent-content.d.ts +58 -0
  14. package/dist/src/content/subagent-content.js +101 -0
  15. package/dist/src/index.d.ts +23 -0
  16. package/dist/src/index.js +23 -0
  17. package/dist/src/knowledge/index.d.ts +9 -0
  18. package/dist/src/knowledge/index.js +9 -0
  19. package/dist/src/knowledge/knowledge-search.d.ts +32 -0
  20. package/dist/src/knowledge/knowledge-search.js +147 -0
  21. package/dist/src/knowledge/okf.d.ts +86 -0
  22. package/dist/src/knowledge/okf.js +1090 -0
  23. package/dist/src/knowledge/package-inspection.d.ts +125 -0
  24. package/dist/src/knowledge/package-inspection.js +45 -0
  25. package/dist/src/lint/catalog/hook/decision-portability.d.ts +4 -0
  26. package/dist/src/lint/catalog/hook/decision-portability.js +40 -0
  27. package/dist/src/lint/catalog/hook/entrypoint-exists.d.ts +4 -0
  28. package/dist/src/lint/catalog/hook/entrypoint-exists.js +39 -0
  29. package/dist/src/lint/catalog/hook/envelope.d.ts +6 -0
  30. package/dist/src/lint/catalog/hook/envelope.js +15 -0
  31. package/dist/src/lint/catalog/hook/matcher-raw-portability.d.ts +4 -0
  32. package/dist/src/lint/catalog/hook/matcher-raw-portability.js +51 -0
  33. package/dist/src/lint/catalog/hook.d.ts +4 -0
  34. package/dist/src/lint/catalog/hook.js +15 -0
  35. package/dist/src/lint/catalog/knowledge/diagnostics.d.ts +128 -0
  36. package/dist/src/lint/catalog/knowledge/diagnostics.js +78 -0
  37. package/dist/src/lint/catalog/knowledge/envelope.d.ts +6 -0
  38. package/dist/src/lint/catalog/knowledge/envelope.js +15 -0
  39. package/dist/src/lint/catalog/knowledge.d.ts +11 -0
  40. package/dist/src/lint/catalog/knowledge.js +15 -0
  41. package/dist/src/lint/catalog/mcp-server/envelope.d.ts +6 -0
  42. package/dist/src/lint/catalog/mcp-server/envelope.js +15 -0
  43. package/dist/src/lint/catalog/mcp-server.d.ts +4 -0
  44. package/dist/src/lint/catalog/mcp-server.js +4 -0
  45. package/dist/src/lint/catalog/pack/manifest-keys-recognized.d.ts +28 -0
  46. package/dist/src/lint/catalog/pack/manifest-keys-recognized.js +38 -0
  47. package/dist/src/lint/catalog/pack/manifest-present.d.ts +17 -0
  48. package/dist/src/lint/catalog/pack/manifest-present.js +24 -0
  49. package/dist/src/lint/catalog/pack/manifest-schema-valid.d.ts +25 -0
  50. package/dist/src/lint/catalog/pack/manifest-schema-valid.js +33 -0
  51. package/dist/src/lint/catalog/pack-accessor/contexts.d.ts +51 -0
  52. package/dist/src/lint/catalog/pack-accessor/contexts.js +45 -0
  53. package/dist/src/lint/catalog/pack-accessor/platform.d.ts +56 -0
  54. package/dist/src/lint/catalog/pack-accessor/platform.js +93 -0
  55. package/dist/src/lint/catalog/pack-accessor/vft.d.ts +60 -0
  56. package/dist/src/lint/catalog/pack-accessor/vft.js +85 -0
  57. package/dist/src/lint/catalog/pack.d.ts +31 -0
  58. package/dist/src/lint/catalog/pack.js +36 -0
  59. package/dist/src/lint/catalog/rule/envelope.d.ts +6 -0
  60. package/dist/src/lint/catalog/rule/envelope.js +15 -0
  61. package/dist/src/lint/catalog/rule.d.ts +4 -0
  62. package/dist/src/lint/catalog/rule.js +4 -0
  63. package/dist/src/lint/catalog/shared/envelope-rules.d.ts +88 -0
  64. package/dist/src/lint/catalog/shared/envelope-rules.js +84 -0
  65. package/dist/src/lint/catalog/shared/manifest-json.d.ts +18 -0
  66. package/dist/src/lint/catalog/shared/manifest-json.js +28 -0
  67. package/dist/src/lint/catalog/shared/manifest-present.d.ts +25 -0
  68. package/dist/src/lint/catalog/shared/manifest-present.js +37 -0
  69. package/dist/src/lint/catalog/shared/recommended-packs-rules.d.ts +70 -0
  70. package/dist/src/lint/catalog/shared/recommended-packs-rules.js +139 -0
  71. package/dist/src/lint/catalog/shared/schema-rule.d.ts +57 -0
  72. package/dist/src/lint/catalog/shared/schema-rule.js +102 -0
  73. package/dist/src/lint/catalog/skill/frontmatter-parseable.d.ts +31 -0
  74. package/dist/src/lint/catalog/skill/frontmatter-parseable.js +148 -0
  75. package/dist/src/lint/catalog/skill/frontmatter-standard-valid.d.ts +13 -0
  76. package/dist/src/lint/catalog/skill/frontmatter-standard-valid.js +61 -0
  77. package/dist/src/lint/catalog/skill/manifest-keys-recognized.d.ts +26 -0
  78. package/dist/src/lint/catalog/skill/manifest-keys-recognized.js +41 -0
  79. package/dist/src/lint/catalog/skill/manifest-present.d.ts +23 -0
  80. package/dist/src/lint/catalog/skill/manifest-present.js +32 -0
  81. package/dist/src/lint/catalog/skill/manifest-schema-valid.d.ts +21 -0
  82. package/dist/src/lint/catalog/skill/manifest-schema-valid.js +36 -0
  83. package/dist/src/lint/catalog/skill/recommended-packs-valid.d.ts +8 -0
  84. package/dist/src/lint/catalog/skill/recommended-packs-valid.js +12 -0
  85. package/dist/src/lint/catalog/skill/skill-md-present.d.ts +17 -0
  86. package/dist/src/lint/catalog/skill/skill-md-present.js +37 -0
  87. package/dist/src/lint/catalog/skill/standalone-declaration-valid.d.ts +8 -0
  88. package/dist/src/lint/catalog/skill/standalone-declaration-valid.js +12 -0
  89. package/dist/src/lint/catalog/skill-accessor/contexts.d.ts +61 -0
  90. package/dist/src/lint/catalog/skill-accessor/contexts.js +55 -0
  91. package/dist/src/lint/catalog/skill-accessor/platform.d.ts +53 -0
  92. package/dist/src/lint/catalog/skill-accessor/platform.js +90 -0
  93. package/dist/src/lint/catalog/skill-accessor/vft.d.ts +77 -0
  94. package/dist/src/lint/catalog/skill-accessor/vft.js +135 -0
  95. package/dist/src/lint/catalog/skill.d.ts +38 -0
  96. package/dist/src/lint/catalog/skill.js +53 -0
  97. package/dist/src/lint/catalog/subagent/envelope.d.ts +6 -0
  98. package/dist/src/lint/catalog/subagent/envelope.js +15 -0
  99. package/dist/src/lint/catalog/subagent.d.ts +4 -0
  100. package/dist/src/lint/catalog/subagent.js +4 -0
  101. package/dist/src/lint/catalog-metadata.d.ts +125 -0
  102. package/dist/src/lint/catalog-metadata.js +642 -0
  103. package/dist/src/lint/compose-path.d.ts +28 -0
  104. package/dist/src/lint/compose-path.js +64 -0
  105. package/dist/src/lint/config.d.ts +77 -0
  106. package/dist/src/lint/config.js +99 -0
  107. package/dist/src/lint/context.d.ts +239 -0
  108. package/dist/src/lint/context.js +17 -0
  109. package/dist/src/lint/describe-document.d.ts +31 -0
  110. package/dist/src/lint/describe-document.js +50 -0
  111. package/dist/src/lint/evaluate.d.ts +47 -0
  112. package/dist/src/lint/evaluate.js +73 -0
  113. package/dist/src/lint/index.d.ts +36 -0
  114. package/dist/src/lint/index.js +34 -0
  115. package/dist/src/lint/issues-to-findings.d.ts +35 -0
  116. package/dist/src/lint/issues-to-findings.js +149 -0
  117. package/dist/src/lint/rule.d.ts +97 -0
  118. package/dist/src/lint/rule.js +17 -0
  119. package/dist/src/packaging/archive-guardrails.d.ts +39 -0
  120. package/dist/src/packaging/archive-guardrails.js +250 -0
  121. package/dist/src/packaging/filtered-package-validation.d.ts +24 -0
  122. package/dist/src/packaging/filtered-package-validation.js +117 -0
  123. package/dist/src/packaging/ingest-limits.d.ts +25 -0
  124. package/dist/src/packaging/ingest-limits.js +41 -0
  125. package/dist/src/packaging/input-normalization.d.ts +40 -0
  126. package/dist/src/packaging/input-normalization.js +125 -0
  127. package/dist/src/packaging/manifest-policy.d.ts +611 -0
  128. package/dist/src/packaging/manifest-policy.js +196 -0
  129. package/dist/src/packaging/test-zip-helpers.d.ts +13 -0
  130. package/dist/src/packaging/test-zip-helpers.js +117 -0
  131. package/dist/src/testing.d.ts +9 -0
  132. package/dist/src/testing.js +9 -0
  133. package/package.json +65 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Shared schema-delegation plumbing for `-schema-valid` rules.
3
+ *
4
+ * Every rule whose id ends in `-schema-valid` implements `check` by
5
+ * running the canonical schema through `Schema.decodeUnknownResult` with
6
+ * `onExcessProperty: "ignore"` and `errors: "all"`, then mapping the issues
7
+ * through `issuesToFindings`.
8
+ *
9
+ * The helper is intentionally narrow — only the surface the `-schema-valid`
10
+ * rules need.
11
+ *
12
+ * @experimental This API is unstable and may change without notice.
13
+ * @packageDocumentation
14
+ */
15
+ import * as Effect from "effect/Effect";
16
+ import * as Result from "effect/Result";
17
+ import * as Schema from "effect/Schema";
18
+ import { describeSchemaDocument } from "../../describe-document.js";
19
+ import { issuesToFindings } from "../../issues-to-findings.js";
20
+ import { isManifestJsonParseFailure, manifestJsonParseFailureToFinding } from "./manifest-json.js";
21
+ // -----------------------------------------------------------------------------
22
+ // schemaDecodeFindings
23
+ // -----------------------------------------------------------------------------
24
+ /**
25
+ * Decode `input` against `schema` (excess keys ignored, all issues collected)
26
+ * and return one advisory finding per leaf issue. Success produces `[]`.
27
+ *
28
+ * `input` of `undefined` short-circuits to `[]` — the caller is expected to
29
+ * have already guarded on "manifest exists" via the complementary
30
+ * `-present` rule.
31
+ *
32
+ * @param ruleId - `<namespace>/<name>` id of the calling rule.
33
+ * @param severity - Severity to stamp on each emitted finding.
34
+ * @param file - Accessor-relative file path to stamp on `location.file`.
35
+ * @param schema - Canonical Effect schema; `Schema.decodeUnknownResult`
36
+ * runs with `onExcessProperty: "ignore"` and `errors: "all"`.
37
+ * @param input - Raw decoded JSON value to check (typically `subject.*Json`).
38
+ *
39
+ * @experimental This API is unstable and may change without notice.
40
+ */
41
+ export const schemaDecodeFindings = (ruleId, severity, file, schema, input) => {
42
+ if (input === undefined) {
43
+ return Effect.succeed([]);
44
+ }
45
+ if (isManifestJsonParseFailure(input)) {
46
+ return Effect.succeed([manifestJsonParseFailureToFinding(ruleId, severity, file, input)]);
47
+ }
48
+ const result = Schema.decodeUnknownResult(schema)(input, {
49
+ onExcessProperty: "ignore",
50
+ errors: "all",
51
+ });
52
+ if (Result.isSuccess(result)) {
53
+ return Effect.succeed([]);
54
+ }
55
+ return Effect.succeed(issuesToFindings(ruleId, severity, file, result.failure.issue));
56
+ };
57
+ // -----------------------------------------------------------------------------
58
+ // enumerateUnknownTopLevelKeys
59
+ // -----------------------------------------------------------------------------
60
+ /**
61
+ * Read the top-level field names of a `Schema.Struct` value.
62
+ *
63
+ * Callers produce an `allowedKeys` set in one place, driven by the schema
64
+ * itself — no copy-paste of field names into rule bodies. If the schema
65
+ * gains a field the allowed-keys set grows by construction.
66
+ *
67
+ * @experimental This API is unstable and may change without notice.
68
+ */
69
+ export const structFieldKeys = (struct) => new Set(Object.keys(struct.fields));
70
+ /**
71
+ * Enumerate top-level keys present on `input` that are not declared by
72
+ * `allowedKeys`. Returns one advisory finding per unknown key.
73
+ *
74
+ * `input` of `undefined` or non-object short-circuits to `[]`.
75
+ *
76
+ * @experimental This API is unstable and may change without notice.
77
+ */
78
+ export const enumerateUnknownTopLevelKeys = (ruleId, severity, file, allowedKeys, input) => {
79
+ if (isManifestJsonParseFailure(input)) {
80
+ return [];
81
+ }
82
+ if (!isPlainRecord(input)) {
83
+ return [];
84
+ }
85
+ const findings = [];
86
+ for (const key of Object.keys(input)) {
87
+ if (allowedKeys.has(key)) {
88
+ continue;
89
+ }
90
+ findings.push({
91
+ kind: "advisory",
92
+ ruleId,
93
+ severity,
94
+ message: `${describeSchemaDocument(file)} has unrecognized top-level field '${key}'. ` +
95
+ `The current schema does not recognize this field.`,
96
+ location: { file },
97
+ });
98
+ }
99
+ return findings;
100
+ };
101
+ const isPlainRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
102
+ //# sourceMappingURL=schema-rule.js.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `skill/frontmatter-parseable` — SKILL.md frontmatter parses as a YAML
3
+ * mapping.
4
+ *
5
+ * Cascade (reports the first failure in the order below; later arms
6
+ * short-circuit):
7
+ *
8
+ * 1. SKILL.md begins with `---` at byte 0 (no BOM, no leading whitespace, no
9
+ * leading HTML comment). This is the arm that caught the
10
+ * `@agentxm/skills/axm` regression — an HTML comment preceded the
11
+ * frontmatter delimiter, so YAML parsers silently treated the content as
12
+ * body.
13
+ * 2. Frontmatter YAML parses without error.
14
+ * 3. Parsed frontmatter is a mapping (not a list, not a scalar).
15
+ *
16
+ * Presence is handled by `skill/skill-md-present`; this rule early-returns
17
+ * `[]` when `SKILL.md` is absent.
18
+ *
19
+ * Advisory-only — the cascade mixes one mechanically-fixable arm
20
+ * (strip-leading-bytes) with arms requiring human judgment (fix YAML
21
+ * syntax). Per the lint design, splitting by
22
+ * kind or adding a byte-range mutation Operation is deferred until a second
23
+ * mechanical arm justifies it.
24
+ *
25
+ * @experimental This API is unstable and may change without notice.
26
+ * @packageDocumentation
27
+ */
28
+ import type { SkillRuleContext } from "../../context.js";
29
+ import type { AdvisoryRule } from "../../rule.js";
30
+ export declare const frontmatterParseableRule: AdvisoryRule<SkillRuleContext>;
31
+ //# sourceMappingURL=frontmatter-parseable.d.ts.map
@@ -0,0 +1,148 @@
1
+ /**
2
+ * `skill/frontmatter-parseable` — SKILL.md frontmatter parses as a YAML
3
+ * mapping.
4
+ *
5
+ * Cascade (reports the first failure in the order below; later arms
6
+ * short-circuit):
7
+ *
8
+ * 1. SKILL.md begins with `---` at byte 0 (no BOM, no leading whitespace, no
9
+ * leading HTML comment). This is the arm that caught the
10
+ * `@agentxm/skills/axm` regression — an HTML comment preceded the
11
+ * frontmatter delimiter, so YAML parsers silently treated the content as
12
+ * body.
13
+ * 2. Frontmatter YAML parses without error.
14
+ * 3. Parsed frontmatter is a mapping (not a list, not a scalar).
15
+ *
16
+ * Presence is handled by `skill/skill-md-present`; this rule early-returns
17
+ * `[]` when `SKILL.md` is absent.
18
+ *
19
+ * Advisory-only — the cascade mixes one mechanically-fixable arm
20
+ * (strip-leading-bytes) with arms requiring human judgment (fix YAML
21
+ * syntax). Per the lint design, splitting by
22
+ * kind or adding a byte-range mutation Operation is deferred until a second
23
+ * mechanical arm justifies it.
24
+ *
25
+ * @experimental This API is unstable and may change without notice.
26
+ * @packageDocumentation
27
+ */
28
+ import * as Effect from "effect/Effect";
29
+ import YAML from "yaml";
30
+ const RULE_ID = "skill/frontmatter-parseable";
31
+ const SKILL_MD = "SKILL.md";
32
+ const DELIMITER = "---";
33
+ // U+FEFF — UTF-8 BOM as a single code point. Escape form so the editor /
34
+ // formatter can't silently strip the literal.
35
+ const UTF8_BOM = "\uFEFF";
36
+ // `ignoreBOM: true` here means "pass the BOM through to the decoded string,
37
+ // don't strip it" — cascade arm 1 must see the BOM to flag it.
38
+ const decoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
39
+ export const frontmatterParseableRule = {
40
+ id: RULE_ID,
41
+ description: "SKILL.md frontmatter is a valid YAML mapping.",
42
+ kind: "advisory",
43
+ severity: "error",
44
+ check: (context) => Effect.gen(function* () {
45
+ const exists = yield* context.files.exists(SKILL_MD);
46
+ if (!exists) {
47
+ // Presence is covered by `skill/skill-md-present`.
48
+ return [];
49
+ }
50
+ const bytesResult = yield* context.files.readBytes(SKILL_MD).pipe(Effect.map((bytes) => ({ kind: "ok", bytes })),
51
+ // Treat read errors the same as absence — presence rule already owns
52
+ // that path. If `exists` said true but read fails, the cascade can't
53
+ // run anyway; silence here keeps the finding count at one.
54
+ Effect.catch(() => Effect.succeed({ kind: "none" })));
55
+ if (bytesResult.kind === "none") {
56
+ return [];
57
+ }
58
+ const content = decoder.decode(bytesResult.bytes);
59
+ return evaluateCascade(content);
60
+ }),
61
+ };
62
+ // -----------------------------------------------------------------------------
63
+ // Cascade
64
+ // -----------------------------------------------------------------------------
65
+ const evaluateCascade = (content) => {
66
+ const leading = detectLeadingBytes(content);
67
+ if (leading !== undefined) {
68
+ return [leading];
69
+ }
70
+ const parsed = parseFrontmatterYaml(content);
71
+ if (parsed === undefined) {
72
+ // No frontmatter block. Treat as bad (cascade arm 1 "begins with ---"
73
+ // already handled the "literally no ---" case; reaching here means the
74
+ // delimiter was found but the closing delimiter is missing).
75
+ return [
76
+ finding("SKILL.md frontmatter is malformed because the closing `---` delimiter is missing. Add a closing `---` after the frontmatter block."),
77
+ ];
78
+ }
79
+ if (parsed.kind === "parse-error") {
80
+ return [
81
+ finding(`SKILL.md frontmatter YAML is invalid. Detail: ${parsed.message}. Fix the YAML syntax in the frontmatter block.`),
82
+ ];
83
+ }
84
+ if (!isMapping(parsed.value)) {
85
+ return [
86
+ finding("SKILL.md frontmatter must be a YAML mapping, not a list or scalar. Rewrite the frontmatter block in `SKILL.md` as `key: value` pairs."),
87
+ ];
88
+ }
89
+ return [];
90
+ };
91
+ // -----------------------------------------------------------------------------
92
+ // Arm 1: leading bytes before `---`
93
+ // -----------------------------------------------------------------------------
94
+ const detectLeadingBytes = (content) => {
95
+ if (content.startsWith(UTF8_BOM)) {
96
+ return finding("SKILL.md starts with a UTF-8 BOM before the frontmatter delimiter. Remove the BOM so the file starts with `---`.", { line: 1 });
97
+ }
98
+ if (content.startsWith(DELIMITER)) {
99
+ return undefined;
100
+ }
101
+ // Any non-`---` leading content is a cascade-arm-1 violation. Detect the
102
+ // common HTML-comment case explicitly so the finding message is clear.
103
+ if (/^\s*<!--/.test(content)) {
104
+ return finding("SKILL.md starts with an HTML comment before the frontmatter delimiter. Move or remove the comment so the file starts with `---`.", { line: 1 });
105
+ }
106
+ return finding("SKILL.md must start with the frontmatter delimiter `---`. Remove any leading content so the file starts with `---`.", { line: 1 });
107
+ };
108
+ const parseFrontmatterYaml = (content) => {
109
+ // content starts with `---` (arm 1 guaranteed). Find closing delimiter on a
110
+ // new line.
111
+ const afterOpening = content.indexOf("\n");
112
+ if (afterOpening === -1) {
113
+ return undefined;
114
+ }
115
+ const closingIndex = content.indexOf(`\n${DELIMITER}`, afterOpening);
116
+ if (closingIndex === -1) {
117
+ return undefined;
118
+ }
119
+ const yamlContent = content.slice(afterOpening + 1, closingIndex);
120
+ try {
121
+ // YAML.parse returns `null | undefined` for empty input; we care about
122
+ // shape, not emptiness at this arm.
123
+ const value = YAML.parse(yamlContent);
124
+ return { kind: "parsed", value };
125
+ }
126
+ catch (error) {
127
+ return {
128
+ kind: "parse-error",
129
+ message: error instanceof Error ? error.message : String(error),
130
+ };
131
+ }
132
+ };
133
+ const isMapping = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
134
+ // -----------------------------------------------------------------------------
135
+ // Finding helpers
136
+ // -----------------------------------------------------------------------------
137
+ const finding = (message, position) => ({
138
+ kind: "advisory",
139
+ ruleId: RULE_ID,
140
+ severity: "error",
141
+ message,
142
+ location: {
143
+ file: SKILL_MD,
144
+ ...(position?.line !== undefined ? { line: position.line } : {}),
145
+ ...(position?.column !== undefined ? { column: position.column } : {}),
146
+ },
147
+ });
148
+ //# sourceMappingURL=frontmatter-parseable.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `skill/frontmatter-standard-valid` — SKILL.md metadata conforms to the
3
+ * pinned Agent Skills specification and reference validator.
4
+ *
5
+ * Parsing failures are owned by `skill/frontmatter-parseable`; this rule
6
+ * returns no findings until the frontmatter is a YAML mapping.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import type { SkillRuleContext } from "../../context.js";
11
+ import type { AdvisoryRule } from "../../rule.js";
12
+ export declare const frontmatterStandardValidRule: AdvisoryRule<SkillRuleContext>;
13
+ //# sourceMappingURL=frontmatter-standard-valid.d.ts.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `skill/frontmatter-standard-valid` — SKILL.md metadata conforms to the
3
+ * pinned Agent Skills specification and reference validator.
4
+ *
5
+ * Parsing failures are owned by `skill/frontmatter-parseable`; this rule
6
+ * returns no findings until the frontmatter is a YAML mapping.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import * as Effect from "effect/Effect";
11
+ import YAML from "yaml";
12
+ import { validateSkillFrontmatter } from "../../../content/skill-content.js";
13
+ const RULE_ID = "skill/frontmatter-standard-valid";
14
+ const SKILL_MD = "SKILL.md";
15
+ const decoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
16
+ const parseFrontmatterMapping = (content) => {
17
+ if (!content.startsWith("---"))
18
+ return undefined;
19
+ const openingEnd = content.indexOf("\n");
20
+ if (openingEnd === -1)
21
+ return undefined;
22
+ const closingStart = content.indexOf("\n---", openingEnd);
23
+ if (closingStart === -1)
24
+ return undefined;
25
+ try {
26
+ const parsed = YAML.parse(content.slice(openingEnd + 1, closingStart));
27
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
28
+ ? parsed
29
+ : undefined;
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ };
35
+ const finding = (message) => ({
36
+ kind: "advisory",
37
+ ruleId: RULE_ID,
38
+ severity: "error",
39
+ message,
40
+ location: { file: SKILL_MD, line: 1 },
41
+ });
42
+ export const frontmatterStandardValidRule = {
43
+ id: RULE_ID,
44
+ description: "SKILL.md metadata conforms to the pinned Agent Skills standard.",
45
+ kind: "advisory",
46
+ severity: "error",
47
+ check: (context) => Effect.gen(function* () {
48
+ const exists = yield* context.files.exists(SKILL_MD);
49
+ if (!exists)
50
+ return [];
51
+ const content = yield* context.files.readBytes(SKILL_MD).pipe(Effect.map((bytes) => decoder.decode(bytes)), Effect.catch(() => Effect.succeed(undefined)));
52
+ if (content === undefined)
53
+ return [];
54
+ const parsed = parseFrontmatterMapping(content);
55
+ if (parsed === undefined)
56
+ return [];
57
+ const validation = validateSkillFrontmatter(parsed, context.subject.expectedName);
58
+ return validation.valid ? [] : validation.errors.map(finding);
59
+ }),
60
+ };
61
+ //# sourceMappingURL=frontmatter-standard-valid.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `skill/manifest-keys-recognized` — `skill.json` contains only keys
3
+ * declared by `SkillManifestSchema`.
4
+ *
5
+ * The paired `-schema-valid` rule ignores excess properties by construction
6
+ * (`onExcessProperty: "ignore"`); this rule rejects them so publish never
7
+ * silently drops unrecognized manifest data.
8
+ *
9
+ * Allowed-keys set is derived from `SkillManifestSchema.fields` — no
10
+ * copy-paste of field names. A schema gain (or rename) automatically updates
11
+ * the allowlist.
12
+ *
13
+ * Early-return arms (no findings):
14
+ *
15
+ * - `subject.isNative === false` — non-native skills have no manifest to
16
+ * check.
17
+ * - `subject.skillJson === undefined` / non-object — nothing to enumerate;
18
+ * `skill/manifest-present` owns the absence case.
19
+ *
20
+ * @experimental This API is unstable and may change without notice.
21
+ * @packageDocumentation
22
+ */
23
+ import type { SkillRuleContext } from "../../context.js";
24
+ import type { AdvisoryRule } from "../../rule.js";
25
+ export declare const manifestKeysRecognizedRule: AdvisoryRule<SkillRuleContext>;
26
+ //# sourceMappingURL=manifest-keys-recognized.d.ts.map
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `skill/manifest-keys-recognized` — `skill.json` contains only keys
3
+ * declared by `SkillManifestSchema`.
4
+ *
5
+ * The paired `-schema-valid` rule ignores excess properties by construction
6
+ * (`onExcessProperty: "ignore"`); this rule rejects them so publish never
7
+ * silently drops unrecognized manifest data.
8
+ *
9
+ * Allowed-keys set is derived from `SkillManifestSchema.fields` — no
10
+ * copy-paste of field names. A schema gain (or rename) automatically updates
11
+ * the allowlist.
12
+ *
13
+ * Early-return arms (no findings):
14
+ *
15
+ * - `subject.isNative === false` — non-native skills have no manifest to
16
+ * check.
17
+ * - `subject.skillJson === undefined` / non-object — nothing to enumerate;
18
+ * `skill/manifest-present` owns the absence case.
19
+ *
20
+ * @experimental This API is unstable and may change without notice.
21
+ * @packageDocumentation
22
+ */
23
+ import * as Effect from "effect/Effect";
24
+ import { SkillManifestSchema } from "@agentxm/extension-model/unstable/skills/manifest-schema";
25
+ import { enumerateUnknownTopLevelKeys, structFieldKeys } from "../shared/schema-rule.js";
26
+ const RULE_ID = "skill/manifest-keys-recognized";
27
+ const SKILL_JSON = "skill.json";
28
+ const allowedKeys = structFieldKeys(SkillManifestSchema);
29
+ export const manifestKeysRecognizedRule = {
30
+ id: RULE_ID,
31
+ description: "skill.json uses only supported top-level fields.",
32
+ kind: "advisory",
33
+ severity: "error",
34
+ check: (context) => {
35
+ if (!context.subject.isNative) {
36
+ return Effect.succeed([]);
37
+ }
38
+ return Effect.succeed(enumerateUnknownTopLevelKeys(RULE_ID, "error", SKILL_JSON, allowedKeys, context.subject.skillJson));
39
+ },
40
+ };
41
+ //# sourceMappingURL=manifest-keys-recognized.js.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `skill/manifest-present` — native skills must have a `skill.json` at the
3
+ * package root.
4
+ *
5
+ * Reads through `context.packageFiles` (package-root accessor) rather than
6
+ * `context.files` (content-root accessor). For native skills, the package
7
+ * root contains `skill.json` and a `src/` directory holding the skill
8
+ * content; `context.files` is rooted at `src/`, so `skill.json` is only
9
+ * reachable via `packageFiles`.
10
+ *
11
+ * Native-only via `check` early-return: when `subject.isNative === false`
12
+ * (managed-external skills without a declared manifest), the rule produces
13
+ * no findings. No separate `applies` predicate per
14
+ * the lint design.
15
+ *
16
+ * Advisory-only — scaffolding a manifest is a user-authored action.
17
+ *
18
+ * @experimental This API is unstable and may change without notice.
19
+ * @packageDocumentation
20
+ */
21
+ import type { SkillRuleContext } from "../../context.js";
22
+ export declare const manifestPresentRule: import("../../rule.ts").AdvisoryRule<SkillRuleContext<import("../../context.js").SkillContent>>;
23
+ //# sourceMappingURL=manifest-present.d.ts.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `skill/manifest-present` — native skills must have a `skill.json` at the
3
+ * package root.
4
+ *
5
+ * Reads through `context.packageFiles` (package-root accessor) rather than
6
+ * `context.files` (content-root accessor). For native skills, the package
7
+ * root contains `skill.json` and a `src/` directory holding the skill
8
+ * content; `context.files` is rooted at `src/`, so `skill.json` is only
9
+ * reachable via `packageFiles`.
10
+ *
11
+ * Native-only via `check` early-return: when `subject.isNative === false`
12
+ * (managed-external skills without a declared manifest), the rule produces
13
+ * no findings. No separate `applies` predicate per
14
+ * the lint design.
15
+ *
16
+ * Advisory-only — scaffolding a manifest is a user-authored action.
17
+ *
18
+ * @experimental This API is unstable and may change without notice.
19
+ * @packageDocumentation
20
+ */
21
+ import { makeManifestPresentRule } from "../shared/manifest-present.js";
22
+ const RULE_ID = "skill/manifest-present";
23
+ const SKILL_JSON = "skill.json";
24
+ export const manifestPresentRule = makeManifestPresentRule({
25
+ ruleId: RULE_ID,
26
+ description: "Native skills include a root skill.json manifest.",
27
+ manifestFile: SKILL_JSON,
28
+ missingMessage: "skill.json is missing for this native skill. Create skill.json with the required manifest fields (`owner`, `type`, `name`, `version`).",
29
+ getFiles: (context) => context.packageFiles,
30
+ applies: (context) => context.subject.isNative,
31
+ });
32
+ //# sourceMappingURL=manifest-present.js.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `skill/manifest-schema-valid` — `skill.json` conforms to
3
+ * `SkillManifestSchema`.
4
+ *
5
+ * Delegates to Effect Schema. Issues map 1:1 to findings via
6
+ * `issuesToFindings`.
7
+ *
8
+ * Early-return arms (no findings):
9
+ *
10
+ * - `subject.isNative === false` — non-native skills have no manifest to
11
+ * check (complement of `skill/manifest-present`).
12
+ * - `subject.skillJson === undefined` — manifest is absent (covered by
13
+ * `skill/manifest-present`).
14
+ *
15
+ * @experimental This API is unstable and may change without notice.
16
+ * @packageDocumentation
17
+ */
18
+ import type { SkillRuleContext } from "../../context.js";
19
+ import type { AdvisoryRule } from "../../rule.js";
20
+ export declare const manifestSchemaValidRule: AdvisoryRule<SkillRuleContext>;
21
+ //# sourceMappingURL=manifest-schema-valid.d.ts.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `skill/manifest-schema-valid` — `skill.json` conforms to
3
+ * `SkillManifestSchema`.
4
+ *
5
+ * Delegates to Effect Schema. Issues map 1:1 to findings via
6
+ * `issuesToFindings`.
7
+ *
8
+ * Early-return arms (no findings):
9
+ *
10
+ * - `subject.isNative === false` — non-native skills have no manifest to
11
+ * check (complement of `skill/manifest-present`).
12
+ * - `subject.skillJson === undefined` — manifest is absent (covered by
13
+ * `skill/manifest-present`).
14
+ *
15
+ * @experimental This API is unstable and may change without notice.
16
+ * @packageDocumentation
17
+ */
18
+ import { SkillManifestSchema } from "@agentxm/extension-model/unstable/skills/manifest-schema";
19
+ import { schemaDecodeFindings } from "../shared/schema-rule.js";
20
+ const RULE_ID = "skill/manifest-schema-valid";
21
+ const SKILL_JSON = "skill.json";
22
+ export const manifestSchemaValidRule = {
23
+ id: RULE_ID,
24
+ description: "skill.json defines a valid skill manifest.",
25
+ kind: "advisory",
26
+ severity: "error",
27
+ check: (context) => {
28
+ if (!context.subject.isNative) {
29
+ // Non-native skills have no skill.json to schema-validate. The
30
+ // presence rule (manifest-present) does not fire for non-native either.
31
+ return schemaDecodeFindings(RULE_ID, "error", SKILL_JSON, SkillManifestSchema, undefined);
32
+ }
33
+ return schemaDecodeFindings(RULE_ID, "error", SKILL_JSON, SkillManifestSchema, context.subject.skillJson);
34
+ },
35
+ };
36
+ //# sourceMappingURL=manifest-schema-valid.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `skill/recommended-packs-valid` — recommended packs are bare FQNs, never
3
+ * version-ranged specs. See `../shared/recommended-packs-rules.ts`.
4
+ */
5
+ import type { SkillRuleContext } from "../../context.js";
6
+ import type { AdvisoryRule } from "../../rule.js";
7
+ export declare const recommendedPacksValidRule: AdvisoryRule<SkillRuleContext>;
8
+ //# sourceMappingURL=recommended-packs-valid.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `skill/recommended-packs-valid` — recommended packs are bare FQNs, never
3
+ * version-ranged specs. See `../shared/recommended-packs-rules.ts`.
4
+ */
5
+ import { MANIFEST_FILENAME } from "@agentxm/extension-model/unstable/skills/manifest-schema";
6
+ import { makeRecommendedPacksValidRule } from "../shared/recommended-packs-rules.js";
7
+ export const recommendedPacksValidRule = makeRecommendedPacksValidRule({
8
+ namespace: "skill",
9
+ manifestFile: MANIFEST_FILENAME,
10
+ manifestJson: (context) => context.subject.skillJson,
11
+ });
12
+ //# sourceMappingURL=recommended-packs-valid.js.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `skill/skill-md-present` — every skill must have a `SKILL.md` at its root.
3
+ *
4
+ * Applies to every skill context (native and non-native). Upstream-required
5
+ * by the agentskills specification; also the precondition for the
6
+ * `skill/frontmatter-parseable` cascade.
7
+ *
8
+ * Advisory-only (no autofix). Scaffolding `SKILL.md` requires user-authored
9
+ * content and is not a meaning-preserving normalization.
10
+ *
11
+ * @experimental This API is unstable and may change without notice.
12
+ * @packageDocumentation
13
+ */
14
+ import type { SkillRuleContext } from "../../context.js";
15
+ import type { AdvisoryRule } from "../../rule.js";
16
+ export declare const skillMdPresentRule: AdvisoryRule<SkillRuleContext>;
17
+ //# sourceMappingURL=skill-md-present.d.ts.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `skill/skill-md-present` — every skill must have a `SKILL.md` at its root.
3
+ *
4
+ * Applies to every skill context (native and non-native). Upstream-required
5
+ * by the agentskills specification; also the precondition for the
6
+ * `skill/frontmatter-parseable` cascade.
7
+ *
8
+ * Advisory-only (no autofix). Scaffolding `SKILL.md` requires user-authored
9
+ * content and is not a meaning-preserving normalization.
10
+ *
11
+ * @experimental This API is unstable and may change without notice.
12
+ * @packageDocumentation
13
+ */
14
+ import * as Effect from "effect/Effect";
15
+ const RULE_ID = "skill/skill-md-present";
16
+ const SKILL_MD = "SKILL.md";
17
+ export const skillMdPresentRule = {
18
+ id: RULE_ID,
19
+ description: "Skills include a root SKILL.md file.",
20
+ kind: "advisory",
21
+ severity: "error",
22
+ check: (context) => Effect.map(context.files.exists(SKILL_MD), (present) => {
23
+ if (present) {
24
+ return [];
25
+ }
26
+ return [
27
+ {
28
+ kind: "advisory",
29
+ ruleId: RULE_ID,
30
+ severity: "error",
31
+ message: "SKILL.md is missing. Create SKILL.md with the required frontmatter (`name`, `description`).",
32
+ location: { file: SKILL_MD },
33
+ },
34
+ ];
35
+ }),
36
+ };
37
+ //# sourceMappingURL=skill-md-present.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `skill/standalone-declaration-valid` — a manifest that opts out of standalone
3
+ * use names the packs it needs. See `../shared/recommended-packs-rules.ts`.
4
+ */
5
+ import type { SkillRuleContext } from "../../context.js";
6
+ import type { AdvisoryRule } from "../../rule.js";
7
+ export declare const standaloneDeclarationValidRule: AdvisoryRule<SkillRuleContext>;
8
+ //# sourceMappingURL=standalone-declaration-valid.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `skill/standalone-declaration-valid` — a manifest that opts out of standalone
3
+ * use names the packs it needs. See `../shared/recommended-packs-rules.ts`.
4
+ */
5
+ import { MANIFEST_FILENAME } from "@agentxm/extension-model/unstable/skills/manifest-schema";
6
+ import { makeStandaloneDeclarationValidRule } from "../shared/recommended-packs-rules.js";
7
+ export const standaloneDeclarationValidRule = makeStandaloneDeclarationValidRule({
8
+ namespace: "skill",
9
+ manifestFile: MANIFEST_FILENAME,
10
+ manifestJson: (context) => context.subject.skillJson,
11
+ });
12
+ //# sourceMappingURL=standalone-declaration-valid.js.map