claude-autopm 1.18.0 → 1.20.1
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 +159 -0
- package/autopm/.claude/agents/README.md +1 -1
- package/autopm/.claude/agents/core/mcp-manager.md +1 -1
- package/autopm/.claude/agents/decision-matrices/python-backend-selection.md +25 -25
- package/autopm/.claude/agents/decision-matrices/ui-framework-selection.md +43 -43
- package/autopm/.claude/agents/devops/github-operations-specialist.md +1 -1
- package/autopm/.claude/agents/frameworks/README.md +5 -5
- package/autopm/.claude/agents/frameworks/e2e-test-engineer.md +1 -1
- package/autopm/.claude/agents/frameworks/nats-messaging-expert.md +1 -1
- package/autopm/.claude/agents/frameworks/react-frontend-engineer.md +1 -1
- package/autopm/.claude/agents/frameworks/react-ui-expert.md +3 -3
- package/autopm/.claude/agents/frameworks/tailwindcss-expert.md +3 -3
- package/autopm/.claude/agents/frameworks/ux-design-expert.md +3 -3
- package/autopm/.claude/commands/infrastructure/traefik-setup.md +1 -1
- package/autopm/.claude/commands/playwright/test-scaffold.md +1 -1
- package/autopm/.claude/commands/pm/context.md +11 -0
- package/autopm/.claude/commands/pm/epic-decompose.md +25 -2
- package/autopm/.claude/commands/pm/epic-oneshot.md +13 -0
- package/autopm/.claude/commands/pm/epic-start.md +19 -0
- package/autopm/.claude/commands/pm/epic-sync-modular.md +10 -10
- package/autopm/.claude/commands/pm/epic-sync.md +14 -14
- package/autopm/.claude/commands/pm/issue-start.md +50 -5
- package/autopm/.claude/commands/pm/issue-sync.md +15 -15
- package/autopm/.claude/commands/pm/what-next.md +11 -0
- package/autopm/.claude/commands/ui/bootstrap-scaffold.md +6 -5
- package/autopm/.claude/commands/ui/tailwind-system.md +1 -1
- package/autopm/.claude/examples/mcp/playwright-mcp.md +2 -2
- package/autopm/.claude/examples/mcp-servers.example.json +2 -2
- package/autopm/.claude/hooks/docker-first-enforcement.sh +1 -1
- package/autopm/.claude/mcp/MCP-REGISTRY.md +1 -1
- package/autopm/.claude/mcp/playwright-mcp.md +2 -2
- package/autopm/.claude/rules/agent-coordination.md +26 -24
- package/autopm/.claude/rules/docker-first-development.md +1 -1
- package/autopm/.claude/rules/infrastructure-pipeline.md +1 -1
- package/autopm/.claude/rules/ui-development-standards.md +1 -1
- package/autopm/.claude/rules/visual-testing.md +3 -3
- package/autopm/.claude/scripts/azure/active-work.js +2 -2
- package/autopm/.claude/scripts/azure/blocked.js +13 -13
- package/autopm/.claude/scripts/azure/daily.js +1 -1
- package/autopm/.claude/scripts/azure/dashboard.js +1 -1
- package/autopm/.claude/scripts/azure/feature-list.js +2 -2
- package/autopm/.claude/scripts/azure/feature-status.js +1 -1
- package/autopm/.claude/scripts/azure/next-task.js +1 -1
- package/autopm/.claude/scripts/azure/search.js +1 -1
- package/autopm/.claude/scripts/azure/setup.js +15 -15
- package/autopm/.claude/scripts/azure/sprint-report.js +2 -2
- package/autopm/.claude/scripts/azure/sync.js +1 -1
- package/autopm/.claude/scripts/azure/us-list.js +1 -1
- package/autopm/.claude/scripts/azure/us-status.js +1 -1
- package/autopm/.claude/scripts/azure/validate.js +13 -13
- package/autopm/.claude/scripts/lib/frontmatter-utils.sh +42 -7
- package/autopm/.claude/scripts/lib/logging-utils.sh +20 -16
- package/autopm/.claude/scripts/lib/validation-utils.sh +1 -1
- package/autopm/.claude/scripts/pm/context.js +338 -0
- package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +3 -3
- package/autopm/.claude/scripts/pm/lib/README.md +85 -0
- package/autopm/.claude/scripts/pm/lib/logger.js +78 -0
- package/autopm/.claude/scripts/pm/next.js +25 -1
- package/autopm/.claude/scripts/pm/what-next.js +660 -0
- package/autopm/.claude/teams.json +3 -5
- package/autopm/.claude/templates/claude-templates/addons/devops-agents.md +2 -2
- package/autopm/.claude/templates/claude-templates/addons/docker-agents.md +4 -4
- package/autopm/.claude/templates/claude-templates/addons/minimal-agents.md +1 -1
- package/autopm/.claude/templates/issue-decomposition/api.yaml +2 -2
- package/autopm/.claude/templates/issue-decomposition/auth.yaml +4 -4
- package/autopm/.claude/templates/issue-decomposition/crud.yaml +3 -3
- package/autopm/.claude/templates/issue-decomposition/default.yaml +1 -1
- package/autopm/.claude/templates/issue-decomposition/ui-feature.yaml +2 -2
- package/bin/autopm.js +25 -0
- package/package.json +1 -2
- package/lib/agentExecutor.js.deprecated +0 -101
- package/lib/azure/cache.js +0 -80
- package/lib/azure/client.js +0 -77
- package/lib/azure/formatter.js +0 -177
- package/lib/commandHelpers.js +0 -177
- package/lib/context/manager.js +0 -290
- package/lib/documentation/manager.js +0 -528
- package/lib/github/workflow-manager.js +0 -546
- package/lib/helpers/azure-batch-api.js +0 -133
- package/lib/helpers/azure-cache-manager.js +0 -287
- package/lib/helpers/azure-parallel-processor.js +0 -158
- package/lib/helpers/azure-work-item-create.js +0 -278
- package/lib/helpers/gh-issue-create.js +0 -250
- package/lib/helpers/interactive-prompt.js +0 -336
- package/lib/helpers/output-manager.js +0 -335
- package/lib/helpers/progress-indicator.js +0 -258
- package/lib/performance/benchmarker.js +0 -429
- package/lib/pm/epic-decomposer.js +0 -273
- package/lib/pm/epic-syncer.js +0 -221
- package/lib/prdMetadata.js +0 -270
- package/lib/providers/azure/index.js +0 -234
- package/lib/providers/factory.js +0 -87
- package/lib/providers/github/index.js +0 -204
- package/lib/providers/interface.js +0 -73
- package/lib/python/scaffold-manager.js +0 -576
- package/lib/react/scaffold-manager.js +0 -745
- package/lib/regression/analyzer.js +0 -578
- package/lib/release/manager.js +0 -324
- package/lib/tailwind/manager.js +0 -486
- package/lib/traefik/manager.js +0 -484
- package/lib/utils/colors.js +0 -126
- package/lib/utils/config.js +0 -317
- package/lib/utils/filesystem.js +0 -316
- package/lib/utils/logger.js +0 -135
- package/lib/utils/prompts.js +0 -294
- package/lib/utils/shell.js +0 -237
- package/lib/validators/email-validator.js +0 -337
- package/lib/workflow/manager.js +0 -449
package/lib/commandHelpers.js
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Command Helpers Module
|
|
3
|
-
* Common utilities for CLI commands
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const colors = require('./utils/colors');
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Validate kebab-case format
|
|
12
|
-
* @param {string} name - The name to validate
|
|
13
|
-
* @returns {boolean} True if valid kebab-case
|
|
14
|
-
*/
|
|
15
|
-
function isValidKebabCase(name) {
|
|
16
|
-
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Validate command input
|
|
21
|
-
* @param {string} input - The input to validate
|
|
22
|
-
* @param {string} type - The type of input (e.g., 'story-name', 'task-name')
|
|
23
|
-
* @returns {Object} Validation result
|
|
24
|
-
*/
|
|
25
|
-
function validateInput(input, type = 'name') {
|
|
26
|
-
if (!input) {
|
|
27
|
-
return {
|
|
28
|
-
valid: false,
|
|
29
|
-
message: `❌ ${type} is required`
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!isValidKebabCase(input)) {
|
|
34
|
-
return {
|
|
35
|
-
valid: false,
|
|
36
|
-
message: `❌ ${type} must be kebab-case (lowercase letters, numbers, hyphens only). Examples: user-auth, payment-v2, notification-system`
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return { valid: true };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Load environment variables from .claude/.env
|
|
45
|
-
*/
|
|
46
|
-
function loadEnvironment() {
|
|
47
|
-
const envPath = path.join(process.cwd(), '.claude', '.env');
|
|
48
|
-
|
|
49
|
-
if (fs.existsSync(envPath)) {
|
|
50
|
-
require('dotenv').config({ path: envPath });
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Check if a command should be run in verbose mode
|
|
59
|
-
* @param {Object} argv - Command arguments
|
|
60
|
-
* @returns {boolean} True if verbose mode
|
|
61
|
-
*/
|
|
62
|
-
function isVerbose(argv) {
|
|
63
|
-
return argv.verbose || process.env.VERBOSE === 'true';
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Check if a command should be run in debug mode
|
|
68
|
-
* @param {Object} argv - Command arguments
|
|
69
|
-
* @returns {boolean} True if debug mode
|
|
70
|
-
*/
|
|
71
|
-
function isDebug(argv) {
|
|
72
|
-
return argv.debug || process.env.DEBUG === 'true';
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Print a formatted error message
|
|
77
|
-
* @param {string} message - The error message
|
|
78
|
-
* @param {Error} error - Optional error object
|
|
79
|
-
*/
|
|
80
|
-
function printError(message, error = null) {
|
|
81
|
-
console.error(colors.red(`❌ ${message}`));
|
|
82
|
-
if (error && isDebug()) {
|
|
83
|
-
console.error(colors.gray(error.stack));
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Print a formatted success message
|
|
89
|
-
* @param {string} message - The success message
|
|
90
|
-
*/
|
|
91
|
-
function printSuccess(message) {
|
|
92
|
-
console.log(colors.green(`✅ ${message}`));
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Print a formatted info message
|
|
97
|
-
* @param {string} message - The info message
|
|
98
|
-
*/
|
|
99
|
-
function printInfo(message) {
|
|
100
|
-
console.log(colors.blue(`ℹ️ ${message}`));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Print a formatted warning message
|
|
105
|
-
* @param {string} message - The warning message
|
|
106
|
-
*/
|
|
107
|
-
function printWarning(message) {
|
|
108
|
-
console.warn(colors.yellow(`⚠️ ${message}`));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Print a formatted step message
|
|
113
|
-
* @param {string} message - The step message
|
|
114
|
-
* @param {number} current - Current step number
|
|
115
|
-
* @param {number} total - Total number of steps
|
|
116
|
-
*/
|
|
117
|
-
function printStep(message, current, total) {
|
|
118
|
-
console.log(colors.cyan(`[${current}/${total}] ${message}`));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Create a progress spinner
|
|
123
|
-
* @param {string} text - The spinner text
|
|
124
|
-
* @returns {Object} Spinner instance
|
|
125
|
-
*/
|
|
126
|
-
function createSpinner(text) {
|
|
127
|
-
const ora = require('ora');
|
|
128
|
-
return ora({
|
|
129
|
-
text: text,
|
|
130
|
-
spinner: 'dots'
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Format a table for console output
|
|
136
|
-
* @param {Array<Array>} data - Table data
|
|
137
|
-
* @param {Object} options - Table options
|
|
138
|
-
* @returns {string} Formatted table
|
|
139
|
-
*/
|
|
140
|
-
function formatTable(data, options = {}) {
|
|
141
|
-
const Table = require('table');
|
|
142
|
-
return Table.table(data, options);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Confirm an action with the user
|
|
147
|
-
* @param {string} message - Confirmation message
|
|
148
|
-
* @returns {Promise<boolean>} User's confirmation
|
|
149
|
-
*/
|
|
150
|
-
async function confirm(message) {
|
|
151
|
-
const inquirer = require('inquirer');
|
|
152
|
-
const { confirmed } = await inquirer.prompt([
|
|
153
|
-
{
|
|
154
|
-
type: 'confirm',
|
|
155
|
-
name: 'confirmed',
|
|
156
|
-
message: message,
|
|
157
|
-
default: false
|
|
158
|
-
}
|
|
159
|
-
]);
|
|
160
|
-
return confirmed;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
module.exports = {
|
|
164
|
-
isValidKebabCase,
|
|
165
|
-
validateInput,
|
|
166
|
-
loadEnvironment,
|
|
167
|
-
isVerbose,
|
|
168
|
-
isDebug,
|
|
169
|
-
printError,
|
|
170
|
-
printSuccess,
|
|
171
|
-
printInfo,
|
|
172
|
-
printWarning,
|
|
173
|
-
printStep,
|
|
174
|
-
createSpinner,
|
|
175
|
-
formatTable,
|
|
176
|
-
confirm
|
|
177
|
-
};
|
package/lib/context/manager.js
DELETED
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Manager
|
|
3
|
-
* Provides utilities for managing context files
|
|
4
|
-
* TDD Phase: REFACTOR - Extracting common functionality
|
|
5
|
-
* Task: 1.1
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const fs = require('fs').promises;
|
|
9
|
-
const path = require('path');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Validates context name
|
|
13
|
-
* @param {string} name - Context name to validate
|
|
14
|
-
* @returns {boolean} - True if valid
|
|
15
|
-
*/
|
|
16
|
-
function validateContextName(name) {
|
|
17
|
-
// Only alphanumeric, hyphens, and underscores allowed
|
|
18
|
-
const pattern = /^[a-zA-Z0-9_-]+$/;
|
|
19
|
-
return pattern.test(name);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Loads template file
|
|
24
|
-
* @param {string} templateName - Template name (without extension)
|
|
25
|
-
* @param {string} projectRoot - Project root directory
|
|
26
|
-
* @returns {Promise<string|null>} - Template content or null if not found
|
|
27
|
-
*/
|
|
28
|
-
async function loadTemplate(templateName, projectRoot) {
|
|
29
|
-
const templatePath = path.join(projectRoot, '.claude', 'templates', `context-${templateName}.md`);
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const content = await fs.readFile(templatePath, 'utf8');
|
|
33
|
-
return content;
|
|
34
|
-
} catch (error) {
|
|
35
|
-
if (error.code === 'ENOENT') {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
throw error;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Replaces template variables
|
|
44
|
-
* @param {string} template - Template content
|
|
45
|
-
* @param {object} variables - Variables to replace
|
|
46
|
-
* @returns {string} - Processed template
|
|
47
|
-
*/
|
|
48
|
-
function processTemplate(template, variables) {
|
|
49
|
-
let processed = template;
|
|
50
|
-
|
|
51
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
52
|
-
const pattern = new RegExp(`{{${key}}}`, 'g');
|
|
53
|
-
processed = processed.replace(pattern, value);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return processed;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Gets the context directory path
|
|
61
|
-
* @param {string} projectRoot - Project root directory
|
|
62
|
-
* @returns {string} - Context directory path
|
|
63
|
-
*/
|
|
64
|
-
function getContextDir(projectRoot) {
|
|
65
|
-
return path.join(projectRoot, '.claude', 'contexts');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Gets the context file path
|
|
70
|
-
* @param {string} projectRoot - Project root directory
|
|
71
|
-
* @param {string} name - Context name
|
|
72
|
-
* @returns {string} - Context file path
|
|
73
|
-
*/
|
|
74
|
-
function getContextPath(projectRoot, name) {
|
|
75
|
-
return path.join(getContextDir(projectRoot), `${name}.md`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Checks if context exists
|
|
80
|
-
* @param {string} projectRoot - Project root directory
|
|
81
|
-
* @param {string} name - Context name
|
|
82
|
-
* @returns {Promise<boolean>} - True if exists
|
|
83
|
-
*/
|
|
84
|
-
async function contextExists(projectRoot, name) {
|
|
85
|
-
const contextPath = getContextPath(projectRoot, name);
|
|
86
|
-
try {
|
|
87
|
-
await fs.access(contextPath);
|
|
88
|
-
return true;
|
|
89
|
-
} catch (error) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Lists all contexts
|
|
96
|
-
* @param {string} projectRoot - Project root directory
|
|
97
|
-
* @returns {Promise<string[]>} - Array of context names
|
|
98
|
-
*/
|
|
99
|
-
async function listContexts(projectRoot) {
|
|
100
|
-
const contextDir = getContextDir(projectRoot);
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
const files = await fs.readdir(contextDir);
|
|
104
|
-
return files
|
|
105
|
-
.filter(file => file.endsWith('.md'))
|
|
106
|
-
.map(file => file.replace('.md', ''));
|
|
107
|
-
} catch (error) {
|
|
108
|
-
if (error.code === 'ENOENT') {
|
|
109
|
-
return [];
|
|
110
|
-
}
|
|
111
|
-
throw error;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Reads context content
|
|
117
|
-
* @param {string} projectRoot - Project root directory
|
|
118
|
-
* @param {string} name - Context name
|
|
119
|
-
* @returns {Promise<string>} - Context content
|
|
120
|
-
*/
|
|
121
|
-
async function readContext(projectRoot, name) {
|
|
122
|
-
const contextPath = getContextPath(projectRoot, name);
|
|
123
|
-
return await fs.readFile(contextPath, 'utf8');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Gets default template content
|
|
128
|
-
* @returns {string} - Default template
|
|
129
|
-
*/
|
|
130
|
-
function getDefaultTemplate() {
|
|
131
|
-
return `# Context: {{name}}
|
|
132
|
-
Created: {{date}}
|
|
133
|
-
Type: {{type}}
|
|
134
|
-
|
|
135
|
-
## Description
|
|
136
|
-
{{description}}
|
|
137
|
-
|
|
138
|
-
## Content
|
|
139
|
-
<!-- Add context content here -->`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Gets the sessions directory path
|
|
144
|
-
* @param {string} projectRoot - Project root directory
|
|
145
|
-
* @returns {string} - Sessions directory path
|
|
146
|
-
*/
|
|
147
|
-
function getSessionsDir(projectRoot) {
|
|
148
|
-
return path.join(projectRoot, '.claude', 'sessions');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Creates a session
|
|
153
|
-
* @param {string} projectRoot - Project root directory
|
|
154
|
-
* @param {object} sessionData - Session data
|
|
155
|
-
* @returns {Promise<void>}
|
|
156
|
-
*/
|
|
157
|
-
async function createSession(projectRoot, sessionData) {
|
|
158
|
-
const sessionsDir = getSessionsDir(projectRoot);
|
|
159
|
-
await fs.mkdir(sessionsDir, { recursive: true });
|
|
160
|
-
|
|
161
|
-
const currentPath = path.join(sessionsDir, 'current.json');
|
|
162
|
-
await fs.writeFile(currentPath, JSON.stringify(sessionData, null, 2));
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Gets current session
|
|
167
|
-
* @param {string} projectRoot - Project root directory
|
|
168
|
-
* @returns {Promise<object|null>} - Current session or null
|
|
169
|
-
*/
|
|
170
|
-
async function getCurrentSession(projectRoot) {
|
|
171
|
-
const currentPath = path.join(getSessionsDir(projectRoot), 'current.json');
|
|
172
|
-
|
|
173
|
-
try {
|
|
174
|
-
const data = await fs.readFile(currentPath, 'utf8');
|
|
175
|
-
return JSON.parse(data);
|
|
176
|
-
} catch (error) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Updates session history
|
|
183
|
-
* @param {string} projectRoot - Project root directory
|
|
184
|
-
* @param {object} session - Session to add to history
|
|
185
|
-
* @returns {Promise<void>}
|
|
186
|
-
*/
|
|
187
|
-
async function updateSessionHistory(projectRoot, session) {
|
|
188
|
-
const sessionsDir = getSessionsDir(projectRoot);
|
|
189
|
-
const historyPath = path.join(sessionsDir, 'history.json');
|
|
190
|
-
|
|
191
|
-
let history = [];
|
|
192
|
-
try {
|
|
193
|
-
const data = await fs.readFile(historyPath, 'utf8');
|
|
194
|
-
history = JSON.parse(data);
|
|
195
|
-
} catch (error) {
|
|
196
|
-
// History file doesn't exist yet
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
history.push(session);
|
|
200
|
-
|
|
201
|
-
// Keep only last 100 entries
|
|
202
|
-
if (history.length > 100) {
|
|
203
|
-
history = history.slice(-100);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
await fs.writeFile(historyPath, JSON.stringify(history, null, 2));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Creates a backup of a context file
|
|
211
|
-
* @param {string} projectRoot - Project root directory
|
|
212
|
-
* @param {string} name - Context name
|
|
213
|
-
* @returns {Promise<string>} - Backup file path
|
|
214
|
-
*/
|
|
215
|
-
async function createContextBackup(projectRoot, name) {
|
|
216
|
-
const content = await readContext(projectRoot, name);
|
|
217
|
-
const backupDir = path.join(projectRoot, '.claude', 'contexts', '.backups');
|
|
218
|
-
await fs.mkdir(backupDir, { recursive: true });
|
|
219
|
-
|
|
220
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
221
|
-
const backupPath = path.join(backupDir, `${name}_${timestamp}.md`);
|
|
222
|
-
await fs.writeFile(backupPath, content);
|
|
223
|
-
|
|
224
|
-
return backupPath;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Updates context update history
|
|
229
|
-
* @param {string} projectRoot - Project root directory
|
|
230
|
-
* @param {string} name - Context name
|
|
231
|
-
* @param {object} updateInfo - Update information
|
|
232
|
-
* @returns {Promise<void>}
|
|
233
|
-
*/
|
|
234
|
-
async function updateContextHistory(projectRoot, name, updateInfo) {
|
|
235
|
-
const historyDir = path.join(projectRoot, '.claude', 'contexts', '.history');
|
|
236
|
-
await fs.mkdir(historyDir, { recursive: true });
|
|
237
|
-
|
|
238
|
-
const historyPath = path.join(historyDir, `${name}.json`);
|
|
239
|
-
|
|
240
|
-
let history = [];
|
|
241
|
-
try {
|
|
242
|
-
const data = await fs.readFile(historyPath, 'utf8');
|
|
243
|
-
history = JSON.parse(data);
|
|
244
|
-
} catch (error) {
|
|
245
|
-
// History doesn't exist yet
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
history.push({
|
|
249
|
-
timestamp: new Date().toISOString(),
|
|
250
|
-
...updateInfo
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Keep last 50 updates
|
|
254
|
-
if (history.length > 50) {
|
|
255
|
-
history = history.slice(-50);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
await fs.writeFile(historyPath, JSON.stringify(history, null, 2));
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Writes updated context content
|
|
263
|
-
* @param {string} projectRoot - Project root directory
|
|
264
|
-
* @param {string} name - Context name
|
|
265
|
-
* @param {string} content - New content
|
|
266
|
-
* @returns {Promise<void>}
|
|
267
|
-
*/
|
|
268
|
-
async function writeContext(projectRoot, name, content) {
|
|
269
|
-
const contextPath = getContextPath(projectRoot, name);
|
|
270
|
-
await fs.writeFile(contextPath, content);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
module.exports = {
|
|
274
|
-
validateContextName,
|
|
275
|
-
loadTemplate,
|
|
276
|
-
processTemplate,
|
|
277
|
-
getContextDir,
|
|
278
|
-
getContextPath,
|
|
279
|
-
contextExists,
|
|
280
|
-
listContexts,
|
|
281
|
-
readContext,
|
|
282
|
-
writeContext,
|
|
283
|
-
getDefaultTemplate,
|
|
284
|
-
getSessionsDir,
|
|
285
|
-
createSession,
|
|
286
|
-
getCurrentSession,
|
|
287
|
-
updateSessionHistory,
|
|
288
|
-
createContextBackup,
|
|
289
|
-
updateContextHistory
|
|
290
|
-
};
|