@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,15 @@
1
+ /**
2
+ * `rule/*` manifest envelope — see `../shared/envelope-rules.ts`.
3
+ */
4
+ import { RuleManifestSchema, RULE_MANIFEST_FILENAME, } from "@agentxm/extension-model/unstable/rules/manifest-schema";
5
+ import { makeManifestEnvelopeRules } from "../shared/envelope-rules.js";
6
+ export const ruleEnvelopeRules = makeManifestEnvelopeRules({
7
+ namespace: "rule",
8
+ manifestFile: RULE_MANIFEST_FILENAME,
9
+ schema: RuleManifestSchema,
10
+ manifestJson: (context) => context.subject.ruleJson,
11
+ presentDescription: "Rules include a root rule.json manifest.",
12
+ presentMissingMessage: "rule.json is missing. Create rule.json with the required manifest fields (`owner`, `type`, `name`, `version`).",
13
+ schemaDescription: "rule.json defines a valid rule manifest.",
14
+ });
15
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1,4 @@
1
+ import type { RuleRuleContext } from "../context.js";
2
+ import type { LintRule } from "../rule.js";
3
+ export declare const ruleRules: ReadonlyArray<LintRule<RuleRuleContext>>;
4
+ //# sourceMappingURL=rule.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { ruleEnvelopeRules } from "./rule/envelope.js";
2
+ import { orderedEnvelopeRules } from "./shared/envelope-rules.js";
3
+ export const ruleRules = orderedEnvelopeRules(ruleEnvelopeRules);
4
+ //# sourceMappingURL=rule.js.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The five-rule manifest envelope every non-pack per-extension catalog ships.
3
+ *
4
+ * `skill`, `subagent`, `mcp-server`, `hook`, `rule`, and `knowledge` each
5
+ * enforce the same five invariants against their own
6
+ * manifest:
7
+ *
8
+ * 1. `<ns>/manifest-present` — the manifest file exists.
9
+ * 2. `<ns>/manifest-schema-valid` — it decodes against the canonical schema.
10
+ * 3. `<ns>/manifest-keys-recognized` — it carries no unknown top-level keys.
11
+ * 4. `<ns>/standalone-declaration-valid` — `standalone: false` names its packs.
12
+ * 5. `<ns>/recommended-packs-valid` — recommended packs are bare FQNs.
13
+ *
14
+ * Rules 1, 4, and 5 already had factories; rules 2 and 3 were hand-copied per
15
+ * type. This module composes all five so a new extension type's envelope is
16
+ * one call, and so the publish-safe barrel (`lint/publish.ts`) and the
17
+ * `axm lint` catalog (`catalog/<type>.ts`) build from the same definitions.
18
+ *
19
+ * @experimental This API is unstable and may change without notice.
20
+ * @packageDocumentation
21
+ */
22
+ import * as Effect from "effect/Effect";
23
+ import type * as Schema from "effect/Schema";
24
+ import type { AdvisoryRule } from "../../rule.js";
25
+ /**
26
+ * A manifest schema usable by the envelope: decodable, and introspectable for
27
+ * its declared top-level field names.
28
+ *
29
+ * @experimental This API is unstable and may change without notice.
30
+ */
31
+ export type ManifestEnvelopeSchema<A, I> = Schema.Codec<A, I> & {
32
+ readonly fields: Readonly<Record<string, unknown>>;
33
+ };
34
+ /**
35
+ * Per-catalog parameters for {@link makeManifestEnvelopeRules}.
36
+ *
37
+ * @experimental This API is unstable and may change without notice.
38
+ */
39
+ export interface ManifestEnvelopeOptions<C, A, I> {
40
+ /** Rule-id namespace; matches the context kind (`skill`, `hook`, ...). */
41
+ readonly namespace: string;
42
+ /** Accessor-relative manifest filename stamped on `location.file`. */
43
+ readonly manifestFile: string;
44
+ /** Canonical manifest schema for this type. */
45
+ readonly schema: ManifestEnvelopeSchema<A, I>;
46
+ /** Reads the caller-decoded manifest JSON off the rule context. */
47
+ readonly manifestJson: (context: C) => unknown;
48
+ /** `description` for `<ns>/manifest-present`. */
49
+ readonly presentDescription: string;
50
+ /** Finding message emitted when the manifest file is absent. */
51
+ readonly presentMissingMessage: string;
52
+ /** `description` for `<ns>/manifest-schema-valid`. */
53
+ readonly schemaDescription: string;
54
+ }
55
+ /**
56
+ * The five envelope rules, named so callers can order them alongside their own
57
+ * bespoke rules rather than splicing an opaque array.
58
+ *
59
+ * @experimental This API is unstable and may change without notice.
60
+ */
61
+ export interface ManifestEnvelopeRules<C> {
62
+ readonly manifestPresent: AdvisoryRule<C>;
63
+ readonly manifestSchemaValid: AdvisoryRule<C>;
64
+ readonly manifestKeysRecognized: AdvisoryRule<C>;
65
+ readonly standaloneDeclarationValid: AdvisoryRule<C>;
66
+ readonly recommendedPacksValid: AdvisoryRule<C>;
67
+ }
68
+ /**
69
+ * Build one catalog's five manifest envelope rules.
70
+ *
71
+ * The context only has to expose a `files` accessor with `exists`; the
72
+ * manifest value itself is read through `options.manifestJson`, so the factory
73
+ * never assumes a subject field name.
74
+ *
75
+ * @experimental This API is unstable and may change without notice.
76
+ */
77
+ export declare const makeManifestEnvelopeRules: <C extends {
78
+ readonly files: {
79
+ readonly exists: (path: string) => Effect.Effect<boolean>;
80
+ };
81
+ }, A, I>(options: ManifestEnvelopeOptions<C, A, I>) => ManifestEnvelopeRules<C>;
82
+ /**
83
+ * The envelope rules in canonical catalog order.
84
+ *
85
+ * @experimental This API is unstable and may change without notice.
86
+ */
87
+ export declare const orderedEnvelopeRules: <C>(rules: ManifestEnvelopeRules<C>) => ReadonlyArray<AdvisoryRule<C>>;
88
+ //# sourceMappingURL=envelope-rules.d.ts.map
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The five-rule manifest envelope every non-pack per-extension catalog ships.
3
+ *
4
+ * `skill`, `subagent`, `mcp-server`, `hook`, `rule`, and `knowledge` each
5
+ * enforce the same five invariants against their own
6
+ * manifest:
7
+ *
8
+ * 1. `<ns>/manifest-present` — the manifest file exists.
9
+ * 2. `<ns>/manifest-schema-valid` — it decodes against the canonical schema.
10
+ * 3. `<ns>/manifest-keys-recognized` — it carries no unknown top-level keys.
11
+ * 4. `<ns>/standalone-declaration-valid` — `standalone: false` names its packs.
12
+ * 5. `<ns>/recommended-packs-valid` — recommended packs are bare FQNs.
13
+ *
14
+ * Rules 1, 4, and 5 already had factories; rules 2 and 3 were hand-copied per
15
+ * type. This module composes all five so a new extension type's envelope is
16
+ * one call, and so the publish-safe barrel (`lint/publish.ts`) and the
17
+ * `axm lint` catalog (`catalog/<type>.ts`) build from the same definitions.
18
+ *
19
+ * @experimental This API is unstable and may change without notice.
20
+ * @packageDocumentation
21
+ */
22
+ import * as Effect from "effect/Effect";
23
+ import { makeManifestPresentRule } from "./manifest-present.js";
24
+ import { makeRecommendedPacksValidRule, makeStandaloneDeclarationValidRule, } from "./recommended-packs-rules.js";
25
+ import { enumerateUnknownTopLevelKeys, schemaDecodeFindings, structFieldKeys, } from "./schema-rule.js";
26
+ /**
27
+ * Build one catalog's five manifest envelope rules.
28
+ *
29
+ * The context only has to expose a `files` accessor with `exists`; the
30
+ * manifest value itself is read through `options.manifestJson`, so the factory
31
+ * never assumes a subject field name.
32
+ *
33
+ * @experimental This API is unstable and may change without notice.
34
+ */
35
+ export const makeManifestEnvelopeRules = (options) => {
36
+ const schemaValidRuleId = `${options.namespace}/manifest-schema-valid`;
37
+ const keysRecognizedRuleId = `${options.namespace}/manifest-keys-recognized`;
38
+ const allowedKeys = structFieldKeys(options.schema);
39
+ return {
40
+ manifestPresent: makeManifestPresentRule({
41
+ ruleId: `${options.namespace}/manifest-present`,
42
+ description: options.presentDescription,
43
+ manifestFile: options.manifestFile,
44
+ missingMessage: options.presentMissingMessage,
45
+ }),
46
+ manifestSchemaValid: {
47
+ id: schemaValidRuleId,
48
+ description: options.schemaDescription,
49
+ kind: "advisory",
50
+ severity: "error",
51
+ check: (context) => schemaDecodeFindings(schemaValidRuleId, "error", options.manifestFile, options.schema, options.manifestJson(context)),
52
+ },
53
+ manifestKeysRecognized: {
54
+ id: keysRecognizedRuleId,
55
+ description: `${options.manifestFile} uses only supported top-level fields.`,
56
+ kind: "advisory",
57
+ severity: "error",
58
+ check: (context) => Effect.succeed(enumerateUnknownTopLevelKeys(keysRecognizedRuleId, "error", options.manifestFile, allowedKeys, options.manifestJson(context))),
59
+ },
60
+ standaloneDeclarationValid: makeStandaloneDeclarationValidRule({
61
+ namespace: options.namespace,
62
+ manifestFile: options.manifestFile,
63
+ manifestJson: options.manifestJson,
64
+ }),
65
+ recommendedPacksValid: makeRecommendedPacksValidRule({
66
+ namespace: options.namespace,
67
+ manifestFile: options.manifestFile,
68
+ manifestJson: options.manifestJson,
69
+ }),
70
+ };
71
+ };
72
+ /**
73
+ * The envelope rules in canonical catalog order.
74
+ *
75
+ * @experimental This API is unstable and may change without notice.
76
+ */
77
+ export const orderedEnvelopeRules = (rules) => [
78
+ rules.manifestPresent,
79
+ rules.manifestSchemaValid,
80
+ rules.manifestKeysRecognized,
81
+ rules.standaloneDeclarationValid,
82
+ rules.recommendedPacksValid,
83
+ ];
84
+ //# sourceMappingURL=envelope-rules.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Shared loose-manifest JSON helpers.
3
+ *
4
+ * Workspace lint parses installed manifests before per-extension rules run.
5
+ * The parsed value must stay raw JSON, not a schema-decoded manifest, so
6
+ * `*-keys-recognized` rules can still see excess top-level fields.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import type { AdvisoryFinding, Severity } from "../../rule.js";
11
+ export interface ManifestJsonParseFailure {
12
+ readonly _tag: "ManifestJsonParseFailure";
13
+ readonly file: string;
14
+ }
15
+ export declare const makeManifestJsonParseFailure: (file: string) => ManifestJsonParseFailure;
16
+ export declare const isManifestJsonParseFailure: (value: unknown) => value is ManifestJsonParseFailure;
17
+ export declare const manifestJsonParseFailureToFinding: (ruleId: string, severity: Severity, file: string, input: ManifestJsonParseFailure) => AdvisoryFinding;
18
+ //# sourceMappingURL=manifest-json.d.ts.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Shared loose-manifest JSON helpers.
3
+ *
4
+ * Workspace lint parses installed manifests before per-extension rules run.
5
+ * The parsed value must stay raw JSON, not a schema-decoded manifest, so
6
+ * `*-keys-recognized` rules can still see excess top-level fields.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import { describeSchemaDocument } from "../../describe-document.js";
11
+ export const makeManifestJsonParseFailure = (file) => ({
12
+ _tag: "ManifestJsonParseFailure",
13
+ file,
14
+ });
15
+ export const isManifestJsonParseFailure = (value) => {
16
+ if (value === null || typeof value !== "object") {
17
+ return false;
18
+ }
19
+ return "_tag" in value && value._tag === "ManifestJsonParseFailure";
20
+ };
21
+ export const manifestJsonParseFailureToFinding = (ruleId, severity, file, input) => ({
22
+ kind: "advisory",
23
+ ruleId,
24
+ severity,
25
+ message: `${describeSchemaDocument(file)} contains invalid JSON. Edit \`${input.file}\` and fix the JSON syntax.`,
26
+ location: { file },
27
+ });
28
+ //# sourceMappingURL=manifest-json.js.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shared factory for `manifest-present` advisory rules.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ */
6
+ import * as Effect from "effect/Effect";
7
+ import type { AdvisoryRule, Severity } from "../../rule.js";
8
+ interface ManifestFileAccessor {
9
+ readonly exists: (path: string) => Effect.Effect<boolean>;
10
+ }
11
+ interface ManifestPresentRuleContext {
12
+ readonly files: ManifestFileAccessor;
13
+ }
14
+ interface ManifestPresentRuleArgs<C> {
15
+ readonly ruleId: string;
16
+ readonly description: string;
17
+ readonly manifestFile: string;
18
+ readonly missingMessage: string;
19
+ readonly severity?: Severity;
20
+ readonly getFiles?: (context: C) => ManifestFileAccessor;
21
+ readonly applies?: (context: C) => boolean;
22
+ }
23
+ export declare const makeManifestPresentRule: <C extends ManifestPresentRuleContext>(args: ManifestPresentRuleArgs<C>) => AdvisoryRule<C>;
24
+ export {};
25
+ //# sourceMappingURL=manifest-present.d.ts.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared factory for `manifest-present` advisory rules.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ */
6
+ import * as Effect from "effect/Effect";
7
+ export const makeManifestPresentRule = (args) => {
8
+ const severity = args.severity ?? "error";
9
+ const getFiles = args.getFiles ?? ((context) => context.files);
10
+ const applies = args.applies ?? (() => true);
11
+ return {
12
+ id: args.ruleId,
13
+ description: args.description,
14
+ kind: "advisory",
15
+ severity,
16
+ check: (context) => {
17
+ if (!applies(context)) {
18
+ return Effect.succeed([]);
19
+ }
20
+ return Effect.map(getFiles(context).exists(args.manifestFile), (present) => {
21
+ if (present) {
22
+ return [];
23
+ }
24
+ return [
25
+ {
26
+ kind: "advisory",
27
+ ruleId: args.ruleId,
28
+ severity,
29
+ message: args.missingMessage,
30
+ location: { file: args.manifestFile },
31
+ },
32
+ ];
33
+ });
34
+ },
35
+ };
36
+ };
37
+ //# sourceMappingURL=manifest-present.js.map
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared factories for the `standalone` / `recommendedPacks` coherence rules.
3
+ *
4
+ * Both fields come from `NonPackManifestFields` in
5
+ * `extensions/common.ts`, so every non-pack catalog (`skill`, `subagent`,
6
+ * `mcp-server`, `rule`, `hook`, `knowledge`) enforces the same two invariants
7
+ * against its own manifest. Rather than copy twelve near-identical rule
8
+ * bodies, each catalog registers a rule produced here and parameterized by
9
+ * namespace and manifest accessor — the same shape `shared/schema-rule.ts`
10
+ * establishes for the `-schema-valid` rules.
11
+ *
12
+ * Both rules ship at `warning`. They would otherwise retroactively reject
13
+ * manifests published before the rules existed, which the rule-authoring
14
+ * guide's "new rules start soft" clause forbids.
15
+ *
16
+ * @experimental This API is unstable and may change without notice.
17
+ * @packageDocumentation
18
+ */
19
+ import type { AdvisoryRule } from "../../rule.js";
20
+ /**
21
+ * Per-catalog parameters for the shared non-pack manifest rules.
22
+ *
23
+ * @experimental This API is unstable and may change without notice.
24
+ */
25
+ export interface RecommendedPacksRuleOptions<C> {
26
+ /** Rule-id namespace; matches the context kind (`skill`, `hook`, ...). */
27
+ readonly namespace: string;
28
+ /** Accessor-relative manifest filename stamped on `location.file`. */
29
+ readonly manifestFile: string;
30
+ /** Reads the caller-decoded manifest JSON off the rule context. */
31
+ readonly manifestJson: (context: C) => unknown;
32
+ }
33
+ /**
34
+ * Split a `recommendedPacks` entry into its FQN and optional version range.
35
+ *
36
+ * Mirrors the separator search in `PackSpecSchema`: the range delimiter is the
37
+ * first `@` after the last `/`, since the owner segment also starts with `@`.
38
+ *
39
+ * @experimental This API is unstable and may change without notice.
40
+ */
41
+ export declare const splitPackSpec: (spec: string) => {
42
+ readonly fqn: string;
43
+ readonly range: string | undefined;
44
+ };
45
+ /**
46
+ * Build the `<namespace>/standalone-declaration-valid` rule for one catalog.
47
+ *
48
+ * A manifest with `standalone: false` declares that it is meaningless without
49
+ * one of its recommended packs. With `recommendedPacks` absent or empty that
50
+ * declaration is self-contradictory and nothing downstream — registry, Library
51
+ * UI, or `workspace/recommended-packs-retained` — can act on it.
52
+ *
53
+ * @experimental This API is unstable and may change without notice.
54
+ */
55
+ export declare const makeStandaloneDeclarationValidRule: <C>(options: RecommendedPacksRuleOptions<C>) => AdvisoryRule<C>;
56
+ /**
57
+ * Build the `<namespace>/recommended-packs-valid` rule for one catalog.
58
+ *
59
+ * `recommendedPacks` is typed `PackSpecSchema`, which permits a trailing
60
+ * version range, but nothing consumes one — recommendations are matched by
61
+ * name — and `axm help packs` tells authors to use the bare reference. One
62
+ * finding per offending entry.
63
+ *
64
+ * When published manifests have drained, the field can move to
65
+ * `PackFqnSchema` and this rule retires: decoding takes over.
66
+ *
67
+ * @experimental This API is unstable and may change without notice.
68
+ */
69
+ export declare const makeRecommendedPacksValidRule: <C>(options: RecommendedPacksRuleOptions<C>) => AdvisoryRule<C>;
70
+ //# sourceMappingURL=recommended-packs-rules.d.ts.map
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Shared factories for the `standalone` / `recommendedPacks` coherence rules.
3
+ *
4
+ * Both fields come from `NonPackManifestFields` in
5
+ * `extensions/common.ts`, so every non-pack catalog (`skill`, `subagent`,
6
+ * `mcp-server`, `rule`, `hook`, `knowledge`) enforces the same two invariants
7
+ * against its own manifest. Rather than copy twelve near-identical rule
8
+ * bodies, each catalog registers a rule produced here and parameterized by
9
+ * namespace and manifest accessor — the same shape `shared/schema-rule.ts`
10
+ * establishes for the `-schema-valid` rules.
11
+ *
12
+ * Both rules ship at `warning`. They would otherwise retroactively reject
13
+ * manifests published before the rules existed, which the rule-authoring
14
+ * guide's "new rules start soft" clause forbids.
15
+ *
16
+ * @experimental This API is unstable and may change without notice.
17
+ * @packageDocumentation
18
+ */
19
+ import * as Effect from "effect/Effect";
20
+ import { isManifestJsonParseFailure } from "./manifest-json.js";
21
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
22
+ /**
23
+ * Narrow a caller-decoded manifest value to a plain record, or `undefined`
24
+ * when there is nothing for these rules to read. Absent manifests are the
25
+ * `-present` rule's problem; unparseable ones are the `-schema-valid` rule's.
26
+ */
27
+ const manifestRecord = (input) => {
28
+ if (input === undefined || isManifestJsonParseFailure(input) || !isRecord(input)) {
29
+ return undefined;
30
+ }
31
+ return input;
32
+ };
33
+ const stringEntries = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
34
+ /**
35
+ * Split a `recommendedPacks` entry into its FQN and optional version range.
36
+ *
37
+ * Mirrors the separator search in `PackSpecSchema`: the range delimiter is the
38
+ * first `@` after the last `/`, since the owner segment also starts with `@`.
39
+ *
40
+ * @experimental This API is unstable and may change without notice.
41
+ */
42
+ export const splitPackSpec = (spec) => {
43
+ const lastSlash = spec.lastIndexOf("/");
44
+ const rangeAt = lastSlash > 0 ? spec.indexOf("@", lastSlash + 1) : -1;
45
+ if (rangeAt <= 0) {
46
+ return { fqn: spec, range: undefined };
47
+ }
48
+ return { fqn: spec.slice(0, rangeAt), range: spec.slice(rangeAt + 1) };
49
+ };
50
+ // -----------------------------------------------------------------------------
51
+ // <namespace>/standalone-declaration-valid
52
+ // -----------------------------------------------------------------------------
53
+ /**
54
+ * Build the `<namespace>/standalone-declaration-valid` rule for one catalog.
55
+ *
56
+ * A manifest with `standalone: false` declares that it is meaningless without
57
+ * one of its recommended packs. With `recommendedPacks` absent or empty that
58
+ * declaration is self-contradictory and nothing downstream — registry, Library
59
+ * UI, or `workspace/recommended-packs-retained` — can act on it.
60
+ *
61
+ * @experimental This API is unstable and may change without notice.
62
+ */
63
+ export const makeStandaloneDeclarationValidRule = (options) => {
64
+ const ruleId = `${options.namespace}/standalone-declaration-valid`;
65
+ return {
66
+ id: ruleId,
67
+ description: "Extensions that are not standalone recommend at least one pack.",
68
+ kind: "advisory",
69
+ severity: "warning",
70
+ check: (context) => {
71
+ const manifest = manifestRecord(options.manifestJson(context));
72
+ if (manifest === undefined || manifest["standalone"] !== false) {
73
+ return Effect.succeed([]);
74
+ }
75
+ if (stringEntries(manifest["recommendedPacks"]).length > 0) {
76
+ return Effect.succeed([]);
77
+ }
78
+ return Effect.succeed([
79
+ {
80
+ kind: "advisory",
81
+ ruleId,
82
+ severity: "warning",
83
+ message: "`standalone` is set to false, which says this extension only works alongside one of its recommended packs, but no `recommendedPacks` are declared. " +
84
+ `To keep the restriction, add each pack's fully qualified name (\`@owner/packs/<name>\`) under \`recommendedPacks\` in \`${options.manifestFile}\`. ` +
85
+ `If the extension does work on its own, remove the \`standalone\` key from \`${options.manifestFile}\`.`,
86
+ location: { file: options.manifestFile },
87
+ },
88
+ ]);
89
+ },
90
+ };
91
+ };
92
+ // -----------------------------------------------------------------------------
93
+ // <namespace>/recommended-packs-valid
94
+ // -----------------------------------------------------------------------------
95
+ /**
96
+ * Build the `<namespace>/recommended-packs-valid` rule for one catalog.
97
+ *
98
+ * `recommendedPacks` is typed `PackSpecSchema`, which permits a trailing
99
+ * version range, but nothing consumes one — recommendations are matched by
100
+ * name — and `axm help packs` tells authors to use the bare reference. One
101
+ * finding per offending entry.
102
+ *
103
+ * When published manifests have drained, the field can move to
104
+ * `PackFqnSchema` and this rule retires: decoding takes over.
105
+ *
106
+ * @experimental This API is unstable and may change without notice.
107
+ */
108
+ export const makeRecommendedPacksValidRule = (options) => {
109
+ const ruleId = `${options.namespace}/recommended-packs-valid`;
110
+ return {
111
+ id: ruleId,
112
+ description: "Recommended packs are referenced by name without a version range.",
113
+ kind: "advisory",
114
+ severity: "warning",
115
+ check: (context) => {
116
+ const manifest = manifestRecord(options.manifestJson(context));
117
+ if (manifest === undefined) {
118
+ return Effect.succeed([]);
119
+ }
120
+ const findings = [];
121
+ for (const entry of stringEntries(manifest["recommendedPacks"])) {
122
+ const { fqn, range } = splitPackSpec(entry);
123
+ if (range === undefined) {
124
+ continue;
125
+ }
126
+ findings.push({
127
+ kind: "advisory",
128
+ ruleId,
129
+ severity: "warning",
130
+ message: `\`recommendedPacks\` entry '${entry}' pins a version range, but recommended packs are matched by name only, so the range is ignored. ` +
131
+ `Replace it with the bare pack reference '${fqn}' under \`recommendedPacks\` in \`${options.manifestFile}\`.`,
132
+ location: { file: options.manifestFile },
133
+ });
134
+ }
135
+ return Effect.succeed(findings);
136
+ },
137
+ };
138
+ };
139
+ //# sourceMappingURL=recommended-packs-rules.js.map
@@ -0,0 +1,57 @@
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 Schema from "effect/Schema";
17
+ import type { AdvisoryFinding, Severity } from "../../rule.js";
18
+ /**
19
+ * Decode `input` against `schema` (excess keys ignored, all issues collected)
20
+ * and return one advisory finding per leaf issue. Success produces `[]`.
21
+ *
22
+ * `input` of `undefined` short-circuits to `[]` — the caller is expected to
23
+ * have already guarded on "manifest exists" via the complementary
24
+ * `-present` rule.
25
+ *
26
+ * @param ruleId - `<namespace>/<name>` id of the calling rule.
27
+ * @param severity - Severity to stamp on each emitted finding.
28
+ * @param file - Accessor-relative file path to stamp on `location.file`.
29
+ * @param schema - Canonical Effect schema; `Schema.decodeUnknownResult`
30
+ * runs with `onExcessProperty: "ignore"` and `errors: "all"`.
31
+ * @param input - Raw decoded JSON value to check (typically `subject.*Json`).
32
+ *
33
+ * @experimental This API is unstable and may change without notice.
34
+ */
35
+ export declare const schemaDecodeFindings: <A, I>(ruleId: string, severity: Severity, file: string, schema: Schema.Codec<A, I>, input: unknown) => Effect.Effect<ReadonlyArray<AdvisoryFinding>>;
36
+ /**
37
+ * Read the top-level field names of a `Schema.Struct` value.
38
+ *
39
+ * Callers produce an `allowedKeys` set in one place, driven by the schema
40
+ * itself — no copy-paste of field names into rule bodies. If the schema
41
+ * gains a field the allowed-keys set grows by construction.
42
+ *
43
+ * @experimental This API is unstable and may change without notice.
44
+ */
45
+ export declare const structFieldKeys: (struct: {
46
+ readonly fields: Readonly<Record<string, unknown>>;
47
+ }) => ReadonlySet<string>;
48
+ /**
49
+ * Enumerate top-level keys present on `input` that are not declared by
50
+ * `allowedKeys`. Returns one advisory finding per unknown key.
51
+ *
52
+ * `input` of `undefined` or non-object short-circuits to `[]`.
53
+ *
54
+ * @experimental This API is unstable and may change without notice.
55
+ */
56
+ export declare const enumerateUnknownTopLevelKeys: (ruleId: string, severity: Severity, file: string, allowedKeys: ReadonlySet<string>, input: unknown) => ReadonlyArray<AdvisoryFinding>;
57
+ //# sourceMappingURL=schema-rule.d.ts.map