@yeison.restrepo.r/code-conductor 1.23.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/LICENSE +185 -0
- package/README.md +314 -0
- package/bin/code-conductor.mjs +133 -0
- package/global/CLAUDE.md +93 -0
- package/global/commands/cc-checkpoint.md +50 -0
- package/global/commands/cc-compact.md +49 -0
- package/global/commands/cc-lang.md +32 -0
- package/global/commands/cc-stack.md +69 -0
- package/global/hooks/graphify-ast-refresh.py +81 -0
- package/global/hooks/verbosity-remind.sh +372 -0
- package/global/memory/personal.md +24 -0
- package/global/memory/verbosity.md +7 -0
- package/global/settings.json +24 -0
- package/lib/installer/config.mjs +51 -0
- package/lib/installer/deploy.mjs +76 -0
- package/lib/installer/env.mjs +35 -0
- package/lib/installer/settings.mjs +77 -0
- package/package.json +34 -0
- package/project-template/.claude/commands/cc-debug.md +42 -0
- package/project-template/.claude/commands/cc-docs.md +49 -0
- package/project-template/.claude/commands/cc-implement.md +164 -0
- package/project-template/.claude/commands/cc-init.md +84 -0
- package/project-template/.claude/commands/cc-plan.md +114 -0
- package/project-template/.claude/commands/cc-refactor.md +42 -0
- package/project-template/.claude/commands/cc-resume.md +142 -0
- package/project-template/.claude/commands/cc-review.md +77 -0
- package/project-template/.claude/commands/cc-spec.md +138 -0
- package/project-template/.claude/commands/cc-test.md +56 -0
- package/project-template/.claude/hooks/context-guard.ps1 +55 -0
- package/project-template/.claude/hooks/context-guard.sh +43 -0
- package/project-template/.claude/hooks/post-compact.ps1 +41 -0
- package/project-template/.claude/hooks/post-compact.sh +36 -0
- package/project-template/.claude/hooks/pre-tool-use.sh +81 -0
- package/project-template/.claude/hooks/verbosity-remind.sh +168 -0
- package/project-template/.claude/memory/context-threshold.txt +1 -0
- package/project-template/.claude/memory/project.md +48 -0
- package/project-template/.claude/settings.json +52 -0
- package/project-template/CLAUDE.md +104 -0
- package/skills/agent-delegation.md +44 -0
- package/skills/code-simplifier.md +124 -0
- package/skills/critical-review.md +75 -0
- package/skills/memory-first.md +50 -0
- package/skills/verbosity.md +30 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "(Conductor) Restore full session context in a fresh Claude Code session"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Step 1 — Verify project initialization
|
|
6
|
+
|
|
7
|
+
Check if `CLAUDE.md` exists in the current directory.
|
|
8
|
+
|
|
9
|
+
- If **absent**: stop immediately and output — `"Project not initialized. Run /cc-init first."`
|
|
10
|
+
- If **present but `## Project Identity` fields are all empty**: continue and include this warning at the top of the final report: `"⚠ Project identity incomplete — run /cc-init to fill it in."`
|
|
11
|
+
|
|
12
|
+
## Step 2 — Read project identity
|
|
13
|
+
|
|
14
|
+
Read `CLAUDE.md`. Extract:
|
|
15
|
+
- **Name** (from `- **Name:**`)
|
|
16
|
+
- **Description** (from `- **Description:**`)
|
|
17
|
+
- **Stack** (from `- **Stack:**`)
|
|
18
|
+
- **Language** (from `- **Language:**`)
|
|
19
|
+
|
|
20
|
+
Use `—` for any missing fields.
|
|
21
|
+
|
|
22
|
+
**Auto-fill blank command fields (BUG-015):** After reading the identity fields, check if any of `Build`, `Test`, `Lint`, `Format`, `Setup` in CLAUDE.md are still `<command>` (any case) or blank after the colon. If at least one is blank AND `scripts/detect-stack.mjs` exists at `$PWD`:
|
|
23
|
+
|
|
24
|
+
1. Run `node scripts/detect-stack.mjs "$PWD"` and capture the JSON output.
|
|
25
|
+
2. For each blank/placeholder command field, if the JSON contains a matching key (`build`, `test`, `lint`, `format`, `setup`), replace the placeholder with the detected value using a single `Edit` call.
|
|
26
|
+
3. Never overwrite a field that already contains a non-placeholder value.
|
|
27
|
+
4. If all five fields are already populated, or if `scripts/detect-stack.mjs` does not exist, skip this step silently.
|
|
28
|
+
5. If the JSON is `{}` or node exits non-zero, skip silently.
|
|
29
|
+
|
|
30
|
+
Re-read the updated CLAUDE.md fields after this step so the session resume report reflects the filled values.
|
|
31
|
+
|
|
32
|
+
## Step 3 — Read project memory
|
|
33
|
+
|
|
34
|
+
Read `.claude/memory/project.md`.
|
|
35
|
+
|
|
36
|
+
Extract:
|
|
37
|
+
- The content of the most recent `## Checkpoint [...]` block (3 bullets max)
|
|
38
|
+
- Any entries under `## Active Conventions`
|
|
39
|
+
- Any entries under `## Technical Debt`
|
|
40
|
+
|
|
41
|
+
If the file is absent or has no `## Checkpoint` block, note `"No checkpoints yet"`.
|
|
42
|
+
|
|
43
|
+
## Step 4 — Read personal preferences
|
|
44
|
+
|
|
45
|
+
Read `.claude/memory/personal.md`. Extract developer preferences (verbosity, shortcuts, habits).
|
|
46
|
+
|
|
47
|
+
If the file is absent, skip silently.
|
|
48
|
+
|
|
49
|
+
## Step 5 — Find latest spec
|
|
50
|
+
|
|
51
|
+
List files in `docs/superpowers/specs/`. Select the file with the most recent modification time (`mtime`). Extract its first `#` heading as a one-line summary.
|
|
52
|
+
|
|
53
|
+
If the directory is absent or empty, use `none`.
|
|
54
|
+
|
|
55
|
+
## Step 6 — Find latest plan
|
|
56
|
+
|
|
57
|
+
List files in `docs/superpowers/plans/`. Select the file with the most recent modification time (`mtime`). Extract its first `#` heading as a one-line summary.
|
|
58
|
+
|
|
59
|
+
If the directory is absent or empty, use `none`.
|
|
60
|
+
|
|
61
|
+
## Step 6a: Scan active plan for in-progress and failed tasks
|
|
62
|
+
|
|
63
|
+
If a plan file was found in Step 6, scan it for active-state markers:
|
|
64
|
+
|
|
65
|
+
Run `Grep` with:
|
|
66
|
+
- `pattern`: `\[>\]|\[!\]`
|
|
67
|
+
- `path`: the plan file path found in Step 6
|
|
68
|
+
- `output_mode`: `content`
|
|
69
|
+
|
|
70
|
+
Collect results:
|
|
71
|
+
- Lines containing `[>]` are **in-progress tasks** (execution interrupted mid-flight)
|
|
72
|
+
- Lines containing `[!]` are **failed tasks** (execution halted; manual resolution required)
|
|
73
|
+
|
|
74
|
+
Extract the task ID (e.g. `[T-001-A]`) from each matching line. Store counts and IDs for the report.
|
|
75
|
+
|
|
76
|
+
If no `[>]` or `[!]` lines are found, skip these fields in the report.
|
|
77
|
+
|
|
78
|
+
## Step 7 — Read git state
|
|
79
|
+
|
|
80
|
+
Run:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git log --oneline -10
|
|
84
|
+
git status --short
|
|
85
|
+
git branch --show-current
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Count the lines in the `git status --short` output — each line represents one uncommitted file. If the output is empty, the count is `"none"`.
|
|
89
|
+
|
|
90
|
+
If not inside a git repository, skip silently.
|
|
91
|
+
|
|
92
|
+
## Step 8 — Check for updates
|
|
93
|
+
|
|
94
|
+
Read the local installed version from `~/.claude/memory/conductor-version.md`.
|
|
95
|
+
|
|
96
|
+
Fetch the remote version:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
curl -fsSL --max-time 5 https://raw.githubusercontent.com/yeisonrestrepo/code-conductor/main/VERSION 2>/dev/null
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If the remote version differs from the local version, store this notice for the report:
|
|
103
|
+
`"⚡ code-conductor [remote version] available — run: bash install.sh to update"`
|
|
104
|
+
|
|
105
|
+
If the fetch fails or times out, skip silently. Do not stop the session.
|
|
106
|
+
|
|
107
|
+
## Step 9 — Render report
|
|
108
|
+
|
|
109
|
+
Output this report, populating each field from the steps above:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
## Session Resume — [Name] · [YYYY-MM-DD]
|
|
113
|
+
|
|
114
|
+
[⚠ Project identity incomplete — run /cc-init to fill it in.] ← include only if applicable
|
|
115
|
+
[⚡ code-conductor X.Y.Z available — run: bash install.sh to update] ← include only if applicable
|
|
116
|
+
|
|
117
|
+
### Active Work
|
|
118
|
+
Spec: [spec filename] — [spec title]
|
|
119
|
+
Plan: [plan filename] — [plan title]
|
|
120
|
+
In-progress: [count] task(s) - [task IDs] (include only if [>] tasks were found in Step 6a)
|
|
121
|
+
Failed: [count] task(s) - [task IDs] (include only if [!] tasks were found in Step 6a)
|
|
122
|
+
|
|
123
|
+
### Recent Commits
|
|
124
|
+
[git log --oneline -10 output]
|
|
125
|
+
|
|
126
|
+
### Open Changes
|
|
127
|
+
Branch: [branch name] · Uncommitted: [count, or "none"]
|
|
128
|
+
|
|
129
|
+
### Memory Highlights
|
|
130
|
+
[latest checkpoint block — 3 bullets max]
|
|
131
|
+
|
|
132
|
+
### Session Preferences
|
|
133
|
+
[personal.md relevant lines]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Step 10 — Load stack profile
|
|
137
|
+
|
|
138
|
+
Run `/cc-stack` to detect and load the matching stack profile.
|
|
139
|
+
|
|
140
|
+
If `/cc-stack` cannot detect a stack or reports an error, append this line to the report:
|
|
141
|
+
`"⚠ Stack could not be detected — run /cc-stack manually."`
|
|
142
|
+
Do not stop the session.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "(Conductor) Review code changes against spec and standards"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Phase entry - Handoff enforcement
|
|
6
|
+
|
|
7
|
+
Before doing anything else, perform this blocking check:
|
|
8
|
+
|
|
9
|
+
1. Count the number of turns in the current conversation history.
|
|
10
|
+
2. If turn count exceeds 5, halt immediately and output:
|
|
11
|
+
|
|
12
|
+
> "Phase boundary detected. Please execute /compact to clear history before proceeding."
|
|
13
|
+
|
|
14
|
+
Do not start any review tasks. Enter standby. Wait for the user to confirm `/compact` has been run before continuing.
|
|
15
|
+
|
|
16
|
+
3. If turn count ≤ 5 AND `.claude/memory/session-snapshot.md` exists, proceed to the Destructive Read Invariant below.
|
|
17
|
+
4. If turn count ≤ 5 AND `.claude/memory/session-snapshot.md` is absent, skip the Destructive Read Invariant and proceed directly - no snapshot context available (read-if-present fallback).
|
|
18
|
+
|
|
19
|
+
## Phase entry - Destructive Read Invariant
|
|
20
|
+
|
|
21
|
+
Applies only when snapshot exists (step 3 above).
|
|
22
|
+
|
|
23
|
+
1. Read `.claude/memory/session-snapshot.md` into context.
|
|
24
|
+
2. Delete the file immediately.
|
|
25
|
+
3. Use the snapshot contents as the starting context for this phase.
|
|
26
|
+
|
|
27
|
+
If the file cannot be deleted after reading, report the error and halt.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Phase 0 — Skill activation
|
|
32
|
+
|
|
33
|
+
Before doing anything else, invoke both skills in order:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Skill({ skill: "subagent-driven-development", args: "$ARGUMENTS" })
|
|
37
|
+
Skill({ skill: "critical-review" })
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`subagent-driven-development` spawns one `Explore` sub-agent per review layer (Critical / Important / Suggestions) — each returns findings, the main context aggregates only. `critical-review` then runs Phases 2–4: Adversarial Review (RESILIENCE / EFFICIENCY / FRICTION checks), Self-Correction Loop for any weakness found, and the mandatory `[VALIDATION]` section at the end.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
Determine what to review:
|
|
45
|
+
- No argument → `git diff HEAD`
|
|
46
|
+
- File path → review that file
|
|
47
|
+
- Directory → review all changed files in that directory
|
|
48
|
+
|
|
49
|
+
Review in three layers:
|
|
50
|
+
|
|
51
|
+
### 🔴 Critical — Blocks merge
|
|
52
|
+
Issues that will cause bugs, security vulnerabilities, data loss, or breaking changes:
|
|
53
|
+
- Logic errors or incorrect algorithm
|
|
54
|
+
- SQL injection, XSS, hardcoded secrets, missing auth checks
|
|
55
|
+
- Mutations that bypass validation
|
|
56
|
+
- Breaking changes to public API without versioning
|
|
57
|
+
|
|
58
|
+
### 🟡 Important — Must fix before shipping
|
|
59
|
+
Issues that degrade quality or create risk:
|
|
60
|
+
- Missing error handling for real failure cases
|
|
61
|
+
- Missing tests for new behavior
|
|
62
|
+
- Convention violations that will confuse future readers
|
|
63
|
+
- N+1 queries or obvious performance problems
|
|
64
|
+
- Missing input validation at system boundaries
|
|
65
|
+
|
|
66
|
+
### 🟢 Suggestions — Optional improvements
|
|
67
|
+
Style, clarity, or minor improvements that would be nice but don't block the merge.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
**Verdict:**
|
|
72
|
+
- `APPROVED` — no critical or important issues
|
|
73
|
+
- `APPROVED WITH CHANGES` — important issues found, fix before shipping
|
|
74
|
+
- `BLOCKED` — critical issues found, do not merge
|
|
75
|
+
|
|
76
|
+
After showing the report, offer:
|
|
77
|
+
"Want me to auto-fix the critical and important issues?"
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "(Conductor) Define the problem and generate an approved spec"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Phase entry - Resume Read
|
|
6
|
+
|
|
7
|
+
Before doing anything else, restore any stored context for the current commit by running `scripts/resume-read.mjs`. It resolves the current git hash, prefers a valid DB snapshot (`conductor-db get-snapshot`), falls back to the `.claude/memory/session-snapshot.json` handoff file, and prints a `RESUME_HIT` block on a hit / nothing on a miss. Capture its stdout **and** its exit code with the canonical per-platform form (each first probes for `node` and treats its absence as a clean miss, never an error):
|
|
8
|
+
|
|
9
|
+
- **Unix / Git Bash:**
|
|
10
|
+
```sh
|
|
11
|
+
if command -v node >/dev/null 2>&1; then
|
|
12
|
+
resume_out="$(node scripts/resume-read.mjs 2>>.conductor/last-write.log)"; resume_rc=$?
|
|
13
|
+
else resume_rc=3; resume_out=""; fi
|
|
14
|
+
```
|
|
15
|
+
- **PowerShell:**
|
|
16
|
+
```powershell
|
|
17
|
+
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
18
|
+
$__eap = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
|
|
19
|
+
if (Test-Path variable:PSNativeCommandUseErrorActionPreference) {
|
|
20
|
+
$__nap = $PSNativeCommandUseErrorActionPreference; $PSNativeCommandUseErrorActionPreference = $false
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
$resume_out = node scripts/resume-read.mjs 2>> .conductor/last-write.log; $resume_rc = $LASTEXITCODE
|
|
24
|
+
} catch { $resume_rc = 3; $resume_out = "" }
|
|
25
|
+
finally {
|
|
26
|
+
$ErrorActionPreference = $__eap
|
|
27
|
+
if (Test-Path variable:__nap) { $PSNativeCommandUseErrorActionPreference = $__nap }
|
|
28
|
+
}
|
|
29
|
+
} else { $resume_rc = 3; $resume_out = "" }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Branch on `resume_rc` - **only `0` and `4` are meaningful; every other code proceeds fresh:**
|
|
33
|
+
|
|
34
|
+
- **`0`** → parse the captured block and adopt it as this phase's starting context, then echo one banner to the user: `> Resumed from stored snapshot @ <commit> (phase: <phase>)`, appending ` (checkpoint prose available)` when the block reports `prose: available`. Parsing (the command owns normalization): split on `\n`; strip a trailing `\r` from every line; drop leading/trailing wholly-blank lines; require `lines[0].trim() === 'RESUME_HIT'` (anything else = miss); `key: value` lines split on the first `': '` (both sides trimmed); the `pending:` block is every subsequent `^\s*-\s+` line up to the first blank line or EOF, each item trimmed. Unknown keys are ignored. In PowerShell, `node …` binds `string[]` for multi-line output - normalize with `$lines = @($resume_out)`; a `$null`/empty capture with `resume_rc = 3` is a miss.
|
|
35
|
+
- **`4`** → **operational halt.** Do not run this phase's normal work. Emit exactly: `SNAP_INVALID: corrupt handoff at .claude/memory/session-snapshot.json - inspect or remove it, then re-run.` and enter standby awaiting user action. The corrupt file is left on disk (the script did not delete it).
|
|
36
|
+
- **`3` or any other code** → **proceed fresh** (clean miss, bypass, degrade, absent `node`, or any unexpected runtime code). Ignore the capture.
|
|
37
|
+
|
|
38
|
+
`resume-read.mjs` writes its own trace lines to `.conductor/last-write.log` via `appendFileSync`; the `2>>` redirect above only sinks the incidental exit-4 halt reason away from the UI - it is not the trace channel.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Phase 0 — Skill activation
|
|
43
|
+
|
|
44
|
+
Before doing anything else, invoke both skills in order:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Skill({ skill: "brainstorming", args: "$ARGUMENTS" })
|
|
48
|
+
Skill({ skill: "critical-review" })
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`brainstorming` explores the problem space and surfaces unknowns. `critical-review` Phase 1 then runs the Pre-Flight Analysis (Happy Path / Failure Points / Boundary Conditions) on the proposed solution before the spec is written. Do not write the spec until both have completed.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Spec Read Budget
|
|
56
|
+
|
|
57
|
+
Before reading any file:
|
|
58
|
+
1. Run Grep or Glob to locate relevant files. Skip this step only if the user's prompt names the exact file path.
|
|
59
|
+
2. Apply the correct read rule based on file type:
|
|
60
|
+
|
|
61
|
+
**Capped source files** - read the first 30 lines only (`offset` omitted, `limit: 30`). Starting at any offset other than the beginning is forbidden; if the first 30 lines are insufficient, defer the file. Multiple reads of the same file at any offset are forbidden.
|
|
62
|
+
Extensions: `.ts` `.tsx` `.js` `.jsx` `.mjs` `.cjs` `.py` `.go` `.rs` `.java` `.rb` `.cs` `.cpp` `.c` `.h` `.swift` `.kt` `.php` `.sh` `.html` `.css` `.scss` `.sass` `.less` `.svelte` `.vue`
|
|
63
|
+
|
|
64
|
+
**Exempt files** - may be read in full:
|
|
65
|
+
Named manifests/config: `package.json` `package-lock.json` `yarn.lock` `pnpm-lock.yaml` `bun.lockb` `go.mod` `go.sum` `Cargo.toml` `Cargo.lock` `pyproject.toml` `requirements.txt` `Pipfile` `Gemfile` `Gemfile.lock` `tsconfig.json` `tsconfig.*.json` `.gitignore` `.eslintrc.*` `.prettierrc.*` `.env.example` `.nvmrc` `.node-version` `.python-version` `.tool-versions`
|
|
66
|
+
Patterns: `*.yaml` `*.yml` `*.toml` `*.json` (config/manifest root files only - do not apply to data or generated JSON) `*.md` `CLAUDE.md` `Makefile` `Dockerfile` `Dockerfile.*` `*.dockerfile` `Jenkinsfile` `Procfile` `Brewfile`
|
|
67
|
+
Note: `.env`, `.env.local`, `.env.*` (real values) are **not exempt** - the agent should not read them during spec phase.
|
|
68
|
+
|
|
69
|
+
**Extensionless files** - exempt only when the exact name appears in the Named manifests/config list or Patterns above. All other extensionless files (including unknown dotfiles) default to capped.
|
|
70
|
+
|
|
71
|
+
**Default** - any file not matched by the above rules defaults to capped.
|
|
72
|
+
|
|
73
|
+
**Deferred reads** - if a capped source file cannot be understood from 30 lines, record it in `### Files Requiring Full Read (deferred to /cc-plan)` and move on. Do not slice-read it.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
Search the codebase for existing code related to `$ARGUMENTS` before asking any questions.
|
|
78
|
+
|
|
79
|
+
Run: `grep -r "$ARGUMENTS" src/ --include="*.{ts,js,py,java,go,rs}" -l 2>/dev/null | head -20`
|
|
80
|
+
|
|
81
|
+
Then ask only for missing context. You need to understand:
|
|
82
|
+
1. **Problem** — what is broken or missing?
|
|
83
|
+
2. **User** — who is affected and what do they expect?
|
|
84
|
+
3. **Constraints** — performance, security, backward compatibility?
|
|
85
|
+
4. **Similar features** — anything in the codebase to stay consistent with?
|
|
86
|
+
|
|
87
|
+
Generate a spec with these sections:
|
|
88
|
+
|
|
89
|
+
## Problem
|
|
90
|
+
[What is broken or missing, from the user's perspective]
|
|
91
|
+
|
|
92
|
+
## Solution
|
|
93
|
+
[What will be built, one paragraph]
|
|
94
|
+
|
|
95
|
+
## Behavior
|
|
96
|
+
|
|
97
|
+
### Main path
|
|
98
|
+
[Step-by-step: what happens in the happy path]
|
|
99
|
+
|
|
100
|
+
### Alternative paths
|
|
101
|
+
[Edge cases the user might hit]
|
|
102
|
+
|
|
103
|
+
### Error cases
|
|
104
|
+
[What happens when things go wrong]
|
|
105
|
+
|
|
106
|
+
## Acceptance Criteria
|
|
107
|
+
- [ ] [Testable criterion]
|
|
108
|
+
- [ ] [Testable criterion]
|
|
109
|
+
|
|
110
|
+
## Out of Scope
|
|
111
|
+
[Explicitly list what this spec does NOT cover]
|
|
112
|
+
|
|
113
|
+
## System Impact
|
|
114
|
+
[What existing code will be affected or needs to be reviewed]
|
|
115
|
+
|
|
116
|
+
### Files Requiring Full Read (deferred to /cc-plan)
|
|
117
|
+
|
|
118
|
+
_None. List any source files that could not be understood within the 30-line cap. /cc-plan will perform full reads of these files before task breakdown._
|
|
119
|
+
|
|
120
|
+
## Complexity Estimate
|
|
121
|
+
[S / M / L — with one sentence justification]
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
Wait for explicit approval before proceeding to `/cc-plan`.
|
|
126
|
+
|
|
127
|
+
Once approved, append a summary to `.claude/memory/project.md` under:
|
|
128
|
+
`## Spec: [name] [YYYY-MM-DD]`
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Phase exit
|
|
133
|
+
|
|
134
|
+
Once the spec is approved and the summary has been appended to `.claude/memory/project.md`, instruct the user:
|
|
135
|
+
|
|
136
|
+
> "Spec complete. Run `/cc-compact` now before starting `/cc-plan`."
|
|
137
|
+
|
|
138
|
+
Do not proceed to plan phase without user confirmation that `/cc-compact` has been run.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "(Conductor) Analyze coverage gaps and write missing tests"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Phase 0 — Skill activation
|
|
6
|
+
|
|
7
|
+
Before doing anything else, invoke the `subagent-driven-development` Superpowers skill:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Skill({ skill: "subagent-driven-development", args: "$ARGUMENTS" })
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Delegate coverage analysis to an `Explore` sub-agent. Delegate each test file to a separate sub-agent. The main context receives summaries and final file paths only.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Analyze coverage gaps first. Run:
|
|
18
|
+
```bash
|
|
19
|
+
# language-specific coverage command
|
|
20
|
+
# e.g.: pnpm test --coverage | tail -20
|
|
21
|
+
# e.g.: pytest --cov=src --cov-report=term-missing
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Identify what is untested. Prioritize:
|
|
25
|
+
1. Public functions and API endpoints with no tests
|
|
26
|
+
2. Error paths and edge cases in critical paths
|
|
27
|
+
3. Integration points between modules
|
|
28
|
+
|
|
29
|
+
**Strategy:**
|
|
30
|
+
- Unit: logic with no I/O dependencies
|
|
31
|
+
- Integration: modules that talk to a database, API, or file system
|
|
32
|
+
- E2E: user-facing flows (use Playwright)
|
|
33
|
+
|
|
34
|
+
**All tests use AAA structure:**
|
|
35
|
+
```
|
|
36
|
+
// Arrange
|
|
37
|
+
// Act
|
|
38
|
+
// Assert
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Test names:** "should [expected behavior] when [condition]"
|
|
42
|
+
|
|
43
|
+
**For E2E with Playwright:**
|
|
44
|
+
1. Confirm the app is running: `curl -f http://localhost:3000 || echo "App not running"`
|
|
45
|
+
2. Navigate to the relevant page
|
|
46
|
+
3. Interact with the UI to trigger the flow
|
|
47
|
+
4. Capture a screenshot
|
|
48
|
+
5. Generate the Playwright test
|
|
49
|
+
|
|
50
|
+
**Run tests after writing them.** Confirm before running.
|
|
51
|
+
|
|
52
|
+
**Report:**
|
|
53
|
+
- Passed: N
|
|
54
|
+
- Failed: N (with failure messages)
|
|
55
|
+
- Skipped: N
|
|
56
|
+
- Coverage delta: before → after (if available)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
try {
|
|
2
|
+
$root = if ($env:CC_PROJECT_ROOT) { $env:CC_PROJECT_ROOT } else { '.' }
|
|
3
|
+
$mem = Join-Path $root '.claude\memory'
|
|
4
|
+
if ((Test-Path $mem) -and -not (Test-Path $mem -PathType Container)) { exit 0 }
|
|
5
|
+
New-Item -ItemType Directory -Force $mem -ErrorAction SilentlyContinue | Out-Null
|
|
6
|
+
if (-not (Test-Path $mem -PathType Container)) { exit 0 }
|
|
7
|
+
|
|
8
|
+
$critical = 25
|
|
9
|
+
$threshFile = Join-Path $mem 'context-threshold.txt'
|
|
10
|
+
try {
|
|
11
|
+
$raw = [System.IO.File]::ReadAllText($threshFile, [System.Text.Encoding]::UTF8)
|
|
12
|
+
$val = $raw.Split("`n")[0].TrimEnd("`r").Trim()
|
|
13
|
+
if ($val -match '^[1-9][0-9]*$') { $critical = [int]$val }
|
|
14
|
+
} catch { }
|
|
15
|
+
|
|
16
|
+
$count = 0
|
|
17
|
+
$countFile = Join-Path $mem 'turn-count.txt'
|
|
18
|
+
try {
|
|
19
|
+
$raw = [System.IO.File]::ReadAllText($countFile, [System.Text.Encoding]::UTF8)
|
|
20
|
+
$val = $raw.Split("`n")[0].TrimEnd("`r").Trim()
|
|
21
|
+
if ($val -match '^[0-9]+$') { $count = [int]$val }
|
|
22
|
+
} catch { }
|
|
23
|
+
|
|
24
|
+
$warning = [Math]::Truncate($critical * 80 / 100)
|
|
25
|
+
$newCount = [Math]::Min($count + 1, 99999)
|
|
26
|
+
|
|
27
|
+
$target = Join-Path $mem 'turn-count.txt'
|
|
28
|
+
$tmp = Join-Path $mem 'turn-count.txt.tmp'
|
|
29
|
+
$enc = [System.Text.UTF8Encoding]::new($false)
|
|
30
|
+
[System.IO.File]::WriteAllText($tmp, "$newCount`n", $enc)
|
|
31
|
+
try {
|
|
32
|
+
[System.IO.File]::Replace($tmp, $target, $null)
|
|
33
|
+
} catch [System.IO.FileNotFoundException] {
|
|
34
|
+
try {
|
|
35
|
+
[System.IO.File]::Move($tmp, $target)
|
|
36
|
+
} catch {
|
|
37
|
+
Remove-Item $tmp -Force -ErrorAction SilentlyContinue
|
|
38
|
+
exit 0
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if ($env:CC_GUARD_DEBUG) {
|
|
43
|
+
Write-Host "[context-guard] root=$root count=$newCount critical=$critical warning=$warning"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if ($newCount -ge 99999) {
|
|
47
|
+
"[!!] CONTEXT CRITICAL: Turn 99999/$critical (counter saturated) -- run /cc-compact NOW."
|
|
48
|
+
} elseif ($newCount -ge $critical) {
|
|
49
|
+
"[!!] CONTEXT CRITICAL: Turn $newCount/$critical -- run /cc-compact NOW before context overflows."
|
|
50
|
+
} elseif ($warning -gt 0 -and $newCount -ge $warning) {
|
|
51
|
+
"[!] CONTEXT WARNING: Turn $newCount/$critical -- consider running /cc-compact soon."
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
exit 0
|
|
55
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set +e
|
|
3
|
+
main() {
|
|
4
|
+
_mem="${CC_PROJECT_ROOT:-.}/.claude/memory"
|
|
5
|
+
if [ -e "$_mem" ] && [ ! -d "$_mem" ]; then exit 0; fi
|
|
6
|
+
mkdir -p "$_mem" 2>/dev/null || exit 0
|
|
7
|
+
|
|
8
|
+
# Read threshold
|
|
9
|
+
_thresh=""
|
|
10
|
+
IFS= read -r _thresh < "${_mem}/context-threshold.txt" 2>/dev/null || _thresh=""
|
|
11
|
+
_thresh="${_thresh%$'\r'}"
|
|
12
|
+
_thresh="${_thresh#$'\xef\xbb\xbf'}"
|
|
13
|
+
[[ "$_thresh" =~ ^[1-9][0-9]*$ ]] || _thresh=25
|
|
14
|
+
critical=$_thresh
|
|
15
|
+
warning=$(( (critical * 80) / 100 ))
|
|
16
|
+
|
|
17
|
+
# Read count
|
|
18
|
+
_c=""
|
|
19
|
+
IFS= read -r _c < "${_mem}/turn-count.txt" 2>/dev/null || _c=""
|
|
20
|
+
_c="${_c%$'\r'}"
|
|
21
|
+
_c="${_c#$'\xef\xbb\xbf'}"
|
|
22
|
+
[[ "$_c" =~ ^[0-9]+$ ]] || _c=0
|
|
23
|
+
count=$_c
|
|
24
|
+
|
|
25
|
+
new_count=$(( count < 99999 ? count + 1 : 99999 ))
|
|
26
|
+
|
|
27
|
+
_target="${_mem}/turn-count.txt"
|
|
28
|
+
_tmp="${_mem}/turn-count.txt.tmp"
|
|
29
|
+
printf '%d\n' "$new_count" > "$_tmp" && mv -f "$_tmp" "$_target" \
|
|
30
|
+
|| { rm -f "$_tmp" 2>/dev/null; exit 0; }
|
|
31
|
+
|
|
32
|
+
[ -n "${CC_GUARD_DEBUG:-}" ] && printf '[context-guard] root=%s count=%d critical=%d warning=%d\n' \
|
|
33
|
+
"${CC_PROJECT_ROOT:-.}" "$new_count" "$critical" "$warning" >&2
|
|
34
|
+
|
|
35
|
+
if [ "$new_count" -ge 99999 ]; then
|
|
36
|
+
printf '🚨 CONTEXT CRITICAL: Turn 99999/%d (counter saturated) — run /cc-compact NOW.\n' "$critical"
|
|
37
|
+
elif [ "$new_count" -ge "$critical" ]; then
|
|
38
|
+
printf '🚨 CONTEXT CRITICAL: Turn %d/%d — run /cc-compact NOW before context overflows.\n' "$new_count" "$critical"
|
|
39
|
+
elif [ "$warning" -gt 0 ] && [ "$new_count" -ge "$warning" ]; then
|
|
40
|
+
printf '⚠ CONTEXT WARNING: Turn %d/%d — consider running /cc-compact soon.\n' "$new_count" "$critical"
|
|
41
|
+
fi
|
|
42
|
+
}
|
|
43
|
+
main || exit 0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
try {
|
|
2
|
+
$root = if ($env:CC_PROJECT_ROOT) { $env:CC_PROJECT_ROOT } else { '.' }
|
|
3
|
+
$mem = Join-Path $root '.claude\memory'
|
|
4
|
+
if ((Test-Path $mem) -and -not (Test-Path $mem -PathType Container)) { exit 0 }
|
|
5
|
+
New-Item -ItemType Directory -Force $mem -ErrorAction SilentlyContinue | Out-Null
|
|
6
|
+
if (-not (Test-Path $mem -PathType Container)) { exit 0 }
|
|
7
|
+
|
|
8
|
+
$target = Join-Path $mem 'turn-count.txt'
|
|
9
|
+
$tmp = Join-Path $mem 'turn-count.txt.tmp'
|
|
10
|
+
$enc = [System.Text.UTF8Encoding]::new($false)
|
|
11
|
+
[System.IO.File]::WriteAllText($tmp, "0`n", $enc)
|
|
12
|
+
try {
|
|
13
|
+
[System.IO.File]::Replace($tmp, $target, $null)
|
|
14
|
+
} catch [System.IO.FileNotFoundException] {
|
|
15
|
+
try {
|
|
16
|
+
[System.IO.File]::Move($tmp, $target)
|
|
17
|
+
} catch {
|
|
18
|
+
Remove-Item $tmp -Force -ErrorAction SilentlyContinue
|
|
19
|
+
exit 0
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
""
|
|
24
|
+
"[PKG] Conversation compacted. Context counter reset to 0."
|
|
25
|
+
$projMd = Join-Path $root '.claude\memory\project.md'
|
|
26
|
+
if (Test-Path $projMd) {
|
|
27
|
+
$lastMatch = Select-String '## Checkpoint' $projMd | Select-Object -Last 1
|
|
28
|
+
if ($lastMatch) { " Last checkpoint: $($lastMatch.Line)" } else { " No checkpoints recorded yet in project.md." }
|
|
29
|
+
} else { " No project.md found." }
|
|
30
|
+
""
|
|
31
|
+
" [TIP] If this session had important decisions, run /checkpoint before continuing."
|
|
32
|
+
|
|
33
|
+
$cond = Join-Path $root '.conductor'
|
|
34
|
+
Remove-Item -Force -ErrorAction SilentlyContinue (Join-Path $cond 'session-id')
|
|
35
|
+
Remove-Item -Force -ErrorAction SilentlyContinue (Join-Path $cond 'session-id.*.tmp')
|
|
36
|
+
Remove-Item -Force -ErrorAction SilentlyContinue (Join-Path $cond 'resume-validate.*.tmp.json')
|
|
37
|
+
|
|
38
|
+
""
|
|
39
|
+
} catch {
|
|
40
|
+
exit 0
|
|
41
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set +e
|
|
3
|
+
main() {
|
|
4
|
+
_mem="${CC_PROJECT_ROOT:-.}/.claude/memory"
|
|
5
|
+
if [ -e "$_mem" ] && [ ! -d "$_mem" ]; then exit 0; fi
|
|
6
|
+
mkdir -p "$_mem" 2>/dev/null || exit 0
|
|
7
|
+
|
|
8
|
+
_target="${_mem}/turn-count.txt"
|
|
9
|
+
_tmp="${_mem}/turn-count.txt.tmp"
|
|
10
|
+
printf '0\n' > "$_tmp" && mv -f "$_tmp" "$_target" \
|
|
11
|
+
|| { rm -f "$_tmp" 2>/dev/null; exit 0; }
|
|
12
|
+
|
|
13
|
+
echo ""
|
|
14
|
+
echo "📦 Conversation compacted. Context counter reset to 0."
|
|
15
|
+
|
|
16
|
+
_mem_file="${CC_PROJECT_ROOT:-.}/.claude/memory/project.md"
|
|
17
|
+
if [ -f "$_mem_file" ]; then
|
|
18
|
+
_last=$(grep "## Checkpoint" "$_mem_file" | tail -1 || true)
|
|
19
|
+
[ -n "$_last" ] && echo " Last checkpoint: $_last" \
|
|
20
|
+
|| echo " No checkpoints recorded yet in project.md."
|
|
21
|
+
else
|
|
22
|
+
echo " No project.md found."
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
echo ""
|
|
26
|
+
echo " 💡 If this session had important decisions or conventions,"
|
|
27
|
+
echo " run /checkpoint before continuing."
|
|
28
|
+
|
|
29
|
+
_cond="${CC_PROJECT_ROOT:-.}/.conductor"
|
|
30
|
+
rm -f "${_cond}/session-id" 2>/dev/null
|
|
31
|
+
rm -f "${_cond}"/session-id.*.tmp 2>/dev/null
|
|
32
|
+
rm -f "${_cond}"/resume-validate.*.tmp.json 2>/dev/null
|
|
33
|
+
|
|
34
|
+
echo ""
|
|
35
|
+
}
|
|
36
|
+
main || exit 0
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Guards: (1) large-file Read without limit, (2) duplicate file creation.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# ── Guard 1: Large-file Read without limit ─────────────────────────────────────
|
|
7
|
+
if [ "${CLAUDE_TOOL_NAME:-}" = "Read" ]; then
|
|
8
|
+
READ_PATH=$(echo "${CLAUDE_TOOL_INPUT:-}" | grep -o '"file_path":"[^"]*"' | head -1 | sed 's/"file_path":"//;s/"//' || true)
|
|
9
|
+
if [ -n "$READ_PATH" ] && [ -f "$READ_PATH" ]; then
|
|
10
|
+
LINE_COUNT=$(wc -l < "$READ_PATH" 2>/dev/null || echo "0")
|
|
11
|
+
HAS_LIMIT=$(echo "${CLAUDE_TOOL_INPUT:-}" | grep -c '"limit"' || true)
|
|
12
|
+
if [ "$LINE_COUNT" -gt 150 ] && [ "$HAS_LIMIT" -eq 0 ]; then
|
|
13
|
+
echo ""
|
|
14
|
+
echo "⛔ LARGE FILE READ BLOCKED"
|
|
15
|
+
echo " File: $READ_PATH"
|
|
16
|
+
echo " Lines: $LINE_COUNT (>150 — no limit specified)"
|
|
17
|
+
echo ""
|
|
18
|
+
echo " Follow the orchestrator lookup chain:"
|
|
19
|
+
echo " 1. Check .claude/memory/project.md"
|
|
20
|
+
echo " 2. Query graphify for structural questions"
|
|
21
|
+
echo " 3. Use Grep/Glob for pattern searches"
|
|
22
|
+
echo " 4. Read with explicit offset + limit"
|
|
23
|
+
echo ""
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
fi
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# ── Guard 4 — block Read on graphify-out/ and node_modules/ (BUG-017) ─────────────────────
|
|
30
|
+
# To reset to GitHub upstream: delete .claude/hooks/pre-tool-use.sh, then re-run installer.
|
|
31
|
+
if [ "$CLAUDE_TOOL_NAME" = "Read" ]; then
|
|
32
|
+
_g4_result=$(printf '%s' "$CLAUDE_TOOL_INPUT" | python3 -c '
|
|
33
|
+
import json, sys, posixpath
|
|
34
|
+
raw = sys.stdin.buffer.read().decode("utf-8", errors="replace")
|
|
35
|
+
d = json.loads(raw)
|
|
36
|
+
fp = d.get("file_path", "").strip()
|
|
37
|
+
fp_n = posixpath.normpath(fp.replace("\\", "/"))
|
|
38
|
+
parts = [p.lower() for p in fp_n.split("/") if p and p != "."]
|
|
39
|
+
blocked = {"graphify-out", "node_modules"}
|
|
40
|
+
print("BLOCK" if any(p in blocked for p in parts) else "OK")
|
|
41
|
+
' 2>/dev/null) || true
|
|
42
|
+
if [ "$_g4_result" = "BLOCK" ]; then
|
|
43
|
+
echo '{"decision":"block","reason":"Guard 4: direct reads of graphify-out/ and node_modules/ are forbidden. Use Glob for existence checks or the graphify skill: /graphify query \"<question>\"."}'
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
# Debug: set CC_GUARD4_DEBUG=1 to log fail-open events to stderr for diagnostics.
|
|
47
|
+
if [ -n "${CC_GUARD4_DEBUG:-}" ] && [ "$_g4_result" != "OK" ]; then
|
|
48
|
+
printf '[Guard 4 debug] fail-open: _g4_result="%s"\n' "$_g4_result" >&2
|
|
49
|
+
fi
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# ── Guard 2: Duplicate file creation ──────────────────────────────────────────
|
|
53
|
+
FILE_PATH=""
|
|
54
|
+
if [ -n "${CLAUDE_TOOL_INPUT:-}" ]; then
|
|
55
|
+
FILE_PATH=$(echo "$CLAUDE_TOOL_INPUT" | grep -o '"path":"[^"]*"' | head -1 | sed 's/"path":"//;s/"//' || true)
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
if [ -z "$FILE_PATH" ]; then
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if [ ! -f "$FILE_PATH" ]; then
|
|
63
|
+
exit 0
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
LINE_COUNT=$(wc -l < "$FILE_PATH" 2>/dev/null || echo "?")
|
|
67
|
+
LAST_MODIFIED=$(date -r "$FILE_PATH" "+%Y-%m-%d %H:%M" 2>/dev/null || stat -c "%y" "$FILE_PATH" 2>/dev/null | cut -d. -f1 || echo "unknown")
|
|
68
|
+
|
|
69
|
+
echo ""
|
|
70
|
+
echo "⚠️ FILE ALREADY EXISTS"
|
|
71
|
+
echo " Path: $FILE_PATH"
|
|
72
|
+
echo " Lines: $LINE_COUNT"
|
|
73
|
+
echo " Last modified: $LAST_MODIFIED"
|
|
74
|
+
echo ""
|
|
75
|
+
echo " Choose an action:"
|
|
76
|
+
echo " 1. Edit the existing file instead of overwriting"
|
|
77
|
+
echo " 2. Confirm you want to overwrite (re-issue the command)"
|
|
78
|
+
echo " 3. Cancel"
|
|
79
|
+
echo ""
|
|
80
|
+
|
|
81
|
+
exit 1
|