@skill-map/cli 0.35.0 → 0.36.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/dist/cli.js CHANGED
@@ -553,6 +553,63 @@ var claudeProvider = {
553
553
  mentions: ["agent"],
554
554
  invokes: ["command", "skill"]
555
555
  },
556
+ // Reserved invocation names the Claude runtime owns. A user file
557
+ // declaring one of these (e.g. `.claude/commands/help.md`) is
558
+ // silently shadowed: the runtime runs the built-in instead.
559
+ //
560
+ // - `command`: canonical list of built-in slash commands documented
561
+ // at https://docs.claude.com/en/docs/claude-code/slash-commands.
562
+ // The list will drift as Anthropic adds / removes commands;
563
+ // updates ship via a kernel patch + changeset (the catalog is
564
+ // considered API surface that users rely on the analyzer to
565
+ // reflect).
566
+ // - `agent`: built-in agents Anthropic ships with the CLI. Smaller
567
+ // surface than commands today.
568
+ // - `skill`: no built-in skills today (skills are user-defined and
569
+ // discovered from disk); the key is omitted on purpose, defaulting
570
+ // to no reserved names for the kind.
571
+ reservedNames: {
572
+ command: [
573
+ "help",
574
+ "clear",
575
+ "compact",
576
+ "cost",
577
+ "init",
578
+ "model",
579
+ "agents",
580
+ "login",
581
+ "logout",
582
+ "mcp",
583
+ "memory",
584
+ "config",
585
+ "doctor",
586
+ "permissions",
587
+ "add-dir",
588
+ "bug",
589
+ "pr-comments",
590
+ "release-notes",
591
+ "review",
592
+ "terminal-setup",
593
+ "vim",
594
+ "output-style",
595
+ "hooks",
596
+ "install-github-app",
597
+ "migrate-installer",
598
+ "upgrade",
599
+ "resume",
600
+ "exit",
601
+ "quit",
602
+ "security-review",
603
+ "statusline",
604
+ "usage",
605
+ "feedback"
606
+ ],
607
+ agent: [
608
+ "general-purpose",
609
+ "output-style-setup",
610
+ "statusline-setup"
611
+ ]
612
+ },
556
613
  // Auxiliary schemas the per-kind schemas $ref by $id. AJV needs them
557
614
  // registered via addSchema BEFORE the per-kind schemas compile, so the
558
615
  // validator builder pre-registers them. `skill-base.schema.json` is the
@@ -637,7 +694,7 @@ var atDirectiveExtractor = {
637
694
  pluginId: "claude",
638
695
  kind: "extractor",
639
696
  version: "1.0.0",
640
- description: "Detects `@<token>` directives in a node's body using Claude Code interpretation rules. A bare handle (e.g. `@team`) becomes a `mentions` link; a file-flavoured token (e.g. `@docs/api.md`, `@./readme.md`) becomes a `references` link. Gated by `precondition.provider: ['claude']` so Gemini / Cursor / Codex apply their own at-directive flavours via their own extractors.",
697
+ description: "Detects `@<token>` directives in a node's body using Claude Code interpretation rules. A bare handle (e.g. `@team`) becomes a `mentions` link; a file-flavoured token (e.g. `@docs/api.md`, `@./readme.md`) becomes a `references` link. Gated by `precondition.provider: ['claude']` so Antigravity / Cursor / Codex apply their own at-directive flavours via their own extractors.",
641
698
  scope: "body",
642
699
  precondition: { provider: ["claude"] },
643
700
  extract(ctx) {
@@ -705,7 +762,7 @@ var slashExtractor = {
705
762
  pluginId: "claude",
706
763
  kind: "extractor",
707
764
  version: "1.0.0",
708
- description: "Detects `/command` invocations in a node's body using Claude Code routing rules and turns each one into an arrow between nodes in the graph. Gated by `precondition.provider: ['claude']` so Gemini / Cursor / Codex apply their own slash flavours (Gemini has 4 routing separators, Codex deprecated user slash commands, etc.) via their own extractors.",
765
+ description: "Detects `/command` invocations in a node's body using Claude Code routing rules and turns each one into an arrow between nodes in the graph. Gated by `precondition.provider: ['claude']` so Antigravity / Cursor / Codex apply their own slash flavours (Antigravity ships subagent and skill panels, Codex deprecated user slash commands, etc.) via their own extractors.",
709
766
  scope: "body",
710
767
  precondition: { provider: ["claude"] },
711
768
  extract(ctx) {
@@ -738,138 +795,40 @@ var slashExtractor = {
738
795
  }
739
796
  };
740
797
 
741
- // plugins/gemini/providers/gemini/schemas/agent.schema.json
742
- var agent_schema_default2 = {
743
- $schema: "https://json-schema.org/draft/2020-12/schema",
744
- $id: "https://skill-map.dev/providers/gemini/v1/frontmatter/agent.schema.json",
745
- title: "FrontmatterGeminiAgent",
746
- description: "Frontmatter shape for nodes classified as `agent` by the Gemini Provider. Mirrors Google's documented Gemini CLI subagent frontmatter verbatim (https://geminicli.com/docs/core/subagents/): `name` and `description` come from the spec base; this schema adds the 7 vendor-specific fields. skill-map AGGREGATES the vendor spec, it does not curate it. `additionalProperties: true` so future Google additions flow through unchanged until this schema catches up. Note: Gemini's `kind` field (enum `local|remote`) lives at a different layer than the kernel's extension-kind discriminator and the node-kind discriminator \u2014 both use the word `kind` but in distinct namespaces (manifest vs frontmatter).",
747
- allOf: [
748
- { $ref: "https://skill-map.dev/spec/v0/frontmatter/base.schema.json" }
749
- ],
750
- type: "object",
751
- additionalProperties: true,
752
- properties: {
753
- kind: {
754
- type: "string",
755
- enum: ["local", "remote"],
756
- default: "local",
757
- description: "Subagent execution mode. `local` runs in-process; `remote` is the documented value for the future remote-agent surface (https://geminicli.com/docs/core/remote-agents/)."
758
- },
759
- tools: {
760
- type: "array",
761
- description: "Tool names this subagent can invoke. Wildcards supported: `*` (all), `mcp_*` (all MCP), `mcp_<server>_*` (one MCP server). When omitted, the subagent inherits the parent session's full tool set.",
762
- items: { type: "string" }
763
- },
764
- mcpServers: {
765
- type: "object",
766
- additionalProperties: true,
767
- description: "Inline MCP server configuration isolated to this subagent. Shape is platform-defined; preserved as an opaque object."
768
- },
769
- model: {
770
- type: "string",
771
- description: "Model id override (e.g. `gemini-3-flash-preview`). When omitted, inherits from the parent session."
772
- },
773
- temperature: {
774
- type: "number",
775
- minimum: 0,
776
- maximum: 2,
777
- default: 1,
778
- description: "Model sampling temperature. Range 0.0\u20132.0 per Google docs."
779
- },
780
- max_turns: {
781
- type: "integer",
782
- minimum: 1,
783
- default: 30,
784
- description: "Hard cap on conversation turns before the subagent must return."
785
- },
786
- timeout_mins: {
787
- type: "integer",
788
- minimum: 1,
789
- default: 10,
790
- description: "Maximum execution duration in minutes."
791
- }
792
- }
793
- };
794
-
795
- // plugins/gemini/providers/gemini/schemas/skill.schema.json
796
- var skill_schema_default2 = {
797
- $schema: "https://json-schema.org/draft/2020-12/schema",
798
- $id: "https://skill-map.dev/providers/gemini/v1/frontmatter/skill.schema.json",
799
- title: "FrontmatterGeminiSkill",
800
- description: "Frontmatter shape for nodes classified as `skill` by the Gemini Provider \u2014 Agent Skills delivered as `SKILL.md` files (https://geminicli.com/docs/cli/creating-skills/). Google documents only `name` and `description` as required frontmatter fields; both already live in the spec's universal `frontmatter/base.schema.json`. `additionalProperties: true` so vendor additions flow through unchanged.",
801
- allOf: [
802
- { $ref: "https://skill-map.dev/spec/v0/frontmatter/base.schema.json" }
803
- ],
804
- type: "object",
805
- additionalProperties: true,
806
- properties: {}
807
- };
808
-
809
- // plugins/gemini/providers/gemini/index.ts
810
- var geminiProvider = {
811
- id: "gemini",
812
- pluginId: "gemini",
798
+ // plugins/antigravity/providers/antigravity/index.ts
799
+ var antigravityProvider = {
800
+ id: "antigravity",
801
+ pluginId: "antigravity",
813
802
  kind: "provider",
814
803
  version: "1.0.0",
815
- description: "Walks Gemini CLI scope conventions (.gemini/{agents,skills}).",
816
- read: { extensions: [".md"], parser: "frontmatter-yaml" },
817
- // Per spec § A.6, defaultRefreshAction values MUST be qualified
818
- // action ids. The summarize-* actions are not yet implemented as
819
- // registry entries (they ship later under the Gemini bundle), but
820
- // the qualified form is the contract.
821
- //
822
- // UI presentation: kind visuals are normalised across Providers, every
823
- // Provider that contributes `agent` declares the same color + icon as
824
- // Claude, every Provider that contributes `skill` declares the same
825
- // color + icon as Claude, etc. The declaration STAYS per-Provider (the
826
- // shape allows divergence the day a Provider wants its own identity for
827
- // a kind), but today the values mirror Claude so the visual vocabulary
828
- // is uniform regardless of where a node was sourced from.
829
- kinds: {
830
- agent: {
831
- schema: "./schemas/agent.schema.json",
832
- schemaJson: agent_schema_default2,
833
- ui: {
834
- label: "Agents",
835
- color: "#3b82f6",
836
- colorDark: "#60a5fa",
837
- icon: { kind: "pi", id: "pi-user" }
838
- },
839
- identifiers: ["frontmatter.name", "filename-basename"]
840
- },
841
- skill: {
842
- schema: "./schemas/skill.schema.json",
843
- schemaJson: skill_schema_default2,
844
- ui: {
845
- label: "Skills",
846
- color: "#10b981",
847
- colorDark: "#34d399",
848
- icon: { kind: "pi", id: "pi-bolt" }
849
- },
850
- // Gemini skills live at `.gemini/skills/<name>/SKILL.md`; the
851
- // dirname is the invocation handle per Google's docs
852
- // (https://geminicli.com/docs/cli/creating-skills/).
853
- identifiers: ["frontmatter.name", "dirname"]
854
- }
855
- },
856
- // Gemini's invocation surfaces mirror Claude's at the kernel level
857
- // (mentions for agents, slash invokes for skills). Commands are not
858
- // a Gemini concept; only `skill` belongs to `invokes`.
859
- resolution: {
860
- mentions: ["agent"],
861
- invokes: ["skill"]
862
- },
863
- classify(path) {
864
- const lower = path.toLowerCase();
865
- if (lower.startsWith(".gemini/agents/")) return "agent";
866
- if (/^\.gemini\/skills\/[^/]+\/skill\.md$/.test(lower)) return "skill";
804
+ description: "Google Antigravity CLI. Replaces the retired Gemini CLI; skills route through the neutral `agent-skills` Provider via `.agents/skills/`. This Provider contributes lens identity and a reserved-name seed catalog.",
805
+ // No `read` config: this Provider does not walk the filesystem. The
806
+ // kernel walker only fires for Providers with `read` or `walk`; an
807
+ // empty Provider participates in registration (its `ui` block is
808
+ // available, its `reservedNames` catalog is loaded) without owning
809
+ // any on-disk territory.
810
+ kinds: {},
811
+ // Always disclaim: paths are owned by other Providers (`.agents/` ->
812
+ // `agent-skills`, `AGENTS.md` -> `core/markdown` fallback).
813
+ classify() {
867
814
  return null;
815
+ },
816
+ // Seed catalog. Built-in slash commands surfaced by the Antigravity
817
+ // TUI (`/agents`, `/help`, `/quit`, `/skills`, `/hooks`, etc.). The
818
+ // exact list will expand once Google publishes the full reference;
819
+ // start small and document the growth path here rather than over-
820
+ // commit to a catalog that may drift.
821
+ //
822
+ // Inactive today (no nodes are classified under `antigravity`), kept
823
+ // here so the day Antigravity gains an own kind or the analyzer keys
824
+ // on the active lens, the catalog is already in place.
825
+ reservedNames: {
826
+ command: ["agents", "help", "quit", "exit", "skills", "hooks"]
868
827
  }
869
828
  };
870
829
 
871
830
  // plugins/openai/providers/openai/schemas/agent.schema.json
872
- var agent_schema_default3 = {
831
+ var agent_schema_default2 = {
873
832
  $schema: "https://json-schema.org/draft/2020-12/schema",
874
833
  $id: "https://skill-map.dev/providers/openai/v1/frontmatter/agent.schema.json",
875
834
  title: "FrontmatterCodexAgent",
@@ -931,10 +890,10 @@ var openaiProvider = {
931
890
  kinds: {
932
891
  agent: {
933
892
  schema: "./schemas/agent.schema.json",
934
- schemaJson: agent_schema_default3,
893
+ schemaJson: agent_schema_default2,
935
894
  ui: {
936
895
  label: "Codex agents",
937
- // Codex green; distinct from claude / gemini palettes.
896
+ // Codex green; distinct from the claude palette.
938
897
  color: "#22c55e",
939
898
  colorDark: "#4ade80",
940
899
  icon: { kind: "pi", id: "pi-bolt" }
@@ -960,7 +919,7 @@ var openaiProvider = {
960
919
  };
961
920
 
962
921
  // plugins/agent-skills/providers/agent-skills/schemas/skill.schema.json
963
- var skill_schema_default3 = {
922
+ var skill_schema_default2 = {
964
923
  $schema: "https://json-schema.org/draft/2020-12/schema",
965
924
  $id: "https://skill-map.dev/providers/agent-skills/v1/frontmatter/skill.schema.json",
966
925
  title: "FrontmatterAgentSkillsSkill",
@@ -984,7 +943,7 @@ var agentSkillsProvider = {
984
943
  kinds: {
985
944
  skill: {
986
945
  schema: "./schemas/skill.schema.json",
987
- schemaJson: skill_schema_default3,
946
+ schemaJson: skill_schema_default2,
988
947
  ui: {
989
948
  label: "Skills",
990
949
  color: "#10b981",
@@ -1013,7 +972,7 @@ var markdown_schema_default = {
1013
972
  $schema: "https://json-schema.org/draft/2020-12/schema",
1014
973
  $id: "https://skill-map.dev/providers/core/v1/frontmatter/markdown.schema.json",
1015
974
  title: "FrontmatterMarkdown",
1016
- description: "Frontmatter shape for nodes classified as `markdown` by the built-in `core/markdown` Provider \u2014 the universal fallback for any markdown file no vendor-specific Provider claims (Claude / Gemini / agent-skills / future Codex). The kind is named after the *format* because the file is a generic fallback; format-named kinds apply only as the generic fallback \u2014 a TOML file that IS a Codex agent still classifies as `agent`, not `toml`. Extends the spec's universal `frontmatter/base.schema.json` via $ref-by-$id with no additional fields. Ownership relocated from the Claude Provider in spec 0.18.0 \u2014 markdown is provider-agnostic and lives under `core` so adding new vendor Providers (e.g. Codex) does not require choosing which one owns the universal fallback.",
975
+ description: "Frontmatter shape for nodes classified as `markdown` by the built-in `core/markdown` Provider, the universal fallback for any markdown file no vendor-specific Provider claims (Claude, OpenAI Codex, agent-skills, plus the metadata-only Antigravity bundle). The kind is named after the format because the file is a generic fallback; format-named kinds apply only as the generic fallback, a TOML file that IS a Codex agent still classifies as `agent`, not `toml`. Extends the spec's universal `frontmatter/base.schema.json` via $ref-by-$id with no additional fields. Ownership relocated from the Claude Provider in spec 0.18.0, markdown is provider-agnostic and lives under `core` so adding new vendor Providers does not require choosing which one owns the universal fallback.",
1017
976
  allOf: [
1018
977
  { $ref: "https://skill-map.dev/spec/v0/frontmatter/base.schema.json" }
1019
978
  ],
@@ -1034,8 +993,9 @@ var coreMarkdownProvider = {
1034
993
  // as a registry entry (it ships later under the core bundle), but
1035
994
  // the qualified form is the contract.
1036
995
  //
1037
- // UI presentation: same neutral teal that Claude / Gemini used to
1038
- // declare for their per-vendor markdown duplicates. The kindRegistry
996
+ // UI presentation: same neutral teal that the per-vendor Providers
997
+ // (when they shipped their own markdown kind duplicates) used to
998
+ // declare. The kindRegistry
1039
999
  // composer (`buildKindRegistry`) makes this entry the primary owner
1040
1000
  // of the `markdown` kind because no other Provider declares it now;
1041
1001
  // per-node painting still falls through `entry.providers[node.provider]`
@@ -1928,12 +1888,56 @@ function formatBreakdown(byKind, direction) {
1928
1888
  return [direction, ...lines].join("\n");
1929
1889
  }
1930
1890
 
1891
+ // plugins/core/analyzers/reserved-name/text.ts
1892
+ var RESERVED_NAME_TEXTS = {
1893
+ /**
1894
+ * `<path> shadows a built-in <provider> <kind>. The runtime ignores
1895
+ * this file in favour of its own built-in. Rename the file or
1896
+ * `frontmatter.name` to a non-reserved value.`
1897
+ */
1898
+ message: "{{path}} shadows a built-in {{provider}} {{kind}}. The runtime ignores this file in favour of its own built-in. Rename the file or `frontmatter.name` to a non-reserved value."
1899
+ };
1900
+
1901
+ // plugins/core/analyzers/reserved-name/index.ts
1902
+ var ID15 = "reserved-name";
1903
+ var reservedNameAnalyzer = {
1904
+ id: ID15,
1905
+ pluginId: "core",
1906
+ kind: "analyzer",
1907
+ version: "1.0.0",
1908
+ description: "Flags user nodes whose name collides with a Provider runtime's built-in invocable (the runtime shadows the file silently).",
1909
+ mode: "deterministic",
1910
+ evaluate(ctx) {
1911
+ const reserved = ctx.reservedNodePaths;
1912
+ if (!reserved || reserved.size === 0) return [];
1913
+ const byPath3 = /* @__PURE__ */ new Map();
1914
+ for (const node of ctx.nodes) byPath3.set(node.path, node);
1915
+ const issues = [];
1916
+ for (const path of reserved) {
1917
+ const node = byPath3.get(path);
1918
+ if (!node) continue;
1919
+ issues.push({
1920
+ analyzerId: ID15,
1921
+ severity: "warn",
1922
+ nodeIds: [node.path],
1923
+ message: tx(RESERVED_NAME_TEXTS.message, {
1924
+ path: node.path,
1925
+ provider: node.provider,
1926
+ kind: node.kind
1927
+ }),
1928
+ data: { provider: node.provider, kind: node.kind }
1929
+ });
1930
+ }
1931
+ return issues;
1932
+ }
1933
+ };
1934
+
1931
1935
  // plugins/core/analyzers/stability/index.ts
1932
- var ID15 = "stability";
1936
+ var ID16 = "stability";
1933
1937
  var EXPERIMENTAL_TOOLTIP = "Experimental: API may change";
1934
1938
  var DEPRECATED_TOOLTIP = "Deprecated: avoid in new code";
1935
1939
  var stabilityAnalyzer = {
1936
- id: ID15,
1940
+ id: ID16,
1937
1941
  pluginId: "core",
1938
1942
  kind: "analyzer",
1939
1943
  version: "1.0.0",
@@ -1965,7 +1969,7 @@ var stabilityAnalyzer = {
1965
1969
  tooltip: EXPERIMENTAL_TOOLTIP
1966
1970
  });
1967
1971
  issues.push({
1968
- analyzerId: ID15,
1972
+ analyzerId: ID16,
1969
1973
  severity: "info",
1970
1974
  nodeIds: [node.path],
1971
1975
  message: `Node '${node.path}' is marked experimental: API may change.`,
@@ -1978,7 +1982,7 @@ var stabilityAnalyzer = {
1978
1982
  severity: "warn"
1979
1983
  });
1980
1984
  issues.push({
1981
- analyzerId: ID15,
1985
+ analyzerId: ID16,
1982
1986
  severity: "warn",
1983
1987
  nodeIds: [node.path],
1984
1988
  message: `Node '${node.path}' is marked deprecated: avoid in new code.`,
@@ -2012,9 +2016,9 @@ var SUPERSEDED_TEXTS = {
2012
2016
  };
2013
2017
 
2014
2018
  // plugins/core/analyzers/superseded/index.ts
2015
- var ID16 = "superseded";
2019
+ var ID17 = "superseded";
2016
2020
  var supersededAnalyzer = {
2017
- id: ID16,
2021
+ id: ID17,
2018
2022
  pluginId: "core",
2019
2023
  kind: "analyzer",
2020
2024
  version: "1.0.0",
@@ -2026,7 +2030,7 @@ var supersededAnalyzer = {
2026
2030
  const supersededBy = pickSupersededBy(node);
2027
2031
  if (supersededBy === null) continue;
2028
2032
  issues.push({
2029
- analyzerId: ID16,
2033
+ analyzerId: ID17,
2030
2034
  severity: "info",
2031
2035
  nodeIds: [node.path],
2032
2036
  message: tx(SUPERSEDED_TEXTS.message, {
@@ -2075,14 +2079,14 @@ var TRIGGER_COLLISION_TEXTS = {
2075
2079
  };
2076
2080
 
2077
2081
  // plugins/core/analyzers/trigger-collision/index.ts
2078
- var ID17 = "trigger-collision";
2082
+ var ID18 = "trigger-collision";
2079
2083
  var ADVERTISING_KINDS = /* @__PURE__ */ new Set([
2080
2084
  "command",
2081
2085
  "skill",
2082
2086
  "agent"
2083
2087
  ]);
2084
2088
  var triggerCollisionAnalyzer = {
2085
- id: ID17,
2089
+ id: ID18,
2086
2090
  pluginId: "core",
2087
2091
  kind: "analyzer",
2088
2092
  mode: "deterministic",
@@ -2181,7 +2185,7 @@ function analyzeTriggerBucket(normalized, claims) {
2181
2185
  part: parts[0]
2182
2186
  });
2183
2187
  return {
2184
- analyzerId: ID17,
2188
+ analyzerId: ID18,
2185
2189
  severity: "error",
2186
2190
  nodeIds,
2187
2191
  message,
@@ -2221,10 +2225,10 @@ var UNKNOWN_FIELD_TEXTS = {
2221
2225
  };
2222
2226
 
2223
2227
  // plugins/core/analyzers/unknown-field/index.ts
2224
- var ID18 = "unknown-field";
2228
+ var ID19 = "unknown-field";
2225
2229
  var RESERVED_ROOT_BLOCKS = /* @__PURE__ */ new Set(["identity", "annotations", "settings", "audit"]);
2226
2230
  var unknownFieldAnalyzer = {
2227
- id: ID18,
2231
+ id: ID19,
2228
2232
  pluginId: "core",
2229
2233
  kind: "analyzer",
2230
2234
  version: "1.0.0",
@@ -2282,7 +2286,7 @@ var unknownFieldAnalyzer = {
2282
2286
  for (const key of Object.keys(annotations)) {
2283
2287
  if (!knownAnnotationKeys.has(key)) {
2284
2288
  issues.push({
2285
- analyzerId: ID18,
2289
+ analyzerId: ID19,
2286
2290
  severity: "warn",
2287
2291
  nodeIds: [node.path],
2288
2292
  message: tx(UNKNOWN_FIELD_TEXTS.unknownAnnotationKey, {
@@ -2309,7 +2313,7 @@ var unknownFieldAnalyzer = {
2309
2313
  if (validator(value)) continue;
2310
2314
  const errors = (validator.errors ?? []).map((e) => `${e.instancePath || "(root)"} ${e.message ?? e.keyword}`).join("; ");
2311
2315
  issues.push({
2312
- analyzerId: ID18,
2316
+ analyzerId: ID19,
2313
2317
  severity: "warn",
2314
2318
  nodeIds: [node.path],
2315
2319
  message: tx(UNKNOWN_FIELD_TEXTS.pluginNamespaceInvalid, {
@@ -2325,7 +2329,7 @@ var unknownFieldAnalyzer = {
2325
2329
  continue;
2326
2330
  }
2327
2331
  issues.push({
2328
- analyzerId: ID18,
2332
+ analyzerId: ID19,
2329
2333
  severity: "warn",
2330
2334
  nodeIds: [node.path],
2331
2335
  message: tx(UNKNOWN_FIELD_TEXTS.unknownRootKey, {
@@ -2618,9 +2622,9 @@ var VALIDATE_ALL_TEXTS = {
2618
2622
  };
2619
2623
 
2620
2624
  // plugins/core/analyzers/validate-all/index.ts
2621
- var ID19 = "validate-all";
2625
+ var ID20 = "validate-all";
2622
2626
  var validateAllAnalyzer = {
2623
- id: ID19,
2627
+ id: ID20,
2624
2628
  pluginId: "core",
2625
2629
  kind: "analyzer",
2626
2630
  version: "1.0.0",
@@ -2683,7 +2687,7 @@ function collectNodeFindings(v, node, out) {
2683
2687
  const result = v.validate("node", toNodeForSchema(node));
2684
2688
  if (result.ok) return;
2685
2689
  out.push({
2686
- analyzerId: ID19,
2690
+ analyzerId: ID20,
2687
2691
  severity: "error",
2688
2692
  nodeIds: [node.path],
2689
2693
  message: tx(VALIDATE_ALL_TEXTS.nodeFailure, {
@@ -2702,7 +2706,7 @@ function collectFrontmatterBaseFindings(node, out) {
2702
2706
  if (isMissingStringField(fm, "description")) missing.push("description");
2703
2707
  if (missing.length === 0) return;
2704
2708
  out.push({
2705
- analyzerId: ID19,
2709
+ analyzerId: ID20,
2706
2710
  // `warn` (not `error`) so the default `sm scan` exit code stays
2707
2711
  // 0 even when nodes are missing frontmatter base fields. Strict
2708
2712
  // mode (`sm scan --strict`) still escalates to exit 1. Matches
@@ -2724,7 +2728,7 @@ function collectLinkFindings(v, link2, out) {
2724
2728
  const result = v.validate("link", toLinkForSchema(link2));
2725
2729
  if (result.ok) return;
2726
2730
  out.push({
2727
- analyzerId: ID19,
2731
+ analyzerId: ID20,
2728
2732
  severity: "error",
2729
2733
  nodeIds: [link2.source],
2730
2734
  message: tx(VALIDATE_ALL_TEXTS.linkFailure, {
@@ -2792,13 +2796,13 @@ var ASCII_FORMATTER_TEXTS = {
2792
2796
  };
2793
2797
 
2794
2798
  // plugins/core/formatters/ascii/index.ts
2795
- var ID20 = "ascii";
2799
+ var ID21 = "ascii";
2796
2800
  var KIND_ORDER = ["agent", "command", "skill", "markdown"];
2797
2801
  var asciiFormatter = {
2798
- id: ID20,
2802
+ id: ID21,
2799
2803
  pluginId: "core",
2800
2804
  kind: "formatter",
2801
- formatId: ID20,
2805
+ formatId: ID21,
2802
2806
  version: "1.0.0",
2803
2807
  description: "Renders the scan as plain text, grouped by kind, arrows, and issues. Used by `sm scan --format=ascii`.",
2804
2808
  // ASCII tree formatter, header + per-kind sections + per-issue
@@ -2893,14 +2897,14 @@ function renderSection(out, kind, group) {
2893
2897
  }
2894
2898
 
2895
2899
  // plugins/core/formatters/json/index.ts
2896
- var ID21 = "json";
2900
+ var ID22 = "json";
2897
2901
  var jsonFormatter = {
2898
- id: ID21,
2902
+ id: ID22,
2899
2903
  pluginId: "core",
2900
2904
  kind: "formatter",
2901
2905
  version: "1.0.0",
2902
2906
  description: "Renders the persisted scan as JSON (conforms to `scan-result.schema.json` when the full ScanResult is available). Used by `sm graph --format json` and `GET /api/graph?format=json`.",
2903
- formatId: ID21,
2907
+ formatId: ID22,
2904
2908
  format(ctx) {
2905
2909
  if (ctx.scanResult !== void 0) {
2906
2910
  return JSON.stringify(ctx.scanResult);
@@ -3039,10 +3043,10 @@ function resolveSpecRoot2() {
3039
3043
  }
3040
3044
 
3041
3045
  // plugins/core/actions/bump/index.ts
3042
- var ID22 = "bump";
3046
+ var ID23 = "bump";
3043
3047
  var PLUGIN_ID = "core";
3044
3048
  var bumpAction = {
3045
- id: ID22,
3049
+ id: ID23,
3046
3050
  pluginId: PLUGIN_ID,
3047
3051
  kind: "action",
3048
3052
  version: "1.0.0",
@@ -3101,10 +3105,10 @@ function pickCurrentVersion(overlay) {
3101
3105
  }
3102
3106
 
3103
3107
  // plugins/core/actions/mark-superseded/index.ts
3104
- var ID23 = "mark-superseded";
3108
+ var ID24 = "mark-superseded";
3105
3109
  var PLUGIN_ID2 = "core";
3106
3110
  var markSupersededAction = {
3107
- id: ID23,
3111
+ id: ID24,
3108
3112
  pluginId: PLUGIN_ID2,
3109
3113
  kind: "action",
3110
3114
  version: "0.0.0",
@@ -3214,7 +3218,7 @@ var UPDATE_CHECK_TEXTS = {
3214
3218
  // package.json
3215
3219
  var package_default = {
3216
3220
  name: "@skill-map/cli",
3217
- version: "0.35.0",
3221
+ version: "0.36.0",
3218
3222
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
3219
3223
  license: "MIT",
3220
3224
  type: "module",
@@ -3593,7 +3597,7 @@ var updateCheckHook = {
3593
3597
  var claudeProvider2 = { ...claudeProvider, pluginId: "claude" };
3594
3598
  var atDirectiveExtractor2 = { ...atDirectiveExtractor, pluginId: "claude" };
3595
3599
  var slashExtractor2 = { ...slashExtractor, pluginId: "claude" };
3596
- var geminiProvider2 = { ...geminiProvider, pluginId: "gemini" };
3600
+ var antigravityProvider2 = { ...antigravityProvider, pluginId: "antigravity" };
3597
3601
  var openaiProvider2 = { ...openaiProvider, pluginId: "openai" };
3598
3602
  var agentSkillsProvider2 = { ...agentSkillsProvider, pluginId: "agent-skills" };
3599
3603
  var coreMarkdownProvider2 = { ...coreMarkdownProvider, pluginId: "core" };
@@ -3609,6 +3613,7 @@ var contributionOrphanAnalyzer2 = { ...contributionOrphanAnalyzer, pluginId: "co
3609
3613
  var jobOrphanFileAnalyzer2 = { ...jobOrphanFileAnalyzer, pluginId: "core" };
3610
3614
  var linkConflictAnalyzer2 = { ...linkConflictAnalyzer, pluginId: "core" };
3611
3615
  var linkCountsAnalyzer2 = { ...linkCountsAnalyzer, pluginId: "core" };
3616
+ var reservedNameAnalyzer2 = { ...reservedNameAnalyzer, pluginId: "core" };
3612
3617
  var stabilityAnalyzer2 = { ...stabilityAnalyzer, pluginId: "core" };
3613
3618
  var supersededAnalyzer2 = { ...supersededAnalyzer, pluginId: "core" };
3614
3619
  var triggerCollisionAnalyzer2 = { ...triggerCollisionAnalyzer, pluginId: "core" };
@@ -3631,11 +3636,11 @@ var builtInBundles = [
3631
3636
  ]
3632
3637
  },
3633
3638
  {
3634
- id: "gemini",
3639
+ id: "antigravity",
3635
3640
  granularity: "bundle",
3636
- description: "Gemini CLI platform integration. Classifies files under `.gemini/{agents,skills}` and parses Gemini-flavored frontmatter.",
3641
+ description: "Google Antigravity CLI platform integration (released 2026-05-19, replaces the retired Gemini CLI). Antigravity adopted the open-standard `.agents/` layout, so skills are classified by the neutral `agent-skills` Provider; this bundle contributes lens identity + a reserved-name seed catalog for future Antigravity built-in invocables.",
3637
3642
  extensions: [
3638
- geminiProvider2
3643
+ antigravityProvider2
3639
3644
  ]
3640
3645
  },
3641
3646
  {
@@ -3672,6 +3677,7 @@ var builtInBundles = [
3672
3677
  jobOrphanFileAnalyzer2,
3673
3678
  linkConflictAnalyzer2,
3674
3679
  linkCountsAnalyzer2,
3680
+ reservedNameAnalyzer2,
3675
3681
  stabilityAnalyzer2,
3676
3682
  supersededAnalyzer2,
3677
3683
  triggerCollisionAnalyzer2,
@@ -5148,7 +5154,7 @@ var AsyncMutex = class {
5148
5154
  this.#locked = true;
5149
5155
  return;
5150
5156
  }
5151
- await new Promise((resolve39) => this.#waiters.push(resolve39));
5157
+ await new Promise((resolve40) => this.#waiters.push(resolve40));
5152
5158
  this.#locked = true;
5153
5159
  }
5154
5160
  unlock() {
@@ -9758,7 +9764,13 @@ import { existsSync as existsSync14 } from "fs";
9758
9764
  import { join as join10 } from "path";
9759
9765
  var DETECTION_RULES = [
9760
9766
  { providerId: "claude", marker: ".claude" },
9761
- { providerId: "gemini", marker: ".gemini" },
9767
+ // `gemini` retired 2026-05-22: Google replaced the Gemini CLI with the
9768
+ // Antigravity CLI (released 2026-05-19; Gemini CLI sunsets 2026-06-18).
9769
+ // Antigravity adopted the open-standard `.agents/` instead of a
9770
+ // vendor-specific directory, so detection of a Google CLI project
9771
+ // falls through to the universal `agent-skills` lens (`.agents/`
9772
+ // already classifies via that neutral provider). The lens can still
9773
+ // be set manually via `sm config set activeProvider antigravity`.
9762
9774
  { providerId: "openai", marker: ".codex" },
9763
9775
  { providerId: "openai", marker: "AGENTS.md" },
9764
9776
  { providerId: "cursor", marker: ".cursor" }
@@ -13139,7 +13151,7 @@ import { Command as Command17, Option as Option16 } from "clipanion";
13139
13151
 
13140
13152
  // kernel/orchestrator/index.ts
13141
13153
  import { existsSync as existsSync22, statSync as statSync7 } from "fs";
13142
- import { isAbsolute as isAbsolute7, resolve as resolve27 } from "path";
13154
+ import { isAbsolute as isAbsolute7, resolve as resolve28 } from "path";
13143
13155
  import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
13144
13156
  import cl100k_base from "js-tiktoken/ranks/cl100k_base";
13145
13157
 
@@ -13508,7 +13520,7 @@ function isExternalUrlLink(link2) {
13508
13520
  }
13509
13521
 
13510
13522
  // kernel/orchestrator/analyzers.ts
13511
- async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher) {
13523
+ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sidecarRoots, annotationContributions, viewContributions, orphanJobFiles, referenceablePaths, cwd, registeredActionIds, emitter, hookDispatcher, reservedNodePaths) {
13512
13524
  const issues = [];
13513
13525
  const contributions = [];
13514
13526
  const validators = loadSchemaValidators();
@@ -13572,6 +13584,7 @@ async function runAnalyzers(analyzers, nodes, internalLinks, orphanSidecars, sid
13572
13584
  orphanJobFiles,
13573
13585
  ...referenceablePaths ? { referenceablePaths } : {},
13574
13586
  ...cwd ? { cwd } : {},
13587
+ ...reservedNodePaths ? { reservedNodePaths } : {},
13575
13588
  emitContribution
13576
13589
  });
13577
13590
  for (const issue of emitted) {
@@ -13792,15 +13805,54 @@ function classifyLinkSource(source, shortIdToQualified, cachedQualifiedIds, appl
13792
13805
  return "obsolete";
13793
13806
  }
13794
13807
 
13795
- // kernel/orchestrator/lift-resolved-link-confidence.ts
13808
+ // kernel/orchestrator/node-identifiers.ts
13796
13809
  import { posix as pathPosix4 } from "path";
13810
+ function deriveNodeIdentifiers(node, kindDescriptor) {
13811
+ const sources = kindDescriptor?.identifiers;
13812
+ if (!sources || sources.length === 0) return [];
13813
+ const out = [];
13814
+ for (const source of sources) {
13815
+ const raw = readIdentifier(source, node);
13816
+ if (!raw) continue;
13817
+ const normalised = normalizeTrigger(raw);
13818
+ if (normalised) out.push(normalised);
13819
+ }
13820
+ return out;
13821
+ }
13822
+ function readIdentifier(source, node) {
13823
+ if (source === "frontmatter.name") return readFrontmatterName(node);
13824
+ if (source === "filename-basename") return readFilenameBasename(node);
13825
+ return readDirname(node);
13826
+ }
13827
+ function readFrontmatterName(node) {
13828
+ const raw = node.frontmatter?.["name"];
13829
+ if (typeof raw !== "string") return null;
13830
+ return raw.length > 0 ? raw : null;
13831
+ }
13832
+ function readFilenameBasename(node) {
13833
+ const base = pathPosix4.basename(node.path);
13834
+ if (!base) return null;
13835
+ const ext = pathPosix4.extname(base);
13836
+ const stem = ext ? base.slice(0, -ext.length) : base;
13837
+ return stem.length > 0 ? stem : null;
13838
+ }
13839
+ function readDirname(node) {
13840
+ const dir = pathPosix4.dirname(node.path);
13841
+ if (!dir || dir === "." || dir === "/") return null;
13842
+ const base = pathPosix4.basename(dir);
13843
+ return base.length > 0 ? base : null;
13844
+ }
13845
+
13846
+ // kernel/orchestrator/lift-resolved-link-confidence.ts
13847
+ var RESERVED_TARGET_CONFIDENCE = 0.1;
13797
13848
  function liftResolvedLinkConfidence(links, nodes, ctx) {
13798
13849
  if (!links.some((l) => l.confidence < 1)) return;
13799
13850
  const indexes = buildIndexes(nodes, ctx);
13800
13851
  for (const link2 of links) {
13801
- if (link2.confidence < 1 && resolves(link2, indexes, ctx)) {
13802
- link2.confidence = 1;
13803
- }
13852
+ if (link2.confidence >= 1) continue;
13853
+ const resolution = resolve27(link2, indexes, ctx);
13854
+ if (resolution === "none") continue;
13855
+ link2.confidence = ctx.reservedNodePaths.has(resolution) ? RESERVED_TARGET_CONFIDENCE : 1;
13804
13856
  }
13805
13857
  }
13806
13858
  function buildIndexes(nodes, ctx) {
@@ -13814,18 +13866,19 @@ function buildIndexes(nodes, ctx) {
13814
13866
  }
13815
13867
  return { byPath: byPath3, byName, nodeByPath };
13816
13868
  }
13817
- function resolves(link2, indexes, ctx) {
13818
- if (indexes.byPath.has(link2.target)) return true;
13819
- return resolvesByName(link2, indexes, ctx);
13869
+ function resolve27(link2, indexes, ctx) {
13870
+ if (indexes.byPath.has(link2.target)) return link2.target;
13871
+ return resolveByName(link2, indexes, ctx);
13820
13872
  }
13821
- function resolvesByName(link2, indexes, ctx) {
13873
+ function resolveByName(link2, indexes, ctx) {
13822
13874
  const stripped = stripTriggerSigil(link2.trigger?.normalizedTrigger);
13823
- if (stripped === null) return false;
13875
+ if (stripped === null) return "none";
13824
13876
  const candidates = indexes.byName.get(stripped);
13825
- if (!candidates?.length) return false;
13877
+ if (!candidates?.length) return "none";
13826
13878
  const allowedKinds = lookupAllowedKinds(link2, indexes, ctx);
13827
- if (!allowedKinds?.length) return false;
13828
- return candidates.some((c) => allowedKinds.includes(c.kind));
13879
+ if (!allowedKinds?.length) return "none";
13880
+ const winner = candidates.find((c) => allowedKinds.includes(c.kind));
13881
+ return winner ? winner.path : "none";
13829
13882
  }
13830
13883
  function lookupAllowedKinds(link2, indexes, ctx) {
13831
13884
  const sourceNode = indexes.nodeByPath.get(link2.source);
@@ -13839,44 +13892,17 @@ function stripTriggerSigil(normalized) {
13839
13892
  }
13840
13893
  function indexNode(node, ctx, byName) {
13841
13894
  const kindDescriptor = ctx.kindRegistry.get(kindKey(node));
13842
- const sources = kindDescriptor?.identifiers;
13843
- if (!sources || sources.length === 0) return;
13844
- for (const source of sources) {
13845
- const raw = deriveIdentifier(source, node);
13846
- if (!raw) continue;
13847
- const normalized = normalizeTrigger(raw);
13848
- if (!normalized) continue;
13849
- const bucket = byName.get(normalized);
13895
+ const normalised = deriveNodeIdentifiers(node, kindDescriptor);
13896
+ for (const name of normalised) {
13897
+ const entry = { kind: node.kind, path: node.path };
13898
+ const bucket = byName.get(name);
13850
13899
  if (bucket) {
13851
- bucket.push({ kind: node.kind });
13900
+ bucket.push(entry);
13852
13901
  } else {
13853
- byName.set(normalized, [{ kind: node.kind }]);
13902
+ byName.set(name, [entry]);
13854
13903
  }
13855
13904
  }
13856
13905
  }
13857
- function deriveIdentifier(source, node) {
13858
- if (source === "frontmatter.name") return readFrontmatterName(node);
13859
- if (source === "filename-basename") return readFilenameBasename(node);
13860
- return readDirname(node);
13861
- }
13862
- function readFrontmatterName(node) {
13863
- const raw = node.frontmatter?.["name"];
13864
- if (typeof raw !== "string") return null;
13865
- return raw.length > 0 ? raw : null;
13866
- }
13867
- function readFilenameBasename(node) {
13868
- const base = pathPosix4.basename(node.path);
13869
- if (!base) return null;
13870
- const ext = pathPosix4.extname(base);
13871
- const stem = ext ? base.slice(0, -ext.length) : base;
13872
- return stem.length > 0 ? stem : null;
13873
- }
13874
- function readDirname(node) {
13875
- const dir = pathPosix4.dirname(node.path);
13876
- if (!dir || dir === "." || dir === "/") return null;
13877
- const base = pathPosix4.basename(dir);
13878
- return base.length > 0 ? base : null;
13879
- }
13880
13906
  function kindKey(node) {
13881
13907
  return `${node.provider}/${node.kind}`;
13882
13908
  }
@@ -14613,7 +14639,7 @@ async function runScanInternal(_kernel, options) {
14613
14639
  pluginStores: options.pluginStores,
14614
14640
  activeProvider: resolveActiveProviderOption(options.activeProvider, options.roots)
14615
14641
  });
14616
- const postWalkCtx = buildPostWalkTransformCtx(_kernel);
14642
+ const postWalkCtx = buildPostWalkTransformCtx(_kernel, walked.nodes);
14617
14643
  walked.internalLinks = applyPostWalkTransforms(walked.internalLinks, walked.nodes, postWalkCtx);
14618
14644
  recomputeLinkCounts(walked.nodes, walked.internalLinks);
14619
14645
  recomputeExternalRefsCount(walked.nodes, walked.externalLinks, walked.cachedPaths);
@@ -14634,7 +14660,8 @@ async function runScanInternal(_kernel, options) {
14634
14660
  options.cwd,
14635
14661
  registeredActionIds,
14636
14662
  emitter,
14637
- hookDispatcher
14663
+ hookDispatcher,
14664
+ postWalkCtx.reservedNodePaths
14638
14665
  );
14639
14666
  mergeAnalyzerEmissions(walked, analyzerResult, exts.analyzers);
14640
14667
  const issues = analyzerResult.issues;
@@ -14647,9 +14674,19 @@ async function runScanInternal(_kernel, options) {
14647
14674
  await hookDispatcher.dispatch("scan.completed", scanCompletedEvent);
14648
14675
  return buildScanReturn(walked, issues, renameOps, stats, options, setup);
14649
14676
  }
14650
- function buildPostWalkTransformCtx(kernel) {
14677
+ function buildPostWalkTransformCtx(kernel, nodes) {
14678
+ const { kindRegistry, providerResolution, reservedNamesByProviderKind } = buildProviderIndexes(kernel);
14679
+ const reservedNodePaths = buildReservedNodePaths(
14680
+ nodes,
14681
+ kindRegistry,
14682
+ reservedNamesByProviderKind
14683
+ );
14684
+ return { kindRegistry, providerResolution, reservedNodePaths };
14685
+ }
14686
+ function buildProviderIndexes(kernel) {
14651
14687
  const kindRegistry = /* @__PURE__ */ new Map();
14652
14688
  const providerResolution = /* @__PURE__ */ new Map();
14689
+ const reservedNamesByProviderKind = /* @__PURE__ */ new Map();
14653
14690
  const providers = kernel.registry.all("provider");
14654
14691
  for (const provider of providers) {
14655
14692
  if (provider.kinds) {
@@ -14660,8 +14697,32 @@ function buildPostWalkTransformCtx(kernel) {
14660
14697
  if (provider.resolution) {
14661
14698
  providerResolution.set(provider.id, provider.resolution);
14662
14699
  }
14700
+ if (provider.reservedNames) {
14701
+ indexReservedNames(provider, reservedNamesByProviderKind);
14702
+ }
14663
14703
  }
14664
- return { kindRegistry, providerResolution };
14704
+ return { kindRegistry, providerResolution, reservedNamesByProviderKind };
14705
+ }
14706
+ function indexReservedNames(provider, out) {
14707
+ for (const [kindName, list] of Object.entries(provider.reservedNames ?? {})) {
14708
+ const normalised = new Set(list.map((raw) => normalizeTrigger(raw)).filter(Boolean));
14709
+ if (normalised.size > 0) {
14710
+ out.set(`${provider.id}/${kindName}`, normalised);
14711
+ }
14712
+ }
14713
+ }
14714
+ function buildReservedNodePaths(nodes, kindRegistry, reservedNamesByProviderKind) {
14715
+ const out = /* @__PURE__ */ new Set();
14716
+ for (const node of nodes) {
14717
+ const key = `${node.provider}/${node.kind}`;
14718
+ const reservedSet = reservedNamesByProviderKind.get(key);
14719
+ if (!reservedSet || reservedSet.size === 0) continue;
14720
+ const ids = deriveNodeIdentifiers(node, kindRegistry.get(key));
14721
+ if (ids.some((id) => reservedSet.has(id))) {
14722
+ out.add(node.path);
14723
+ }
14724
+ }
14725
+ return out;
14665
14726
  }
14666
14727
  function buildScanSetup(options) {
14667
14728
  const start = Date.now();
@@ -14754,7 +14815,7 @@ function validateRoots(roots) {
14754
14815
  function resolveActiveProviderOption(optionValue, roots) {
14755
14816
  if (optionValue !== void 0) return optionValue;
14756
14817
  for (const root of roots) {
14757
- const absRoot = isAbsolute7(root) ? root : resolve27(root);
14818
+ const absRoot = isAbsolute7(root) ? root : resolve28(root);
14758
14819
  if (!existsSync22(absRoot)) continue;
14759
14820
  const detected = resolveActiveProvider(absRoot).resolved;
14760
14821
  if (detected !== null) return detected;
@@ -14763,10 +14824,10 @@ function resolveActiveProviderOption(optionValue, roots) {
14763
14824
  }
14764
14825
 
14765
14826
  // kernel/scan/watcher.ts
14766
- import { resolve as resolve28, relative as relative5, sep as sep4 } from "path";
14827
+ import { resolve as resolve29, relative as relative5, sep as sep4 } from "path";
14767
14828
  import chokidar from "chokidar";
14768
14829
  function createChokidarWatcher(opts) {
14769
- const absRoots = opts.roots.map((r) => resolve28(opts.cwd, r));
14830
+ const absRoots = opts.roots.map((r) => resolve29(opts.cwd, r));
14770
14831
  const ignoreFilterOpt = opts.ignoreFilter;
14771
14832
  const getFilter = ignoreFilterOpt === void 0 ? void 0 : typeof ignoreFilterOpt === "function" ? ignoreFilterOpt : () => ignoreFilterOpt;
14772
14833
  const ignored = getFilter ? (path) => {
@@ -14985,7 +15046,7 @@ function createKernel() {
14985
15046
 
14986
15047
  // kernel/jobs/orphan-files.ts
14987
15048
  import { readdirSync as readdirSync8, statSync as statSync8 } from "fs";
14988
- import { join as join14, resolve as resolve29 } from "path";
15049
+ import { join as join14, resolve as resolve30 } from "path";
14989
15050
  function findOrphanJobFiles(jobsDir, referencedPaths) {
14990
15051
  let entries;
14991
15052
  try {
@@ -15003,7 +15064,7 @@ function findOrphanJobFiles(jobsDir, referencedPaths) {
15003
15064
  if (!entry.isFile()) continue;
15004
15065
  const name = entry.name;
15005
15066
  if (!name.endsWith(".md")) continue;
15006
- const abs = resolve29(join14(jobsDir, name));
15067
+ const abs = resolve30(join14(jobsDir, name));
15007
15068
  if (!referencedPaths.has(abs)) orphans.push(abs);
15008
15069
  }
15009
15070
  orphans.sort();
@@ -15070,12 +15131,12 @@ var SCAN_RUNNER_TEXTS = {
15070
15131
  referenceWalkMissingRoot: 'scan.referencePaths: configured path "{{path}}" does not exist; skipped.',
15071
15132
  /**
15072
15133
  * Active-provider bootstrap: filesystem auto-detect found no
15073
- * markers (`.claude/`, `.gemini/`, `.codex/`, `AGENTS.md`, `.cursor/`)
15074
- * anywhere under cwd or the effective scan roots. Plain-markdown
15075
- * projects keep scanning fine; provider-specific extractors silently
15076
- * no-op for this scan.
15134
+ * markers (`.claude/`, `.codex/`, `AGENTS.md`, `.cursor/`) anywhere
15135
+ * under cwd or the effective scan roots. Plain-markdown projects
15136
+ * keep scanning fine; provider-specific extractors silently no-op
15137
+ * for this scan.
15077
15138
  */
15078
- activeProviderNoMarkerWarning: "No provider markers detected (.claude/, .gemini/, .codex/, AGENTS.md, .cursor/). Scanning as universal markdown only; provider-specific link types (e.g. claude @-directives, /-commands) will not appear in the graph. Set `activeProvider` in .skill-map/settings.json or install a provider plugin to enable them.",
15139
+ activeProviderNoMarkerWarning: "No provider markers detected (.claude/, .codex/, AGENTS.md, .cursor/). Scanning as universal markdown only; provider-specific link types (e.g. claude @-directives, /-commands) will not appear in the graph. Set `activeProvider` in .skill-map/settings.json or install a provider plugin to enable them.",
15079
15140
  /**
15080
15141
  * Active-provider bootstrap: filesystem auto-detect found exactly
15081
15142
  * one marker and persisted the detected id to project settings.
@@ -15122,7 +15183,7 @@ function resolveScanRoots(inputs) {
15122
15183
  // core/runtime/reference-paths-walker.ts
15123
15184
  import { readdirSync as readdirSync9, statSync as statSync9 } from "fs";
15124
15185
  import { homedir as osHomedir2 } from "os";
15125
- import { isAbsolute as isAbsolute8, join as join15, resolve as resolve30 } from "path";
15186
+ import { isAbsolute as isAbsolute8, join as join15, resolve as resolve31 } from "path";
15126
15187
  var REFERENCE_WALK_MAX_FILES = 5e4;
15127
15188
  var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
15128
15189
  "node_modules",
@@ -15130,10 +15191,10 @@ var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
15130
15191
  SKILL_MAP_DIR
15131
15192
  ]);
15132
15193
  function resolveScanPath(raw, cwd) {
15133
- if (raw.startsWith("~/")) return resolve30(join15(osHomedir2(), raw.slice(2)));
15134
- if (raw === "~") return resolve30(osHomedir2());
15135
- if (isAbsolute8(raw)) return resolve30(raw);
15136
- return resolve30(cwd, raw);
15194
+ if (raw.startsWith("~/")) return resolve31(join15(osHomedir2(), raw.slice(2)));
15195
+ if (raw === "~") return resolve31(osHomedir2());
15196
+ if (isAbsolute8(raw)) return resolve31(raw);
15197
+ return resolve31(cwd, raw);
15137
15198
  }
15138
15199
  function walkReferencePaths(rawRoots, cwd) {
15139
15200
  const paths = /* @__PURE__ */ new Set();
@@ -17427,9 +17488,9 @@ var PLUGINS_TEXTS = {
17427
17488
  };
17428
17489
 
17429
17490
  // cli/commands/plugins/shared.ts
17430
- import { resolve as resolve31 } from "path";
17491
+ import { resolve as resolve32 } from "path";
17431
17492
  function resolveSearchPaths2(opts, cwd) {
17432
- if (opts.pluginDir) return [resolve31(opts.pluginDir)];
17493
+ if (opts.pluginDir) return [resolve32(opts.pluginDir)];
17433
17494
  return [defaultProjectPluginsDir({ cwd })];
17434
17495
  }
17435
17496
  async function buildResolver() {
@@ -18451,7 +18512,7 @@ var PluginsEnableCommand = class extends TogglePluginsBase {
18451
18512
  baseline.
18452
18513
 
18453
18514
  Accepts one or more ids in one call, e.g.
18454
- 'sm plugins enable claude gemini openai'. Batches are
18515
+ 'sm plugins enable claude antigravity openai'. Batches are
18455
18516
  all-or-nothing: a single unknown / mismatched id aborts before
18456
18517
  any write. Repeated ids are deduped. Locked plugins inside a
18457
18518
  batch are silently skipped.
@@ -18479,7 +18540,7 @@ var PluginsDisableCommand = class extends TogglePluginsBase {
18479
18540
  will not run them.
18480
18541
 
18481
18542
  Accepts one or more ids in one call, e.g.
18482
- 'sm plugins disable gemini openai agent-skills'. Batches are
18543
+ 'sm plugins disable antigravity openai agent-skills'. Batches are
18483
18544
  all-or-nothing: a single unknown / mismatched id aborts before
18484
18545
  any write. Repeated ids are deduped. Locked plugins inside a
18485
18546
  batch are silently skipped.
@@ -18589,7 +18650,7 @@ function resolveBareToggle(id, catalogue, verb, ansi) {
18589
18650
 
18590
18651
  // cli/commands/plugins/create.ts
18591
18652
  import { existsSync as existsSync23, mkdirSync as mkdirSync6, writeFileSync as writeFileSync3 } from "fs";
18592
- import { join as join18, resolve as resolve32 } from "path";
18653
+ import { join as join18, resolve as resolve33 } from "path";
18593
18654
  import { Command as Command26, Option as Option25 } from "clipanion";
18594
18655
  var PluginsCreateCommand = class extends SmCommand {
18595
18656
  static paths = [["plugins", "create"]];
@@ -18615,7 +18676,7 @@ var PluginsCreateCommand = class extends SmCommand {
18615
18676
  }
18616
18677
  const ctx = defaultRuntimeContext();
18617
18678
  const baseDir = defaultProjectPluginsDir(ctx);
18618
- const targetDir = this.at ? resolve32(this.at) : join18(baseDir, this.pluginId);
18679
+ const targetDir = this.at ? resolve33(this.at) : join18(baseDir, this.pluginId);
18619
18680
  if (existsSync23(targetDir) && !this.force) {
18620
18681
  this.printer.error(
18621
18682
  tx(PLUGINS_TEXTS.createRefuseOverwrite, {
@@ -18856,7 +18917,7 @@ var PLUGIN_COMMANDS = [
18856
18917
 
18857
18918
  // cli/commands/refresh.ts
18858
18919
  import { readFile as readFile3 } from "fs/promises";
18859
- import { resolve as resolve33 } from "path";
18920
+ import { resolve as resolve34 } from "path";
18860
18921
  import { Command as Command29, Option as Option27 } from "clipanion";
18861
18922
 
18862
18923
  // cli/i18n/refresh.texts.ts
@@ -19140,7 +19201,7 @@ var RefreshCommand = class extends SmCommand {
19140
19201
  let body;
19141
19202
  try {
19142
19203
  assertContained(cwd, node.path);
19143
- const raw = await readFile3(resolve33(cwd, node.path), "utf8");
19204
+ const raw = await readFile3(resolve34(cwd, node.path), "utf8");
19144
19205
  body = stripFrontmatterFence(raw);
19145
19206
  } catch (err) {
19146
19207
  if (!this.json) {
@@ -19882,7 +19943,7 @@ var ScanCommand = class extends SmCommand {
19882
19943
  description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
19883
19944
  });
19884
19945
  yes = Option29.Boolean("--yes", false, {
19885
- description: "Non-interactive mode for ambiguous activeProvider auto-detect. With `--yes`, multiple provider markers (.claude/, .gemini/, .codex/, AGENTS.md, .cursor/) under the scan tree exit non-zero instead of prompting the operator. Set the lens manually via `sm config set activeProvider <id>` and re-run."
19946
+ description: "Non-interactive mode for ambiguous activeProvider auto-detect. With `--yes`, multiple provider markers (.claude/, .codex/, AGENTS.md, .cursor/) under the scan tree exit non-zero instead of prompting the operator. Set the lens manually via `sm config set activeProvider <id>` and re-run."
19886
19947
  });
19887
19948
  // Each branch in the orchestrator maps to one validation gate
19888
19949
  // (--watch alias / --changed mutex / -g mutex / dispatch).
@@ -21874,10 +21935,10 @@ import { HTTPException as HTTPException10 } from "hono/http-exception";
21874
21935
 
21875
21936
  // server/util/skillmapignore-io.ts
21876
21937
  import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync4 } from "fs";
21877
- import { resolve as resolve34 } from "path";
21938
+ import { resolve as resolve35 } from "path";
21878
21939
  var IGNORE_FILENAME2 = ".skillmapignore";
21879
21940
  function readPatterns(cwd) {
21880
- const path = resolve34(cwd, IGNORE_FILENAME2);
21941
+ const path = resolve35(cwd, IGNORE_FILENAME2);
21881
21942
  if (!existsSync26(path)) return [];
21882
21943
  let raw;
21883
21944
  try {
@@ -21888,7 +21949,7 @@ function readPatterns(cwd) {
21888
21949
  return raw.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#"));
21889
21950
  }
21890
21951
  function writePatterns(cwd, nextPatterns) {
21891
- const path = resolve34(cwd, IGNORE_FILENAME2);
21952
+ const path = resolve35(cwd, IGNORE_FILENAME2);
21892
21953
  const prior = existsSync26(path) ? safeRead(path) : "";
21893
21954
  const content = buildContent(prior, nextPatterns);
21894
21955
  writeFileSync4(path, content, "utf8");
@@ -22309,14 +22370,14 @@ async function withScanMutex(fn) {
22309
22370
  if (inFlight !== null) {
22310
22371
  throw new ScanBusyError();
22311
22372
  }
22312
- let resolve39;
22373
+ let resolve40;
22313
22374
  inFlight = new Promise((r) => {
22314
- resolve39 = r;
22375
+ resolve40 = r;
22315
22376
  });
22316
22377
  try {
22317
22378
  return await fn();
22318
22379
  } finally {
22319
- resolve39();
22380
+ resolve40();
22320
22381
  inFlight = null;
22321
22382
  }
22322
22383
  }
@@ -22628,7 +22689,7 @@ function emptyScanResult() {
22628
22689
 
22629
22690
  // server/routes/sidecar.ts
22630
22691
  import { HTTPException as HTTPException14 } from "hono/http-exception";
22631
- import { resolve as resolve35 } from "path";
22692
+ import { resolve as resolve36 } from "path";
22632
22693
  var STATUS_FRESH = "fresh";
22633
22694
  var ENVELOPE_KIND2 = "sidecar.bumped";
22634
22695
  var BUMP_BODY_SCHEMA = {
@@ -22662,7 +22723,7 @@ function registerSidecarRoutes(app, deps) {
22662
22723
  let absPath;
22663
22724
  try {
22664
22725
  assertContained(deps.runtimeContext.cwd, node.path);
22665
- absPath = resolve35(deps.runtimeContext.cwd, node.path);
22726
+ absPath = resolve36(deps.runtimeContext.cwd, node.path);
22666
22727
  } catch (err) {
22667
22728
  throw new HTTPException14(500, { message: formatErrorMessage(err) });
22668
22729
  }
@@ -23414,7 +23475,7 @@ function validateNoUi(noUi, uiDist) {
23414
23475
 
23415
23476
  // server/paths.ts
23416
23477
  import { existsSync as existsSync29, statSync as statSync11 } from "fs";
23417
- import { dirname as dirname18, isAbsolute as isAbsolute11, join as join20, resolve as resolve36 } from "path";
23478
+ import { dirname as dirname18, isAbsolute as isAbsolute11, join as join20, resolve as resolve37 } from "path";
23418
23479
  import { fileURLToPath as fileURLToPath5 } from "url";
23419
23480
  var DEFAULT_UI_REL = join20("ui", "dist", "ui", "browser");
23420
23481
  var PACKAGE_UI_REL = "ui";
@@ -23425,7 +23486,7 @@ function resolveDefaultUiDist(ctx) {
23425
23486
  return walkUpForUi(ctx.cwd);
23426
23487
  }
23427
23488
  function resolveExplicitUiDist(ctx, raw) {
23428
- return isAbsolute11(raw) ? raw : resolve36(ctx.cwd, raw);
23489
+ return isAbsolute11(raw) ? raw : resolve37(ctx.cwd, raw);
23429
23490
  }
23430
23491
  function isUiBundleDir(path) {
23431
23492
  if (!existsSync29(path)) return false;
@@ -23459,7 +23520,7 @@ function resolvePackageBundledUiFrom(here) {
23459
23520
  return null;
23460
23521
  }
23461
23522
  function walkUpForUi(startDir) {
23462
- let current = resolve36(startDir);
23523
+ let current = resolve37(startDir);
23463
23524
  for (let i = 0; i < 64; i++) {
23464
23525
  const candidate = join20(current, DEFAULT_UI_REL);
23465
23526
  if (isUiBundleDir(candidate)) return candidate;
@@ -24399,7 +24460,7 @@ function rankConfidenceForGrouping(c) {
24399
24460
 
24400
24461
  // cli/commands/sidecar.ts
24401
24462
  import { existsSync as existsSync31, unlinkSync as unlinkSync2 } from "fs";
24402
- import { resolve as resolve37 } from "path";
24463
+ import { resolve as resolve38 } from "path";
24403
24464
  import { Command as Command35, Option as Option33 } from "clipanion";
24404
24465
 
24405
24466
  // cli/i18n/sidecar.texts.ts
@@ -24550,7 +24611,7 @@ var SidecarRefreshCommand = class extends SmCommand {
24550
24611
  let absPath;
24551
24612
  try {
24552
24613
  assertContained(ctx.cwd, node.path);
24553
- absPath = resolve37(ctx.cwd, node.path);
24614
+ absPath = resolve38(ctx.cwd, node.path);
24554
24615
  } catch (err) {
24555
24616
  this.printer.error(
24556
24617
  tx(SIDECAR_TEXTS.refreshFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
@@ -24831,7 +24892,7 @@ var SidecarAnnotateCommand = class extends SmCommand {
24831
24892
  let absPath;
24832
24893
  try {
24833
24894
  assertContained(ctx.cwd, node.path);
24834
- absPath = resolve37(ctx.cwd, node.path);
24895
+ absPath = resolve38(ctx.cwd, node.path);
24835
24896
  } catch (err) {
24836
24897
  this.printer.error(
24837
24898
  tx(SIDECAR_TEXTS.annotateFailed, { glyph: errGlyph, message: formatErrorMessage(err) })
@@ -25080,7 +25141,7 @@ var STUB_COMMANDS = [
25080
25141
 
25081
25142
  // cli/commands/tutorial.ts
25082
25143
  import { cpSync as cpSync2, existsSync as existsSync32, mkdirSync as mkdirSync7, rmSync as rmSync2, statSync as statSync12 } from "fs";
25083
- import { dirname as dirname19, join as join21, resolve as resolve38 } from "path";
25144
+ import { dirname as dirname19, join as join21, resolve as resolve39 } from "path";
25084
25145
  import { fileURLToPath as fileURLToPath6 } from "url";
25085
25146
  import { Command as Command37, Option as Option35 } from "clipanion";
25086
25147
 
@@ -25254,11 +25315,11 @@ function resolveSkillSourceDir(variant) {
25254
25315
  const here = dirname19(fileURLToPath6(import.meta.url));
25255
25316
  const candidates = [
25256
25317
  // dev: src/cli/commands/ → repo-root .claude/skills/<slug>/
25257
- resolve38(here, "../../..", spec.sourceDir),
25318
+ resolve39(here, "../../..", spec.sourceDir),
25258
25319
  // bundled: dist/cli.js → dist/cli/tutorial/<slug> (sibling)
25259
- resolve38(here, "cli/tutorial", spec.slug),
25320
+ resolve39(here, "cli/tutorial", spec.slug),
25260
25321
  // bundled fallback: any-depth → cli/tutorial/<slug>
25261
- resolve38(here, "../cli/tutorial", spec.slug)
25322
+ resolve39(here, "../cli/tutorial", spec.slug)
25262
25323
  ];
25263
25324
  for (const candidate of candidates) {
25264
25325
  if (existsSync32(candidate) && statSync12(candidate).isDirectory()) {