@codyswann/lisa 2.145.2 → 2.146.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.
Files changed (71) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa-agy/plugin.json +1 -1
  5. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  8. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  9. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  14. package/plugins/lisa-expo-agy/plugin.json +1 -1
  15. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  20. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  25. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  30. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-rails-agy/plugin.json +1 -1
  35. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  40. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-wiki/scripts/_wiki-lib.mjs +19 -0
  45. package/plugins/lisa-wiki/scripts/ingest-git.mjs +10 -9
  46. package/plugins/lisa-wiki/scripts/ingest-memory.mjs +14 -9
  47. package/plugins/lisa-wiki/scripts/ingest-roles.mjs +13 -3
  48. package/plugins/lisa-wiki/scripts/ingest_slack_channel.py +39 -7
  49. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  50. package/plugins/lisa-wiki-agy/scripts/_wiki-lib.mjs +19 -0
  51. package/plugins/lisa-wiki-agy/scripts/ingest-git.mjs +10 -9
  52. package/plugins/lisa-wiki-agy/scripts/ingest-memory.mjs +14 -9
  53. package/plugins/lisa-wiki-agy/scripts/ingest-roles.mjs +13 -3
  54. package/plugins/lisa-wiki-agy/scripts/ingest_slack_channel.py +39 -7
  55. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-wiki-copilot/scripts/_wiki-lib.mjs +19 -0
  57. package/plugins/lisa-wiki-copilot/scripts/ingest-git.mjs +10 -9
  58. package/plugins/lisa-wiki-copilot/scripts/ingest-memory.mjs +14 -9
  59. package/plugins/lisa-wiki-copilot/scripts/ingest-roles.mjs +13 -3
  60. package/plugins/lisa-wiki-copilot/scripts/ingest_slack_channel.py +39 -7
  61. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-wiki-cursor/scripts/_wiki-lib.mjs +19 -0
  63. package/plugins/lisa-wiki-cursor/scripts/ingest-git.mjs +10 -9
  64. package/plugins/lisa-wiki-cursor/scripts/ingest-memory.mjs +14 -9
  65. package/plugins/lisa-wiki-cursor/scripts/ingest-roles.mjs +13 -3
  66. package/plugins/lisa-wiki-cursor/scripts/ingest_slack_channel.py +39 -7
  67. package/plugins/src/wiki/scripts/_wiki-lib.mjs +19 -0
  68. package/plugins/src/wiki/scripts/ingest-git.mjs +10 -9
  69. package/plugins/src/wiki/scripts/ingest-memory.mjs +14 -9
  70. package/plugins/src/wiki/scripts/ingest-roles.mjs +13 -3
  71. package/plugins/src/wiki/scripts/ingest_slack_channel.py +39 -7
package/package.json CHANGED
@@ -84,7 +84,7 @@
84
84
  "lodash": ">=4.18.1"
85
85
  },
86
86
  "name": "@codyswann/lisa",
87
- "version": "2.145.2",
87
+ "version": "2.146.0",
88
88
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
89
89
  "main": "dist/index.js",
90
90
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.145.2",
3
+ "version": "2.146.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import fs from "node:fs";
7
7
  import path from "node:path";
8
+ import { sanitizeWikiSourceText } from "./wiki-safety.mjs";
8
9
 
9
10
  /** Read and parse a JSON file, or return undefined if missing/invalid. */
10
11
  export function readJsonSafe(file) {
@@ -59,6 +60,24 @@ export function walkFiles(dir, { ext } = {}) {
59
60
  return out.sort();
60
61
  }
61
62
 
63
+ /**
64
+ * Sanitize a wiki source note immediately before it is persisted.
65
+ *
66
+ * Connectors should keep fetched raw material in memory or temporary locations
67
+ * outside the repo, render the source note, then call this helper at the final
68
+ * `wiki/sources/**` write boundary. The return value contains safe finding
69
+ * metadata only; callers can include it in handoff metadata when useful.
70
+ */
71
+ export function writeSanitizedSourceNote(file, rawText, sourceMetadata = {}) {
72
+ const result = sanitizeWikiSourceText(rawText, {
73
+ ...sourceMetadata,
74
+ path: sourceMetadata.path ?? file,
75
+ });
76
+ fs.mkdirSync(path.dirname(file), { recursive: true });
77
+ fs.writeFileSync(file, result.text);
78
+ return result;
79
+ }
80
+
62
81
  /**
63
82
  * Minimal frontmatter detector. Returns whether a leading `--- ... ---` block
64
83
  * exists and the top-level keys it declares (enough to check required fields;
@@ -15,7 +15,7 @@
15
15
  import fs from "node:fs";
16
16
  import path from "node:path";
17
17
  import { execFileSync } from "node:child_process";
18
- import { readJsonSafe, SECRET_PATTERNS } from "./_wiki-lib.mjs";
18
+ import { readJsonSafe, writeSanitizedSourceNote } from "./_wiki-lib.mjs";
19
19
 
20
20
  const argv = process.argv.slice(2);
21
21
  const opt = (n, d) => {
@@ -53,12 +53,6 @@ const commitExists = c => {
53
53
  return false;
54
54
  }
55
55
  };
56
- const redact = t =>
57
- SECRET_PATTERNS.reduce(
58
- (acc, { re }) => acc.replace(new RegExp(re, "g"), "[REDACTED]"),
59
- t
60
- );
61
-
62
56
  if (
63
57
  !fs.existsSync(path.join(repo, ".git")) &&
64
58
  !tryGit(["rev-parse", "--is-inside-work-tree"])
@@ -165,8 +159,11 @@ ${
165
159
  }
166
160
  `;
167
161
 
168
- fs.mkdirSync(sourceDir, { recursive: true });
169
- fs.writeFileSync(notePath, redact(note));
162
+ const safety = writeSanitizedSourceNote(notePath, note, {
163
+ sourceId: path.relative(process.cwd(), notePath),
164
+ sourceSystem: "git",
165
+ project: slug,
166
+ });
170
167
 
171
168
  const meta = {
172
169
  connector: "git",
@@ -174,6 +171,10 @@ const meta = {
174
171
  ranAt: new Date().toISOString(),
175
172
  proposedCursor: { lastCommit: head, lastPr },
176
173
  sourceNotes: [path.relative(process.cwd(), notePath)],
174
+ safety: {
175
+ reviewRequired: safety.reviewRequired,
176
+ findings: safety.findings,
177
+ },
177
178
  };
178
179
  if (emitMeta) {
179
180
  fs.mkdirSync(path.dirname(emitMeta), { recursive: true });
@@ -15,7 +15,11 @@
15
15
  import fs from "node:fs";
16
16
  import path from "node:path";
17
17
  import os from "node:os";
18
- import { loadConfig, walkFiles, SECRET_PATTERNS } from "./_wiki-lib.mjs";
18
+ import {
19
+ loadConfig,
20
+ walkFiles,
21
+ writeSanitizedSourceNote,
22
+ } from "./_wiki-lib.mjs";
19
23
 
20
24
  const argv = process.argv.slice(2);
21
25
  const opt = (n, d) => {
@@ -79,15 +83,10 @@ if (!(under(claudeMem) || under(projectCodexMem) || allowedRoots.some(under))) {
79
83
  );
80
84
  }
81
85
 
82
- const redact = t =>
83
- SECRET_PATTERNS.reduce(
84
- (acc, { re }) => acc.replace(new RegExp(re, "g"), "[REDACTED]"),
85
- t
86
- );
87
86
  const mdFiles = walkFiles(resolvedMem, { ext: ".md" });
88
87
  const date = new Date().toISOString().slice(0, 10);
89
88
  const entries = mdFiles.map(f => {
90
- const body = redact(fs.readFileSync(f, "utf8")).trim();
89
+ const body = fs.readFileSync(f, "utf8").trim();
91
90
  return `### ${path.basename(f)}\n\n${body}`;
92
91
  });
93
92
 
@@ -110,8 +109,10 @@ sensitivity: internal
110
109
  ${entries.join("\n\n") || "_(no memory files)_"}
111
110
  `;
112
111
 
113
- fs.mkdirSync(sourceDir, { recursive: true });
114
- fs.writeFileSync(notePath, note);
112
+ const safety = writeSanitizedSourceNote(notePath, note, {
113
+ sourceId: path.relative(process.cwd(), notePath),
114
+ sourceSystem: "memory",
115
+ });
115
116
 
116
117
  const meta = {
117
118
  connector: "memory",
@@ -119,6 +120,10 @@ const meta = {
119
120
  ranAt: new Date().toISOString(),
120
121
  proposedCursor: { files: mdFiles.length, lastIngest: date },
121
122
  sourceNotes: [path.relative(process.cwd(), notePath)],
123
+ safety: {
124
+ reviewRequired: safety.reviewRequired,
125
+ findings: safety.findings,
126
+ },
122
127
  };
123
128
  if (emitMeta) {
124
129
  fs.mkdirSync(path.dirname(emitMeta), { recursive: true });
@@ -10,7 +10,11 @@
10
10
  */
11
11
  import fs from "node:fs";
12
12
  import path from "node:path";
13
- import { loadConfig, walkFiles } from "./_wiki-lib.mjs";
13
+ import {
14
+ loadConfig,
15
+ walkFiles,
16
+ writeSanitizedSourceNote,
17
+ } from "./_wiki-lib.mjs";
14
18
 
15
19
  const argv = process.argv.slice(2);
16
20
  const opt = (n, d) => {
@@ -61,8 +65,10 @@ ${rosterRows}
61
65
  ${staffPages.length ? staffPages.map(p => `- \`${path.relative(wikiRoot, p)}\``).join("\n") : "_(none)_"}
62
66
  `;
63
67
 
64
- fs.mkdirSync(sourceDir, { recursive: true });
65
- fs.writeFileSync(notePath, note);
68
+ const safety = writeSanitizedSourceNote(notePath, note, {
69
+ sourceId: path.relative(process.cwd(), notePath),
70
+ sourceSystem: "roles",
71
+ });
66
72
 
67
73
  const meta = {
68
74
  connector: "roles",
@@ -74,6 +80,10 @@ const meta = {
74
80
  lastIngest: date,
75
81
  },
76
82
  sourceNotes: [path.relative(process.cwd(), notePath)],
83
+ safety: {
84
+ reviewRequired: safety.reviewRequired,
85
+ findings: safety.findings,
86
+ },
77
87
  };
78
88
  if (emitMeta) {
79
89
  fs.mkdirSync(path.dirname(emitMeta), { recursive: true });
@@ -22,10 +22,37 @@ from typing import Any
22
22
 
23
23
 
24
24
  TOKEN_PATTERNS = [
25
- re.compile(r"xox[pbar]-[A-Za-z0-9-]+"),
26
- re.compile(r"(?i)bearer\s+[A-Za-z0-9._~+/=-]{20,}"),
27
- re.compile(r"AKIA[0-9A-Z]{16}"),
28
- re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----.*?-----END [A-Z ]*PRIVATE KEY-----", re.S),
25
+ (re.compile(r"xox[pbar]-[A-Za-z0-9-]+"), "[REDACTED:OAUTH_TOKEN]"),
26
+ (
27
+ re.compile(r"(?i)bearer\s+[A-Za-z0-9._~+/=-]{20,}"),
28
+ "[REDACTED:OAUTH_TOKEN]",
29
+ ),
30
+ (re.compile(r"AKIA[0-9A-Z]{16}"), "[REDACTED:API_KEY]"),
31
+ (
32
+ re.compile(
33
+ r"-----BEGIN [A-Z ]*PRIVATE KEY-----.*?-----END [A-Z ]*PRIVATE KEY-----",
34
+ re.S,
35
+ ),
36
+ "[REDACTED:PRIVATE_KEY]",
37
+ ),
38
+ (
39
+ re.compile(r"\b(?!000|666|9\d\d)\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b"),
40
+ "[REDACTED:SSN]",
41
+ ),
42
+ (
43
+ re.compile(
44
+ r"\b(?:password|passwd|pwd)\s*[:=]\s*(['\"]?)([^\s'\",;]{8,})\1",
45
+ re.I,
46
+ ),
47
+ "[REDACTED:PASSWORD]",
48
+ ),
49
+ (
50
+ re.compile(
51
+ r"\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|client[_-]?secret)\s*[:=]\s*(['\"]?)([A-Za-z0-9._-]{20,})\1",
52
+ re.I,
53
+ ),
54
+ "[REDACTED:API_KEY]",
55
+ ),
29
56
  ]
30
57
 
31
58
 
@@ -49,8 +76,13 @@ def ts_from_input(value: str | None) -> str | None:
49
76
 
50
77
  def redact(text: str) -> str:
51
78
  out = text
52
- for pattern in TOKEN_PATTERNS:
53
- out = pattern.sub("[REDACTED]", out)
79
+ for pattern, replacement in TOKEN_PATTERNS:
80
+ out = pattern.sub(
81
+ lambda match: match.group(0).replace(match.group(2), replacement)
82
+ if len(match.groups()) >= 2
83
+ else replacement,
84
+ out,
85
+ )
54
86
  return out
55
87
 
56
88
 
@@ -289,7 +321,7 @@ def main() -> int:
289
321
  for reply in replies:
290
322
  lines.extend(render_message(reply))
291
323
 
292
- source_path.write_text("\n".join(lines), encoding="utf-8")
324
+ source_path.write_text(redact("\n".join(lines)), encoding="utf-8")
293
325
 
294
326
  latest_ts = previous_state.get("latest_message_ts")
295
327
  if messages: