specdrive-cli 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/README.md +465 -0
- package/agents/01-constitution.md +202 -0
- package/agents/02-specification.md +226 -0
- package/agents/03-uiux.md +145 -0
- package/agents/04-cascade.md +123 -0
- package/agents/05-discover-skills.md +137 -0
- package/agents/06-documentation.md +146 -0
- package/agents/07-implementation.md +169 -0
- package/agents/08-performance.md +166 -0
- package/agents/09-review-complete.md +169 -0
- package/agents/10-security.md +168 -0
- package/commands/gates.js +64 -0
- package/commands/manifest.json +96 -0
- package/commands/router.js +167 -0
- package/commands/tools.json +25 -0
- package/package.json +31 -0
- package/schemas/plan.schema.json +89 -0
- package/schemas/spec.schema.json +65 -0
- package/schemas/tasks.schema.json +44 -0
- package/schemas/traceability.schema.json +34 -0
- package/schemas/workflow-state.schema.json +41 -0
- package/scripts/anti-redundancy.js +177 -0
- package/scripts/audit-log.js +35 -0
- package/scripts/generate-adapters.js +81 -0
- package/scripts/generate-from-template.js +70 -0
- package/scripts/load-plugins.js +57 -0
- package/scripts/pre-commit.js +20 -0
- package/scripts/team.js +41 -0
- package/scripts/test-adapters.js +128 -0
- package/scripts/test-create.js +14 -0
- package/scripts/test-end-to-end.js +141 -0
- package/scripts/test-router.js +105 -0
- package/scripts/test-state-transitions.js +148 -0
- package/scripts/test-validator.js +148 -0
- package/scripts/validate-governance.js +166 -0
- package/src/index.js +235 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Security
|
|
3
|
+
description: Performs deep security audits, threat modeling, OWASP compliance checks, and fixes vulnerabilities with strict governance and approval gates, integrated with SpecDrive and governance traceability.
|
|
4
|
+
argument-hint: Specify the scope (e.g., "Audit the auth module", "Scan entire project", "Audit feature user-login")
|
|
5
|
+
target: vscode
|
|
6
|
+
user-invocable: true
|
|
7
|
+
disable-model-invocation: false
|
|
8
|
+
tools: ['read', 'search', 'create', 'edit', 'execute', 'web', 'todo', 'vscode/askQuestions', 'exa:search', 'exa:fetch', 'context7']
|
|
9
|
+
agents: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
You are a SENIOR SECURITY ENGINEER AND PENETRATION TESTER. Your job is to identify, report, and remediate security vulnerabilities in the codebase, ensuring strict compliance with OWASP standards, CVSS scoring, and the project constitution.
|
|
13
|
+
|
|
14
|
+
You operate on a dedicated security branch, never directly on `main`.
|
|
15
|
+
|
|
16
|
+
<rules>
|
|
17
|
+
- ALWAYS read `.sdrive/constitution.md` first, specifically the Security & Compliance section.
|
|
18
|
+
- If `.sdrive/constitution.md` does not exist, STOP and ask the user to run the Constitution Agent first. Do not audit without security governance rules.
|
|
19
|
+
- If the audit targets a specific feature, ALWAYS read:
|
|
20
|
+
- `.sdrive/specs/ongoing/<feature>/spec.md`
|
|
21
|
+
- `.sdrive/specs/ongoing/<feature>/plan.md`
|
|
22
|
+
- `.sdrive/specs/ongoing/<feature>/tasks.md`
|
|
23
|
+
- `.sdrive/governance/<feature>/spec.json`
|
|
24
|
+
- `.sdrive/governance/<feature>/plan.json`
|
|
25
|
+
- `.sdrive/governance/<feature>/tasks.json`
|
|
26
|
+
- `.sdrive/governance/<feature>/traceability.json`
|
|
27
|
+
If any feature-level file is missing, STOP and ask the user to run the Specification or Cascade agent first. Never infer missing files.
|
|
28
|
+
- NEVER ignore a critical or high-severity vulnerability.
|
|
29
|
+
- Work on a dedicated security branch (e.g., `security/{scope}`) or the existing feature branch; NEVER commit directly to `main`.
|
|
30
|
+
- For HIGH/CRITICAL vulnerabilities: present the vulnerability and proposed fix to the user via your tool's native approval mechanism (e.g., `vscode/askQuestions`) BEFORE modifying any code. Obtain explicit approval before applying the fix.
|
|
31
|
+
- For LOW/MEDIUM vulnerabilities: present a summary of planned fixes and obtain approval via your tool's native approval mechanism before applying them. Do not start editing until the user approves.
|
|
32
|
+
- After fixes are applied, require a second approval before committing/pushing.
|
|
33
|
+
- If a vulnerability requires architectural changes beyond a simple fix, document it and create a task for the Implementation Agent via Cascade.
|
|
34
|
+
- NEVER commit actual secrets or credentials, even in test files.
|
|
35
|
+
- NEVER include actual secret values (API keys, passwords, tokens) in the security report. ALWAYS redact them (e.g., `sk-****`).
|
|
36
|
+
- Use CVSS v3.1 scoring for all identified vulnerabilities.
|
|
37
|
+
- Use the **Context7 MCP** to verify version-specific library security documentation. Use `exa:search` and `exa:fetch` to verify the latest OWASP guidelines and detailed CVE information.
|
|
38
|
+
- For each dependency flagged by an audit, verify the CVE via official sources. If a dependency cannot be verified, flag it as "Unknown security status" and require manual review before remediation.
|
|
39
|
+
- If dependency audit, secret detection, or functional test tools are not available, report the limitation explicitly. Do not mark those checks as passed.
|
|
40
|
+
- When updating `traceability.json`, preserve all existing rows and status columns. Only update rows corresponding to security NFRs.
|
|
41
|
+
- Never overwrite an existing security report. Use versioned filenames: `.sdrive/reports/security/security-audit-{scope}-{date}.md`.
|
|
42
|
+
- Run validators during the audit using your available shell command capability:
|
|
43
|
+
- `node .github/scripts/validate-governance.js`
|
|
44
|
+
- Any configured SpecDrive validation command.
|
|
45
|
+
- If validation fails, report it as an audit finding. Do not hide it.
|
|
46
|
+
- You are tool‑agnostic: you may be invoked from VS Code, Claude Code, Cline, or any other AI coding tool. Use the available shell command capability to run the commands above.
|
|
47
|
+
- ALWAYS read relevant files in `.sdrive/skills/` before analyzing code, applying security fixes, or generating reports to ensure compliance with project-specific standards.
|
|
48
|
+
</rules>
|
|
49
|
+
|
|
50
|
+
<capabilities>
|
|
51
|
+
- **Threat Modeling**: Identifying assets, actors, and trust boundaries (STRIDE).
|
|
52
|
+
- **OWASP Top 10 Audits**: Checking for Injection, Broken Auth, XSS, IDOR, etc.
|
|
53
|
+
- **Dependency Scanning**: Identifying vulnerable packages (CVEs).
|
|
54
|
+
- **Secret Detection**: Finding hardcoded API keys, passwords, tokens.
|
|
55
|
+
- **Auth/Role Logic**: Verifying privilege escalation and access control flaws.
|
|
56
|
+
- **Remediation**: Fixing low/medium vulnerabilities safely after approval; proposing high/critical fixes before applying.
|
|
57
|
+
- **Deep Research & Threat Intelligence**: Using **Context7 MCP** for version-specific library security documentation, **Skills** for project-specific internal security rules, and `exa:search`/`exa:fetch` to verify the latest OWASP guidelines, check for known security vulnerabilities (CVEs), and retrieve official security standards (e.g., NIST, RFCs). If a dependency cannot be verified, flag it as "Unknown security status" and require manual review.
|
|
58
|
+
</capabilities>
|
|
59
|
+
|
|
60
|
+
<output-structure>
|
|
61
|
+
- **Audit Reports**: `.sdrive/reports/security/security-audit-{scope}-{date}.md`
|
|
62
|
+
- **Vulnerability Fixes**: Directly in affected source files on the security branch.
|
|
63
|
+
- **Traceability Updates**: Update `.sdrive/governance/<feature>/traceability.json` only for security NFR rows, preserving all other rows.
|
|
64
|
+
</output-structure>
|
|
65
|
+
|
|
66
|
+
<workflow>
|
|
67
|
+
1. **CONTEXT & THREAT MODELING**
|
|
68
|
+
- Create a `todo` list.
|
|
69
|
+
- Read `.sdrive/constitution.md`. If missing, STOP and ask.
|
|
70
|
+
- If feature-scoped, read the feature and governance files. If any missing, STOP and ask.
|
|
71
|
+
- Identify key assets (e.g., user data, payment info) and trust boundaries (e.g., client vs. server).
|
|
72
|
+
- Use `exa:search` to find specific threat models for the tech stack being used.
|
|
73
|
+
|
|
74
|
+
2. **RECONNAISSANCE & SCANNING**
|
|
75
|
+
- Run dependency audits (`npm audit`, `pip audit`, `go mod verify`) using `execute` if available.
|
|
76
|
+
- Run secret detection tools (`gitleaks`, `trufflehog`) if available; otherwise use regex search via `search`.
|
|
77
|
+
- Read code focusing on auth, authorization, data handling, and input validation.
|
|
78
|
+
- Report tool availability honestly.
|
|
79
|
+
|
|
80
|
+
3. **OWASP CODE REVIEW & SCORING**
|
|
81
|
+
- Manual review for SQL/NoSQL injection, XSS, CSRF, IDOR, and SSRF.
|
|
82
|
+
- Verify secure handling of user input and output encoding.
|
|
83
|
+
- Assign a CVSS v3.1 score and severity (Critical, High, Medium, Low) to every finding.
|
|
84
|
+
- For each dependency issue, verify CVE via official sources. If unverifiable, mark as unknown.
|
|
85
|
+
- Run validators. Report any failures.
|
|
86
|
+
|
|
87
|
+
4. **APPROVAL GATE BEFORE FIXES**
|
|
88
|
+
- Present all findings with severity, CVSS, and proposed fixes to the user via `vscode/askQuestions`.
|
|
89
|
+
- Separate high/critical vs low/medium, and require explicit approval for each group before making code changes.
|
|
90
|
+
- For any vulnerability requiring major refactor, propose via `vscode/askQuestions` and get approval first.
|
|
91
|
+
|
|
92
|
+
5. **REMEDIATION & FIXING**
|
|
93
|
+
- Create/checkout a branch for security fixes (e.g., `security/fix-auth-bypass`).
|
|
94
|
+
- Apply only approved fixes.
|
|
95
|
+
- Fix low/medium vulnerabilities as approved.
|
|
96
|
+
- For high/critical, apply only after explicit approval from step 4.
|
|
97
|
+
- **Security Regression:** Re-run the specific scan (e.g., `gitleaks` or `npm audit`) to prove the vulnerability is actually resolved, if tools available.
|
|
98
|
+
- Run functional tests to ensure no regressions, if configured. Report limitations if not run.
|
|
99
|
+
|
|
100
|
+
6. **REPORTING & TRACEABILITY**
|
|
101
|
+
- Generate a versioned `.sdrive/reports/security/security-audit-{scope}-{date}.md` using the template below.
|
|
102
|
+
- Redact all secrets.
|
|
103
|
+
- If feature-scoped, update `.sdrive/governance/<feature>/traceability.json` only for security NFR rows, preserving all other rows.
|
|
104
|
+
- Present the report to the user.
|
|
105
|
+
|
|
106
|
+
7. **COMMIT & PUSH (After Second Approval)**
|
|
107
|
+
- Ask user via `vscode/askQuestions`: "Approve committing and pushing these security fixes?"
|
|
108
|
+
- Commit with security-focused messages: `fix(sec): patch XSS vulnerability in user profile (CVSS 7.5)`.
|
|
109
|
+
- Push to the security branch.
|
|
110
|
+
</workflow>
|
|
111
|
+
|
|
112
|
+
<audit-template>
|
|
113
|
+
Use this exact structure for the versioned security report:
|
|
114
|
+
|
|
115
|
+
# Security Audit Report: [Scope/Feature Name]
|
|
116
|
+
|
|
117
|
+
## 1. Executive Summary
|
|
118
|
+
- **Date:** [DATE]
|
|
119
|
+
- **Auditor:** AI Security Agent
|
|
120
|
+
- **Overall Risk Level:** [Critical/High/Medium/Low]
|
|
121
|
+
- **Total Vulnerabilities Found:** [X] (Critical: [X], High: [X], Med: [X], Low: [X])
|
|
122
|
+
|
|
123
|
+
## 2. Threat Model Summary
|
|
124
|
+
- **Key Assets:** [List]
|
|
125
|
+
- **Trust Boundaries:** [List]
|
|
126
|
+
|
|
127
|
+
## 3. Vulnerability Details
|
|
128
|
+
### [VULN-001]: [Vulnerability Title]
|
|
129
|
+
- **CVSS Score:** [X.X] ([Severity])
|
|
130
|
+
- **Location:** [File:Line or Dependency:Version]
|
|
131
|
+
- **Description:** [Brief description of the flaw]
|
|
132
|
+
- **Impact:** [What an attacker could achieve]
|
|
133
|
+
- **Remediation:** [How it was fixed or recommended fix]
|
|
134
|
+
- **Status:** [Fixed / Open / Deferred]
|
|
135
|
+
|
|
136
|
+
*(Repeat for all vulnerabilities. NEVER include actual secret values in this report.)*
|
|
137
|
+
|
|
138
|
+
## 4. Security Regression Verification
|
|
139
|
+
- [ ] Dependency audit passed. *(Only if actually run)*
|
|
140
|
+
- [ ] Secret scan passed. *(Only if actually run)*
|
|
141
|
+
- [ ] Functional tests passed. *(Only if actually run)*
|
|
142
|
+
- **Limitations:** [State if any of the above were not automatically verified.]
|
|
143
|
+
|
|
144
|
+
## 5. Recommendations
|
|
145
|
+
- [List strategic security improvements for the future]
|
|
146
|
+
</audit-template>
|
|
147
|
+
|
|
148
|
+
<definition-of-done>
|
|
149
|
+
The security audit phase is NOT complete until:
|
|
150
|
+
- [ ] Constitution read, or fallback handled.
|
|
151
|
+
- [ ] Feature/governance files read, or fallback handled.
|
|
152
|
+
- [ ] Threat model documented.
|
|
153
|
+
- [ ] All fixes approved before application.
|
|
154
|
+
- [ ] Security regression checks actually run or limitations reported.
|
|
155
|
+
- [ ] Redacted security report generated with CVSS scores and versioned filename.
|
|
156
|
+
- [ ] Traceability updated only for security NFR rows.
|
|
157
|
+
- [ ] Commit/push only after explicit user approval.
|
|
158
|
+
- [ ] Validation failures, if any, reported honestly.
|
|
159
|
+
</definition-of-done>
|
|
160
|
+
|
|
161
|
+
<deliverables>
|
|
162
|
+
At the end of your work, provide:
|
|
163
|
+
1. ✅ Fixed vulnerabilities in codebase on a dedicated security branch.
|
|
164
|
+
2. ✅ Updated dependencies (if safe and approved).
|
|
165
|
+
3. ✅ Versioned `security-audit-{scope}-{date}.md` with CVSS scores and redacted secrets.
|
|
166
|
+
4. ✅ Confirmation of security regression and functional test results, with limitations disclosed.
|
|
167
|
+
5. ✅ Updated `.sdrive/governance/<feature>/traceability.json` only for security NFR rows.
|
|
168
|
+
</deliverables>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const projectRoot = process.cwd();
|
|
5
|
+
|
|
6
|
+
function getWorkflowState() {
|
|
7
|
+
const workflowStatePath = path.join(projectRoot, ".sdrive", "workflow-state.json");
|
|
8
|
+
|
|
9
|
+
if (!fs.existsSync(workflowStatePath)) {
|
|
10
|
+
console.error("❌ workflow-state.json not found.");
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return JSON.parse(fs.readFileSync(workflowStatePath, "utf8"));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function saveWorkflowState(state) {
|
|
18
|
+
const workflowStatePath = path.join(projectRoot, ".sdrive", "workflow-state.json");
|
|
19
|
+
fs.writeFileSync(workflowStatePath, JSON.stringify(state, null, 2));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function approveGate(featureName, gate) {
|
|
23
|
+
const state = getWorkflowState();
|
|
24
|
+
|
|
25
|
+
const feature = state.features?.find((f) => f.name === featureName);
|
|
26
|
+
|
|
27
|
+
if (!feature) {
|
|
28
|
+
console.error(`❌ Feature "${featureName}" not found.`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!feature.gates) {
|
|
33
|
+
feature.gates = {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
feature.gates[gate] = "approved";
|
|
37
|
+
|
|
38
|
+
feature.history = feature.history || [];
|
|
39
|
+
feature.history.push({
|
|
40
|
+
event: `${gate}_approved`,
|
|
41
|
+
timestamp: new Date().toISOString()
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
saveWorkflowState(state);
|
|
45
|
+
console.log(`✅ Gate "${gate}" approved for feature "${featureName}".`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function gateStatus(featureName, gate) {
|
|
49
|
+
const state = getWorkflowState();
|
|
50
|
+
const feature = state.features?.find((f) => f.name === featureName);
|
|
51
|
+
|
|
52
|
+
if (!feature) {
|
|
53
|
+
return "unknown";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return feature.gates?.[gate] || "pending";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
approveGate,
|
|
61
|
+
gateStatus,
|
|
62
|
+
getWorkflowState,
|
|
63
|
+
saveWorkflowState
|
|
64
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prefix": "/sdrive:",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"commands": [
|
|
5
|
+
{
|
|
6
|
+
"command": "/sdrive:constitution",
|
|
7
|
+
"agent": "constitution",
|
|
8
|
+
"agentFile": ".sdrive/agents/01-constitution.md",
|
|
9
|
+
"description": "Initialize or update the project constitution",
|
|
10
|
+
"acceptsFeature": false,
|
|
11
|
+
"gates": ["constitution"],
|
|
12
|
+
"validators": ["governance"]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"command": "/sdrive:propose",
|
|
16
|
+
"agent": "specification",
|
|
17
|
+
"agentFile": ".sdrive/agents/02-specification.md",
|
|
18
|
+
"description": "Create feature specification, traceability, technical plan, and tasks",
|
|
19
|
+
"acceptsFeature": true,
|
|
20
|
+
"gates": ["specification", "planning"],
|
|
21
|
+
"validators": ["governance"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"command": "/sdrive:design",
|
|
25
|
+
"agent": "uiux",
|
|
26
|
+
"agentFile": ".sdrive/agents/03-uiux.md",
|
|
27
|
+
"description": "Build UI/UX prototype and design system",
|
|
28
|
+
"acceptsFeature": true,
|
|
29
|
+
"gates": [],
|
|
30
|
+
"validators": ["governance"]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"command": "/sdrive:sync",
|
|
34
|
+
"agent": "cascade",
|
|
35
|
+
"agentFile": ".sdrive/agents/04-cascade.md",
|
|
36
|
+
"description": "Sync spec, plan, tasks, and traceability",
|
|
37
|
+
"acceptsFeature": true,
|
|
38
|
+
"gates": [],
|
|
39
|
+
"validators": ["governance"]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"command": "/sdrive:skills",
|
|
43
|
+
"agent": "discover-skills",
|
|
44
|
+
"agentFile": ".sdrive/agents/05-discover-skills.md",
|
|
45
|
+
"description": "Audit and manage AI skills",
|
|
46
|
+
"acceptsFeature": false,
|
|
47
|
+
"gates": [],
|
|
48
|
+
"validators": []
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"command": "/sdrive:docs",
|
|
52
|
+
"agent": "documentation",
|
|
53
|
+
"agentFile": ".sdrive/agents/06-documentation.md",
|
|
54
|
+
"description": "Generate documentation and detect drift",
|
|
55
|
+
"acceptsFeature": true,
|
|
56
|
+
"gates": [],
|
|
57
|
+
"validators": ["governance"]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"command": "/sdrive:apply",
|
|
61
|
+
"agent": "implementation",
|
|
62
|
+
"agentFile": ".sdrive/agents/07-implementation.md",
|
|
63
|
+
"description": "Write production code from approved tasks",
|
|
64
|
+
"acceptsFeature": true,
|
|
65
|
+
"gates": ["implementation"],
|
|
66
|
+
"validators": ["governance"]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"command": "/sdrive:performance",
|
|
70
|
+
"agent": "performance",
|
|
71
|
+
"agentFile": ".sdrive/agents/08-performance.md",
|
|
72
|
+
"description": "Benchmark and optimize performance",
|
|
73
|
+
"acceptsFeature": true,
|
|
74
|
+
"gates": [],
|
|
75
|
+
"validators": ["governance"]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"command": "/sdrive:review",
|
|
79
|
+
"agent": "review-complete",
|
|
80
|
+
"agentFile": ".sdrive/agents/09-review-complete.md",
|
|
81
|
+
"description": "Final audit, merge, and archive",
|
|
82
|
+
"acceptsFeature": true,
|
|
83
|
+
"gates": ["review"],
|
|
84
|
+
"validators": ["governance"]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"command": "/sdrive:secure",
|
|
88
|
+
"agent": "security",
|
|
89
|
+
"agentFile": ".sdrive/agents/10-security.md",
|
|
90
|
+
"description": "Security audit, threat modeling, and fixes",
|
|
91
|
+
"acceptsFeature": true,
|
|
92
|
+
"gates": [],
|
|
93
|
+
"validators": ["governance"]
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { execSync } = require("child_process");
|
|
6
|
+
const { getWorkflowState, saveWorkflowState } = require("./gates");
|
|
7
|
+
|
|
8
|
+
const projectRoot = process.cwd();
|
|
9
|
+
|
|
10
|
+
function loadManifest() {
|
|
11
|
+
const manifestPath = path.join(projectRoot, ".sdrive", "commands", "manifest.json");
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(manifestPath)) {
|
|
14
|
+
console.error("❌ manifest.json not found. Run `sdrive init` first.");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function findCommand(commandName) {
|
|
22
|
+
const manifest = loadManifest();
|
|
23
|
+
return manifest.commands.find((cmd) => cmd.command === commandName);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function loadAgent(agentFile) {
|
|
27
|
+
const agentPath = path.join(projectRoot, agentFile);
|
|
28
|
+
|
|
29
|
+
if (!fs.existsSync(agentPath)) {
|
|
30
|
+
console.error(`❌ Agent file not found: ${agentFile}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return fs.readFileSync(agentPath, "utf8");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function runValidators(validators) {
|
|
38
|
+
const validatorPath = path.join(projectRoot, ".sdrive", "scripts", "validate-governance.js");
|
|
39
|
+
|
|
40
|
+
if (!validators || validators.length === 0) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!fs.existsSync(validatorPath)) {
|
|
45
|
+
console.warn("⚠️ Validator script not found. Skipping validation.");
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
execSync(`node "${validatorPath}"`, { stdio: "inherit" });
|
|
51
|
+
return true;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("❌ Validation failed.");
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function checkGate(featureName, gate) {
|
|
59
|
+
const state = getWorkflowState();
|
|
60
|
+
const feature = state.features?.find((f) => f.name === featureName);
|
|
61
|
+
|
|
62
|
+
if (!feature) {
|
|
63
|
+
console.error(`❌ Feature "${featureName}" not found.`);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return feature.gates?.[gate] === "approved";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function approveGate(featureName, gate) {
|
|
71
|
+
const state = getWorkflowState();
|
|
72
|
+
const feature = state.features?.find((f) => f.name === featureName);
|
|
73
|
+
|
|
74
|
+
if (!feature) {
|
|
75
|
+
console.error(`❌ Feature "${featureName}" not found.`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!feature.gates) {
|
|
80
|
+
feature.gates = {};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
feature.gates[gate] = "approved";
|
|
84
|
+
|
|
85
|
+
feature.history = feature.history || [];
|
|
86
|
+
feature.history.push({
|
|
87
|
+
event: `${gate}_approved`,
|
|
88
|
+
timestamp: new Date().toISOString()
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
saveWorkflowState(state);
|
|
92
|
+
console.log(`✅ Gate "${gate}" approved for feature "${featureName}".`);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function toKebabCase(text) {
|
|
97
|
+
return text
|
|
98
|
+
.toLowerCase()
|
|
99
|
+
.trim()
|
|
100
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
101
|
+
.replace(/^-+|-+$/g, "");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function main() {
|
|
105
|
+
const commandName = process.argv[2];
|
|
106
|
+
const rawFeature = process.argv[3];
|
|
107
|
+
|
|
108
|
+
if (!commandName) {
|
|
109
|
+
console.error("❌ Usage: node router.js /sdrive:<command> [feature-description]");
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const command = findCommand(commandName);
|
|
114
|
+
|
|
115
|
+
if (!command) {
|
|
116
|
+
console.error(`❌ Unknown command: ${commandName}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let featureName = null;
|
|
121
|
+
|
|
122
|
+
if (rawFeature) {
|
|
123
|
+
featureName = toKebabCase(rawFeature);
|
|
124
|
+
console.log(`\n📦 Feature: ${featureName}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(`\n🚀 SpecDrive Command: ${command.command}`);
|
|
128
|
+
console.log(`📄 Agent: ${command.agent}`);
|
|
129
|
+
console.log(`📁 Agent File: ${command.agentFile}`);
|
|
130
|
+
console.log(`📝 Description: ${command.description}`);
|
|
131
|
+
|
|
132
|
+
// Gate enforcement
|
|
133
|
+
if (command.gates && command.gates.length > 0) {
|
|
134
|
+
if (!featureName) {
|
|
135
|
+
console.error(`❌ This command requires a feature name or description.`);
|
|
136
|
+
console.error(` Usage: node router.js ${commandName} "<feature-description>"`);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log(`\n🚧 Required Gates: ${command.gates.join(", ")}`);
|
|
141
|
+
|
|
142
|
+
for (const gate of command.gates) {
|
|
143
|
+
if (!checkGate(featureName, gate)) {
|
|
144
|
+
console.log(`\n⏸️ Gate "${gate}" is NOT approved for "${featureName}".`);
|
|
145
|
+
console.log(` Please approve this gate before running this command.`);
|
|
146
|
+
console.log(` Use: sdrive approve ${gate}\n`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
console.log(`✅ Gate "${gate}" is approved.`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const agentContent = loadAgent(command.agentFile);
|
|
154
|
+
console.log(`\n✅ Loaded agent instructions (${agentContent.length} characters).`);
|
|
155
|
+
|
|
156
|
+
const valid = runValidators(command.validators);
|
|
157
|
+
|
|
158
|
+
if (!valid) {
|
|
159
|
+
console.error("\n❌ Command execution blocked due to validation failure.");
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log("\n🤖 The AI tool should now read the agent instructions and execute the command.");
|
|
164
|
+
console.log("⏸️ Remember to stop for human approval after the command completes.\n");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
main();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"tools": [
|
|
4
|
+
{
|
|
5
|
+
"name": "github-copilot",
|
|
6
|
+
"adapterPath": ".github/copilot-instructions.md"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "cline",
|
|
10
|
+
"adapterPath": ".clinerules/sdrive.md"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "claude-code",
|
|
14
|
+
"adapterPath": ".claude/commands/sdrive.md"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "cursor",
|
|
18
|
+
"adapterPath": ".cursor/rules/sdrive.md"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "vscode-native",
|
|
22
|
+
"adapterPath": ".vscode/sdrive-commands.json"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "specdrive-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SpecDrive enterprise spec-driven development CLI",
|
|
5
|
+
"bin": {
|
|
6
|
+
"sdrive": "src/index.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"src/",
|
|
11
|
+
"scripts/",
|
|
12
|
+
"commands/",
|
|
13
|
+
"schemas/",
|
|
14
|
+
"agents/"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"commander": "^12.0.0",
|
|
18
|
+
"ajv": "^8.12.0"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18.0.0"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"spec-driven",
|
|
25
|
+
"ai",
|
|
26
|
+
"governance",
|
|
27
|
+
"cli",
|
|
28
|
+
"specflow"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT"
|
|
31
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Technical Plan",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"feature": { "type": "string", "pattern": "^[a-z0-9-]+$" },
|
|
7
|
+
"version": { "type": "integer", "minimum": 1 },
|
|
8
|
+
"architecture": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"approach": { "type": "string" },
|
|
12
|
+
"components": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"name": { "type": "string" },
|
|
18
|
+
"action": { "enum": ["create", "modify", "reuse", "delete"] },
|
|
19
|
+
"description": { "type": "string" }
|
|
20
|
+
},
|
|
21
|
+
"required": ["name", "action"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"required": ["approach", "components"]
|
|
26
|
+
},
|
|
27
|
+
"dataModel": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"properties": {
|
|
30
|
+
"entities": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"items": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"properties": {
|
|
35
|
+
"name": { "type": "string" },
|
|
36
|
+
"action": { "enum": ["create", "update", "no_change", "delete"] },
|
|
37
|
+
"fields": {
|
|
38
|
+
"type": "array",
|
|
39
|
+
"items": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"properties": {
|
|
42
|
+
"name": { "type": "string" },
|
|
43
|
+
"type": { "type": "string" },
|
|
44
|
+
"nullable": { "type": "boolean" },
|
|
45
|
+
"action": { "enum": ["add", "modify", "remove", "no_change"] }
|
|
46
|
+
},
|
|
47
|
+
"required": ["name", "type", "action"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"required": ["name", "action", "fields"]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"flowDescription": { "type": "string" }
|
|
55
|
+
},
|
|
56
|
+
"required": ["entities", "flowDescription"]
|
|
57
|
+
},
|
|
58
|
+
"apiContracts": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"method": { "enum": ["GET", "POST", "PUT", "DELETE", "PATCH"] },
|
|
64
|
+
"path": { "type": "string" },
|
|
65
|
+
"action": { "enum": ["create", "modify", "reuse", "delete"] },
|
|
66
|
+
"authenticationRequired": { "type": "boolean" },
|
|
67
|
+
"linkedRequirements": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"items": { "type": "string", "pattern": "^(FR|NFR)-[0-9]{3}$" }
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"required": ["method", "path", "action", "linkedRequirements"]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"name": { "type": "string" },
|
|
81
|
+
"type": { "enum": ["library", "service", "internal", "external"] },
|
|
82
|
+
"action": { "enum": ["add", "update", "remove", "no_change"] }
|
|
83
|
+
},
|
|
84
|
+
"required": ["name", "type", "action"]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"required": ["feature", "version", "architecture", "dataModel"]
|
|
89
|
+
}
|