facult 2.5.2 → 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,7 +444,9 @@ 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
449
+ - `tools/<tool>/config.local.toml`: machine-local tool config overlay
448
450
  - `tools/<tool>/rules/*.rules`: canonical tool rules
449
451
  - global docs such as `AGENTS.global.md` and `AGENTS.override.global.md`
450
452
 
@@ -479,8 +481,13 @@ Built-ins currently include:
479
481
  Recommended split:
480
482
  - `~/.ai/config.toml` or `<repo>/.ai/config.toml`: tracked, portable, non-secret refs/defaults
481
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
486
+ - `~/.ai/tools/<tool>/config.toml` or `<repo>/.ai/tools/<tool>/config.toml`: tracked tool defaults
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
482
488
  - `[builtin].sync_defaults = false`: disable builtin default sync/materialization for this root
483
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
484
491
 
485
492
  ### Snippets
486
493
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "facult",
3
- "version": "2.5.2",
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(