facult 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -444,6 +444,7 @@ The canonical store can contain several distinct asset classes:
444
444
  - `agents/`: role-specific agent manifests
445
445
  - `skills/`: workflow-specific capability folders
446
446
  - `mcp/`: canonical MCP server definitions
447
+ - `mcp/servers.local.json` or `mcp/mcp.local.json`: ignored machine-local MCP secret overlay
447
448
  - `tools/<tool>/config.toml`: canonical tool config
448
449
  - `tools/<tool>/config.local.toml`: machine-local tool config overlay
449
450
  - `tools/<tool>/rules/*.rules`: canonical tool rules
@@ -480,10 +481,13 @@ Built-ins currently include:
480
481
  Recommended split:
481
482
  - `~/.ai/config.toml` or `<repo>/.ai/config.toml`: tracked, portable, non-secret refs/defaults
482
483
  - `~/.ai/config.local.toml` or `<repo>/.ai/config.local.toml`: ignored, machine-local paths and secrets
484
+ - `~/.ai/mcp/servers.json` or `<repo>/.ai/mcp/servers.json`: tracked canonical MCP definitions
485
+ - `~/.ai/mcp/servers.local.json` or `<repo>/.ai/mcp/servers.local.json`: ignored machine-local MCP env overlay for secrets and per-machine auth
483
486
  - `~/.ai/tools/<tool>/config.toml` or `<repo>/.ai/tools/<tool>/config.toml`: tracked tool defaults
484
487
  - `~/.ai/tools/<tool>/config.local.toml` or `<repo>/.ai/tools/<tool>/config.local.toml`: ignored, machine-local tool overrides merged after tracked tool config during sync
485
488
  - `[builtin].sync_defaults = false`: disable builtin default sync/materialization for this root
486
489
  - `fclt sync --builtin-conflicts overwrite`: allow packaged builtin defaults to overwrite locally modified generated targets
490
+ - `fclt audit fix ...`: move inline MCP secrets from tracked canonical config into the local MCP overlay and re-sync managed tool configs
487
491
 
488
492
  ### Snippets
489
493
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "facult",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "Manage canonical AI capabilities, sync surfaces, and evolution state.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -9,6 +9,10 @@ import {
9
9
  sanitizeCodexTomlMcpText,
10
10
  } from "../util/codex-toml";
11
11
  import { parseJsonLenient } from "../util/json";
12
+ import {
13
+ applyAuditSuppressionsToAgentReport,
14
+ loadAuditSuppressions,
15
+ } from "./suppressions";
12
16
  import {
13
17
  type AuditFinding,
14
18
  type AuditItemResult,
@@ -926,27 +930,7 @@ export async function runAgentAudit(opts?: {
926
930
  });
927
931
  }
928
932
 
929
- // Summary
930
- const bySeverity: Record<Severity, number> = {
931
- low: 0,
932
- medium: 0,
933
- high: 0,
934
- critical: 0,
935
- };
936
- let totalFindings = 0;
937
- let flaggedItems = 0;
938
-
939
- for (const r of results) {
940
- totalFindings += r.findings.length;
941
- if (!r.passed && r.findings.length > 0) {
942
- flaggedItems += 1;
943
- }
944
- for (const f of r.findings) {
945
- bySeverity[f.severity] += 1;
946
- }
947
- }
948
-
949
- const report: AgentAuditReport = {
933
+ let report: AgentAuditReport = {
950
934
  timestamp: new Date().toISOString(),
951
935
  mode: "agent",
952
936
  agent: { tool, model },
@@ -972,12 +956,30 @@ export async function runAgentAudit(opts?: {
972
956
  }),
973
957
  summary: {
974
958
  totalItems: results.length,
975
- totalFindings,
976
- bySeverity,
977
- flaggedItems,
959
+ totalFindings: results.reduce(
960
+ (sum, result) => sum + result.findings.length,
961
+ 0
962
+ ),
963
+ bySeverity: results.reduce<Record<Severity, number>>(
964
+ (acc, result) => {
965
+ for (const finding of result.findings) {
966
+ acc[finding.severity] += 1;
967
+ }
968
+ return acc;
969
+ },
970
+ { low: 0, medium: 0, high: 0, critical: 0 }
971
+ ),
972
+ flaggedItems: results.filter(
973
+ (result) => !result.passed && result.findings.length > 0
974
+ ).length,
978
975
  },
979
976
  };
980
977
 
978
+ report = applyAuditSuppressionsToAgentReport(
979
+ report,
980
+ await loadAuditSuppressions(home)
981
+ );
982
+
981
983
  const auditDir = join(facultStateDir(home), "audit");
982
984
  await mkdir(auditDir, { recursive: true });
983
985
  await Bun.write(