waitsec 0.2.0 → 0.4.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/.cursor-plugin/plugin.json +1 -1
- package/README.md +51 -25
- package/bin/cli.mjs +266 -0
- package/package.json +8 -4
- package/plugin.json +1 -1
- package/rules/AGENTS.md +3 -1
- package/rules/waitsec.md +11 -0
- package/skills/waitsec-code/SKILL.md +26 -0
- package/skills/waitsec-core/SKILL.md +70 -0
- package/skills/waitsec-core/verify-first.md +67 -0
- package/skills/waitsec-quality/SKILL.md +34 -0
- package/skills/waitsec-ui/SKILL.md +26 -0
- package/bin/cli.js +0 -66
- /package/skills/{anti-overengineering/SKILL.md → waitsec-core/anti-overengineering.md} +0 -0
- /package/skills/{ask-first/SKILL.md → waitsec-core/ask-first.md} +0 -0
- /package/skills/{debug-first/SKILL.md → waitsec-core/debug-first.md} +0 -0
- /package/skills/{small-diff/SKILL.md → waitsec-core/small-diff.md} +0 -0
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# waitsec
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://skills.sh/fastroware/waitsec"><img src="https://skills.sh/b/fastroware/waitsec" alt="skills.sh"></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/waitsec"><img src="https://img.shields.io/npm/v/waitsec?color=crimson" alt="npm version"></a>
|
|
6
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2ea44f" alt="License: MIT"></a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
3
9
|
> **Hold on. Think first. Code less.**
|
|
4
10
|
|
|
5
11
|
`waitsec` gives your AI coding agent practical guardrails. It prevents AI from writing hundreds of unneeded lines, inventing imaginary requirements, or over-complicating simple tasks.
|
|
@@ -19,19 +25,13 @@ Most AI coding assistants do not fail because they lack knowledge. They fail bec
|
|
|
19
25
|
|
|
20
26
|
---
|
|
21
27
|
|
|
22
|
-
## The
|
|
23
|
-
|
|
24
|
-
### 1. `ask-first`
|
|
25
|
-
If the prompt is missing essential decisions (schemas, storage locations, permissions), the AI must pause and ask 1 to 3 direct questions instead of guessing.
|
|
26
|
-
|
|
27
|
-
### 2. `anti-overengineering`
|
|
28
|
-
The AI must use existing patterns in your codebase and pick the simplest working solution. No speculative abstractions for hypothetical future needs.
|
|
29
|
-
|
|
30
|
-
### 3. `small-diff`
|
|
31
|
-
Modifications stay strictly scoped to what solves the prompt. No cleaning up surrounding files, no global formatting passes, and no unnecessary dependency changes.
|
|
28
|
+
## The 5 Core Guardrails
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
1. **`ask-first`** — If the prompt is missing essential decisions (schemas, storage locations, permissions), the AI must pause and ask 1 to 3 direct questions instead of guessing.
|
|
31
|
+
2. **`anti-overengineering`** — Rejects unneeded design patterns, DTOs, and speculative abstractions. Keeps code lean while strictly enforcing authentication, authorization, and input validation.
|
|
32
|
+
3. **`small-diff`** — Modifications stay strictly scoped to what solves the prompt. No cleaning up surrounding files, no global formatting passes, and no unnecessary dependency changes.
|
|
33
|
+
4. **`debug-first`** — When something breaks, the AI must read the complete error message and stack trace. Never guess fixes or hide errors behind empty try/catch blocks.
|
|
34
|
+
5. **`verify-first`** — Never declare a task complete without proof. Run tests, verify builds, test edge cases, and ensure no regressions occurred before reporting done.
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
@@ -83,10 +83,20 @@ composer require --dev waitsec/waitsec
|
|
|
83
83
|
The post-install script automatically adds `.kilorules` to your root directory.
|
|
84
84
|
|
|
85
85
|
### 7. Agent Skills Directory (skills.sh)
|
|
86
|
-
Install
|
|
86
|
+
Install the full core bundle (recommended):
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
npx skills add fastroware/waitsec
|
|
89
|
+
npx skills add fastroware/waitsec/skills/waitsec-core
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Or install only the module you need:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Individual guardrails
|
|
96
|
+
npx skills add fastroware/waitsec/skills/waitsec-core # All 5 guardrails
|
|
97
|
+
npx skills add fastroware/waitsec/skills/waitsec-quality # Upcoming
|
|
98
|
+
npx skills add fastroware/waitsec/skills/waitsec-code # Upcoming
|
|
99
|
+
npx skills add fastroware/waitsec/skills/waitsec-ui # Upcoming
|
|
90
100
|
```
|
|
91
101
|
|
|
92
102
|
---
|
|
@@ -96,26 +106,42 @@ npx skills add fastroware/waitsec
|
|
|
96
106
|
```text
|
|
97
107
|
waitsec/
|
|
98
108
|
├── skills/
|
|
99
|
-
│ ├──
|
|
100
|
-
│ │
|
|
101
|
-
│ ├──
|
|
109
|
+
│ ├── waitsec-core/ # ACTIVE — Core 5-phase guardrails
|
|
110
|
+
│ │ ├── SKILL.md # Hub: pipeline overview + links to detail files
|
|
111
|
+
│ │ ├── ask-first.md # Phase 1: Clarify requirements before coding
|
|
112
|
+
│ │ ├── anti-overengineering.md # Phase 2: Lean code + non-negotiable security
|
|
113
|
+
│ │ ├── small-diff.md # Phase 3: Surgical, proportional edits only
|
|
114
|
+
│ │ ├── debug-first.md # Phase 4: Root cause analysis before guessing
|
|
115
|
+
│ │ └── verify-first.md # Phase 5: Proof before declaring done
|
|
116
|
+
│ │
|
|
117
|
+
│ ├── waitsec-quality/ # UPCOMING — Security auditing, testing discipline
|
|
102
118
|
│ │ └── SKILL.md
|
|
103
|
-
│ ├──
|
|
119
|
+
│ ├── waitsec-code/ # UPCOMING — Clean code, anti-comment pollution
|
|
104
120
|
│ │ └── SKILL.md
|
|
105
|
-
│ └──
|
|
121
|
+
│ └── waitsec-ui/ # UPCOMING — Anti-slop CSS, responsive guardrails
|
|
106
122
|
│ └── SKILL.md
|
|
123
|
+
│
|
|
107
124
|
├── rules/
|
|
108
|
-
│ ├── AGENTS.md
|
|
109
|
-
│ └── waitsec.md
|
|
125
|
+
│ ├── AGENTS.md # Universal rule pointer (Antigravity / Claude Code)
|
|
126
|
+
│ └── waitsec.md # All-in-one bundled rules (Kilo Code / Cline / Cursor)
|
|
110
127
|
├── bin/
|
|
111
|
-
│ └── cli.
|
|
112
|
-
├── plugin.json
|
|
113
|
-
├── package.json
|
|
114
|
-
└── composer.json
|
|
128
|
+
│ └── cli.mjs # Interactive terminal installer (Clack prompts)
|
|
129
|
+
├── plugin.json # Antigravity plugin manifest
|
|
130
|
+
├── package.json # npm / npx manifest
|
|
131
|
+
└── composer.json # Composer / Laravel manifest
|
|
115
132
|
```
|
|
116
133
|
|
|
117
134
|
---
|
|
118
135
|
|
|
136
|
+
## Roadmap: Core & Extensions
|
|
137
|
+
|
|
138
|
+
- **Core (Active)**: The 5 foundational guardrails (`ask-first`, `anti-overengineering`, `small-diff`, `debug-first`, `verify-first`).
|
|
139
|
+
- **Quality (Upcoming)**: Specialized deep-dives for `security`, `testing`, `performance`, and `accessibility`.
|
|
140
|
+
- **Code (Upcoming)**: Anti-slop comments, naming conventions, and dependency discipline.
|
|
141
|
+
- **UI (Upcoming)**: Anti-slop interface rules, responsive standards, and clean typography.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
119
145
|
## License
|
|
120
146
|
|
|
121
147
|
MIT
|
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import pc from 'picocolors';
|
|
8
|
+
import { intro, outro, select, multiselect, confirm, isCancel, cancel, log, spinner } from '@clack/prompts';
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
13
|
+
const SKILLS_SOURCE_DIR = path.join(REPO_ROOT, 'skills');
|
|
14
|
+
const RULES_SOURCE_FILE = path.join(REPO_ROOT, 'rules', 'waitsec.md');
|
|
15
|
+
|
|
16
|
+
const CORE_SKILL = 'waitsec-core';
|
|
17
|
+
|
|
18
|
+
const AVAILABLE_SKILLS = [
|
|
19
|
+
{
|
|
20
|
+
value: 'waitsec-core',
|
|
21
|
+
label: 'waitsec-core',
|
|
22
|
+
hint: '5 core guardrails: ask-first, anti-overengineering, small-diff, debug-first, verify-first',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
value: 'waitsec-quality',
|
|
26
|
+
label: 'waitsec-quality (preview)',
|
|
27
|
+
hint: 'Security audits, test discipline, data integrity',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
value: 'waitsec-code',
|
|
31
|
+
label: 'waitsec-code (preview)',
|
|
32
|
+
hint: 'Clean code rules, anti-comment noise, dependency control',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
value: 'waitsec-ui',
|
|
36
|
+
label: 'waitsec-ui (preview)',
|
|
37
|
+
hint: 'Anti-slop UI copy & CSS, responsive guardrails',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const AGENTS = [
|
|
42
|
+
{ id: 'antigravity', label: 'Antigravity / Universal', skillDir: '.agents/skills', ruleFile: 'AGENTS.md' },
|
|
43
|
+
{ id: 'claude', label: 'Claude Code', skillDir: '.claude/skills', ruleFile: 'CLAUDE.md' },
|
|
44
|
+
{ id: 'cursor', label: 'Cursor', skillDir: '.cursor/skills', ruleFile: '.cursorrules' },
|
|
45
|
+
{ id: 'kilo', label: 'Kilo Code (VS Code)', skillDir: '.kilo/skills', ruleFile: '.kilorules' },
|
|
46
|
+
{ id: 'cline', label: 'Cline / Roo Code', skillDir: '.cline/skills', ruleFile: '.clinerules' },
|
|
47
|
+
{ id: 'codex', label: 'Codex', skillDir: '.codex/skills', ruleFile: 'AGENTS.md' },
|
|
48
|
+
{ id: 'gemini', label: 'Gemini CLI', skillDir: '.gemini/skills', ruleFile: 'GEMINI.md' },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
function stop(message) {
|
|
52
|
+
cancel(message);
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function copyDirSync(src, dest) {
|
|
57
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
58
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
59
|
+
const srcPath = path.join(src, entry.name);
|
|
60
|
+
const destPath = path.join(dest, entry.name);
|
|
61
|
+
if (entry.isDirectory()) {
|
|
62
|
+
copyDirSync(srcPath, destPath);
|
|
63
|
+
} else {
|
|
64
|
+
fs.copyFileSync(srcPath, destPath);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const POINTER_START = '<!-- waitsec:start -->';
|
|
70
|
+
const POINTER_END = '<!-- waitsec:end -->';
|
|
71
|
+
|
|
72
|
+
function getPointerBlock(skills) {
|
|
73
|
+
return [
|
|
74
|
+
POINTER_START,
|
|
75
|
+
'# waitsec: AI Coding Guardrails',
|
|
76
|
+
'> Hold on. Think first. Code less.',
|
|
77
|
+
'',
|
|
78
|
+
'Follow the waitsec engineering discipline for all tasks in this workspace:',
|
|
79
|
+
'- **Core Guardrails Active**: ' + skills.map(s => '`' + s + '`').join(', '),
|
|
80
|
+
'- When requirements are ambiguous: pause and ask 1 to 3 direct questions with concrete options.',
|
|
81
|
+
'- Keep solutions lean: reject enterprise boilerplate; never compromise security or input validation.',
|
|
82
|
+
'- Keep diffs surgical: touch only the files strictly required to solve the prompt.',
|
|
83
|
+
'- Debug from evidence: inspect stack traces and root causes before guessing.',
|
|
84
|
+
'- Verify before declaring done: run builds, tests, and verify edge cases.',
|
|
85
|
+
POINTER_END,
|
|
86
|
+
].join('\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function updateRuleFile(filePath, content, isPointer = false) {
|
|
90
|
+
if (!fs.existsSync(filePath)) {
|
|
91
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
92
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
93
|
+
return 'created';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const existing = fs.readFileSync(filePath, 'utf8');
|
|
97
|
+
if (isPointer) {
|
|
98
|
+
if (existing.includes(POINTER_START) && existing.includes(POINTER_END)) {
|
|
99
|
+
const regex = new RegExp(`${POINTER_START}[\\s\\S]*?${POINTER_END}`, 'g');
|
|
100
|
+
const updated = existing.replace(regex, content);
|
|
101
|
+
fs.writeFileSync(filePath, updated, 'utf8');
|
|
102
|
+
return 'updated';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (existing.includes('waitsec: AI Coding Guardrails') || existing.includes(POINTER_START)) {
|
|
107
|
+
return 'already-configured';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fs.appendFileSync(filePath, `\n\n${content}`, 'utf8');
|
|
111
|
+
return 'appended';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function detectActiveAgents(baseDir) {
|
|
115
|
+
return AGENTS.filter((agent) => {
|
|
116
|
+
const rootFolder = agent.skillDir.split('/')[0];
|
|
117
|
+
const folderExists = fs.existsSync(path.join(baseDir, rootFolder));
|
|
118
|
+
const ruleExists = agent.ruleFile && fs.existsSync(path.join(baseDir, agent.ruleFile));
|
|
119
|
+
return folderExists || ruleExists;
|
|
120
|
+
}).map((a) => a.id);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function main() {
|
|
124
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
125
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8'));
|
|
126
|
+
console.log(`waitsec v${pkg.version}`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log(`
|
|
131
|
+
${pc.bold(pc.cyan('██╗ ██╗ █████╗ ██╗████████╗███████╗███████╗ ██████╗'))}
|
|
132
|
+
${pc.bold(pc.cyan('██║ ██║██╔══██╗██║╚══██╔══╝██╔════╝██╔════╝██╔════╝'))}
|
|
133
|
+
${pc.bold(pc.cyan('██║ █╗ ██║███████║██║ ██║ ███████╗█████╗ ██║ '))}
|
|
134
|
+
${pc.bold(pc.cyan('██║███╗██║██╔══██║██║ ██║ ╚════██║██╔══╝ ██║ '))}
|
|
135
|
+
${pc.bold(pc.cyan('╚███╔███╔╝██║ ██║██║ ██║ ███████║███████╗╚██████╗'))}
|
|
136
|
+
${pc.bold(pc.cyan(' ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚══════╝ ╚═════╝'))}
|
|
137
|
+
${pc.dim(' "Hold on. Think first. Code less."')}
|
|
138
|
+
`);
|
|
139
|
+
|
|
140
|
+
intro(pc.bold('Install waitsec guardrails into your AI coding setup'));
|
|
141
|
+
|
|
142
|
+
log.step(pc.bold('1. Select Skills to Install'));
|
|
143
|
+
const selectedSkills = await multiselect({
|
|
144
|
+
message: 'Select the skills you want (Press Space to select, Enter to confirm):',
|
|
145
|
+
options: AVAILABLE_SKILLS,
|
|
146
|
+
initialValues: ['waitsec-core'],
|
|
147
|
+
required: 'You must select at least one skill.',
|
|
148
|
+
});
|
|
149
|
+
if (isCancel(selectedSkills)) stop('Installation cancelled.');
|
|
150
|
+
|
|
151
|
+
log.step(pc.bold('2. Choose Installation Scope'));
|
|
152
|
+
const scope = await select({
|
|
153
|
+
message: 'Where do you want waitsec to be installed?',
|
|
154
|
+
options: [
|
|
155
|
+
{
|
|
156
|
+
value: 'project',
|
|
157
|
+
label: 'This project only',
|
|
158
|
+
hint: 'Creates rules and skill folders in current workspace',
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
value: 'global',
|
|
162
|
+
label: 'Everywhere (Global)',
|
|
163
|
+
hint: 'Installs directly to your machine home directory across all projects',
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
});
|
|
167
|
+
if (isCancel(scope)) stop('Installation cancelled.');
|
|
168
|
+
|
|
169
|
+
const baseDir = scope === 'global' ? os.homedir() : process.cwd();
|
|
170
|
+
const detectedAgentIds = detectActiveAgents(baseDir);
|
|
171
|
+
|
|
172
|
+
log.step(pc.bold('3. Choose Your AI Agents / Editors'));
|
|
173
|
+
const chosenAgentIds = await multiselect({
|
|
174
|
+
message: 'Which coding assistants or editors do you use? (Press Space to select):',
|
|
175
|
+
options: AGENTS.map((a) => ({
|
|
176
|
+
value: a.id,
|
|
177
|
+
label: a.label,
|
|
178
|
+
hint: detectedAgentIds.includes(a.id)
|
|
179
|
+
? pc.green('found in environment')
|
|
180
|
+
: pc.dim(a.ruleFile ? `configures ${a.ruleFile}` : 'creates skill folder'),
|
|
181
|
+
})),
|
|
182
|
+
initialValues: detectedAgentIds.length > 0 ? detectedAgentIds : ['antigravity', 'cursor', 'claude', 'kilo'],
|
|
183
|
+
required: 'Please pick at least one assistant or editor.',
|
|
184
|
+
});
|
|
185
|
+
if (isCancel(chosenAgentIds)) stop('Installation cancelled.');
|
|
186
|
+
|
|
187
|
+
const chosenAgents = AGENTS.filter((a) => chosenAgentIds.includes(a.id));
|
|
188
|
+
|
|
189
|
+
let overwrite = false;
|
|
190
|
+
const existingDestinations = [];
|
|
191
|
+
for (const agent of chosenAgents) {
|
|
192
|
+
for (const skill of selectedSkills) {
|
|
193
|
+
const checkPath = path.join(baseDir, agent.skillDir, skill);
|
|
194
|
+
if (fs.existsSync(checkPath)) {
|
|
195
|
+
existingDestinations.push(checkPath);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (existingDestinations.length > 0) {
|
|
201
|
+
const conflictAction = await select({
|
|
202
|
+
message: `${existingDestinations.length} skill folder(s) already exist. What would you like to do?`,
|
|
203
|
+
options: [
|
|
204
|
+
{ value: 'overwrite', label: 'Overwrite with latest version', hint: 'recommended' },
|
|
205
|
+
{ value: 'skip', label: 'Keep existing folders', hint: 'skip copying over existing skills' },
|
|
206
|
+
],
|
|
207
|
+
});
|
|
208
|
+
if (isCancel(conflictAction)) stop('Installation cancelled.');
|
|
209
|
+
overwrite = conflictAction === 'overwrite';
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const s = spinner();
|
|
213
|
+
s.start('Installing waitsec guardrails...');
|
|
214
|
+
|
|
215
|
+
let copiedSkillsCount = 0;
|
|
216
|
+
for (const agent of chosenAgents) {
|
|
217
|
+
for (const skill of selectedSkills) {
|
|
218
|
+
const srcDir = path.join(SKILLS_SOURCE_DIR, skill);
|
|
219
|
+
const destDir = path.join(baseDir, agent.skillDir, skill);
|
|
220
|
+
|
|
221
|
+
if (!fs.existsSync(srcDir)) continue;
|
|
222
|
+
if (fs.existsSync(destDir) && !overwrite) continue;
|
|
223
|
+
|
|
224
|
+
if (fs.existsSync(destDir) && overwrite) {
|
|
225
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
copyDirSync(srcDir, destDir);
|
|
229
|
+
copiedSkillsCount++;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const configuredRules = [];
|
|
234
|
+
const rulesContent = fs.existsSync(RULES_SOURCE_FILE)
|
|
235
|
+
? fs.readFileSync(RULES_SOURCE_FILE, 'utf8')
|
|
236
|
+
: getPointerBlock(selectedSkills);
|
|
237
|
+
|
|
238
|
+
for (const agent of chosenAgents) {
|
|
239
|
+
if (!agent.ruleFile) continue;
|
|
240
|
+
const rulePath = path.join(baseDir, agent.ruleFile);
|
|
241
|
+
const isSpecialRule = agent.id === 'kilo' || agent.id === 'cline' || agent.id === 'cursor';
|
|
242
|
+
const contentToWrite = isSpecialRule ? rulesContent : getPointerBlock(selectedSkills);
|
|
243
|
+
const action = updateRuleFile(rulePath, contentToWrite, !isSpecialRule);
|
|
244
|
+
configuredRules.push({ file: agent.ruleFile, action });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
s.stop(pc.green('Installation complete!'));
|
|
248
|
+
|
|
249
|
+
console.log('');
|
|
250
|
+
log.message(
|
|
251
|
+
pc.bold('Installed Skills & Configuration Details:') + '\n' +
|
|
252
|
+
chosenAgents.map(a => ` ${pc.cyan('●')} ${pc.bold(a.label)}: ${pc.dim(path.join(baseDir, a.skillDir))}`).join('\n') +
|
|
253
|
+
'\n' +
|
|
254
|
+
configuredRules.map(r => ` ${pc.green('✔')} Configured rule: ${pc.bold(r.file)} (${r.action})`).join('\n')
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
outro(
|
|
258
|
+
pc.bold(pc.green('waitsec is active.')) + ' ' +
|
|
259
|
+
pc.dim('Your AI will now think first, keep diffs small, and prevent overengineering.')
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
main().catch((err) => {
|
|
264
|
+
console.error(pc.red('Unexpected error:'), err);
|
|
265
|
+
process.exit(1);
|
|
266
|
+
});
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "waitsec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Practical guardrails for AI coding agents. Hold on, think first, code less.",
|
|
5
5
|
"main": "rules/waitsec.md",
|
|
6
6
|
"bin": {
|
|
7
|
-
"waitsec": "bin/cli.
|
|
7
|
+
"waitsec": "bin/cli.mjs"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"start": "node ./bin/cli.
|
|
10
|
+
"start": "node ./bin/cli.mjs",
|
|
11
11
|
"ship": "node ./scripts/ship.js"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
@@ -40,5 +40,9 @@
|
|
|
40
40
|
"plugin.json",
|
|
41
41
|
"README.md",
|
|
42
42
|
"LICENSE"
|
|
43
|
-
]
|
|
43
|
+
],
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@clack/prompts": "^1.8.0",
|
|
46
|
+
"picocolors": "^1.1.1"
|
|
47
|
+
}
|
|
44
48
|
}
|
package/plugin.json
CHANGED
package/rules/AGENTS.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# waitsec
|
|
2
2
|
|
|
3
|
-
Wait a second before coding. Follow these
|
|
3
|
+
Wait a second before coding. Follow these five core guardrails:
|
|
4
4
|
|
|
5
5
|
1. **Ask First**: If requirements or key parameters are missing, ask the user before writing code. Do not invent requirements.
|
|
6
6
|
2. **Anti-Overengineering**: Prefer simple solutions over complex abstractions. Build for today's needs, not hypothetical futures. **Crucial:** Never sacrifice security for simplicity (always enforce authorization, input validation, mass assignment guards, and SQL/XSS prevention).
|
|
7
7
|
3. **Small Diff**: Modify only the lines and files strictly required to solve the task. Do not touch unrelated code or reformat global files.
|
|
8
8
|
4. **Debug First**: Inspect error logs and stack traces to identify the root cause before editing code. Never guess.
|
|
9
|
+
5. **Verify First**: Never declare completion without proof. Run tests, build commands, and verify edge cases before closing.
|
|
10
|
+
|
package/rules/waitsec.md
CHANGED
|
@@ -29,3 +29,14 @@ You follow the waitsec discipline: hold on, think first, code less, and keep sec
|
|
|
29
29
|
- Never guess fixes or tweak random lines hoping the error disappears.
|
|
30
30
|
- Never silence errors with empty try/catch blocks or artificial fallback defaults.
|
|
31
31
|
- Fix the root cause at the source, then verify the fix by re-running the failing test or command.
|
|
32
|
+
|
|
33
|
+
## 5. Verify First (Proof Over Assumption)
|
|
34
|
+
- Never declare a task complete without empirical proof.
|
|
35
|
+
- Run tests, build commands, or reproduction scripts before writing your closing response.
|
|
36
|
+
- Verify both the success flow and edge-case failure handling.
|
|
37
|
+
- Ensure changes did not break neighboring functionality (regression check).
|
|
38
|
+
- Present real command outputs and test results to the user.
|
|
39
|
+
|
|
40
|
+
## Coexistence with Other Skills
|
|
41
|
+
- When `waitsec` is installed alongside third-party skills or framework guides, `waitsec` governs the operational discipline (clean diffs, restrained architecture, non-negotiable security, and verification).
|
|
42
|
+
- `waitsec` rules take precedence over suggestions that encourage unnecessary abstractions, speculative files, or bypassed security.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: waitsec-code
|
|
3
|
+
description: "[Coming Soon] Code quality extension for waitsec. Covers clean code patterns, anti-comment pollution, and dependency hygiene."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# waitsec-code: Clean Code Guardrails
|
|
7
|
+
|
|
8
|
+
> **Status: Work in Progress.** This module is not yet active. Check [github.com/fastroware/waitsec](https://github.com/fastroware/waitsec) for release updates.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Planned Guardrails
|
|
13
|
+
|
|
14
|
+
This extension targets the internal quality of the code itself:
|
|
15
|
+
|
|
16
|
+
- **Anti-Comment Pollution** — No redundant inline comments that restate what the code already says. Comments explain *why*, not *what*.
|
|
17
|
+
- **Clean Code Patterns** — Naming clarity, function length limits, single responsibility.
|
|
18
|
+
- **Dependency Hygiene** — Avoid pulling in packages for trivial problems. Audit transitive dependencies before adding them.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## How to Use When Released
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx waitsec --skill waitsec-core --skill waitsec-code
|
|
26
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: waitsec-core
|
|
3
|
+
description: "Core guardrails for AI coding agents. Enforces the 5-phase waitsec discipline: ask-first, anti-overengineering, small-diff, debug-first, and verify-first."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# waitsec-core: The 5 Foundational Guardrails
|
|
7
|
+
|
|
8
|
+
You operate under the **waitsec** engineering discipline. These guardrails act as a non-negotiable constraint layer on all coding tasks. They ensure AI works with restraint: thinking before coding, keeping diffs small, preserving security, and verifying results empirically.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The 5-Phase Pipeline
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
[Prompt Received]
|
|
16
|
+
↓
|
|
17
|
+
[Phase 1: Ingestion] ➔ waitsec: ask-first
|
|
18
|
+
↓ (requirements clear)
|
|
19
|
+
[Phase 2: Architecture] ➔ waitsec: anti-overengineering (security non-negotiable)
|
|
20
|
+
↓ (minimal pattern chosen)
|
|
21
|
+
[Phase 3: Execution] ➔ waitsec: small-diff
|
|
22
|
+
↓ (errors encountered?)
|
|
23
|
+
[Phase 4: Debugging] ➔ waitsec: debug-first
|
|
24
|
+
↓ (ready to close?)
|
|
25
|
+
[Phase 5: Completion] ➔ waitsec: verify-first
|
|
26
|
+
↓
|
|
27
|
+
[Task Delivered]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. Phase 1: Ingestion — [`ask-first`](./ask-first.md)
|
|
33
|
+
* **Rule:** If critical parameters, schemas, or storage targets are missing, stop immediately.
|
|
34
|
+
* Ask 1 to 3 direct questions with concrete choices (Option A vs Option B).
|
|
35
|
+
* Never invent product rules or business assumptions out of thin air.
|
|
36
|
+
* *Deep Dive & Tells:* Read [`skills/waitsec-core/ask-first.md`](./ask-first.md).
|
|
37
|
+
|
|
38
|
+
## 2. Phase 2: Architecture — [`anti-overengineering`](./anti-overengineering.md)
|
|
39
|
+
* **Rule:** Build for today's requirements. Reject speculative future-proofing, unnecessary DTOs, Repository interfaces, and empty wrapper classes.
|
|
40
|
+
* **Lean ≠ Insecure (CRITICAL):** Simplicity applies to architectural layers, never to defense mechanisms. You must enforce:
|
|
41
|
+
- Authentication and authorization checks (no IDOR).
|
|
42
|
+
- Strict input validation and mass assignment protection.
|
|
43
|
+
- Parameterized queries (SQL injection prevention) and proper output escaping (XSS prevention).
|
|
44
|
+
- Secrets loaded from environment variables (`.env`).
|
|
45
|
+
* *Deep Dive & Tells:* Read [`skills/waitsec-core/anti-overengineering.md`](./anti-overengineering.md).
|
|
46
|
+
|
|
47
|
+
## 3. Phase 3: Execution — [`small-diff`](./small-diff.md)
|
|
48
|
+
* **Rule:** Restrict changes strictly to the files and lines that solve the prompt.
|
|
49
|
+
* Do not reformat global whitespace, touch neighboring modules, or perform unsolicited cleanup passes.
|
|
50
|
+
* *Deep Dive & Tells:* Read [`skills/waitsec-core/small-diff.md`](./small-diff.md).
|
|
51
|
+
|
|
52
|
+
## 4. Phase 4: Debugging — [`debug-first`](./debug-first.md)
|
|
53
|
+
* **Rule:** When an error occurs, inspect the complete stack trace and identify the technical root cause before touching any file.
|
|
54
|
+
* Never spray random guesses across files. Never silence crashes with empty `try/catch` blocks.
|
|
55
|
+
* *Deep Dive & Tells:* Read [`skills/waitsec-core/debug-first.md`](./debug-first.md).
|
|
56
|
+
|
|
57
|
+
## 5. Phase 5: Completion — [`verify-first`](./verify-first.md)
|
|
58
|
+
* **Rule:** Never declare a task complete without empirical proof.
|
|
59
|
+
* Run builds, test suites, or reproduction commands. Check edge cases and ensure no regressions occurred.
|
|
60
|
+
* Report real terminal outcomes to the user.
|
|
61
|
+
* *Deep Dive & Tells:* Read [`skills/waitsec-core/verify-first.md`](./verify-first.md).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Framework Boundaries & Skill Coexistence
|
|
66
|
+
|
|
67
|
+
When `waitsec` is installed alongside other third-party agent skills (e.g. language skills, domain frameworks):
|
|
68
|
+
1. **Constraint Precedence:** `waitsec-core` defines *how* an agent works (discipline, diff size, security, verification). Domain skills define *what* API or framework syntax to use.
|
|
69
|
+
2. **Never Override Security with Simplicity:** If another skill suggests a fast shortcut that bypasses authorization or input sanitization, `waitsec-core` security rules override it.
|
|
70
|
+
3. **Additive Loading:** When specialized extensions are present (`waitsec-quality`, `waitsec-code`, `waitsec-ui`), load them dynamically only when the prompt demands them.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verify-first
|
|
3
|
+
description: Never declare a task complete without proving it works. Run tests, verify builds, and check for regressions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Verify First: Proof Over Assumption
|
|
7
|
+
|
|
8
|
+
Never say "I'm done" or "The bug is fixed" without concrete technical proof. Always verify before declaring completion.
|
|
9
|
+
|
|
10
|
+
**Core Principle:** *An unverified change is an incomplete change.* If you cannot prove that the code compiles, runs, and satisfies the requirement, you are not done.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Anti-Patterns (The Tells)
|
|
15
|
+
|
|
16
|
+
### 1. The Premature Victory Lap
|
|
17
|
+
- **Tell:** The agent modifies code, never runs a test or build command, and immediately announces: *"I have fixed the issue and implemented all requirements!"*
|
|
18
|
+
- **Why:** The AI relies on statistical confidence instead of empirical execution. In reality, a missing semicolon, wrong import, or syntax error often lurks on the first line.
|
|
19
|
+
- **Fix:** Run the relevant test suite, build command, or reproduction script before writing your closing message.
|
|
20
|
+
|
|
21
|
+
### 2. Regression Blindness
|
|
22
|
+
- **Tell:** Fixing a bug in component A, but accidentally breaking components B and C because shared state, schema, or props were modified without running the full test suite.
|
|
23
|
+
- **Why:** The AI focuses narrowly on the prompt and ignores downstream dependencies.
|
|
24
|
+
- **Fix:** If the project has automated tests (`npm test`, `pytest`, `php artisan test`, `go test`), run them to ensure no regressions were introduced.
|
|
25
|
+
|
|
26
|
+
### 3. Phantom Verification
|
|
27
|
+
- **Tell:** The agent claims *"I tested the login endpoint and it returned status 200"* when no terminal command, curl request, or test runner was actually executed in the environment.
|
|
28
|
+
- **Why:** Generative models hallucinate successful outcomes based on expectation.
|
|
29
|
+
- **Fix:** Real verification produces real output. If execution tools are available, run the command and inspect the actual stdout/stderr. If tools are unavailable, instruct the user on the exact command to run.
|
|
30
|
+
|
|
31
|
+
### 4. Happy-Path Myopia
|
|
32
|
+
- **Tell:** Testing only the success state (e.g. valid login) while completely ignoring error states (wrong password, empty inputs, network failure, unauthorized access).
|
|
33
|
+
- **Why:** AI naturally gravitates toward the ideal flow.
|
|
34
|
+
- **Fix:** Verify both the happy path and at least one failure/edge case before declaring completion.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The 4-Step Verification Sequence
|
|
39
|
+
|
|
40
|
+
Follow this sequence before declaring any task finished:
|
|
41
|
+
|
|
42
|
+
1. **Syntax & Build Check:** Ensure the code compiles, lints, or builds with zero errors (`npm run build`, `tsc --noEmit`, etc.).
|
|
43
|
+
2. **Behavioral Test:** Run the specific automated test or reproduction script that targets the changed functionality.
|
|
44
|
+
3. **Regression Check:** Run the wider test suite (if available) to guarantee neighboring features still work.
|
|
45
|
+
4. **Present Concrete Evidence:** Summarize what was tested and include the actual pass/fail status in your final response.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Decision Matrix: What to Verify
|
|
50
|
+
|
|
51
|
+
| Task Type | Minimum Verification Required |
|
|
52
|
+
| :--- | :--- |
|
|
53
|
+
| **Bug Fix** | Re-run the reproduction command; prove the error no longer occurs. |
|
|
54
|
+
| **New Feature** | Run unit/feature tests; test both valid input and invalid/empty input. |
|
|
55
|
+
| **Refactoring** | Run existing test suite to ensure 100% backward compatibility. |
|
|
56
|
+
| **Documentation / Copy** | Verify rendered markdown formatting, links, and code block syntax. |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Checklist
|
|
61
|
+
|
|
62
|
+
Before declaring a task complete:
|
|
63
|
+
- [ ] Did I run the build, linter, or type checker to ensure no syntax/compilation errors?
|
|
64
|
+
- [ ] Did I run the relevant automated test or verification command?
|
|
65
|
+
- [ ] Did I verify that existing neighboring functionality was not broken?
|
|
66
|
+
- [ ] Did I check at least one error or edge-case state?
|
|
67
|
+
- [ ] Did I report the real verification outcome to the user instead of assuming success?
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: waitsec-quality
|
|
3
|
+
description: "[Coming Soon] Quality extension for waitsec. Covers security auditing, automated testing discipline, and data integrity guardrails."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# waitsec-quality: Quality & Safety Guardrails
|
|
7
|
+
|
|
8
|
+
> **Status: Work in Progress.** This module is not yet active. Check [github.com/fastroware/waitsec](https://github.com/fastroware/waitsec) for release updates.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Planned Guardrails
|
|
13
|
+
|
|
14
|
+
This extension adds a second layer on top of `waitsec-core`, focused on code quality and systemic safety:
|
|
15
|
+
|
|
16
|
+
- **Security Audit** — Active scanning for common vulnerabilities beyond the baseline enforced in `anti-overengineering`. Includes dependency audits, permission boundaries, and sensitive data exposure checks.
|
|
17
|
+
- **Testing Discipline** — Rules for meaningful tests: no trivial assertions, no mocked-everything suites, no skipping edge cases.
|
|
18
|
+
- **Data Integrity** — Database constraint checks, migration safety, and soft-delete handling patterns.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## How to Use When Released
|
|
23
|
+
|
|
24
|
+
Install alongside `waitsec-core`:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx waitsec --skill waitsec-core --skill waitsec-quality
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or via `skills.sh`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
skills install fastroware/waitsec/skills/waitsec-quality
|
|
34
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: waitsec-ui
|
|
3
|
+
description: "[Coming Soon] UI/frontend extension for waitsec. Covers anti-slop CSS, responsive discipline, and no-decoration-for-decoration's-sake rules."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# waitsec-ui: Frontend Guardrails
|
|
7
|
+
|
|
8
|
+
> **Status: Work in Progress.** This module is not yet active. Check [github.com/fastroware/waitsec](https://github.com/fastroware/waitsec) for release updates.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Planned Guardrails
|
|
13
|
+
|
|
14
|
+
This extension targets frontend and CSS quality:
|
|
15
|
+
|
|
16
|
+
- **Anti-Slop CSS** — No gradient purple for no reason, no box-shadow stacks that add nothing, no animation on elements that don't need it.
|
|
17
|
+
- **Responsive Discipline** — Mobile-first layout rules. No pixel-locked widths on main containers. No horizontal scroll on mobile.
|
|
18
|
+
- **Decoration Restraint** — Every visual element must have a functional purpose. Decorative elements that increase cognitive load without guiding the user get cut.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## How to Use When Released
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx waitsec --skill waitsec-core --skill waitsec-ui
|
|
26
|
+
```
|
package/bin/cli.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const readline = require('readline');
|
|
6
|
-
|
|
7
|
-
const rl = readline.createInterface({
|
|
8
|
-
input: process.stdin,
|
|
9
|
-
output: process.stdout
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const sourceRulePath = path.join(__dirname, '..', 'rules', 'waitsec.md');
|
|
13
|
-
|
|
14
|
-
console.log(`
|
|
15
|
-
=========================================
|
|
16
|
-
waitsec: AI Coding Guardrails Installer
|
|
17
|
-
"Hold on. Think first. Code less."
|
|
18
|
-
=========================================
|
|
19
|
-
`);
|
|
20
|
-
|
|
21
|
-
console.log('Select your editor / coding agent:\n');
|
|
22
|
-
console.log(' 1) Kilo Code (.kilorules)');
|
|
23
|
-
console.log(' 2) Cline / Roo Code (.clinerules)');
|
|
24
|
-
console.log(' 3) Cursor (.cursorrules)');
|
|
25
|
-
console.log(' 4) Antigravity / Universal (AGENTS.md)');
|
|
26
|
-
console.log(' 5) All of the above\n');
|
|
27
|
-
|
|
28
|
-
rl.question('Enter number [1-5] (default: 1): ', (answer) => {
|
|
29
|
-
const choice = (answer || '1').trim();
|
|
30
|
-
const cwd = process.cwd();
|
|
31
|
-
|
|
32
|
-
if (!fs.existsSync(sourceRulePath)) {
|
|
33
|
-
console.error(`Error: Rule template not found at ${sourceRulePath}`);
|
|
34
|
-
rl.close();
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const ruleContent = fs.readFileSync(sourceRulePath, 'utf8');
|
|
39
|
-
|
|
40
|
-
const targets = [];
|
|
41
|
-
if (choice === '1') targets.push('.kilorules');
|
|
42
|
-
else if (choice === '2') targets.push('.clinerules');
|
|
43
|
-
else if (choice === '3') targets.push('.cursorrules');
|
|
44
|
-
else if (choice === '4') targets.push('AGENTS.md');
|
|
45
|
-
else if (choice === '5') targets.push('.kilorules', '.clinerules', '.cursorrules', 'AGENTS.md');
|
|
46
|
-
else {
|
|
47
|
-
console.log('Unknown choice, defaulting to .kilorules');
|
|
48
|
-
targets.push('.kilorules');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
targets.forEach((filename) => {
|
|
52
|
-
const destPath = path.join(cwd, filename);
|
|
53
|
-
if (fs.existsSync(destPath)) {
|
|
54
|
-
console.log(`[!] ${filename} already exists. Appending waitsec rules...`);
|
|
55
|
-
fs.appendFileSync(destPath, `\n\n${ruleContent}`);
|
|
56
|
-
} else {
|
|
57
|
-
fs.writeFileSync(destPath, ruleContent, 'utf8');
|
|
58
|
-
console.log(`[+] Created ${filename}`);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
console.log('\nSuccess! waitsec rules are now active in this project.');
|
|
63
|
-
console.log('Your AI assistant will now pause, check requirements, and avoid bloated code.\n');
|
|
64
|
-
|
|
65
|
-
rl.close();
|
|
66
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|