mustard-claude 3.1.27 → 3.1.28
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/package.json +1 -1
- package/templates/.claude/.agent-state/debug-loop-state.json +6 -0
- package/templates/.claude/.metrics/bash-native-redirect.jsonl +1 -0
- package/templates/.claude/.metrics/rtk-rewrite.jsonl +4 -0
- package/templates/commands/mustard/status/SKILL.md +27 -13
- package/templates/scripts/metrics-collect.js +43 -24
package/package.json
CHANGED
|
@@ -13,3 +13,4 @@
|
|
|
13
13
|
{"ts":"2026-04-14T19:07:59.760Z","event":"bash-native-redirect","tokens_affected":3,"tokens_saved":3,"note":"redirected","from":"cat","to":"Read","command_head":"cat file.txt"}
|
|
14
14
|
{"ts":"2026-04-14T23:33:26.496Z","event":"bash-native-redirect","tokens_affected":8,"tokens_saved":8,"note":"redirected","from":"cat","to":"Read","command_head":"cat /c/Atiz/Mustard/mustard.json"}
|
|
15
15
|
{"ts":"2026-04-16T11:43:50.380Z","event":"bash-native-redirect","tokens_affected":4,"tokens_saved":4,"note":"redirected","from":"ls","to":"Glob","command_head":"ls src/commands/"}
|
|
16
|
+
{"ts":"2026-04-21T04:49:05.072Z","event":"bash-native-redirect","tokens_affected":27,"tokens_saved":27,"note":"redirected","from":"ls","to":"Glob","command_head":"ls \"C:/Atiz/Competi/projetos/sialia/.claude/spec/planned/2026-04-20-wave1-02-con"}
|
|
@@ -2,3 +2,7 @@
|
|
|
2
2
|
{"ts":"2026-04-16T11:31:25.015Z","event":"rtk-rewrite","tokens_affected":17,"tokens_saved":85,"note":"rewritten via rtk","command_head":"cd templates && grep -A3 \"debug-loop-guard\" settings.json | ","savings_rate":0.5}
|
|
3
3
|
{"ts":"2026-04-16T11:43:50.502Z","event":"rtk-rewrite","tokens_affected":4,"tokens_saved":26,"note":"rewritten via rtk","command_head":"ls src/commands/","savings_rate":0.65}
|
|
4
4
|
{"ts":"2026-04-16T11:49:34.177Z","event":"rtk-rewrite","tokens_affected":37,"tokens_saved":222,"note":"rewritten via rtk","command_head":"cat mustard.json 2>/dev/null | head -30 && echo \"---\" && rtk","savings_rate":0.6}
|
|
5
|
+
{"ts":"2026-04-21T04:44:22.627Z","event":"rtk-rewrite","tokens_affected":18,"tokens_saved":0,"note":"rewritten via rtk","command_head":"ls -la \"C:/Atiz/Competi/projetos/sialia/.claude/spec/\" 2>&1 ","rewritten_head":"rtk ls -la \"C:/Atiz/Competi/projetos/sialia/.claude/spec/\" 2"}
|
|
6
|
+
{"ts":"2026-04-21T04:44:28.194Z","event":"rtk-rewrite","tokens_affected":41,"tokens_saved":0,"note":"rewritten via rtk","command_head":"ls \"C:/Atiz/Competi/projetos/sialia/.claude/spec/planned/\" 2","rewritten_head":"rtk ls \"C:/Atiz/Competi/projetos/sialia/.claude/spec/planned"}
|
|
7
|
+
{"ts":"2026-04-21T04:49:05.191Z","event":"rtk-rewrite","tokens_affected":29,"tokens_saved":0,"note":"rewritten via rtk","command_head":"ls \"C:/Atiz/Competi/projetos/sialia/.claude/spec/planned/202","rewritten_head":"rtk ls \"C:/Atiz/Competi/projetos/sialia/.claude/spec/planned"}
|
|
8
|
+
{"ts":"2026-04-21T04:51:12.069Z","event":"rtk-rewrite","tokens_affected":104,"tokens_saved":0,"note":"rewritten via rtk","command_head":"cd C:/Atiz/Mustard && cat mustard.json 2>/dev/null; echo '--","rewritten_head":"cd C:/Atiz/Mustard && rtk read mustard.json 2>/dev/null; ech"}
|
|
@@ -8,20 +8,34 @@
|
|
|
8
8
|
|
|
9
9
|
Shows consolidated project status.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Action
|
|
12
12
|
|
|
13
|
-
1. **Git Status**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
1. **Git Status** — run `rtk git status` and `rtk git log -1 --format=%H %s` for current branch, modified files, and last commit.
|
|
14
|
+
2. **Pipeline** — run `node .claude/scripts/metrics-collect.js` and surface the `## Active:` and any `## Orphaned:` sections. Do NOT attempt to read `.claude/pipeline-state.json` (legacy singular path, no longer written). The canonical source is `.claude/.pipeline-states/*.json`, read via the script above.
|
|
15
|
+
3. **Build** — if `.claude/.last-build.json` exists, report timestamp and pass/fail; otherwise note "no build state persisted".
|
|
16
|
+
4. **Entity Registry** — read `.claude/entity-registry.json` and report `_meta.version`, `_meta.generatedAt`, and total entity count (length of `entities` or equivalent top-level collection).
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
- Active pipeline (if any)
|
|
20
|
-
- Current phase
|
|
18
|
+
## Rules
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
- Always delegate pipeline state reading to `metrics-collect.js` — never parse `.pipeline-states/` directly. This keeps `/status` and `/stats` consistent.
|
|
21
|
+
- If `metrics-collect.js` reports `## Orphaned:` pipelines, include them under the Pipeline section and suggest the user run `/mustard:complete {spec-name}` for each, or `/mustard:maint` for bulk cleanup.
|
|
22
|
+
- If no `.claude/` directory exists, inform user that project is not initialized and suggest `mustard init`.
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
## Information Layout
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
1. Git
|
|
28
|
+
- Branch, modified files, last commit
|
|
29
|
+
|
|
30
|
+
2. Pipeline
|
|
31
|
+
- Active: {name} (phase: {phase}) ← if any
|
|
32
|
+
- Orphaned: {name} (spec no longer in active/) ← if any
|
|
33
|
+
- (or "none" if both empty)
|
|
34
|
+
|
|
35
|
+
3. Build
|
|
36
|
+
- Last validation: {timestamp} — {pass|fail}
|
|
37
|
+
- (or "no build state persisted")
|
|
38
|
+
|
|
39
|
+
4. Entity Registry
|
|
40
|
+
- Version, generated at, total entities
|
|
41
|
+
```
|
|
@@ -24,42 +24,61 @@ function main() {
|
|
|
24
24
|
parts.push('# Pipeline Metrics');
|
|
25
25
|
parts.push('');
|
|
26
26
|
|
|
27
|
-
// Active pipelines
|
|
27
|
+
// Active & Orphaned pipelines
|
|
28
|
+
//
|
|
29
|
+
// A pipeline-state file is "Active" iff its spec still lives in
|
|
30
|
+
// .claude/spec/active/{name}/. If the spec has moved to completed/ or no
|
|
31
|
+
// longer exists, the state file is an orphan — reported under a separate
|
|
32
|
+
// heading so users can reconcile it via /mustard:complete or /mustard:maint.
|
|
28
33
|
const statesDir = path.join(claudeDir, '.pipeline-states');
|
|
34
|
+
const activeSpecDir = path.join(claudeDir, 'spec', 'active');
|
|
29
35
|
if (fs.existsSync(statesDir)) {
|
|
30
36
|
const files = fs.readdirSync(statesDir).filter(f => f.endsWith('.json'));
|
|
37
|
+
const activeBuckets = [];
|
|
38
|
+
const orphanedBuckets = [];
|
|
31
39
|
for (const f of files) {
|
|
32
40
|
try {
|
|
33
41
|
const state = JSON.parse(fs.readFileSync(path.join(statesDir, f), 'utf8'));
|
|
34
|
-
if (state.metrics)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
if (!state.metrics) continue;
|
|
43
|
+
const name = f.replace('.json', '');
|
|
44
|
+
const specPath = path.join(activeSpecDir, name);
|
|
45
|
+
const isOrphaned = !fs.existsSync(specPath);
|
|
46
|
+
const m = state.metrics;
|
|
47
|
+
const duration = m.startedAt ? formatDuration(new Date(m.startedAt), new Date()) : 'unknown';
|
|
48
|
+
const lines = [];
|
|
49
|
+
lines.push(`## ${isOrphaned ? 'Orphaned' : 'Active'}: ${name}`);
|
|
50
|
+
lines.push(`- Duration: ${duration}`);
|
|
51
|
+
lines.push(`- API calls: ${m.apiCalls || 0}`);
|
|
52
|
+
lines.push(`- Retries: ${m.retries || 0}`);
|
|
53
|
+
if (m.toolBreakdown && Object.keys(m.toolBreakdown).length > 0) {
|
|
54
|
+
lines.push('- Tool breakdown:');
|
|
55
|
+
for (const [tool, count] of Object.entries(m.toolBreakdown).sort((a, b) => b[1] - a[1])) {
|
|
56
|
+
lines.push(` - ${tool}: ${count}`);
|
|
47
57
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
58
|
+
}
|
|
59
|
+
if (m.gate_saves !== undefined) lines.push(`- Gate saves: ${m.gate_saves}`);
|
|
60
|
+
if (m.wave_reentry !== undefined) lines.push(`- Wave reentries: ${m.wave_reentry}`);
|
|
61
|
+
if (m.skillHits && Object.keys(m.skillHits).length > 0) {
|
|
62
|
+
lines.push('- Skill hits:');
|
|
63
|
+
for (const [agent, hits] of Object.entries(m.skillHits).sort()) {
|
|
64
|
+
const pct = hits.loaded > 0 ? Math.round((hits.read / hits.loaded) * 100) + '%' : '\u2014';
|
|
65
|
+
lines.push(` - ${agent}: ${hits.read}/${hits.loaded} (${pct})`);
|
|
56
66
|
}
|
|
57
|
-
parts.push('');
|
|
58
67
|
}
|
|
68
|
+
if (isOrphaned) {
|
|
69
|
+
lines.push('- Spec: not in spec/active/ (likely completed without /mustard:complete)');
|
|
70
|
+
}
|
|
71
|
+
lines.push('');
|
|
72
|
+
(isOrphaned ? orphanedBuckets : activeBuckets).push(lines);
|
|
59
73
|
} catch {}
|
|
60
74
|
}
|
|
75
|
+
for (const block of activeBuckets) for (const line of block) parts.push(line);
|
|
76
|
+
for (const block of orphanedBuckets) for (const line of block) parts.push(line);
|
|
77
|
+
if (orphanedBuckets.length > 0) {
|
|
78
|
+
parts.push(`> ${orphanedBuckets.length} orphaned pipeline state(s) detected. Run \`/mustard:complete {spec-name}\` or \`/mustard:maint\` to reconcile.`);
|
|
79
|
+
parts.push('');
|
|
80
|
+
}
|
|
61
81
|
}
|
|
62
|
-
|
|
63
82
|
// Completed pipelines (archived metrics)
|
|
64
83
|
const metricsDir = path.join(claudeDir, 'metrics');
|
|
65
84
|
if (fs.existsSync(metricsDir)) {
|