crewkit 0.1.0 → 1.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.
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: retro
3
+ description: "Post-mortem of a completed task or plan — analyzes fix loops, reviewer findings, lessons learned, and suggests process improvements."
4
+ ---
5
+
6
+ Post-mortem for: $ARGUMENTS
7
+
8
+ If $ARGUMENTS is empty, analyze the most recent completed task from git log.
9
+
10
+ ---
11
+
12
+ ## When to use
13
+
14
+ Use after a task is completed (or after a painful iteration) to extract durable lessons
15
+ and identify process improvements. Not a blame exercise — a signal extraction exercise.
16
+
17
+ ---
18
+
19
+ ## Steps
20
+
21
+ ### 1. Gather signals
22
+
23
+ Run in parallel:
24
+
25
+ ```bash
26
+ git log --oneline -30
27
+ git diff HEAD~10..HEAD --stat
28
+ ```
29
+
30
+ Also read (if they exist):
31
+ - `.ai/plans/` — any plan file matching $ARGUMENTS
32
+ - `.ai/memory/lessons-*.md` — to avoid duplicating existing lessons
33
+
34
+ If $ARGUMENTS points to a specific plan file, read it directly.
35
+
36
+ ### 2. Reconstruct the timeline
37
+
38
+ From git log and plan file, reconstruct:
39
+
40
+ | Phase | What happened | Agent/actor |
41
+ |-------|--------------|-------------|
42
+ | Initial implementation | ... | coder |
43
+ | First test run | PASS / FAIL | tester |
44
+ | First review | APPROVED / NEEDS_CHANGES | reviewer |
45
+ | Fix loop iterations | count + what was fixed | coder |
46
+ | Final state | PASS + APPROVED | — |
47
+
48
+ Flag any phase that repeated more than once.
49
+
50
+ ### 3. Analyze fix loops
51
+
52
+ For each fix loop iteration, identify:
53
+ - **Trigger:** what caused the loop (test failure / reviewer finding / build error)
54
+ - **Root cause category:** one of:
55
+ - `spec-gap` — requirement was ambiguous or incomplete
56
+ - `scope-underestimate` — task was classified smaller than it was
57
+ - `missing-context` — coder lacked critical info (architecture, conventions, existing pattern)
58
+ - `test-gap` — test didn't cover the scenario before the fix
59
+ - `review-gap` — reviewer finding could have been caught earlier
60
+ - `execution-error` — correct spec, wrong implementation (typo, off-by-one, wrong field)
61
+ - `external-dependency` — blocked by something outside the task
62
+
63
+ ### 4. Classify reviewer findings
64
+
65
+ If reviewer output is available (from PR diff, plan notes, or conversation context), classify findings:
66
+
67
+ | Severity | Count | Recurring? | Category |
68
+ |----------|-------|-----------|----------|
69
+ | CRITICAL | ... | yes/no | ... |
70
+ | IMPORTANT | ... | yes/no | ... |
71
+ | MINOR | ... | yes/no | ... |
72
+
73
+ "Recurring" = same finding appeared in a previous retro or lesson file.
74
+
75
+ ### 5. Identify process improvements
76
+
77
+ For each fix loop trigger, propose one concrete process change:
78
+
79
+ | Finding | Proposed change | Target phase |
80
+ |---------|----------------|--------------|
81
+ | e.g. coder missed multi-tenant rule | Add explicit tenant check to coder prompt | Step 0 (classify) |
82
+ | e.g. test missed edge case | Add edge case checklist to tester for this module | tester |
83
+
84
+ Keep proposals concrete and actionable. Do not propose vague "be more careful" items.
85
+
86
+ ### 6. Extract durable lessons
87
+
88
+ For each lesson that would prevent future recurrence, format as:
89
+
90
+ ```markdown
91
+ ### [YYYY-MM-DD] Retro: <short title>
92
+ - **Task:** [what was being built/fixed]
93
+ - **What happened:** [1-2 sentences]
94
+ - **Root cause:** [category from Step 3]
95
+ - **Lesson:** [actionable guidance for next time]
96
+ - **Applies to:** [domain: .NET / gateway / Blazor / process / all]
97
+ ```
98
+
99
+ Append to the correct `.ai/memory/lessons-{domain}.md`.
100
+ If lesson is process-level, append to `lessons-process.md` (create if missing).
101
+
102
+ ### 7. Update plan status
103
+
104
+ If a plan file was identified, update its status to **DONE** (if not already).
105
+
106
+ ---
107
+
108
+ ## Return Format
109
+
110
+ ```markdown
111
+ ---
112
+ **Retro: [task name or git range]**
113
+ **Period:** [date range from git log]
114
+ **Fix loop count:** [N]
115
+
116
+ **Timeline summary:**
117
+ [reconstructed table from Step 2]
118
+
119
+ **Fix loop analysis:**
120
+ [table from Step 3]
121
+
122
+ **Reviewer findings:**
123
+ [table from Step 4, or "not available"]
124
+
125
+ **Process improvements:**
126
+ [table from Step 5]
127
+
128
+ **Lessons documented:** [N lessons → file(s)]
129
+
130
+ **Top recommendation:** [single most impactful process change]
131
+ ---
132
+ ```
133
+
134
+ If no fix loops occurred and review was clean on the first pass, state that explicitly — it is a positive signal worth noting.
@@ -9,7 +9,10 @@ Review pull request: $ARGUMENTS
9
9
 
10
10
  ### 1. Fetch PR data
11
11
 
12
- Run in parallel:
12
+ Try each source in order, stopping at the first that succeeds.
13
+
14
+ #### 1a. GitHub (gh CLI)
15
+
13
16
  ```bash
14
17
  gh pr view $ARGUMENTS --json number,title,body,author,baseRefName,headRefName,additions,deletions,changedFiles
15
18
  gh pr diff $ARGUMENTS
@@ -17,6 +20,32 @@ gh pr diff $ARGUMENTS
17
20
 
18
21
  If $ARGUMENTS is empty, use `gh pr view` (current branch's PR).
19
22
 
23
+ If `gh` is not installed or returns an error, proceed to **1b**.
24
+
25
+ #### 1b. GitLab (glab CLI)
26
+
27
+ ```bash
28
+ glab mr view $ARGUMENTS --output json
29
+ glab mr diff $ARGUMENTS
30
+ ```
31
+
32
+ If $ARGUMENTS is empty, use `glab mr view` (current branch's MR).
33
+
34
+ If `glab` is not installed or returns an error, proceed to **1c**.
35
+
36
+ #### 1c. Pure git fallback
37
+
38
+ ```bash
39
+ git log main..HEAD --oneline
40
+ git diff main...HEAD
41
+ ```
42
+
43
+ When using this fallback:
44
+ - PR metadata (title, description, author, reviewer comments) is **not available**.
45
+ - Communicate this clearly to the reviewer agent.
46
+ - Ask the user to provide context about the changes if possible:
47
+ > "No GitHub/GitLab CLI was found. I'm reviewing based on raw git diff only. PR title, description, and comments are unavailable. If you can share what this change is about, it will improve the review."
48
+
20
49
  ### 2. Load project context
21
50
 
22
51
  Read `.ai/memory/architecture.md` and `.ai/memory/conventions.md`.
@@ -24,9 +53,10 @@ Read `.ai/memory/architecture.md` and `.ai/memory/conventions.md`.
24
53
  ### 3. Run reviewer agent
25
54
 
26
55
  Pass to **reviewer** subagent:
27
- - Full PR diff
28
- - PR title and description
29
- - File count and change size
56
+ - Full PR/MR diff (or git diff if fallback)
57
+ - PR/MR title and description (if available; otherwise note "unavailable — git fallback")
58
+ - File count and change size (derive from diff if metadata unavailable)
59
+ - Source used: GitHub / GitLab / git fallback
30
60
  - Project context from step 2
31
61
 
32
62
  The reviewer applies all checks from its instructions and `.ai/memory/conventions.md`, including project-specific rules (e.g., multi-tenant enforcement, architecture layer violations, forbidden patterns).
@@ -37,6 +67,7 @@ The reviewer applies all checks from its instructions and `.ai/memory/convention
37
67
  ---
38
68
  **PR #[number] — [title]**
39
69
  **Author:** [author] | **Branch:** [head] → [base]
70
+ **Source:** GitHub / GitLab / git fallback (no PR metadata)
40
71
  **Size:** +[additions] / -[deletions] in [changedFiles] files
41
72
 
42
73
  **Findings:**
@@ -50,4 +81,7 @@ The reviewer applies all checks from its instructions and `.ai/memory/convention
50
81
  ---
51
82
  ```
52
83
 
53
- If no PR number provided and no current branch PR exists, ask for the PR number.
84
+ If using git fallback, omit fields that are unavailable (number, author, branch names) and add a note:
85
+ > "Review based on git diff only — PR metadata was not available."
86
+
87
+ If no PR/MR number provided and no current branch PR/MR exists and git fallback also fails, ask the user for a PR number or a base branch to diff against.
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: security-scan
3
+ description: "Scan for known CRITICAL security issues and OWASP top 10 vulnerabilities specific to this project. Reports status of each known issue."
4
+ ---
5
+
6
+ Run security scan for: $ARGUMENTS
7
+
8
+ If $ARGUMENTS is empty, scan the full codebase.
9
+ If $ARGUMENTS is a path or module name, scope the scan to that area.
10
+
11
+ ---
12
+
13
+ ## When to use
14
+
15
+ Use before merging changes that touch auth, tenant isolation, input handling, external integrations,
16
+ or any area that directly processes user-supplied data. Not a replacement for automated SAST —
17
+ a targeted, context-aware review using project conventions.
18
+
19
+ ---
20
+
21
+ ## Steps
22
+
23
+ ### 1. Load project context
24
+
25
+ Read `.ai/memory/conventions.md` and `.ai/memory/architecture.md`.
26
+
27
+ Extract:
28
+ - Security rules declared in conventions (e.g., TenantId must come from JWT, not body)
29
+ - Auth mechanism (JWT, sessions, API keys)
30
+ - Data flow: where external input enters the system
31
+ - Stack-specific concerns (e.g., SQL via ORM, HTML rendering, file uploads)
32
+
33
+ ### 2. Map attack surface
34
+
35
+ Identify entry points within the scan scope:
36
+
37
+ ```bash
38
+ # Find API endpoint definitions
39
+ # (adapt pattern to the project's stack — controllers, routes, handlers, etc.)
40
+
41
+ # Find places that read from request body, query string, or headers
42
+ # Find places that write to DB or execute queries
43
+ # Find places that render HTML or return user-supplied content
44
+ # Find places that call external services
45
+ # Find files that handle auth or session state
46
+ ```
47
+
48
+ Run searches appropriate to the detected stack. Do not run all commands if the stack is clear
49
+ from `.ai/memory/architecture.md`.
50
+
51
+ ### 3. Check OWASP Top 10
52
+
53
+ For each category, determine status based on code inspection:
54
+
55
+ | # | Category | Status | Evidence |
56
+ |---|----------|--------|----------|
57
+ | A01 | Broken Access Control | PASS / FAIL / PARTIAL / SKIP | [file:line or reason for skip] |
58
+ | A02 | Cryptographic Failures | PASS / FAIL / PARTIAL / SKIP | |
59
+ | A03 | Injection (SQL, NoSQL, cmd) | PASS / FAIL / PARTIAL / SKIP | |
60
+ | A04 | Insecure Design | PASS / FAIL / PARTIAL / SKIP | |
61
+ | A05 | Security Misconfiguration | PASS / FAIL / PARTIAL / SKIP | |
62
+ | A06 | Vulnerable Components | PASS / FAIL / PARTIAL / SKIP | |
63
+ | A07 | Auth & Session Management | PASS / FAIL / PARTIAL / SKIP | |
64
+ | A08 | Software & Data Integrity | PASS / FAIL / PARTIAL / SKIP | |
65
+ | A09 | Security Logging & Monitoring | PASS / FAIL / PARTIAL / SKIP | |
66
+ | A10 | Server-Side Request Forgery | PASS / FAIL / PARTIAL / SKIP | |
67
+
68
+ **Status definitions:**
69
+ - `PASS` — checked, no issue found
70
+ - `FAIL` — issue found, report exact location
71
+ - `PARTIAL` — partially mitigated, describe gap
72
+ - `SKIP` — not applicable to this scope (explain why)
73
+
74
+ ### 4. Check project-specific security rules
75
+
76
+ From the rules extracted in Step 1, verify each one explicitly.
77
+
78
+ Common examples (adapt to what conventions.md actually says):
79
+
80
+ | Rule | Status | Evidence |
81
+ |------|--------|----------|
82
+ | TenantId sourced from JWT only (never from body/query) | PASS / FAIL | |
83
+ | No hardcoded secrets or API keys in source files | PASS / FAIL | |
84
+ | Auth enforced on all non-public endpoints | PASS / FAIL | |
85
+ | User-supplied data never passed to raw SQL or shell | PASS / FAIL | |
86
+ | File uploads validated for type and size | PASS / FAIL / N/A | |
87
+ | External service calls use timeout and error handling | PASS / FAIL / N/A | |
88
+
89
+ ### 5. Check for secrets in code
90
+
91
+ Search for common secret patterns:
92
+
93
+ ```bash
94
+ # Patterns to search: password=, secret=, apikey=, token=, connectionstring=
95
+ # in non-test, non-example source files
96
+ # Flag any hardcoded value that is not an environment variable reference
97
+ ```
98
+
99
+ Report any findings with file path and line number. Flag `FAIL` in A02 if found.
100
+
101
+ ### 6. Classify findings
102
+
103
+ | Severity | Criteria |
104
+ |----------|----------|
105
+ | CRITICAL | Exploitable without authentication, or exposes tenant data across boundaries |
106
+ | HIGH | Exploitable by authenticated users, privilege escalation, or data exposure |
107
+ | MEDIUM | Requires specific conditions, indirect exposure, or defense-in-depth gap |
108
+ | LOW | Best practice violation, minor information leakage, or hardening opportunity |
109
+
110
+ ---
111
+
112
+ ## Return Format
113
+
114
+ ```markdown
115
+ ---
116
+ **Security Scan Report**
117
+ **Scope:** [full codebase or specific module]
118
+ **Stack:** [detected from architecture.md]
119
+
120
+ ## OWASP Top 10 Status
121
+ [table from Step 3]
122
+
123
+ ## Project-Specific Rules
124
+ [table from Step 4]
125
+
126
+ ## Findings
127
+
128
+ ### CRITICAL
129
+ - [none | list with file:line, description, remediation]
130
+
131
+ ### HIGH
132
+ - [none | list]
133
+
134
+ ### MEDIUM
135
+ - [none | list]
136
+
137
+ ### LOW
138
+ - [none | list]
139
+
140
+ ## Summary
141
+ | Total findings | CRITICAL | HIGH | MEDIUM | LOW |
142
+ |---------------|----------|------|--------|-----|
143
+ | N | N | N | N | N |
144
+
145
+ **Overall status:** CLEAN / NEEDS_ATTENTION / CRITICAL_ACTION_REQUIRED
146
+
147
+ ## Recommended next steps
148
+ [numbered list, prioritized by severity]
149
+ ---
150
+ ```
151
+
152
+ **CLEAN** = zero CRITICAL or HIGH findings.
153
+ **NEEDS_ATTENTION** = one or more MEDIUM findings, zero CRITICAL/HIGH.
154
+ **CRITICAL_ACTION_REQUIRED** = any CRITICAL or HIGH finding present.
155
+
156
+ Do not suggest generic remediation. Every recommendation must reference the specific file,
157
+ function, or rule from conventions.md.
package/src/add.js ADDED
@@ -0,0 +1,45 @@
1
+ import { cpSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+
5
+ const OPTIONAL_SKILLS = ['retro', 'dev-metrics', 'security-scan', 'impact'];
6
+
7
+ export function add(skillName) {
8
+ if (!skillName) {
9
+ console.error('Error: skill name is required.');
10
+ console.log(`\n Available optional skills:\n${OPTIONAL_SKILLS.map(s => ` - ${s}`).join('\n')}\n`);
11
+ process.exit(1);
12
+ }
13
+
14
+ if (!OPTIONAL_SKILLS.includes(skillName)) {
15
+ console.error(`Error: "${skillName}" is not a known optional skill.`);
16
+ console.log(`\n Available optional skills:\n${OPTIONAL_SKILLS.map(s => ` - ${s}`).join('\n')}\n`);
17
+ process.exit(1);
18
+ }
19
+
20
+ const source = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'templates', 'skills', skillName, 'SKILL.md');
21
+
22
+ if (!existsSync(source)) {
23
+ console.error(`Error: source not found at ${source}`);
24
+ console.log(' Make sure crewkit is installed first: npx crewkit install');
25
+ process.exit(1);
26
+ }
27
+
28
+ const targetDir = join(process.cwd(), '.claude', 'skills', skillName);
29
+ const target = join(targetDir, 'SKILL.md');
30
+
31
+ if (existsSync(target)) {
32
+ console.log(` Warning: ${target} already exists. Overwriting.`);
33
+ }
34
+
35
+ mkdirSync(targetDir, { recursive: true });
36
+ cpSync(source, target);
37
+
38
+ console.log(`
39
+ ✓ Skill "${skillName}" installed
40
+
41
+ Copied to: ${target}
42
+
43
+ Use /${skillName} in Claude Code to run it.
44
+ `);
45
+ }
package/src/cli.js CHANGED
@@ -1,16 +1,20 @@
1
1
  import { install } from './install.js';
2
+ import { update } from './update.js';
3
+ import { add } from './add.js';
2
4
 
3
5
  const HELP = `
4
6
  crewkit — Context engineering for AI-assisted development
5
7
 
6
8
  Commands:
7
- install Install crewkit skill globally (~/.claude/skills/)
8
- update Update to latest version (re-run install)
9
- help Show this message
9
+ install Install crewkit skill globally (~/.claude/skills/)
10
+ update Update to latest version (re-run install)
11
+ add <skill> Add an optional skill to the current project
12
+ help Show this message
10
13
 
11
14
  Usage:
12
- npx crewkit install # one-time setup
13
- /crewkit-setup # run in your IDE to scan & calibrate a project
15
+ npx crewkit install # one-time setup
16
+ npx crewkit add retro # add optional skill to project
17
+ /crewkit-setup # run in your IDE to scan & calibrate a project
14
18
  `;
15
19
 
16
20
  export function run(args) {
@@ -18,9 +22,14 @@ export function run(args) {
18
22
 
19
23
  switch (command) {
20
24
  case 'install':
21
- case 'update':
22
25
  install();
23
26
  break;
27
+ case 'update':
28
+ update();
29
+ break;
30
+ case 'add':
31
+ add(args[1]);
32
+ break;
24
33
  case 'help':
25
34
  case '--help':
26
35
  case '-h':
package/src/install.js CHANGED
@@ -1,4 +1,4 @@
1
- import { cpSync, mkdirSync, existsSync, readFileSync } from 'node:fs';
1
+ import { cpSync, mkdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { fileURLToPath } from 'node:url';
@@ -25,6 +25,9 @@ export function install() {
25
25
  // Read version
26
26
  const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
27
27
 
28
+ // Write version marker
29
+ writeFileSync(join(skillDest, '.version'), pkg.version, 'utf8');
30
+
28
31
  console.log(`
29
32
  ✓ crewkit v${pkg.version} installed
30
33
 
package/src/update.js ADDED
@@ -0,0 +1,28 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { install } from './install.js';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ export function update() {
11
+ const versionFile = join(homedir(), '.claude', 'skills', 'crewkit-setup', '.version');
12
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
13
+
14
+ const newVersion = pkg.version;
15
+ const currentVersion = existsSync(versionFile)
16
+ ? readFileSync(versionFile, 'utf8').trim()
17
+ : 'unknown';
18
+
19
+ if (currentVersion === newVersion) {
20
+ console.log(` Already up to date (v${newVersion})`);
21
+ return;
22
+ }
23
+
24
+ install();
25
+
26
+ const fromLabel = currentVersion === 'unknown' ? 'v0.1 (untracked)' : `v${currentVersion}`;
27
+ console.log(` Updated: ${fromLabel} → v${newVersion}`);
28
+ }