@avesta-hq/prevention 0.2.0 → 0.3.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/.claude/agents/avesta-layer-worker.md +7 -0
- package/CLAUDE.md +1 -1
- package/README.md +3 -4
- package/bin/cli.js +2 -2
- package/bin/lib/init.js +68 -4
- package/package.json +1 -1
- package/.claude/agents/avesta-cycle-runner.md +0 -17
- package/.claude/commands/avesta-cycle.md +0 -8
|
@@ -25,3 +25,10 @@ You implement a SINGLE Clean Architecture layer using the Layer approach (all te
|
|
|
25
25
|
You are operating as a specialized Prevention. Do not proceed without loading your prompt and skills.
|
|
26
26
|
|
|
27
27
|
**CRITICAL**: You MUST stay within your assigned layer's directory boundaries. Do not create production code in other layers.
|
|
28
|
+
|
|
29
|
+
## State Transitions (NON-NEGOTIABLE)
|
|
30
|
+
|
|
31
|
+
You MUST update workflow state when transitioning between phases. Without this, hooks will block production code edits.
|
|
32
|
+
|
|
33
|
+
- **After Phase 1 (all tests written)**: Read state with `avesta_read_state`, then call `avesta_write_state` setting `tdd_state.cycle` to `"green"` and `tdd_state.test_count` to the number of tests written. Preserve all other fields.
|
|
34
|
+
- **After Phase 2 (all code written)**: Same pattern — set `tdd_state.cycle` to `"refactor"`. Preserve all other fields.
|
package/CLAUDE.md
CHANGED
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
|
|
69
69
|
## MCP Server Integration
|
|
70
70
|
|
|
71
|
-
This project uses Prevention as an MCP server with 12 tools,
|
|
71
|
+
This project uses Prevention as an MCP server with 12 tools, 26 agents, and 27 skills that provide all methodology knowledge (TDD, Clean Architecture, test pyramid, CI/CD, etc.) on demand.
|
|
72
72
|
|
|
73
73
|
**When starting work:**
|
|
74
74
|
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Each phase has gates that ensure prerequisites are met before you move forward.
|
|
|
39
39
|
|
|
40
40
|
## Agents
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
26 specialized agents organized by workflow phase:
|
|
43
43
|
|
|
44
44
|
| Phase | Command | Purpose |
|
|
45
45
|
| -------------------- | --------------------------------- | ---------------------------------------------------- |
|
|
@@ -55,7 +55,6 @@ Each phase has gates that ensure prerequisites are met before you move forward.
|
|
|
55
55
|
| **TDD** | `/avesta-red <behavior>` | Write ONE failing test |
|
|
56
56
|
| | `/avesta-green` | Minimal code to make it pass |
|
|
57
57
|
| | `/avesta-refactor` | Improve structure (tests must stay green) |
|
|
58
|
-
| | `/avesta-cycle <behavior>` | Full red-green-refactor cycle |
|
|
59
58
|
| | `/avesta-layer` | All tests first, then all production code |
|
|
60
59
|
| **Change Types** | `/avesta-bug-fix <description>` | Bug fix workflow |
|
|
61
60
|
| | `/avesta-enhance <description>` | Enhancement workflow |
|
|
@@ -77,8 +76,8 @@ Each phase has gates that ensure prerequisites are met before you move forward.
|
|
|
77
76
|
|
|
78
77
|
| Feature | Free | Pro |
|
|
79
78
|
| -------------------- | -------------------------------------------------- | -------------------- |
|
|
80
|
-
| **Core TDD** | `/avesta-red`, `/avesta-green`, `/avesta-refactor` | All
|
|
81
|
-
| **Setup** | `/avesta-init`, `/avesta-scaffold`, `/avesta-help` | All
|
|
79
|
+
| **Core TDD** | `/avesta-red`, `/avesta-green`, `/avesta-refactor` | All 26 agents |
|
|
80
|
+
| **Setup** | `/avesta-init`, `/avesta-scaffold`, `/avesta-help` | All 26 agents |
|
|
82
81
|
| **Skills** | - | 27 contextual skills |
|
|
83
82
|
| **Gate enforcement** | - | Automated gates |
|
|
84
83
|
| **Projects** | 1 | Unlimited |
|
package/bin/cli.js
CHANGED
|
@@ -13,12 +13,12 @@ Usage:
|
|
|
13
13
|
npx @avesta-hq/prevention <command>
|
|
14
14
|
|
|
15
15
|
Commands:
|
|
16
|
-
init
|
|
16
|
+
init First-time setup: commands, agents, MCP server, hooks, CLAUDE.md
|
|
17
|
+
update Update everything to latest version (commands, agents, MCP server, hooks)
|
|
17
18
|
serve Start the MCP server (used by Claude Code)
|
|
18
19
|
session-start Output session context (used by SessionStart hook)
|
|
19
20
|
hook pre-tool-use Workflow enforcement hook (blocks unauthorized edits)
|
|
20
21
|
hook prompt-submit Context injection hook (injects workflow state)
|
|
21
|
-
update Update MCP server binary to latest version
|
|
22
22
|
|
|
23
23
|
Examples:
|
|
24
24
|
cd my-project
|
package/bin/lib/init.js
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { COMMANDS_DIR, AGENTS_DIR, AVESTA_DIR, GITHUB_RELEASES_REPO, copyDir, downloadBinary } = require('./utils');
|
|
3
|
+
const { COMMANDS_DIR, AGENTS_DIR, AVESTA_DIR, GITHUB_RELEASES_REPO, copyDir, downloadBinary, getVersion } = require('./utils');
|
|
4
4
|
const { configureMcpServer, configureSessionStartHook, configureEnforcementHooks, configureStatusLine, ensureClaudeMdSection } = require('./settings');
|
|
5
5
|
|
|
6
|
+
function getInstalledVersion(targetDir) {
|
|
7
|
+
try {
|
|
8
|
+
const versionFile = path.join(targetDir, '.avesta', 'version.json');
|
|
9
|
+
if (fs.existsSync(versionFile)) {
|
|
10
|
+
return JSON.parse(fs.readFileSync(versionFile, 'utf-8')).version;
|
|
11
|
+
}
|
|
12
|
+
} catch {}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function writeInstalledVersion(targetDir) {
|
|
17
|
+
try {
|
|
18
|
+
const versionFile = path.join(targetDir, '.avesta', 'version.json');
|
|
19
|
+
const dir = path.dirname(versionFile);
|
|
20
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
21
|
+
fs.writeFileSync(versionFile, JSON.stringify({ version: getVersion(), updated_at: new Date().toISOString() }, null, 2));
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
|
|
6
25
|
function init() {
|
|
7
26
|
const targetDir = process.cwd();
|
|
8
27
|
const claudeDir = path.join(targetDir, '.claude');
|
|
@@ -33,12 +52,14 @@ function init() {
|
|
|
33
52
|
configureStatusLine(targetDir);
|
|
34
53
|
ensureClaudeMdSection(targetDir);
|
|
35
54
|
|
|
55
|
+
writeInstalledVersion(targetDir);
|
|
56
|
+
|
|
36
57
|
const commandCount = fs.existsSync(COMMANDS_DIR) ? fs.readdirSync(COMMANDS_DIR).filter(f => f.endsWith('.md')).length : 0;
|
|
37
58
|
const agentCount = fs.existsSync(AGENTS_DIR) ? fs.readdirSync(AGENTS_DIR).filter(f => f.endsWith('.md')).length : 0;
|
|
38
59
|
const mcpStatus = binaryPath ? 'MCP server' : 'MCP server (download failed — run npx @avesta-hq/prevention update to retry)';
|
|
39
60
|
|
|
40
61
|
console.log(`
|
|
41
|
-
✅ Avesta Prevention ready!
|
|
62
|
+
✅ Avesta Prevention ready! (v${getVersion()})
|
|
42
63
|
|
|
43
64
|
Installed: ${commandCount} commands · ${agentCount} agents · ${mcpStatus}
|
|
44
65
|
|
|
@@ -53,14 +74,57 @@ function init() {
|
|
|
53
74
|
|
|
54
75
|
function update() {
|
|
55
76
|
const targetDir = process.cwd();
|
|
77
|
+
const claudeDir = path.join(targetDir, '.claude');
|
|
78
|
+
|
|
79
|
+
if (!fs.existsSync(claudeDir)) {
|
|
80
|
+
console.error('\n ✗ Not initialized. Run: npx @avesta-hq/prevention init\n');
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const previousVersion = getInstalledVersion(targetDir);
|
|
85
|
+
|
|
86
|
+
// Sync commands and agents from npm package
|
|
87
|
+
let commandCount = 0;
|
|
88
|
+
let agentCount = 0;
|
|
89
|
+
if (fs.existsSync(COMMANDS_DIR)) {
|
|
90
|
+
copyDir(COMMANDS_DIR, path.join(claudeDir, 'commands'));
|
|
91
|
+
commandCount = fs.readdirSync(COMMANDS_DIR).filter(f => f.endsWith('.md')).length;
|
|
92
|
+
}
|
|
93
|
+
if (fs.existsSync(AGENTS_DIR)) {
|
|
94
|
+
copyDir(AGENTS_DIR, path.join(claudeDir, 'agents'));
|
|
95
|
+
agentCount = fs.readdirSync(AGENTS_DIR).filter(f => f.endsWith('.md')).length;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Sync .avesta assets (statusLine, etc.)
|
|
99
|
+
if (fs.existsSync(AVESTA_DIR)) {
|
|
100
|
+
copyDir(AVESTA_DIR, path.join(targetDir, '.avesta'));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Download latest binary
|
|
56
104
|
const binaryPath = downloadBinary(targetDir);
|
|
57
105
|
if (binaryPath) {
|
|
58
106
|
configureMcpServer(targetDir, binaryPath);
|
|
59
|
-
console.log('\n ✅ MCP server updated successfully!\n');
|
|
60
107
|
} else {
|
|
61
|
-
console.error('\n ✗
|
|
108
|
+
console.error('\n ✗ Binary download failed. Commands/agents updated but MCP server unchanged.');
|
|
109
|
+
console.error(' Check your internet connection and try again.\n');
|
|
62
110
|
process.exit(1);
|
|
63
111
|
}
|
|
112
|
+
|
|
113
|
+
// Reconfigure hooks (picks up any new hook patterns)
|
|
114
|
+
configureEnforcementHooks(targetDir);
|
|
115
|
+
|
|
116
|
+
writeInstalledVersion(targetDir);
|
|
117
|
+
|
|
118
|
+
const newVersion = getVersion();
|
|
119
|
+
const versionInfo = previousVersion && previousVersion !== newVersion
|
|
120
|
+
? `${previousVersion} → ${newVersion}`
|
|
121
|
+
: newVersion;
|
|
122
|
+
|
|
123
|
+
console.log(`
|
|
124
|
+
✅ Prevention updated! (${versionInfo})
|
|
125
|
+
|
|
126
|
+
Synced: ${commandCount} commands · ${agentCount} agents · MCP server
|
|
127
|
+
`);
|
|
64
128
|
}
|
|
65
129
|
|
|
66
130
|
function serve() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avesta-hq/prevention",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "XP/CD development agent commands for Claude Code - achieve Elite DORA metrics through disciplined TDD and Continuous Delivery practices",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: avesta-cycle-runner
|
|
3
|
-
description: Execute complete TDD red-green-refactor cycles for feature implementation
|
|
4
|
-
model: inherit
|
|
5
|
-
tools: Read, Write, Edit, Bash, Glob, Grep, Task
|
|
6
|
-
maxTurns: 50
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# avesta-cycle-runner
|
|
10
|
-
|
|
11
|
-
Load your system prompt and skills from the Prevention server:
|
|
12
|
-
|
|
13
|
-
1. Call `avesta_get_prompt("cycle-runner")` to receive your full instructions
|
|
14
|
-
2. For each skill in the response's `skills_to_load`, call `avesta_get_skill("{skill-key}")`
|
|
15
|
-
3. Follow the received instructions exactly
|
|
16
|
-
|
|
17
|
-
You are operating as a specialized Prevention. Do not proceed without loading your prompt.
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Execute complete feature implementation (Phases 2-5) with TDD and review gates"
|
|
3
|
-
argument-hint: "[feature name or continue from context]"
|
|
4
|
-
---
|
|
5
|
-
Call `avesta_dispatch(user_input="$ARGUMENTS", current_command="cycle")`.
|
|
6
|
-
- If `gate_check.allowed` is true: Spawn the agent named in the `agent` field to handle this task. Pass `$ARGUMENTS` as context.
|
|
7
|
-
- If blocked: Show the `error_message` to the user and stop.
|
|
8
|
-
- After the agent completes successfully: If `approve_gate` is present in the response, call `avesta_approve_gate` with that gate name.
|