facult 2.7.2 → 2.7.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "facult",
3
- "version": "2.7.2",
3
+ "version": "2.7.3",
4
4
  "description": "Manage canonical AI capabilities, sync surfaces, and evolution state.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/ai.ts CHANGED
@@ -308,6 +308,7 @@ function mapGraphNodeKind(kind: GraphNodeKind): string {
308
308
  case "agent":
309
309
  case "skill":
310
310
  case "mcp":
311
+ case "automation":
311
312
  case "doc":
312
313
  case "rendered-target":
313
314
  return kind;
@@ -16,6 +16,7 @@ function ensureIndexStructure(index: FacultIndex): FacultIndex {
16
16
  skills: index.skills ?? {},
17
17
  mcp: index.mcp ?? { servers: {} },
18
18
  agents: index.agents ?? {},
19
+ automations: index.automations ?? {},
19
20
  snippets: index.snippets ?? {},
20
21
  instructions: index.instructions ?? {},
21
22
  };
@@ -36,6 +36,7 @@ function ensureIndexStructure(index: FacultIndex): FacultIndex {
36
36
  skills: index.skills ?? {},
37
37
  mcp: index.mcp ?? { servers: {} },
38
38
  agents: index.agents ?? {},
39
+ automations: index.automations ?? {},
39
40
  snippets: index.snippets ?? {},
40
41
  instructions: index.instructions ?? {},
41
42
  };
@@ -12,6 +12,7 @@ type QueryableGraphKind =
12
12
  | GraphNodeKind
13
13
  | "skills"
14
14
  | "agents"
15
+ | "automations"
15
16
  | "snippets"
16
17
  | "instructions"
17
18
  | "docs"
@@ -34,6 +35,8 @@ const KIND_ALIASES: Record<QueryableGraphKind, GraphNodeKind> = {
34
35
  skills: "skill",
35
36
  agent: "agent",
36
37
  agents: "agent",
38
+ automation: "automation",
39
+ automations: "automation",
37
40
  snippet: "snippet",
38
41
  snippets: "snippet",
39
42
  instruction: "instruction",
package/src/graph.ts CHANGED
@@ -11,6 +11,7 @@ export type GraphNodeKind =
11
11
  | "skill"
12
12
  | "mcp"
13
13
  | "agent"
14
+ | "automation"
14
15
  | "snippet"
15
16
  | "instruction"
16
17
  | "doc"
@@ -77,6 +77,12 @@ export interface AgentEntry {
77
77
  lastAuditAt?: string;
78
78
  }
79
79
 
80
+ export interface AutomationEntry {
81
+ name: string;
82
+ path: string;
83
+ lastModifiedAt?: string;
84
+ }
85
+
80
86
  export interface SnippetEntry {
81
87
  name: string;
82
88
  path: string;
@@ -102,6 +108,7 @@ interface ToolAssetEntry extends AssetEntryBase {
102
108
  export interface SkillEntry extends AssetEntryBase {}
103
109
  export interface McpEntry extends AssetEntryBase {}
104
110
  export interface AgentEntry extends AssetEntryBase {}
111
+ export interface AutomationEntry extends AssetEntryBase {}
105
112
  export interface SnippetEntry extends AssetEntryBase {}
106
113
  export interface InstructionEntry extends AssetEntryBase {}
107
114
 
@@ -111,6 +118,7 @@ export interface FacultIndex {
111
118
  skills: Record<string, SkillEntry>;
112
119
  mcp: { servers: Record<string, McpEntry> };
113
120
  agents: Record<string, AgentEntry>;
121
+ automations?: Record<string, AutomationEntry>;
114
122
  snippets: Record<string, SnippetEntry>;
115
123
  instructions: Record<string, InstructionEntry>;
116
124
  }
@@ -127,6 +135,7 @@ interface SourceAssets {
127
135
  skills: Record<string, SkillEntry>;
128
136
  mcpServers: Record<string, McpEntry>;
129
137
  agents: Record<string, AgentEntry>;
138
+ automations: Record<string, AutomationEntry>;
130
139
  snippets: Record<string, SnippetEntry>;
131
140
  instructions: Record<string, InstructionEntry>;
132
141
  toolConfigs: Record<string, ToolAssetEntry>;
@@ -460,6 +469,7 @@ function canonicalRefForPath(
460
469
  category:
461
470
  | "skills"
462
471
  | "agents"
472
+ | "automations"
463
473
  | "snippets"
464
474
  | "instructions"
465
475
  | "mcp"
@@ -687,6 +697,39 @@ async function indexAgents(
687
697
  return out;
688
698
  }
689
699
 
700
+ async function indexAutomations(
701
+ automationsDir: string,
702
+ source: IndexedSource
703
+ ): Promise<Record<string, AutomationEntry>> {
704
+ const out: Record<string, AutomationEntry> = {};
705
+ const dirs = await listSubdirs(automationsDir);
706
+ for (const d of dirs) {
707
+ const automationToml = join(d, "automation.toml");
708
+ try {
709
+ const st = await Bun.file(automationToml).stat();
710
+ if (!st.isFile()) {
711
+ continue;
712
+ }
713
+
714
+ const name = basename(d);
715
+ out[name] = {
716
+ name,
717
+ path: automationToml,
718
+ canonicalRef: canonicalRefForPath(
719
+ source,
720
+ "automations",
721
+ automationToml
722
+ ),
723
+ lastModifiedAt: await statIsoTime(automationToml),
724
+ ...entryScopeMeta(source),
725
+ };
726
+ } catch {
727
+ // Ignore malformed automation entries.
728
+ }
729
+ }
730
+ return out;
731
+ }
732
+
690
733
  async function indexSnippets(
691
734
  snippetsDir: string,
692
735
  source: IndexedSource
@@ -838,6 +881,7 @@ async function indexSourceAssets(
838
881
  ): Promise<SourceAssets> {
839
882
  const skillsDir = join(source.rootDir, "skills");
840
883
  const agentsDir = join(source.rootDir, "agents");
884
+ const automationsDir = join(source.rootDir, "automations");
841
885
  const snippetsDir = join(source.rootDir, "snippets");
842
886
  const instructionsDir = join(source.rootDir, "instructions");
843
887
  const toolsDir = join(source.rootDir, "tools");
@@ -862,20 +906,29 @@ async function indexSourceAssets(
862
906
  >)
863
907
  : undefined;
864
908
 
865
- const [skills, mcpServers, agents, snippets, instructions, toolAssets] =
866
- await Promise.all([
867
- indexSkills(skillsDir, source, prevSkills),
868
- indexMcpServers(canonicalMcpPath, source, prevMcpMap),
869
- indexAgents(agentsDir, source, prevAgents),
870
- indexSnippets(snippetsDir, source),
871
- indexInstructions(instructionsDir, source),
872
- indexToolAssets(toolsDir, source),
873
- ]);
909
+ const [
910
+ skills,
911
+ mcpServers,
912
+ agents,
913
+ automations,
914
+ snippets,
915
+ instructions,
916
+ toolAssets,
917
+ ] = await Promise.all([
918
+ indexSkills(skillsDir, source, prevSkills),
919
+ indexMcpServers(canonicalMcpPath, source, prevMcpMap),
920
+ indexAgents(agentsDir, source, prevAgents),
921
+ indexAutomations(automationsDir, source),
922
+ indexSnippets(snippetsDir, source),
923
+ indexInstructions(instructionsDir, source),
924
+ indexToolAssets(toolsDir, source),
925
+ ]);
874
926
 
875
927
  return {
876
928
  skills,
877
929
  mcpServers,
878
930
  agents,
931
+ automations,
879
932
  snippets,
880
933
  instructions,
881
934
  toolConfigs: toolAssets.toolConfigs,
@@ -907,6 +960,7 @@ function registerGraphEntries<
907
960
  | "skill"
908
961
  | "mcp"
909
962
  | "agent"
963
+ | "automation"
910
964
  | "snippet"
911
965
  | "instruction"
912
966
  | "doc"
@@ -1006,6 +1060,11 @@ function buildActiveEntryMap(
1006
1060
  for (const [name, entry] of Object.entries(sourceEntry.assets.agents)) {
1007
1061
  active.set(activeEntryKey("agent", name), sourceIdentity(entry));
1008
1062
  }
1063
+ for (const [name, entry] of Object.entries(
1064
+ sourceEntry.assets.automations
1065
+ )) {
1066
+ active.set(activeEntryKey("automation", name), sourceIdentity(entry));
1067
+ }
1009
1068
  for (const [name, entry] of Object.entries(sourceEntry.assets.snippets)) {
1010
1069
  active.set(activeEntryKey("snippet", name), sourceIdentity(entry));
1011
1070
  }
@@ -1089,6 +1148,7 @@ async function addReferenceEdgesForEntries<
1089
1148
  kind:
1090
1149
  | "skill"
1091
1150
  | "agent"
1151
+ | "automation"
1092
1152
  | "snippet"
1093
1153
  | "instruction"
1094
1154
  | "doc"
@@ -1243,6 +1303,7 @@ function sourceNodeIdForEntry(args: {
1243
1303
  | "skill"
1244
1304
  | "mcp"
1245
1305
  | "agent"
1306
+ | "automation"
1246
1307
  | "snippet"
1247
1308
  | "instruction"
1248
1309
  | "doc"
@@ -1534,6 +1595,9 @@ export async function buildIndex(opts?: {
1534
1595
  sourceIndexes.map((entry) => entry.assets.mcpServers)
1535
1596
  );
1536
1597
  const agents = mergeByName(sourceIndexes.map((entry) => entry.assets.agents));
1598
+ const automations = mergeByName(
1599
+ sourceIndexes.map((entry) => entry.assets.automations)
1600
+ );
1537
1601
  const snippets = mergeByName(
1538
1602
  sourceIndexes.map((entry) => entry.assets.snippets)
1539
1603
  );
@@ -1547,6 +1611,7 @@ export async function buildIndex(opts?: {
1547
1611
  skills,
1548
1612
  mcp: { servers },
1549
1613
  agents,
1614
+ automations,
1550
1615
  snippets,
1551
1616
  instructions,
1552
1617
  };
@@ -1579,6 +1644,12 @@ export async function buildIndex(opts?: {
1579
1644
  "agent",
1580
1645
  activeSelections
1581
1646
  );
1647
+ registerGraphEntries(
1648
+ graph,
1649
+ sourceEntry.assets.automations,
1650
+ "automation",
1651
+ activeSelections
1652
+ );
1582
1653
  registerGraphEntries(
1583
1654
  graph,
1584
1655
  sourceEntry.assets.snippets,
@@ -1633,6 +1704,12 @@ export async function buildIndex(opts?: {
1633
1704
  "agent",
1634
1705
  refsByRoot
1635
1706
  );
1707
+ await addReferenceEdgesForEntries(
1708
+ graph,
1709
+ sourceEntry.assets.automations,
1710
+ "automation",
1711
+ refsByRoot
1712
+ );
1636
1713
  await addReferenceEdgesForEntries(
1637
1714
  graph,
1638
1715
  sourceEntry.assets.snippets,
package/src/trust-list.ts CHANGED
@@ -234,6 +234,7 @@ export async function applyOrgTrustList(
234
234
  }),
235
235
  },
236
236
  agents: index.agents ?? {},
237
+ automations: index.automations ?? {},
237
238
  snippets: index.snippets ?? {},
238
239
  instructions: index.instructions ?? {},
239
240
  };
package/src/trust.ts CHANGED
@@ -23,6 +23,7 @@ function ensureIndexStructure(index: FacultIndex): FacultIndex {
23
23
  skills: index.skills ?? {},
24
24
  mcp: index.mcp ?? { servers: {} },
25
25
  agents: index.agents ?? {},
26
+ automations: index.automations ?? {},
26
27
  snippets: index.snippets ?? {},
27
28
  instructions: index.instructions ?? {},
28
29
  };