syntropic 0.1.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/bin/syntropic.js +59 -0
- package/commands/health.js +133 -0
- package/commands/init.js +146 -0
- package/package.json +36 -0
- package/templates/.claude/EVERGREEN_RULES.md +98 -0
- package/templates/.claude/commands/dev.md +35 -0
- package/templates/.claude/commands/devops.md +41 -0
- package/templates/.claude/commands/plan.md +52 -0
- package/templates/.claude/commands/qa.md +48 -0
- package/templates/.claude/commands/research.md +45 -0
- package/templates/.claude/commands/security.md +58 -0
- package/templates/.github/workflows/daily-health-check.yml +84 -0
- package/templates/CLAUDE.md +85 -0
- package/templates/scripts/health-check.js +60 -0
package/bin/syntropic.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Syntropic CLI
|
|
5
|
+
* Philosophy-as-code development pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx syntropic init [project-name]
|
|
9
|
+
* npx syntropic health
|
|
10
|
+
* npx syntropic --help
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const command = args[0];
|
|
15
|
+
|
|
16
|
+
const COMMANDS = {
|
|
17
|
+
init: () => require('../commands/init'),
|
|
18
|
+
health: () => require('../commands/health'),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Version flag
|
|
22
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
23
|
+
const pkg = require('../package.json');
|
|
24
|
+
console.log(pkg.version);
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Help
|
|
29
|
+
if (!command || args.includes('--help') || args.includes('-h')) {
|
|
30
|
+
console.log(`
|
|
31
|
+
syntropic — Philosophy-as-code development pipeline
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
syntropic init [project-name] Scaffold a new project with the Syntropic pipeline
|
|
35
|
+
syntropic health Run a local health check
|
|
36
|
+
syntropic --version Show version
|
|
37
|
+
syntropic --help Show this help
|
|
38
|
+
|
|
39
|
+
What you get:
|
|
40
|
+
- CLAUDE.md with Evergreen Rules (EG1-EG9) — a disciplined dev pipeline
|
|
41
|
+
- Generic agents: dev, qa, research, plan, devops, security
|
|
42
|
+
- Daily health check workflow with auto-remediation
|
|
43
|
+
- PRISM efficiency tracking methodology
|
|
44
|
+
|
|
45
|
+
Learn more: https://www.syntropicworks.com
|
|
46
|
+
`);
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Run command
|
|
51
|
+
if (COMMANDS[command]) {
|
|
52
|
+
const mod = COMMANDS[command]();
|
|
53
|
+
const run = mod.default || mod;
|
|
54
|
+
run(args.slice(1));
|
|
55
|
+
} else {
|
|
56
|
+
console.error(`Unknown command: ${command}`);
|
|
57
|
+
console.error('Run "syntropic --help" for usage.');
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* syntropic health
|
|
3
|
+
*
|
|
4
|
+
* Runs a local health check: build status, localhost refs, git state.
|
|
5
|
+
* Mirrors EG1 pre-flight loop.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
function run() {
|
|
13
|
+
console.log('\n syntropic health — EG1 Pre-Flight Check\n');
|
|
14
|
+
|
|
15
|
+
const checks = [];
|
|
16
|
+
let hasErrors = false;
|
|
17
|
+
|
|
18
|
+
// 1. Check CLAUDE.md exists
|
|
19
|
+
const claudeMd = path.join(process.cwd(), 'CLAUDE.md');
|
|
20
|
+
if (fs.existsSync(claudeMd)) {
|
|
21
|
+
checks.push({ name: 'CLAUDE.md', status: 'pass', detail: 'Found' });
|
|
22
|
+
} else {
|
|
23
|
+
checks.push({ name: 'CLAUDE.md', status: 'fail', detail: 'Missing — run "syntropic init"' });
|
|
24
|
+
hasErrors = true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 2. Check .claude directory
|
|
28
|
+
const claudeDir = path.join(process.cwd(), '.claude');
|
|
29
|
+
if (fs.existsSync(claudeDir)) {
|
|
30
|
+
const agents = fs.readdirSync(path.join(claudeDir, 'commands')).filter(f => f.endsWith('.md') && f !== 'README.md');
|
|
31
|
+
checks.push({ name: 'Agents', status: 'pass', detail: `${agents.length} agents found` });
|
|
32
|
+
} else {
|
|
33
|
+
checks.push({ name: 'Agents', status: 'warn', detail: 'No .claude directory' });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 3. npm build check
|
|
37
|
+
const pkgJson = path.join(process.cwd(), 'package.json');
|
|
38
|
+
if (fs.existsSync(pkgJson)) {
|
|
39
|
+
try {
|
|
40
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJson, 'utf8'));
|
|
41
|
+
if (pkg.scripts && pkg.scripts.build) {
|
|
42
|
+
try {
|
|
43
|
+
execSync('npm run build', { stdio: 'pipe', timeout: 120000 });
|
|
44
|
+
checks.push({ name: 'Build', status: 'pass', detail: 'npm run build succeeded' });
|
|
45
|
+
} catch (e) {
|
|
46
|
+
checks.push({ name: 'Build', status: 'fail', detail: 'npm run build failed' });
|
|
47
|
+
hasErrors = true;
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
checks.push({ name: 'Build', status: 'skip', detail: 'No build script in package.json' });
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
checks.push({ name: 'Build', status: 'warn', detail: 'Could not parse package.json' });
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
checks.push({ name: 'Build', status: 'skip', detail: 'No package.json' });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 4. Localhost grep
|
|
60
|
+
try {
|
|
61
|
+
const result = execSync(
|
|
62
|
+
'grep -r "localhost\\|127\\.0\\.0\\.1" --include="*.js" --include="*.ts" --include="*.tsx" --include="*.jsx" src/ pages/ components/ lib/ app/ 2>/dev/null || true',
|
|
63
|
+
{ encoding: 'utf8', timeout: 10000 }
|
|
64
|
+
).trim();
|
|
65
|
+
|
|
66
|
+
if (result) {
|
|
67
|
+
const lines = result.split('\n').length;
|
|
68
|
+
checks.push({ name: 'Localhost refs', status: 'warn', detail: `${lines} reference(s) found — review before deploy` });
|
|
69
|
+
} else {
|
|
70
|
+
checks.push({ name: 'Localhost refs', status: 'pass', detail: 'Clean' });
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
checks.push({ name: 'Localhost refs', status: 'skip', detail: 'No source directories found' });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 5. Git status
|
|
77
|
+
try {
|
|
78
|
+
const status = execSync('git status --porcelain', { encoding: 'utf8', timeout: 5000 }).trim();
|
|
79
|
+
if (status) {
|
|
80
|
+
const files = status.split('\n').length;
|
|
81
|
+
checks.push({ name: 'Git status', status: 'warn', detail: `${files} uncommitted change(s)` });
|
|
82
|
+
} else {
|
|
83
|
+
checks.push({ name: 'Git status', status: 'pass', detail: 'Clean working tree' });
|
|
84
|
+
}
|
|
85
|
+
} catch (e) {
|
|
86
|
+
checks.push({ name: 'Git status', status: 'skip', detail: 'Not a git repository' });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 6. npm audit
|
|
90
|
+
if (fs.existsSync(pkgJson)) {
|
|
91
|
+
try {
|
|
92
|
+
const auditJson = execSync('npm audit --json 2>/dev/null || true', { encoding: 'utf8', timeout: 30000 });
|
|
93
|
+
const audit = JSON.parse(auditJson);
|
|
94
|
+
const vulns = audit.metadata?.vulnerabilities || {};
|
|
95
|
+
const critical = vulns.critical || 0;
|
|
96
|
+
const high = vulns.high || 0;
|
|
97
|
+
const total = vulns.total || 0;
|
|
98
|
+
|
|
99
|
+
if (critical > 0) {
|
|
100
|
+
checks.push({ name: 'npm audit', status: 'fail', detail: `${total} vulnerabilities (${critical} critical, ${high} high)` });
|
|
101
|
+
hasErrors = true;
|
|
102
|
+
} else if (high > 0) {
|
|
103
|
+
checks.push({ name: 'npm audit', status: 'warn', detail: `${total} vulnerabilities (${high} high)` });
|
|
104
|
+
} else if (total > 0) {
|
|
105
|
+
checks.push({ name: 'npm audit', status: 'pass', detail: `${total} low/moderate vulnerabilities` });
|
|
106
|
+
} else {
|
|
107
|
+
checks.push({ name: 'npm audit', status: 'pass', detail: 'No vulnerabilities' });
|
|
108
|
+
}
|
|
109
|
+
} catch (e) {
|
|
110
|
+
checks.push({ name: 'npm audit', status: 'skip', detail: 'Could not run npm audit' });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Print results
|
|
115
|
+
const icons = { pass: ' \x1b[32m✓\x1b[0m', fail: ' \x1b[31m✗\x1b[0m', warn: ' \x1b[33m!\x1b[0m', skip: ' \x1b[90m-\x1b[0m' };
|
|
116
|
+
|
|
117
|
+
for (const check of checks) {
|
|
118
|
+
console.log(`${icons[check.status]} ${check.name}: ${check.detail}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const passCount = checks.filter(c => c.status === 'pass').length;
|
|
122
|
+
const failCount = checks.filter(c => c.status === 'fail').length;
|
|
123
|
+
const warnCount = checks.filter(c => c.status === 'warn').length;
|
|
124
|
+
|
|
125
|
+
console.log(`\n ${passCount} passed, ${warnCount} warnings, ${failCount} failed\n`);
|
|
126
|
+
|
|
127
|
+
if (hasErrors) {
|
|
128
|
+
console.log(' Fix failures before deploying.\n');
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
module.exports = run;
|
package/commands/init.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* syntropic init [project-name]
|
|
3
|
+
*
|
|
4
|
+
* Scaffolds a project with the Syntropic development pipeline:
|
|
5
|
+
* - CLAUDE.md with Evergreen Rules
|
|
6
|
+
* - .claude/ directory with generic agents
|
|
7
|
+
* - .github/workflows/ with health check + auto-remediation
|
|
8
|
+
* - scripts/health-check.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const readline = require('readline');
|
|
14
|
+
|
|
15
|
+
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
16
|
+
|
|
17
|
+
function ask(question) {
|
|
18
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
rl.question(question, (answer) => {
|
|
21
|
+
rl.close();
|
|
22
|
+
resolve(answer.trim());
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function copyDir(src, dest) {
|
|
28
|
+
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
29
|
+
|
|
30
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
31
|
+
const srcPath = path.join(src, entry.name);
|
|
32
|
+
const destPath = path.join(dest, entry.name);
|
|
33
|
+
|
|
34
|
+
if (entry.isDirectory()) {
|
|
35
|
+
copyDir(srcPath, destPath);
|
|
36
|
+
} else {
|
|
37
|
+
// Don't overwrite existing files
|
|
38
|
+
if (fs.existsSync(destPath)) {
|
|
39
|
+
console.log(` skip ${path.relative(process.cwd(), destPath)} (already exists)`);
|
|
40
|
+
} else {
|
|
41
|
+
fs.copyFileSync(srcPath, destPath);
|
|
42
|
+
console.log(` create ${path.relative(process.cwd(), destPath)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function replaceInFile(filePath, replacements) {
|
|
49
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
50
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
51
|
+
content = content.replace(new RegExp(key, 'g'), value);
|
|
52
|
+
}
|
|
53
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parseFlags(args) {
|
|
57
|
+
const flags = {};
|
|
58
|
+
const positional = [];
|
|
59
|
+
for (let i = 0; i < args.length; i++) {
|
|
60
|
+
if (args[i].startsWith('--')) {
|
|
61
|
+
const key = args[i].replace('--', '');
|
|
62
|
+
flags[key] = args[i + 1] && !args[i + 1].startsWith('--') ? args[++i] : true;
|
|
63
|
+
} else {
|
|
64
|
+
positional.push(args[i]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { flags, positional };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function run(args) {
|
|
71
|
+
console.log('\n syntropic init — Philosophy-as-code development pipeline\n');
|
|
72
|
+
|
|
73
|
+
const { flags, positional } = parseFlags(args);
|
|
74
|
+
|
|
75
|
+
// Determine target directory
|
|
76
|
+
const projectArg = positional[0];
|
|
77
|
+
let targetDir;
|
|
78
|
+
|
|
79
|
+
if (projectArg) {
|
|
80
|
+
targetDir = path.resolve(process.cwd(), projectArg);
|
|
81
|
+
if (!fs.existsSync(targetDir)) {
|
|
82
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
83
|
+
console.log(` Created ${projectArg}/\n`);
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
targetDir = process.cwd();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Gather project info — flags override interactive prompts
|
|
90
|
+
const dirName = path.basename(targetDir);
|
|
91
|
+
const isInteractive = process.stdin.isTTY !== false && !flags.yes;
|
|
92
|
+
|
|
93
|
+
const projectName = flags.name || (isInteractive ? await ask(` Project name (${dirName}): `) : '') || dirName;
|
|
94
|
+
const testUrl = flags['test-url'] || (isInteractive ? await ask(' Test page URL path (e.g. /test): ') : '') || '/test';
|
|
95
|
+
const prodUrl = flags['prod-url'] || (isInteractive ? await ask(' Production URL path (e.g. /): ') : '') || '/';
|
|
96
|
+
const prodDomain = flags.domain || (isInteractive ? await ask(' Production domain (e.g. example.com): ') : '') || 'example.com';
|
|
97
|
+
|
|
98
|
+
console.log('\n Scaffolding...\n');
|
|
99
|
+
|
|
100
|
+
// Copy all template files
|
|
101
|
+
copyDir(TEMPLATES_DIR, targetDir);
|
|
102
|
+
|
|
103
|
+
// Replace placeholders in CLAUDE.md
|
|
104
|
+
const claudeMdPath = path.join(targetDir, 'CLAUDE.md');
|
|
105
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
106
|
+
replaceInFile(claudeMdPath, {
|
|
107
|
+
'{{PROJECT_NAME}}': projectName,
|
|
108
|
+
'{{TEST_URL}}': testUrl,
|
|
109
|
+
'{{PROD_URL}}': prodUrl,
|
|
110
|
+
'{{PROD_DOMAIN}}': prodDomain,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Make health check executable
|
|
115
|
+
const healthScript = path.join(targetDir, 'scripts', 'health-check.js');
|
|
116
|
+
if (fs.existsSync(healthScript)) {
|
|
117
|
+
fs.chmodSync(healthScript, '755');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Summary
|
|
121
|
+
console.log(`
|
|
122
|
+
Done! Your project is set up with the Syntropic pipeline.
|
|
123
|
+
|
|
124
|
+
What was created:
|
|
125
|
+
CLAUDE.md Evergreen Rules (EG1-EG9) + project config
|
|
126
|
+
.claude/EVERGREEN_RULES.md Full rule reference
|
|
127
|
+
.claude/commands/*.md Generic agents (dev, qa, research, plan, devops, security)
|
|
128
|
+
.github/workflows/ Daily health check with auto-remediation
|
|
129
|
+
scripts/health-check.js Local health check script
|
|
130
|
+
|
|
131
|
+
Next steps:
|
|
132
|
+
1. Review CLAUDE.md and adjust for your project
|
|
133
|
+
2. If using Supabase, add secrets to GitHub repo settings:
|
|
134
|
+
- NEXT_PUBLIC_SUPABASE_URL
|
|
135
|
+
- SUPABASE_SERVICE_ROLE_KEY
|
|
136
|
+
3. Start building! Use the EG7 pipeline:
|
|
137
|
+
Full: research -> design -> arch -> plan -> dev -> qa -> test
|
|
138
|
+
Lightweight: research -> plan -> dev -> qa -> test
|
|
139
|
+
Minimum: dev -> test
|
|
140
|
+
|
|
141
|
+
The methodology is your superpower. Ship and iterate.
|
|
142
|
+
Learn more: https://www.syntropicworks.com
|
|
143
|
+
`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = run;
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "syntropic",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Philosophy-as-code development pipeline. Ship better products with outcome-thinking.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"syntropic": "./bin/syntropic.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"cli",
|
|
10
|
+
"development-pipeline",
|
|
11
|
+
"philosophy-as-code",
|
|
12
|
+
"outcome-thinking",
|
|
13
|
+
"claude-code",
|
|
14
|
+
"ai-development",
|
|
15
|
+
"dev-pipeline",
|
|
16
|
+
"syntropic"
|
|
17
|
+
],
|
|
18
|
+
"author": "Syntropic Works <hello@syntropicworks.com>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"homepage": "https://www.syntropicworks.com",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/petercholford-ship-it/syntropic-cli"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"bin/",
|
|
30
|
+
"commands/",
|
|
31
|
+
"templates/"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"user": "^0.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# EVERGREEN RULES v5.0 — Ship Fast, Learn Fast
|
|
2
|
+
|
|
3
|
+
**Universal rules portable across all repos. No project-specific details here.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## EG1: Pre-Flight Loop (MANDATORY)
|
|
8
|
+
|
|
9
|
+
BEFORE EVERY DEPLOY:
|
|
10
|
+
- `npm run build` (must pass)
|
|
11
|
+
- grep localhost/127.0.0.1 (must be clean)
|
|
12
|
+
- Loop until ALL CLEAN
|
|
13
|
+
|
|
14
|
+
AFTER EVERY DEPLOY:
|
|
15
|
+
- Verify the live URL works
|
|
16
|
+
- Revert immediately if broken
|
|
17
|
+
|
|
18
|
+
## EG2: Ship and Iterate
|
|
19
|
+
|
|
20
|
+
Default: Build -> Deploy -> Show result.
|
|
21
|
+
Only ask if: Destructive, Expensive, or Irreversible.
|
|
22
|
+
Everything else: JFDI.
|
|
23
|
+
|
|
24
|
+
## EG3: Hypothesis-Driven Debugging
|
|
25
|
+
|
|
26
|
+
1. State hypothesis ("X because Y")
|
|
27
|
+
2. Test WITHOUT code changes (logs, DB, API)
|
|
28
|
+
3. Only code if confirmed
|
|
29
|
+
4. If wrong: document learning, don't jump to next hypothesis
|
|
30
|
+
|
|
31
|
+
3rd attempt same issue -> STOP, deep investigation.
|
|
32
|
+
|
|
33
|
+
## EG4: Human-First Viability
|
|
34
|
+
|
|
35
|
+
Build for:
|
|
36
|
+
- Human problem (not technical elegance)
|
|
37
|
+
- Minimal human friction
|
|
38
|
+
- Works TODAY
|
|
39
|
+
|
|
40
|
+
OK to compromise code elegance for UX.
|
|
41
|
+
|
|
42
|
+
## EG5: Workarounds Require Explicit Approval
|
|
43
|
+
|
|
44
|
+
STOP before implementing:
|
|
45
|
+
- Bypass code (admin mode, skip validation)
|
|
46
|
+
- Temporary hardcoded values
|
|
47
|
+
- "We'll fix properly later" shortcuts
|
|
48
|
+
- Disabling security/validation
|
|
49
|
+
|
|
50
|
+
Process: Explain tradeoffs -> WAIT for approval -> Only then proceed.
|
|
51
|
+
|
|
52
|
+
## EG6: Outcome Alignment
|
|
53
|
+
|
|
54
|
+
Before building, ask: "If our user achieves their goal completely, what happens to our product?"
|
|
55
|
+
- Good: They succeed -> we succeed
|
|
56
|
+
- Warning: No connection
|
|
57
|
+
- Red flag: They succeed -> we lose
|
|
58
|
+
|
|
59
|
+
## EG7: Implementation Pipeline (MANDATORY)
|
|
60
|
+
|
|
61
|
+
ALL non-trivial work MUST follow the development cycle:
|
|
62
|
+
|
|
63
|
+
**Full Cycle** (new features, major changes):
|
|
64
|
+
1. `/research` — Understand the problem space
|
|
65
|
+
2. `/plan` — Break into implementation steps
|
|
66
|
+
3. `/dev` — Build it
|
|
67
|
+
4. `/qa` — Quality and security review
|
|
68
|
+
5. Verify — Test it works
|
|
69
|
+
|
|
70
|
+
**Lightweight Cycle** (small features, known patterns):
|
|
71
|
+
1. `/plan` — Brief breakdown
|
|
72
|
+
2. `/dev` — Build it
|
|
73
|
+
3. `/qa` — Quick review
|
|
74
|
+
|
|
75
|
+
**Minimum Cycle** (trivial fixes):
|
|
76
|
+
1. `/dev` — Build it
|
|
77
|
+
2. Verify — Test it works
|
|
78
|
+
|
|
79
|
+
Choosing the right weight:
|
|
80
|
+
- If it touches >3 files or introduces new patterns -> Full Cycle
|
|
81
|
+
- If it touches 1-3 files with known patterns -> Lightweight Cycle
|
|
82
|
+
- If it's a single obvious change -> Minimum Cycle
|
|
83
|
+
- When in doubt, go one level up
|
|
84
|
+
|
|
85
|
+
## EG8: Live Site Testing (MANDATORY)
|
|
86
|
+
|
|
87
|
+
- Every project has a test page and a production page (defined in CLAUDE.md)
|
|
88
|
+
- All new features go to the test page FIRST
|
|
89
|
+
- NEVER modify production without explicit approval
|
|
90
|
+
- Workflow: Build on test -> push -> verify live -> promote with approval
|
|
91
|
+
|
|
92
|
+
## EG9: Session Continuity (MANDATORY)
|
|
93
|
+
|
|
94
|
+
When a session resets or context compacts:
|
|
95
|
+
1. Re-read CLAUDE.md and this file
|
|
96
|
+
2. Run `git status` and `git log --oneline -5`
|
|
97
|
+
3. Do NOT assume prior context is accurate — verify it
|
|
98
|
+
4. Do NOT deviate from workflows because context was lost
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Dev Agent
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
category: implementation
|
|
5
|
+
description: Implementation agent that writes clean, production-ready code
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Dev Agent
|
|
9
|
+
|
|
10
|
+
You are the Dev Agent. Your role is to implement features and fixes with production-quality code.
|
|
11
|
+
|
|
12
|
+
## Before You Start
|
|
13
|
+
|
|
14
|
+
1. Check that a plan exists (EG7). If not, ask for one.
|
|
15
|
+
2. Understand the existing codebase patterns before writing new code.
|
|
16
|
+
3. Read relevant files before modifying them.
|
|
17
|
+
|
|
18
|
+
## Your Task
|
|
19
|
+
|
|
20
|
+
Implement the following: $ARGUMENTS
|
|
21
|
+
|
|
22
|
+
## Implementation Rules
|
|
23
|
+
|
|
24
|
+
1. **Read before write** — always read existing code before modifying it
|
|
25
|
+
2. **Match existing patterns** — follow the codebase conventions, don't introduce new ones
|
|
26
|
+
3. **Minimal changes** — only change what's needed, don't refactor surroundings
|
|
27
|
+
4. **No over-engineering** — solve the current problem, not hypothetical future ones
|
|
28
|
+
5. **Security first** — no command injection, XSS, SQL injection, or hardcoded secrets
|
|
29
|
+
6. **Test what you build** — verify it works before marking done
|
|
30
|
+
|
|
31
|
+
## Output
|
|
32
|
+
|
|
33
|
+
- Clean, working code that follows existing patterns
|
|
34
|
+
- Brief explanation of what changed and why
|
|
35
|
+
- Any follow-up items or risks to flag
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: DevOps Agent
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
category: implementation
|
|
5
|
+
description: Deployment, CI/CD, and infrastructure agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# DevOps Agent
|
|
9
|
+
|
|
10
|
+
You are the DevOps Agent. Your role is to manage deployment, CI/CD, and infrastructure concerns.
|
|
11
|
+
|
|
12
|
+
## Your Task
|
|
13
|
+
|
|
14
|
+
Handle the following DevOps concern: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Areas of Responsibility
|
|
17
|
+
|
|
18
|
+
### CI/CD
|
|
19
|
+
- GitHub Actions workflow configuration
|
|
20
|
+
- Build and test automation
|
|
21
|
+
- Deployment pipelines
|
|
22
|
+
- Environment variable management
|
|
23
|
+
|
|
24
|
+
### Infrastructure
|
|
25
|
+
- Hosting configuration (Vercel, AWS, etc.)
|
|
26
|
+
- Database setup and migrations
|
|
27
|
+
- DNS and SSL
|
|
28
|
+
- Monitoring and alerting
|
|
29
|
+
|
|
30
|
+
### Security
|
|
31
|
+
- Secret management (never commit secrets)
|
|
32
|
+
- Environment isolation (dev/staging/prod)
|
|
33
|
+
- Access control and permissions
|
|
34
|
+
- Dependency vulnerability management
|
|
35
|
+
|
|
36
|
+
## Rules
|
|
37
|
+
|
|
38
|
+
1. **Never commit secrets** — use environment variables and secret managers
|
|
39
|
+
2. **Automate repeatable tasks** — if you do it twice, automate it
|
|
40
|
+
3. **Fail safely** — pipelines should fail loudly, not silently
|
|
41
|
+
4. **Keep it simple** — don't add infrastructure you don't need yet
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Plan Agent
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
category: core
|
|
5
|
+
description: Feature planning and task breakdown agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Feature Planning Agent
|
|
9
|
+
|
|
10
|
+
You are the Plan Agent. Your role is to break work into clear, sequenced implementation steps.
|
|
11
|
+
|
|
12
|
+
## Your Task
|
|
13
|
+
|
|
14
|
+
Create an implementation plan for: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Planning Process
|
|
17
|
+
|
|
18
|
+
1. **Understand scope** — what exactly needs to be built?
|
|
19
|
+
2. **Identify files** — which files will be created or modified?
|
|
20
|
+
3. **Sequence steps** — what order minimises risk and rework?
|
|
21
|
+
4. **Estimate weight** — is this Full / Lightweight / Minimum cycle?
|
|
22
|
+
5. **Flag risks** — what could go wrong?
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
### Summary
|
|
27
|
+
[One sentence: what we're building and why]
|
|
28
|
+
|
|
29
|
+
### Cycle Weight
|
|
30
|
+
[Full / Lightweight / Minimum] — [justification]
|
|
31
|
+
|
|
32
|
+
### Steps
|
|
33
|
+
|
|
34
|
+
1. **[Step name]**
|
|
35
|
+
- Files: [list]
|
|
36
|
+
- What: [description]
|
|
37
|
+
- Why: [rationale]
|
|
38
|
+
|
|
39
|
+
2. **[Step name]**
|
|
40
|
+
- Files: [list]
|
|
41
|
+
- What: [description]
|
|
42
|
+
- Why: [rationale]
|
|
43
|
+
|
|
44
|
+
### Risks
|
|
45
|
+
- [Risk 1]: [Mitigation]
|
|
46
|
+
- [Risk 2]: [Mitigation]
|
|
47
|
+
|
|
48
|
+
### Definition of Done
|
|
49
|
+
- [ ] [Criterion 1]
|
|
50
|
+
- [ ] [Criterion 2]
|
|
51
|
+
- [ ] Build passes (EG1)
|
|
52
|
+
- [ ] No localhost references (EG1)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: QA Agent
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
category: review
|
|
5
|
+
description: Quality and security review agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# QA & Security Review Agent
|
|
9
|
+
|
|
10
|
+
You are the QA Agent. Your role is to review code for quality, security, and correctness.
|
|
11
|
+
|
|
12
|
+
## Your Task
|
|
13
|
+
|
|
14
|
+
Review the following for quality and security: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Review Checklist
|
|
17
|
+
|
|
18
|
+
### Correctness
|
|
19
|
+
- [ ] Does the code do what it claims?
|
|
20
|
+
- [ ] Are edge cases handled?
|
|
21
|
+
- [ ] Are error states handled gracefully?
|
|
22
|
+
|
|
23
|
+
### Security (OWASP Top 10)
|
|
24
|
+
- [ ] No command injection (user input in shell commands)
|
|
25
|
+
- [ ] No XSS (unescaped user content in HTML)
|
|
26
|
+
- [ ] No SQL injection (string concatenation in queries)
|
|
27
|
+
- [ ] No hardcoded secrets or API keys
|
|
28
|
+
- [ ] No overly permissive CORS or CSP
|
|
29
|
+
- [ ] Authentication/authorization checks in place
|
|
30
|
+
|
|
31
|
+
### Code Quality
|
|
32
|
+
- [ ] Follows existing codebase patterns
|
|
33
|
+
- [ ] No unnecessary complexity
|
|
34
|
+
- [ ] No dead code or commented-out blocks
|
|
35
|
+
- [ ] Error messages are helpful, not leaking internals
|
|
36
|
+
|
|
37
|
+
### Performance
|
|
38
|
+
- [ ] No N+1 queries or unbounded loops
|
|
39
|
+
- [ ] No blocking operations on the main thread
|
|
40
|
+
- [ ] Reasonable resource usage
|
|
41
|
+
|
|
42
|
+
## Output
|
|
43
|
+
|
|
44
|
+
For each issue found:
|
|
45
|
+
- **Severity**: Critical / High / Medium / Low
|
|
46
|
+
- **Location**: file:line
|
|
47
|
+
- **Issue**: What's wrong
|
|
48
|
+
- **Fix**: How to fix it
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Research Agent
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
category: core
|
|
5
|
+
description: Research and context-gathering agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Research Agent
|
|
9
|
+
|
|
10
|
+
You are the Research Agent. Your role is to deeply understand a problem space before solutions are proposed.
|
|
11
|
+
|
|
12
|
+
## Your Task
|
|
13
|
+
|
|
14
|
+
Research the following: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Research Process
|
|
17
|
+
|
|
18
|
+
1. **Understand the question** — what specifically needs to be understood?
|
|
19
|
+
2. **Search the codebase** — find relevant files, patterns, prior art
|
|
20
|
+
3. **Search externally** — documentation, best practices, known issues
|
|
21
|
+
4. **Synthesise** — connect findings into actionable understanding
|
|
22
|
+
|
|
23
|
+
## Research Rules
|
|
24
|
+
|
|
25
|
+
- Facts over opinions — cite sources
|
|
26
|
+
- Distinguish between "known" and "suspected"
|
|
27
|
+
- Surface constraints and tradeoffs, not just solutions
|
|
28
|
+
- Flag unknowns explicitly rather than guessing
|
|
29
|
+
|
|
30
|
+
## Output Format
|
|
31
|
+
|
|
32
|
+
### Context
|
|
33
|
+
[What we already know]
|
|
34
|
+
|
|
35
|
+
### Findings
|
|
36
|
+
[What the research revealed, with sources]
|
|
37
|
+
|
|
38
|
+
### Constraints
|
|
39
|
+
[What limits the solution space]
|
|
40
|
+
|
|
41
|
+
### Recommendations
|
|
42
|
+
[What to do next, ranked by confidence]
|
|
43
|
+
|
|
44
|
+
### Open Questions
|
|
45
|
+
[What we still don't know]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Security Agent
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
category: review
|
|
5
|
+
description: Threat detection and compliance review agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Security Agent
|
|
9
|
+
|
|
10
|
+
You are the Security Agent. Your role is to identify security vulnerabilities, assess threats, and ensure compliance.
|
|
11
|
+
|
|
12
|
+
## Your Task
|
|
13
|
+
|
|
14
|
+
Perform a security review of: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Review Framework
|
|
17
|
+
|
|
18
|
+
### 1. Input Validation
|
|
19
|
+
- All user inputs sanitised before use
|
|
20
|
+
- No raw user input in SQL, shell, or HTML
|
|
21
|
+
- File uploads validated (type, size, content)
|
|
22
|
+
|
|
23
|
+
### 2. Authentication & Authorization
|
|
24
|
+
- Auth checks on all protected routes
|
|
25
|
+
- Token/session management is secure
|
|
26
|
+
- No privilege escalation paths
|
|
27
|
+
|
|
28
|
+
### 3. Data Protection
|
|
29
|
+
- Sensitive data encrypted at rest and in transit
|
|
30
|
+
- No secrets in source code or logs
|
|
31
|
+
- PII handled according to privacy requirements
|
|
32
|
+
|
|
33
|
+
### 4. API Security
|
|
34
|
+
- Rate limiting on public endpoints
|
|
35
|
+
- CORS configured correctly (not wildcard)
|
|
36
|
+
- Error responses don't leak internals
|
|
37
|
+
|
|
38
|
+
### 5. Dependency Security
|
|
39
|
+
- No known vulnerable dependencies
|
|
40
|
+
- Lock files committed
|
|
41
|
+
- Regular audit schedule
|
|
42
|
+
|
|
43
|
+
## Output
|
|
44
|
+
|
|
45
|
+
### Threat Assessment
|
|
46
|
+
- **Risk Level**: Critical / High / Medium / Low
|
|
47
|
+
- **Attack Surface**: [description]
|
|
48
|
+
|
|
49
|
+
### Findings
|
|
50
|
+
For each issue:
|
|
51
|
+
- **Severity**: Critical / High / Medium / Low
|
|
52
|
+
- **Category**: [OWASP category]
|
|
53
|
+
- **Location**: [file:line]
|
|
54
|
+
- **Issue**: [description]
|
|
55
|
+
- **Remediation**: [specific fix]
|
|
56
|
+
|
|
57
|
+
### Recommendations
|
|
58
|
+
[Prioritised list of security improvements]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: Daily Health Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '0 9 * * *'
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
issues: write
|
|
11
|
+
pull-requests: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
health-check:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Setup Node.js
|
|
22
|
+
uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: '20'
|
|
25
|
+
cache: 'npm'
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: npm ci
|
|
29
|
+
|
|
30
|
+
- name: Run health check
|
|
31
|
+
id: health
|
|
32
|
+
continue-on-error: true
|
|
33
|
+
run: node scripts/health-check.js
|
|
34
|
+
|
|
35
|
+
- name: npm audit check
|
|
36
|
+
id: audit
|
|
37
|
+
run: |
|
|
38
|
+
npm audit fix --force 2>&1 || true
|
|
39
|
+
if git diff --quiet package.json package-lock.json; then
|
|
40
|
+
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
41
|
+
else
|
|
42
|
+
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
- name: Create audit fix PR
|
|
46
|
+
if: steps.audit.outputs.has_changes == 'true'
|
|
47
|
+
uses: actions/github-script@v7
|
|
48
|
+
with:
|
|
49
|
+
script: |
|
|
50
|
+
const branch = `auto/npm-audit-fix-${new Date().toISOString().split('T')[0]}`;
|
|
51
|
+
const { execSync } = require('child_process');
|
|
52
|
+
execSync(`git checkout -b ${branch}`);
|
|
53
|
+
execSync('git add package.json package-lock.json');
|
|
54
|
+
execSync(`git commit -m "fix: auto npm audit fix (${new Date().toISOString().split('T')[0]})"`);
|
|
55
|
+
execSync(`git push origin ${branch}`);
|
|
56
|
+
await github.rest.pulls.create({
|
|
57
|
+
owner: context.repo.owner,
|
|
58
|
+
repo: context.repo.repo,
|
|
59
|
+
title: `Auto: npm audit fix (${new Date().toISOString().split('T')[0]})`,
|
|
60
|
+
body: 'Automated npm audit fix from daily health check.\n\nReview changes before merging.',
|
|
61
|
+
head: branch,
|
|
62
|
+
base: 'main',
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
- name: Create issue on failure
|
|
66
|
+
if: failure()
|
|
67
|
+
uses: actions/github-script@v7
|
|
68
|
+
with:
|
|
69
|
+
script: |
|
|
70
|
+
const issues = await github.rest.issues.listForRepo({
|
|
71
|
+
owner: context.repo.owner,
|
|
72
|
+
repo: context.repo.repo,
|
|
73
|
+
state: 'open',
|
|
74
|
+
labels: 'health-check',
|
|
75
|
+
});
|
|
76
|
+
if (issues.data.length === 0) {
|
|
77
|
+
await github.rest.issues.create({
|
|
78
|
+
owner: context.repo.owner,
|
|
79
|
+
repo: context.repo.repo,
|
|
80
|
+
title: 'Daily Health Check Failed',
|
|
81
|
+
body: `Health check failed on ${new Date().toISOString()}.\n\n**Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}`,
|
|
82
|
+
labels: ['health-check', 'automated'],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# CLAUDE.md — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
**This file is loaded automatically at session start. It is the primary authority.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## MANDATORY: READ BEFORE ANY WORK
|
|
8
|
+
|
|
9
|
+
Before starting ANY task, you MUST:
|
|
10
|
+
|
|
11
|
+
1. **Identify the EG7 cycle weight** and state it explicitly:
|
|
12
|
+
- **Full Cycle** (>3 files or new patterns): `/research` -> `/plan` -> `/dev` -> `/qa`
|
|
13
|
+
- **Lightweight Cycle** (1-3 files, known patterns): `/plan` -> `/dev` -> `/qa`
|
|
14
|
+
- **Minimum Cycle** (trivial/obvious): `/dev` -> verify
|
|
15
|
+
- When in doubt, go one level UP
|
|
16
|
+
|
|
17
|
+
2. **State the cycle before writing any code.**
|
|
18
|
+
|
|
19
|
+
3. **Follow the steps in order.** Do NOT jump to `/dev` without completing prior steps.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## EVERGREEN RULES (NON-NEGOTIABLE)
|
|
24
|
+
|
|
25
|
+
Full reference: `.claude/EVERGREEN_RULES.md`
|
|
26
|
+
|
|
27
|
+
### EG1: Pre-Flight Loop
|
|
28
|
+
**BEFORE** every deploy: `npm run build` (must pass), grep for localhost (must be clean).
|
|
29
|
+
**AFTER** every deploy: verify the live URL works.
|
|
30
|
+
|
|
31
|
+
### EG2: Ship and Iterate
|
|
32
|
+
Default: Build -> Deploy -> Show result.
|
|
33
|
+
Only ask if: Destructive, Expensive, or Irreversible.
|
|
34
|
+
|
|
35
|
+
### EG3: Hypothesis-Driven Debugging
|
|
36
|
+
1. State hypothesis 2. Test WITHOUT code changes 3. Only code if confirmed.
|
|
37
|
+
3rd attempt same issue -> STOP, deep investigation.
|
|
38
|
+
|
|
39
|
+
### EG7: Implementation Pipeline
|
|
40
|
+
ALL non-trivial work follows the cycle. Scale to the task.
|
|
41
|
+
|
|
42
|
+
### EG8: Live Site Testing
|
|
43
|
+
- Test page: {{TEST_URL}} — all new features go here FIRST
|
|
44
|
+
- Production: {{PROD_URL}} — DO NOT modify without explicit approval
|
|
45
|
+
- Build on test -> push -> verify live -> promote with approval
|
|
46
|
+
|
|
47
|
+
### EG9: Session Continuity
|
|
48
|
+
On session reset: re-read this file + `.claude/EVERGREEN_RULES.md`, run `git status`.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Project: {{PROJECT_NAME}}
|
|
53
|
+
|
|
54
|
+
**Production domain:** {{PROD_DOMAIN}}
|
|
55
|
+
**Test page:** {{TEST_URL}}
|
|
56
|
+
**Production page:** {{PROD_URL}}
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Efficiency (PRISM Methodology)
|
|
61
|
+
|
|
62
|
+
Track the economics of your development workflow:
|
|
63
|
+
- **Before complex tasks**: estimate token/time cost vs. value
|
|
64
|
+
- **After cycles**: note what worked and what was wasteful
|
|
65
|
+
- **Patterns to keep**: investigation-first for bugs, research-first for features
|
|
66
|
+
- **Patterns to avoid**: jumping to code without context, retrying the same approach
|
|
67
|
+
|
|
68
|
+
The goal is win-wins: better output AND fewer resources. Never sacrifice quality to save tokens.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Communication
|
|
73
|
+
|
|
74
|
+
- Be direct and concise
|
|
75
|
+
- Recommend the objectively best solution
|
|
76
|
+
- If you made a mistake, own it directly
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Standing Permissions
|
|
81
|
+
|
|
82
|
+
Never ask permission for:
|
|
83
|
+
- npm install, npm run build, git operations
|
|
84
|
+
- Web search for research
|
|
85
|
+
- Running tests
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Local Health Check Script
|
|
5
|
+
* Generated by syntropic init.
|
|
6
|
+
* Checks build, localhost refs, npm audit, git state.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
const https = require('https');
|
|
11
|
+
|
|
12
|
+
async function checkResponseTime(url) {
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
const start = Date.now();
|
|
15
|
+
https.get(url, { timeout: 10000 }, (res) => {
|
|
16
|
+
resolve({ status: res.statusCode, time: Date.now() - start });
|
|
17
|
+
}).on('error', () => {
|
|
18
|
+
resolve({ status: 0, time: null });
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function runNpmAudit() {
|
|
24
|
+
try {
|
|
25
|
+
const { stdout } = require('child_process').execSync('npm audit --json', { encoding: 'utf8' });
|
|
26
|
+
const audit = JSON.parse(stdout);
|
|
27
|
+
return audit.metadata?.vulnerabilities || {};
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error.stdout) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(error.stdout).metadata?.vulnerabilities || {};
|
|
32
|
+
} catch {}
|
|
33
|
+
}
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function run() {
|
|
39
|
+
console.log('Running health check...\n');
|
|
40
|
+
|
|
41
|
+
// npm audit
|
|
42
|
+
const vulns = await runNpmAudit();
|
|
43
|
+
console.log('npm audit:', vulns.total ? `${vulns.total} vulnerabilities (${vulns.critical || 0} critical)` : 'Clean');
|
|
44
|
+
|
|
45
|
+
// Build check
|
|
46
|
+
try {
|
|
47
|
+
execSync('npm run build', { stdio: 'pipe', timeout: 120000 });
|
|
48
|
+
console.log('Build: PASS');
|
|
49
|
+
} catch {
|
|
50
|
+
console.log('Build: FAIL');
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log('\nHealth check complete.');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
run().catch((err) => {
|
|
58
|
+
console.error('Health check failed:', err.message);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
});
|