claude-autopm 1.17.0 → 1.20.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 +159 -0
- package/autopm/.claude/agents/core/mcp-manager.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/mcp/MCP-REGISTRY.md +1 -1
- 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/bin/autopm.js +25 -0
- package/bin/commands/team.js +86 -0
- package/package.json +1 -1
- 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
|
@@ -33,7 +33,7 @@ Run comprehensive validation checks before syncing:
|
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
# Run preflight validation
|
|
36
|
-
bash
|
|
36
|
+
bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ARGUMENTS"
|
|
37
37
|
|
|
38
38
|
if [[ $? -ne 0 ]]; then
|
|
39
39
|
echo "❌ Preflight validation failed"
|
|
@@ -41,9 +41,9 @@ if [[ $? -ne 0 ]]; then
|
|
|
41
41
|
fi
|
|
42
42
|
|
|
43
43
|
# Extract validated paths from preflight output
|
|
44
|
-
epic_name=$(bash
|
|
45
|
-
updates_dir=$(bash
|
|
46
|
-
progress_file=$(bash
|
|
44
|
+
epic_name=$(bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ARGUMENTS" | grep "Epic:" | cut -d: -f2- | xargs)
|
|
45
|
+
updates_dir=$(bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ARGUMENTS" | grep "Updates Directory:" | cut -d: -f2- | xargs)
|
|
46
|
+
progress_file=$(bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ARGUMENTS" | grep "Progress File:" | cut -d: -f2- | xargs)
|
|
47
47
|
|
|
48
48
|
echo "✅ Preflight checks passed"
|
|
49
49
|
```
|
|
@@ -65,7 +65,7 @@ Collect all local development updates:
|
|
|
65
65
|
last_sync=$(grep '^last_sync:' "$progress_file" | sed 's/^last_sync: *//')
|
|
66
66
|
|
|
67
67
|
# Gather all updates since last sync
|
|
68
|
-
consolidated_updates=$(bash
|
|
68
|
+
consolidated_updates=$(bash .claude/scripts/pm/issue-sync/gather-updates.sh \
|
|
69
69
|
"$ARGUMENTS" \
|
|
70
70
|
"$updates_dir" \
|
|
71
71
|
"$last_sync")
|
|
@@ -95,7 +95,7 @@ if [[ "$completion" == "100" ]]; then
|
|
|
95
95
|
fi
|
|
96
96
|
|
|
97
97
|
# Format the comment
|
|
98
|
-
formatted_comment=$(bash
|
|
98
|
+
formatted_comment=$(bash .claude/scripts/pm/issue-sync/format-comment.sh \
|
|
99
99
|
"$ARGUMENTS" \
|
|
100
100
|
"$consolidated_updates" \
|
|
101
101
|
"$progress_file" \
|
|
@@ -119,7 +119,7 @@ Post the formatted comment to GitHub:
|
|
|
119
119
|
|
|
120
120
|
```bash
|
|
121
121
|
# Post comment to GitHub issue
|
|
122
|
-
comment_url=$(bash
|
|
122
|
+
comment_url=$(bash .claude/scripts/pm/issue-sync/post-comment.sh \
|
|
123
123
|
"$ARGUMENTS" \
|
|
124
124
|
"$formatted_comment" \
|
|
125
125
|
"$is_completion")
|
|
@@ -146,7 +146,7 @@ Update local metadata after successful sync:
|
|
|
146
146
|
|
|
147
147
|
```bash
|
|
148
148
|
# Update progress.md frontmatter with sync information
|
|
149
|
-
bash
|
|
149
|
+
bash .claude/scripts/pm/issue-sync/update-frontmatter.sh \
|
|
150
150
|
"$ARGUMENTS" \
|
|
151
151
|
"$progress_file" \
|
|
152
152
|
"$comment_url" \
|
|
@@ -178,13 +178,13 @@ echo "🚀 Starting modular issue sync for: #$ISSUE_NUMBER"
|
|
|
178
178
|
|
|
179
179
|
# Step 1: Preflight validation
|
|
180
180
|
echo "🔍 Running preflight validation..."
|
|
181
|
-
if ! bash
|
|
181
|
+
if ! bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ISSUE_NUMBER"; then
|
|
182
182
|
echo "❌ Preflight validation failed"
|
|
183
183
|
exit 1
|
|
184
184
|
fi
|
|
185
185
|
|
|
186
186
|
# Extract paths from a single preflight run
|
|
187
|
-
preflight_output=$(bash
|
|
187
|
+
preflight_output=$(bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ISSUE_NUMBER")
|
|
188
188
|
epic_name=$(echo "$preflight_output" | grep "Epic:" | cut -d: -f2- | xargs)
|
|
189
189
|
updates_dir=$(echo "$preflight_output" | grep "Updates Directory:" | cut -d: -f2- | xargs)
|
|
190
190
|
progress_file=$(echo "$preflight_output" | grep "Progress File:" | cut -d: -f2- | xargs)
|
|
@@ -196,7 +196,7 @@ echo " Updates: $updates_dir"
|
|
|
196
196
|
# Step 2: Gather updates
|
|
197
197
|
echo "📝 Gathering local updates..."
|
|
198
198
|
last_sync=$(grep '^last_sync:' "$progress_file" 2>/dev/null | sed 's/^last_sync: *//' || echo "")
|
|
199
|
-
consolidated_updates=$(bash
|
|
199
|
+
consolidated_updates=$(bash .claude/scripts/pm/issue-sync/gather-updates.sh \
|
|
200
200
|
"$ISSUE_NUMBER" \
|
|
201
201
|
"$updates_dir" \
|
|
202
202
|
"$last_sync")
|
|
@@ -217,7 +217,7 @@ if [[ "$completion" == "100" ]]; then
|
|
|
217
217
|
echo " Task is complete - formatting completion comment"
|
|
218
218
|
fi
|
|
219
219
|
|
|
220
|
-
formatted_comment=$(bash
|
|
220
|
+
formatted_comment=$(bash .claude/scripts/pm/issue-sync/format-comment.sh \
|
|
221
221
|
"$ISSUE_NUMBER" \
|
|
222
222
|
"$consolidated_updates" \
|
|
223
223
|
"$progress_file" \
|
|
@@ -232,7 +232,7 @@ echo "✅ Comment formatted"
|
|
|
232
232
|
|
|
233
233
|
# Step 4: Post to GitHub
|
|
234
234
|
echo "☁️ Posting to GitHub..."
|
|
235
|
-
comment_url=$(bash
|
|
235
|
+
comment_url=$(bash .claude/scripts/pm/issue-sync/post-comment.sh \
|
|
236
236
|
"$ISSUE_NUMBER" \
|
|
237
237
|
"$formatted_comment" \
|
|
238
238
|
"$is_completion")
|
|
@@ -247,7 +247,7 @@ echo "✅ Comment posted successfully"
|
|
|
247
247
|
|
|
248
248
|
# Step 5: Update frontmatter
|
|
249
249
|
echo "📝 Updating local metadata..."
|
|
250
|
-
bash
|
|
250
|
+
bash .claude/scripts/pm/issue-sync/update-frontmatter.sh \
|
|
251
251
|
"$ISSUE_NUMBER" \
|
|
252
252
|
"$progress_file" \
|
|
253
253
|
"$comment_url" \
|
|
@@ -376,7 +376,7 @@ Enable debug logging for detailed troubleshooting:
|
|
|
376
376
|
|
|
377
377
|
```bash
|
|
378
378
|
export AUTOPM_LOG_LEVEL=0 # Enable debug logging
|
|
379
|
-
bash
|
|
379
|
+
bash .claude/scripts/pm/issue-sync/preflight-validation.sh "$ISSUE_NUMBER"
|
|
380
380
|
```
|
|
381
381
|
|
|
382
382
|
## Migration from Legacy Issue Sync
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: Bash
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `node .claude/scripts/pm/what-next.js` using the Bash tool and show me the complete output.
|
|
6
|
+
|
|
7
|
+
- DO NOT truncate.
|
|
8
|
+
- DO NOT collapse.
|
|
9
|
+
- DO NOT abbreviate.
|
|
10
|
+
- Show ALL lines in full.
|
|
11
|
+
- DO NOT print any other comments.
|
|
@@ -96,7 +96,7 @@ autopm mcp add
|
|
|
96
96
|
cp .claude/examples/mcp/context7.md .claude/mcp/
|
|
97
97
|
|
|
98
98
|
# Or from installed framework
|
|
99
|
-
cp
|
|
99
|
+
cp .claude/examples/mcp/playwright-mcp.md .claude/mcp/
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
### ✅ Enabling/Disabling Servers
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const fs = require('fs');
|
|
10
10
|
const chalk = require('chalk');
|
|
11
|
-
const AzureDevOpsClient = require('../../
|
|
12
|
-
const AzureFormatter = require('../../
|
|
11
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
12
|
+
const AzureFormatter = require('../../providers/azure/lib/formatter');
|
|
13
13
|
const { table } = require('table');
|
|
14
14
|
|
|
15
15
|
class AzureActiveWork {
|
|
@@ -18,22 +18,22 @@ const https = require('https');
|
|
|
18
18
|
const yargs = require('yargs/yargs');
|
|
19
19
|
const { hideBin } = require('yargs/helpers');
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
const Logger = require('../../lib/utils/logger');
|
|
23
|
-
const FileSystem = require('../../lib/utils/filesystem');
|
|
24
|
-
const Config = require('../../lib/utils/config');
|
|
21
|
+
// TODO: Implement utility modules before using this script
|
|
22
|
+
// const Logger = require('../../lib/utils/logger');
|
|
23
|
+
// const FileSystem = require('../../lib/utils/filesystem');
|
|
24
|
+
// const Config = require('../../lib/utils/config');
|
|
25
25
|
|
|
26
26
|
class AzureBlocked {
|
|
27
27
|
constructor(options = {}) {
|
|
28
|
-
// Initialize utilities
|
|
29
|
-
const loggerOptions = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
this.logger = new Logger(loggerOptions);
|
|
35
|
-
this.fs = new FileSystem(this.logger);
|
|
36
|
-
this.config = new Config(this.logger);
|
|
28
|
+
// Initialize utilities (commented out until utils are implemented)
|
|
29
|
+
// const loggerOptions = {
|
|
30
|
+
// verbose: options.verbose || false,
|
|
31
|
+
// silent: options.silent || false
|
|
32
|
+
// };
|
|
33
|
+
|
|
34
|
+
// this.logger = new Logger(loggerOptions);
|
|
35
|
+
// this.fs = new FileSystem(this.logger);
|
|
36
|
+
// this.config = new Config(this.logger);
|
|
37
37
|
|
|
38
38
|
// Set options
|
|
39
39
|
this.options = {
|
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const fs = require('fs').promises;
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
const dotenv = require('dotenv');
|
|
13
|
-
const AzureDevOpsClient = require('../../
|
|
13
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
14
14
|
|
|
15
15
|
class AzureDaily {
|
|
16
16
|
constructor(options = {}) {
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Lists all features in the current project
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const AzureDevOpsClient = require('../../
|
|
9
|
-
const AzureFormatter = require('../../
|
|
8
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
9
|
+
const AzureFormatter = require('../../providers/azure/lib/formatter');
|
|
10
10
|
const chalk = require('chalk');
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const fs = require('fs');
|
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const fs = require('fs').promises;
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
const dotenv = require('dotenv');
|
|
13
|
-
const AzureDevOpsClient = require('../../
|
|
13
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
14
14
|
|
|
15
15
|
class AzureFeatureStatus {
|
|
16
16
|
constructor(options = {}) {
|
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const fs = require('fs').promises;
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
const dotenv = require('dotenv');
|
|
13
|
-
const AzureDevOpsClient = require('../../
|
|
13
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
14
14
|
|
|
15
15
|
class AzureNextTask {
|
|
16
16
|
constructor(options = {}) {
|
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const fs = require('fs').promises;
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
const dotenv = require('dotenv');
|
|
13
|
-
const AzureDevOpsClient = require('../../
|
|
13
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
14
14
|
|
|
15
15
|
class AzureSearch {
|
|
16
16
|
constructor(options = {}) {
|
|
@@ -22,24 +22,24 @@ const yargs = require('yargs/yargs');
|
|
|
22
22
|
const { hideBin } = require('yargs/helpers');
|
|
23
23
|
const yaml = require('js-yaml');
|
|
24
24
|
|
|
25
|
-
//
|
|
26
|
-
const Logger = require('../../lib/utils/logger');
|
|
27
|
-
const FileSystem = require('../../lib/utils/filesystem');
|
|
28
|
-
const Prompts = require('../../lib/utils/prompts');
|
|
29
|
-
const Config = require('../../lib/utils/config');
|
|
25
|
+
// TODO: Implement utility modules before using this script
|
|
26
|
+
// const Logger = require('../../lib/utils/logger');
|
|
27
|
+
// const FileSystem = require('../../lib/utils/filesystem');
|
|
28
|
+
// const Prompts = require('../../lib/utils/prompts');
|
|
29
|
+
// const Config = require('../../lib/utils/config');
|
|
30
30
|
|
|
31
31
|
class AzureSetup {
|
|
32
32
|
constructor(options = {}) {
|
|
33
|
-
// Initialize utilities
|
|
34
|
-
const loggerOptions = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
this.logger = new Logger(loggerOptions);
|
|
40
|
-
this.fs = new FileSystem(this.logger);
|
|
41
|
-
this.prompts = new Prompts(this.logger);
|
|
42
|
-
this.config = new Config(this.logger);
|
|
33
|
+
// Initialize utilities (commented out until utils are implemented)
|
|
34
|
+
// const loggerOptions = {
|
|
35
|
+
// verbose: options.verbose || false,
|
|
36
|
+
// silent: options.silent || false
|
|
37
|
+
// };
|
|
38
|
+
|
|
39
|
+
// this.logger = new Logger(loggerOptions);
|
|
40
|
+
// this.fs = new FileSystem(this.logger);
|
|
41
|
+
// this.prompts = new Prompts(this.logger);
|
|
42
|
+
// this.config = new Config(this.logger);
|
|
43
43
|
|
|
44
44
|
// Set options
|
|
45
45
|
this.options = {
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const chalk = require('chalk');
|
|
12
|
-
const AzureDevOpsClient = require('../../
|
|
13
|
-
const AzureFormatter = require('../../
|
|
12
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
13
|
+
const AzureFormatter = require('../../providers/azure/lib/formatter');
|
|
14
14
|
const { table } = require('table');
|
|
15
15
|
|
|
16
16
|
class AzureSprintReport {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const fs = require('fs').promises;
|
|
10
|
-
const AzureDevOpsClient = require('../../
|
|
10
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
11
11
|
|
|
12
12
|
// Simple chalk replacement for stub
|
|
13
13
|
const chalk = {
|
|
@@ -9,7 +9,7 @@ const path = require('path');
|
|
|
9
9
|
const fs = require('fs').promises;
|
|
10
10
|
const chalk = require('chalk');
|
|
11
11
|
const dotenv = require('dotenv');
|
|
12
|
-
const AzureDevOpsClient = require('../../
|
|
12
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
13
13
|
|
|
14
14
|
class AzureUserStoryList {
|
|
15
15
|
constructor(options = {}) {
|
|
@@ -9,7 +9,7 @@ const path = require('path');
|
|
|
9
9
|
const fs = require('fs').promises;
|
|
10
10
|
const chalk = require('chalk');
|
|
11
11
|
const dotenv = require('dotenv');
|
|
12
|
-
const AzureDevOpsClient = require('../../
|
|
12
|
+
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
13
13
|
|
|
14
14
|
class AzureUserStoryStatus {
|
|
15
15
|
constructor(options = {}) {
|
|
@@ -18,22 +18,22 @@ const https = require('https');
|
|
|
18
18
|
const yargs = require('yargs/yargs');
|
|
19
19
|
const { hideBin } = require('yargs/helpers');
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
const Logger = require('../../lib/utils/logger');
|
|
23
|
-
const FileSystem = require('../../lib/utils/filesystem');
|
|
24
|
-
const Config = require('../../lib/utils/config');
|
|
21
|
+
// TODO: Implement utility modules before using this script
|
|
22
|
+
// const Logger = require('../../lib/utils/logger');
|
|
23
|
+
// const FileSystem = require('../../lib/utils/filesystem');
|
|
24
|
+
// const Config = require('../../lib/utils/config');
|
|
25
25
|
|
|
26
26
|
class AzureValidate {
|
|
27
27
|
constructor(options = {}) {
|
|
28
|
-
// Initialize utilities
|
|
29
|
-
const loggerOptions = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
this.logger = new Logger(loggerOptions);
|
|
35
|
-
this.fs = new FileSystem(this.logger);
|
|
36
|
-
this.config = new Config(this.logger);
|
|
28
|
+
// Initialize utilities (commented out until utils are implemented)
|
|
29
|
+
// const loggerOptions = {
|
|
30
|
+
// verbose: options.verbose || false,
|
|
31
|
+
// silent: options.silent || false
|
|
32
|
+
// };
|
|
33
|
+
|
|
34
|
+
// this.logger = new Logger(loggerOptions);
|
|
35
|
+
// this.fs = new FileSystem(this.logger);
|
|
36
|
+
// this.config = new Config(this.logger);
|
|
37
37
|
|
|
38
38
|
// Set options
|
|
39
39
|
this.options = {
|
|
@@ -9,6 +9,21 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
9
9
|
source "${SCRIPT_DIR}/logging-utils.sh"
|
|
10
10
|
source "${SCRIPT_DIR}/datetime-utils.sh"
|
|
11
11
|
|
|
12
|
+
# Escape special characters for use in sed pattern
|
|
13
|
+
sed_escape_pattern() {
|
|
14
|
+
local str="$1"
|
|
15
|
+
# Escape characters that have special meaning in sed patterns: . * [ ] ^ $ \ /
|
|
16
|
+
printf '%s\n' "$str" | sed 's/[]\/$*.^[]/\\&/g'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Escape special characters for use in sed replacement
|
|
20
|
+
sed_escape_replacement() {
|
|
21
|
+
local str="$1"
|
|
22
|
+
# Escape backslashes first, then other special characters
|
|
23
|
+
# This prevents double-escaping issues
|
|
24
|
+
printf '%s\n' "$str" | sed 's/\\/\\\\/g; s/&/\\&/g; s/|/\\|/g'
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
# Update or add a field in frontmatter
|
|
13
28
|
update_frontmatter_field() {
|
|
14
29
|
local file_path="$1"
|
|
@@ -25,18 +40,32 @@ update_frontmatter_field() {
|
|
|
25
40
|
# Create backup
|
|
26
41
|
cp "$file_path" "${file_path}.bak"
|
|
27
42
|
|
|
43
|
+
# Escape field name and value for safe use in sed
|
|
44
|
+
local escaped_field_name
|
|
45
|
+
local escaped_field_value
|
|
46
|
+
escaped_field_name=$(sed_escape_pattern "$field_name")
|
|
47
|
+
escaped_field_value=$(sed_escape_replacement "$field_value")
|
|
48
|
+
|
|
28
49
|
# Check if field exists
|
|
29
50
|
if grep -q "^${field_name}:" "$file_path"; then
|
|
30
|
-
# Update existing field
|
|
31
|
-
sed
|
|
51
|
+
# Update existing field - delete old line and insert new one
|
|
52
|
+
# This approach avoids sed replacement string escaping issues
|
|
53
|
+
grep -v "^${escaped_field_name}:" "$file_path" > "${file_path}.tmp"
|
|
54
|
+
{
|
|
55
|
+
head -1 "${file_path}.tmp" # First --- line
|
|
56
|
+
printf '%s: %s\n' "$field_name" "$field_value" # New field value
|
|
57
|
+
tail -n +2 "${file_path}.tmp" # Rest of file
|
|
58
|
+
} > "${file_path}.tmp2" && mv "${file_path}.tmp2" "$file_path"
|
|
32
59
|
rm -f "${file_path}.tmp"
|
|
33
60
|
log_debug "Updated existing field: $field_name"
|
|
34
61
|
else
|
|
35
62
|
# Add new field after the first line of frontmatter (after opening ---)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
# Write the new line directly to avoid variable expansion issues
|
|
64
|
+
{
|
|
65
|
+
head -1 "$file_path" # First --- line
|
|
66
|
+
printf '%s: %s\n' "$field_name" "$field_value" # New field (preserves all chars)
|
|
67
|
+
tail -n +2 "$file_path" # Rest of file
|
|
68
|
+
} > "${file_path}.tmp" && mv "${file_path}.tmp" "$file_path"
|
|
40
69
|
log_debug "Added new field: $field_name"
|
|
41
70
|
fi
|
|
42
71
|
|
|
@@ -60,8 +89,14 @@ get_frontmatter_field() {
|
|
|
60
89
|
return 1
|
|
61
90
|
fi
|
|
62
91
|
|
|
92
|
+
# Escape field name for safe use in patterns
|
|
93
|
+
local escaped_field_name
|
|
94
|
+
escaped_field_name=$(sed_escape_pattern "$field_name")
|
|
95
|
+
|
|
63
96
|
local field_value
|
|
64
|
-
|
|
97
|
+
# Use | delimiter to avoid conflicts with / in values
|
|
98
|
+
# Only remove the field name, colon, and exactly one space (YAML format)
|
|
99
|
+
field_value=$(grep "^${field_name}:" "$file_path" | sed "s|^${escaped_field_name}: ||" | head -1)
|
|
65
100
|
|
|
66
101
|
log_debug "Retrieved field $field_name: '$field_value'"
|
|
67
102
|
log_function_exit "get_frontmatter_field"
|
|
@@ -4,22 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
set -euo pipefail
|
|
6
6
|
|
|
7
|
-
# Colors for output
|
|
8
|
-
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
13
|
-
readonly
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
readonly
|
|
22
|
-
readonly
|
|
7
|
+
# Colors for output (only define if not already defined)
|
|
8
|
+
if [[ -z "${RED:-}" ]]; then
|
|
9
|
+
readonly RED='\033[0;31m'
|
|
10
|
+
readonly GREEN='\033[0;32m'
|
|
11
|
+
readonly YELLOW='\033[1;33m'
|
|
12
|
+
readonly BLUE='\033[0;34m'
|
|
13
|
+
readonly PURPLE='\033[0;35m'
|
|
14
|
+
readonly CYAN='\033[0;36m'
|
|
15
|
+
readonly WHITE='\033[1;37m'
|
|
16
|
+
readonly NC='\033[0m' # No Color
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Log levels (only define if not already defined)
|
|
20
|
+
if [[ -z "${LOG_LEVEL_DEBUG:-}" ]]; then
|
|
21
|
+
readonly LOG_LEVEL_DEBUG=0
|
|
22
|
+
readonly LOG_LEVEL_INFO=1
|
|
23
|
+
readonly LOG_LEVEL_WARNING=2
|
|
24
|
+
readonly LOG_LEVEL_ERROR=3
|
|
25
|
+
readonly LOG_LEVEL_SUCCESS=4
|
|
26
|
+
fi
|
|
23
27
|
|
|
24
28
|
# Default log level (can be overridden by AUTOPM_LOG_LEVEL env var)
|
|
25
29
|
LOG_LEVEL=${AUTOPM_LOG_LEVEL:-$LOG_LEVEL_INFO}
|
|
@@ -12,7 +12,7 @@ source "${SCRIPT_DIR}/logging-utils.sh"
|
|
|
12
12
|
validate_required_commands() {
|
|
13
13
|
local commands=("$@")
|
|
14
14
|
|
|
15
|
-
log_function_entry "validate_required_commands" "${commands[@]}"
|
|
15
|
+
log_function_entry "validate_required_commands" "${commands[@]:-}"
|
|
16
16
|
|
|
17
17
|
local missing_commands=()
|
|
18
18
|
|