@soleri/forge 5.1.2 → 5.1.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.
@@ -27,7 +27,7 @@ export function generateActivate(config) {
27
27
  "import { join } from 'node:path';",
28
28
  "import { homedir } from 'node:os';",
29
29
  "import { PERSONA } from '../identity/persona.js';",
30
- "import { hasAgentMarker } from './inject-claude-md.js';",
30
+ "import { hasAgentMarker, removeClaudeMdGlobal } from './inject-claude-md.js';",
31
31
  "import type { Vault, Planner, Plan } from '@soleri/core';",
32
32
  '',
33
33
  'export interface ActivationResult {',
@@ -54,6 +54,9 @@ export function generateActivate(config) {
54
54
  'export interface DeactivationResult {',
55
55
  ' deactivated: boolean;',
56
56
  ' message: string;',
57
+ ' cleanup?: {',
58
+ ' globalClaudeMd: boolean;',
59
+ ' };',
57
60
  '}',
58
61
  '',
59
62
  '/**',
@@ -126,12 +129,17 @@ export function generateActivate(config) {
126
129
  '}',
127
130
  '',
128
131
  '/**',
129
- ` * Deactivate ${config.name} — drops persona for the session.`,
132
+ ` * Deactivate ${config.name} — drops persona and cleans up CLAUDE.md sections.`,
130
133
  ' */',
131
134
  'export function deactivateAgent(): DeactivationResult {',
135
+ ' // Remove agent sections from global CLAUDE.md on deactivation',
136
+ ' const globalResult = removeClaudeMdGlobal();',
132
137
  ' return {',
133
138
  ' deactivated: true,',
134
139
  ` message: 'Goodbye! ' + PERSONA.name + ' persona deactivated. Reverting to default behavior.',`,
140
+ ' cleanup: {',
141
+ ' globalClaudeMd: globalResult.removed,',
142
+ ' },',
135
143
  ' };',
136
144
  '}',
137
145
  ].join('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"activate.js","sourceRoot":"","sources":["../../src/templates/activate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"activate.js","sourceRoot":"","sources":["../../src/templates/activate.ts"],"names":[],"mappings":"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"}
@@ -80,6 +80,42 @@ export function generateInjectClaudeMd(config) {
80
80
  '}',
81
81
  '',
82
82
  '/**',
83
+ ' * Remove agent section from a specific CLAUDE.md file.',
84
+ ' * Returns true if the section was found and removed.',
85
+ ' */',
86
+ 'function removeFromFile(filePath: string): { removed: boolean; path: string } {',
87
+ ' if (!existsSync(filePath)) return { removed: false, path: filePath };',
88
+ " const existing = readFileSync(filePath, 'utf-8');",
89
+ ' const marker = getClaudeMdMarker();',
90
+ ` const startMarker = '<!-- ' + marker + ' -->';`,
91
+ ` const endMarker = '<!-- /' + marker + ' -->';`,
92
+ ' const startIdx = existing.indexOf(startMarker);',
93
+ ' if (startIdx === -1) return { removed: false, path: filePath };',
94
+ ' const endIdx = existing.indexOf(endMarker);',
95
+ ' if (endIdx === -1) return { removed: false, path: filePath };',
96
+ " const before = existing.slice(0, startIdx).replace(/\\n+$/, '');",
97
+ " const after = existing.slice(endIdx + endMarker.length).replace(/^\\n+/, '');",
98
+ " const cleaned = before + (before && after ? '\\n\\n' : '') + after;",
99
+ " writeFileSync(filePath, cleaned || '', 'utf-8');",
100
+ ' return { removed: true, path: filePath };',
101
+ '}',
102
+ '',
103
+ '/**',
104
+ ' * Remove agent section from the global ~/.claude/CLAUDE.md.',
105
+ ' * Called on deactivation to clean up after test agents.',
106
+ ' */',
107
+ 'export function removeClaudeMdGlobal(): { removed: boolean; path: string } {',
108
+ " return removeFromFile(join(homedir(), '.claude', 'CLAUDE.md'));",
109
+ '}',
110
+ '',
111
+ '/**',
112
+ ' * Remove agent section from a project CLAUDE.md.',
113
+ ' */',
114
+ 'export function removeClaudeMd(projectPath: string): { removed: boolean; path: string } {',
115
+ " return removeFromFile(join(projectPath, 'CLAUDE.md'));",
116
+ '}',
117
+ '',
118
+ '/**',
83
119
  ' * Check if the agent marker exists in a CLAUDE.md file.',
84
120
  ' */',
85
121
  'export function hasAgentMarker(filePath: string): boolean {',
@@ -1 +1 @@
1
- {"version":3,"file":"inject-claude-md.js","sourceRoot":"","sources":["../../src/templates/inject-claude-md.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAmB;IACxD,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,OAAO,CAAC;IAEnC,OAAO;QACL,+EAA+E;QAC/E,oCAAoC;QACpC,mCAAmC;QACnC,iFAAiF;QACjF,EAAE;QACF,iCAAiC;QACjC,sBAAsB;QACtB,iBAAiB;QACjB,+CAA+C;QAC/C,GAAG;QACH,EAAE;QACF,KAAK;QACL,gDAAgD;QAChD,8DAA8D;QAC9D,KAAK;QACL,2DAA2D;QAC3D,yCAAyC;QACzC,uCAAuC;QACvC,kDAAkD;QAClD,iDAAiD;QACjD,EAAE;QACF,gCAAgC;QAChC,wDAAwD;QACxD,mEAAmE;QACnE,KAAK;QACL,EAAE;QACF,qDAAqD;QACrD,EAAE;QACF,yCAAyC;QACzC,qDAAqD;QACrD,iDAAiD;QACjD,0BAA0B;QAC1B,sHAAsH;QACtH,kDAAkD;QAClD,qEAAqE;QACrE,OAAO;QACP,wGAAwG;QACxG,gDAAgD;QAChD,mEAAmE;QACnE,KAAK;QACL,EAAE;QACF,kEAAkE;QAClE,6EAA6E;QAC7E,kEAAkE;QAClE,GAAG;QACH,EAAE;QACF,KAAK;QACL,mDAAmD;QACnD,0CAA0C;QAC1C,+DAA+D;QAC/D,4CAA4C;QAC5C,KAAK;QACL,qEAAqE;QACrE,0DAA0D;QAC1D,GAAG;QACH,EAAE;QACF,KAAK;QACL,wEAAwE;QACxE,sDAAsD;QACtD,0DAA0D;QAC1D,KAAK;QACL,wDAAwD;QACxD,iDAAiD;QACjD,iCAAiC;QACjC,gDAAgD;QAChD,KAAK;QACL,wDAAwD;QACxD,GAAG;QACH,EAAE;QACF,KAAK;QACL,0DAA0D;QAC1D,KAAK;QACL,6DAA6D;QAC7D,4CAA4C;QAC5C,oDAAoD;QACpD,mCAAmC,MAAM,SAAS;QAClD,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"inject-claude-md.js","sourceRoot":"","sources":["../../src/templates/inject-claude-md.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAmB;IACxD,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,OAAO,CAAC;IAEnC,OAAO;QACL,+EAA+E;QAC/E,oCAAoC;QACpC,mCAAmC;QACnC,iFAAiF;QACjF,EAAE;QACF,iCAAiC;QACjC,sBAAsB;QACtB,iBAAiB;QACjB,+CAA+C;QAC/C,GAAG;QACH,EAAE;QACF,KAAK;QACL,gDAAgD;QAChD,8DAA8D;QAC9D,KAAK;QACL,2DAA2D;QAC3D,yCAAyC;QACzC,uCAAuC;QACvC,kDAAkD;QAClD,iDAAiD;QACjD,EAAE;QACF,gCAAgC;QAChC,wDAAwD;QACxD,mEAAmE;QACnE,KAAK;QACL,EAAE;QACF,qDAAqD;QACrD,EAAE;QACF,yCAAyC;QACzC,qDAAqD;QACrD,iDAAiD;QACjD,0BAA0B;QAC1B,sHAAsH;QACtH,kDAAkD;QAClD,qEAAqE;QACrE,OAAO;QACP,wGAAwG;QACxG,gDAAgD;QAChD,mEAAmE;QACnE,KAAK;QACL,EAAE;QACF,kEAAkE;QAClE,6EAA6E;QAC7E,kEAAkE;QAClE,GAAG;QACH,EAAE;QACF,KAAK;QACL,mDAAmD;QACnD,0CAA0C;QAC1C,+DAA+D;QAC/D,4CAA4C;QAC5C,KAAK;QACL,qEAAqE;QACrE,0DAA0D;QAC1D,GAAG;QACH,EAAE;QACF,KAAK;QACL,wEAAwE;QACxE,sDAAsD;QACtD,0DAA0D;QAC1D,KAAK;QACL,wDAAwD;QACxD,iDAAiD;QACjD,iCAAiC;QACjC,gDAAgD;QAChD,KAAK;QACL,wDAAwD;QACxD,GAAG;QACH,EAAE;QACF,KAAK;QACL,yDAAyD;QACzD,uDAAuD;QACvD,KAAK;QACL,iFAAiF;QACjF,yEAAyE;QACzE,qDAAqD;QACrD,uCAAuC;QACvC,kDAAkD;QAClD,iDAAiD;QACjD,mDAAmD;QACnD,mEAAmE;QACnE,+CAA+C;QAC/C,iEAAiE;QACjE,oEAAoE;QACpE,iFAAiF;QACjF,uEAAuE;QACvE,oDAAoD;QACpD,6CAA6C;QAC7C,GAAG;QACH,EAAE;QACF,KAAK;QACL,8DAA8D;QAC9D,0DAA0D;QAC1D,KAAK;QACL,8EAA8E;QAC9E,mEAAmE;QACnE,GAAG;QACH,EAAE;QACF,KAAK;QACL,mDAAmD;QACnD,KAAK;QACL,2FAA2F;QAC3F,0DAA0D;QAC1D,GAAG;QACH,EAAE;QACF,KAAK;QACL,0DAA0D;QAC1D,KAAK;QACL,6DAA6D;QAC7D,4CAA4C;QAC5C,oDAAoD;QACpD,mCAAmC,MAAM,SAAS;QAClD,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soleri/forge",
3
- "version": "5.1.2",
3
+ "version": "5.1.3",
4
4
  "description": "Scaffold AI agents that learn, remember, and grow with you.",
5
5
  "keywords": [
6
6
  "agent",
@@ -34,7 +34,7 @@ export function generateActivate(config: AgentConfig): string {
34
34
  "import { join } from 'node:path';",
35
35
  "import { homedir } from 'node:os';",
36
36
  "import { PERSONA } from '../identity/persona.js';",
37
- "import { hasAgentMarker } from './inject-claude-md.js';",
37
+ "import { hasAgentMarker, removeClaudeMdGlobal } from './inject-claude-md.js';",
38
38
  "import type { Vault, Planner, Plan } from '@soleri/core';",
39
39
  '',
40
40
  'export interface ActivationResult {',
@@ -61,6 +61,9 @@ export function generateActivate(config: AgentConfig): string {
61
61
  'export interface DeactivationResult {',
62
62
  ' deactivated: boolean;',
63
63
  ' message: string;',
64
+ ' cleanup?: {',
65
+ ' globalClaudeMd: boolean;',
66
+ ' };',
64
67
  '}',
65
68
  '',
66
69
  '/**',
@@ -133,12 +136,17 @@ export function generateActivate(config: AgentConfig): string {
133
136
  '}',
134
137
  '',
135
138
  '/**',
136
- ` * Deactivate ${config.name} — drops persona for the session.`,
139
+ ` * Deactivate ${config.name} — drops persona and cleans up CLAUDE.md sections.`,
137
140
  ' */',
138
141
  'export function deactivateAgent(): DeactivationResult {',
142
+ ' // Remove agent sections from global CLAUDE.md on deactivation',
143
+ ' const globalResult = removeClaudeMdGlobal();',
139
144
  ' return {',
140
145
  ' deactivated: true,',
141
146
  ` message: 'Goodbye! ' + PERSONA.name + ' persona deactivated. Reverting to default behavior.',`,
147
+ ' cleanup: {',
148
+ ' globalClaudeMd: globalResult.removed,',
149
+ ' },',
142
150
  ' };',
143
151
  '}',
144
152
  ].join('\n');
@@ -83,6 +83,42 @@ export function generateInjectClaudeMd(config: AgentConfig): string {
83
83
  '}',
84
84
  '',
85
85
  '/**',
86
+ ' * Remove agent section from a specific CLAUDE.md file.',
87
+ ' * Returns true if the section was found and removed.',
88
+ ' */',
89
+ 'function removeFromFile(filePath: string): { removed: boolean; path: string } {',
90
+ ' if (!existsSync(filePath)) return { removed: false, path: filePath };',
91
+ " const existing = readFileSync(filePath, 'utf-8');",
92
+ ' const marker = getClaudeMdMarker();',
93
+ ` const startMarker = '<!-- ' + marker + ' -->';`,
94
+ ` const endMarker = '<!-- /' + marker + ' -->';`,
95
+ ' const startIdx = existing.indexOf(startMarker);',
96
+ ' if (startIdx === -1) return { removed: false, path: filePath };',
97
+ ' const endIdx = existing.indexOf(endMarker);',
98
+ ' if (endIdx === -1) return { removed: false, path: filePath };',
99
+ " const before = existing.slice(0, startIdx).replace(/\\n+$/, '');",
100
+ " const after = existing.slice(endIdx + endMarker.length).replace(/^\\n+/, '');",
101
+ " const cleaned = before + (before && after ? '\\n\\n' : '') + after;",
102
+ " writeFileSync(filePath, cleaned || '', 'utf-8');",
103
+ ' return { removed: true, path: filePath };',
104
+ '}',
105
+ '',
106
+ '/**',
107
+ ' * Remove agent section from the global ~/.claude/CLAUDE.md.',
108
+ ' * Called on deactivation to clean up after test agents.',
109
+ ' */',
110
+ 'export function removeClaudeMdGlobal(): { removed: boolean; path: string } {',
111
+ " return removeFromFile(join(homedir(), '.claude', 'CLAUDE.md'));",
112
+ '}',
113
+ '',
114
+ '/**',
115
+ ' * Remove agent section from a project CLAUDE.md.',
116
+ ' */',
117
+ 'export function removeClaudeMd(projectPath: string): { removed: boolean; path: string } {',
118
+ " return removeFromFile(join(projectPath, 'CLAUDE.md'));",
119
+ '}',
120
+ '',
121
+ '/**',
86
122
  ' * Check if the agent marker exists in a CLAUDE.md file.',
87
123
  ' */',
88
124
  'export function hasAgentMarker(filePath: string): boolean {',