ecc_infisense 0.0.1
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/.claude-plugin/plugin.json +17 -0
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/agents/component-designer.md +261 -0
- package/agents/plugin-inspector.md +160 -0
- package/agents/release-executor.md +349 -0
- package/commands/infi-component-creator.md +132 -0
- package/commands/infi-ecc-helper.md +44 -0
- package/commands/infi-release.md +83 -0
- package/hooks/hooks.json +53 -0
- package/install.sh +237 -0
- package/package.json +50 -0
- package/rules/common/agents.md +28 -0
- package/rules/common/development-workflow.md +26 -0
- package/rules/common/git-workflow.md +45 -0
- package/rules/common/hooks.md +36 -0
- package/scripts/hooks/pre-compact.js +72 -0
- package/scripts/hooks/session-end.js +72 -0
- package/scripts/hooks/session-start.js +124 -0
- package/scripts/hooks/suggest-compact.js +58 -0
- package/scripts/lib/session-aliases.js +481 -0
- package/scripts/lib/session-manager.js +442 -0
- package/scripts/lib/utils.js +593 -0
- package/skills/component-templates/SKILL.md +306 -0
- package/skills/release-workflow/SKILL.md +180 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Git commit and npm publish with version management.
|
|
3
|
+
category: plugin
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Release Management
|
|
7
|
+
|
|
8
|
+
Manage ECC InfiSense releases through three workflows: git update, npm publish,
|
|
9
|
+
and status. Delegates execution to the `release-executor` agent.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
`/infi-release [git-update|publish|status] [options]`
|
|
14
|
+
|
|
15
|
+
If mode is omitted, present an interactive menu using AskUserQuestion:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Which release workflow do you want to run?
|
|
19
|
+
|
|
20
|
+
1. git update
|
|
21
|
+
Detect changes, commit with conventional commits, update CHANGELOG.md
|
|
22
|
+
2. npm publish
|
|
23
|
+
Bump version, update CHANGELOG.md, tag, push, npm publish
|
|
24
|
+
3. status
|
|
25
|
+
Show current version, last tag, and unreleased changes
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 1. git update
|
|
31
|
+
|
|
32
|
+
Detect uncommitted changes, make all necessary file modifications, then commit.
|
|
33
|
+
|
|
34
|
+
Delegate to `release-executor` agent which will:
|
|
35
|
+
|
|
36
|
+
1. **Detect changes** — scan git status for modified, added, deleted files
|
|
37
|
+
2. **Analyze and group** — map file paths to commit types/scopes using
|
|
38
|
+
`release-workflow` skill conventions
|
|
39
|
+
3. **Safety checks** — scan for dangerous files, debug code, validate message format
|
|
40
|
+
4. **Update CHANGELOG.md** — categorize changes per Keep a Changelog format
|
|
41
|
+
5. **Update documentation** — sync component counts in README.md, GUIDE.md, CLAUDE.md
|
|
42
|
+
6. **Commit** — stage and commit (single or multiple atomic commits)
|
|
43
|
+
|
|
44
|
+
Show all findings and grouping plan to user. Wait for confirmation before committing.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 2. npm publish
|
|
49
|
+
|
|
50
|
+
Full release: bump version, finalize changelog, tag, push, publish.
|
|
51
|
+
|
|
52
|
+
Delegate to `release-executor` agent which will:
|
|
53
|
+
|
|
54
|
+
1. **Ensure clean tree** — run git update first if uncommitted changes exist
|
|
55
|
+
2. **Pre-flight** — run `npm test`, abort if tests fail
|
|
56
|
+
3. **Bump version** — ask user for level (patch/minor/major), update package.json
|
|
57
|
+
and plugin.json
|
|
58
|
+
4. **Finalize changelog** — move `[Unreleased]` to versioned section
|
|
59
|
+
5. **Update documentation** — sync version and counts in README.md, GUIDE.md
|
|
60
|
+
6. **Commit, tag, push, publish** — single release commit with version tag
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 3. status
|
|
65
|
+
|
|
66
|
+
Read-only — show current state without making changes.
|
|
67
|
+
|
|
68
|
+
Delegate to `release-executor` agent to display:
|
|
69
|
+
|
|
70
|
+
- Current version from package.json
|
|
71
|
+
- Last git tag
|
|
72
|
+
- Commit count since last tag
|
|
73
|
+
- Uncommitted changes summary
|
|
74
|
+
- Unreleased changelog entries
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Cross-References
|
|
79
|
+
|
|
80
|
+
- Agent: `release-executor` — executes all three release workflows
|
|
81
|
+
- Skill: `release-workflow` — commit conventions, path-scope mapping, changelog format
|
|
82
|
+
- Related: `/infi-component-creator` — create components before releasing
|
|
83
|
+
- Related: `/infi-ecc-helper` — view current plugin overview
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PreToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "Edit|Write",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/suggest-compact.js\""
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"description": "Suggest manual compaction at logical intervals"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"PreCompact": [
|
|
17
|
+
{
|
|
18
|
+
"matcher": "*",
|
|
19
|
+
"hooks": [
|
|
20
|
+
{
|
|
21
|
+
"type": "command",
|
|
22
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/pre-compact.js\""
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"description": "Save state before context compaction"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"SessionStart": [
|
|
29
|
+
{
|
|
30
|
+
"matcher": "*",
|
|
31
|
+
"hooks": [
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-start.js\""
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"description": "Load previous context and detect build system on new session"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"SessionEnd": [
|
|
41
|
+
{
|
|
42
|
+
"matcher": "*",
|
|
43
|
+
"hooks": [
|
|
44
|
+
{
|
|
45
|
+
"type": "command",
|
|
46
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-end.js\""
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"description": "Persist session state on end"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
package/install.sh
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# install.sh — Install ECC InfiSense plugin for Claude Code.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./install.sh
|
|
6
|
+
#
|
|
7
|
+
# This script copies all plugin components into ~/.claude/:
|
|
8
|
+
# - rules/ → ~/.claude/rules/common/
|
|
9
|
+
# - commands/ → ~/.claude/commands/
|
|
10
|
+
# - agents/ → ~/.claude/agents/
|
|
11
|
+
# - skills/ → ~/.claude/skills/
|
|
12
|
+
# - hooks → ~/.claude/settings.json (merged)
|
|
13
|
+
#
|
|
14
|
+
# Update safety:
|
|
15
|
+
# A manifest file (~/.claude/.ecc-infisense-manifest) tracks every file
|
|
16
|
+
# installed by this plugin. On re-install, files listed in the old manifest
|
|
17
|
+
# but absent from the new version are automatically removed, without
|
|
18
|
+
# touching files owned by the user or other plugins.
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# Resolve symlinks — needed when invoked as `ecc-infisense-install` via npm/bun bin symlink
|
|
23
|
+
SCRIPT_PATH="$0"
|
|
24
|
+
while [ -L "$SCRIPT_PATH" ]; do
|
|
25
|
+
link_dir="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
26
|
+
SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
|
|
27
|
+
# Resolve relative symlinks
|
|
28
|
+
[[ "$SCRIPT_PATH" != /* ]] && SCRIPT_PATH="$link_dir/$SCRIPT_PATH"
|
|
29
|
+
done
|
|
30
|
+
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
31
|
+
RULES_DIR="$SCRIPT_DIR/rules"
|
|
32
|
+
|
|
33
|
+
# --- Manifest helpers ---
|
|
34
|
+
# The manifest tracks every file installed by this plugin so that upgrades
|
|
35
|
+
# can remove files that no longer exist in the new version, without touching
|
|
36
|
+
# files owned by the user or other plugins.
|
|
37
|
+
|
|
38
|
+
MANIFEST_FILE="$HOME/.claude/.ecc-infisense-manifest"
|
|
39
|
+
NEW_MANIFEST=()
|
|
40
|
+
|
|
41
|
+
# Record a file path into the new manifest (call after each cp)
|
|
42
|
+
record() {
|
|
43
|
+
NEW_MANIFEST+=("$1")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Record all files under a directory tree
|
|
47
|
+
record_tree() {
|
|
48
|
+
local dir="$1"
|
|
49
|
+
while IFS= read -r -d '' f; do
|
|
50
|
+
record "$f"
|
|
51
|
+
done < <(find "$dir" -type f -print0 2>/dev/null)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Remove files from old manifest that are not in the new manifest
|
|
55
|
+
cleanup_old_manifest() {
|
|
56
|
+
if [[ ! -f "$MANIFEST_FILE" ]]; then
|
|
57
|
+
return
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
local removed=0
|
|
61
|
+
while IFS= read -r old_file; do
|
|
62
|
+
[[ -z "$old_file" ]] && continue
|
|
63
|
+
# Check if this file is still in the new manifest
|
|
64
|
+
local found=false
|
|
65
|
+
for new_file in "${NEW_MANIFEST[@]}"; do
|
|
66
|
+
if [[ "$new_file" == "$old_file" ]]; then
|
|
67
|
+
found=true
|
|
68
|
+
break
|
|
69
|
+
fi
|
|
70
|
+
done
|
|
71
|
+
if ! $found && [[ -f "$old_file" ]]; then
|
|
72
|
+
rm -f "$old_file"
|
|
73
|
+
removed=$((removed + 1))
|
|
74
|
+
fi
|
|
75
|
+
done < "$MANIFEST_FILE"
|
|
76
|
+
|
|
77
|
+
if [[ $removed -gt 0 ]]; then
|
|
78
|
+
echo "Cleaned up $removed file(s) from previous installation."
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Remove empty directories left behind (only under ~/.claude/)
|
|
82
|
+
find "$HOME/.claude/rules" "$HOME/.claude/commands" "$HOME/.claude/agents" "$HOME/.claude/skills" \
|
|
83
|
+
-type d -empty -delete 2>/dev/null || true
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Write the new manifest to disk
|
|
87
|
+
save_manifest() {
|
|
88
|
+
mkdir -p "$(dirname "$MANIFEST_FILE")"
|
|
89
|
+
printf '%s\n' "${NEW_MANIFEST[@]}" > "$MANIFEST_FILE"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# --- Install ---
|
|
93
|
+
|
|
94
|
+
install_plugin() {
|
|
95
|
+
local DEST_DIR="${CLAUDE_RULES_DIR:-$HOME/.claude/rules}"
|
|
96
|
+
local CMD_DIR="$HOME/.claude/commands"
|
|
97
|
+
local AGENTS_DIR="$HOME/.claude/agents"
|
|
98
|
+
local SKILLS_DIR="$HOME/.claude/skills"
|
|
99
|
+
local COMMANDS_SRC="$SCRIPT_DIR/commands"
|
|
100
|
+
local AGENTS_SRC="$SCRIPT_DIR/agents"
|
|
101
|
+
local SKILLS_SRC="$SCRIPT_DIR/skills"
|
|
102
|
+
local SETTINGS_FILE="$HOME/.claude/settings.json"
|
|
103
|
+
local HOOKS_SRC="$SCRIPT_DIR/hooks/hooks.json"
|
|
104
|
+
|
|
105
|
+
# --- Rules ---
|
|
106
|
+
|
|
107
|
+
# Install common rules
|
|
108
|
+
if [[ -d "$RULES_DIR/common" ]]; then
|
|
109
|
+
echo "Installing rules -> $DEST_DIR/common/"
|
|
110
|
+
rm -rf "$DEST_DIR/common"
|
|
111
|
+
mkdir -p "$DEST_DIR/common"
|
|
112
|
+
cp -r "$RULES_DIR/common/." "$DEST_DIR/common/"
|
|
113
|
+
record_tree "$DEST_DIR/common"
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# Install language-specific rules if they exist
|
|
117
|
+
for lang_dir in "$RULES_DIR"/*/; do
|
|
118
|
+
[[ -d "$lang_dir" ]] || continue
|
|
119
|
+
local lang
|
|
120
|
+
lang="$(basename "$lang_dir")"
|
|
121
|
+
[[ "$lang" == "common" ]] && continue
|
|
122
|
+
|
|
123
|
+
echo "Installing $lang rules -> $DEST_DIR/$lang/"
|
|
124
|
+
rm -rf "$DEST_DIR/$lang"
|
|
125
|
+
mkdir -p "$DEST_DIR/$lang"
|
|
126
|
+
cp -r "$lang_dir." "$DEST_DIR/$lang/"
|
|
127
|
+
record_tree "$DEST_DIR/$lang"
|
|
128
|
+
done
|
|
129
|
+
|
|
130
|
+
echo "Rules installed to $DEST_DIR/"
|
|
131
|
+
|
|
132
|
+
# --- Commands ---
|
|
133
|
+
if [[ -d "$COMMANDS_SRC" ]]; then
|
|
134
|
+
echo "Installing commands -> $CMD_DIR/"
|
|
135
|
+
mkdir -p "$CMD_DIR"
|
|
136
|
+
for f in "$COMMANDS_SRC"/*.md; do
|
|
137
|
+
[[ -f "$f" ]] || continue
|
|
138
|
+
local dest="$CMD_DIR/$(basename "$f")"
|
|
139
|
+
cp "$f" "$dest"
|
|
140
|
+
record "$dest"
|
|
141
|
+
done
|
|
142
|
+
echo "Commands installed ($(ls "$COMMANDS_SRC"/*.md 2>/dev/null | wc -l) files)"
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
# --- Agents ---
|
|
146
|
+
if [[ -d "$AGENTS_SRC" ]]; then
|
|
147
|
+
echo "Installing agents -> $AGENTS_DIR/"
|
|
148
|
+
mkdir -p "$AGENTS_DIR"
|
|
149
|
+
for f in "$AGENTS_SRC"/*; do
|
|
150
|
+
[[ -f "$f" ]] || continue
|
|
151
|
+
local dest="$AGENTS_DIR/$(basename "$f")"
|
|
152
|
+
cp "$f" "$dest"
|
|
153
|
+
record "$dest"
|
|
154
|
+
done
|
|
155
|
+
echo "Agents installed ($(ls "$AGENTS_SRC"/ 2>/dev/null | wc -l) files)"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# --- Skills ---
|
|
159
|
+
if [[ -d "$SKILLS_SRC" ]]; then
|
|
160
|
+
echo "Installing skills -> $SKILLS_DIR/"
|
|
161
|
+
mkdir -p "$SKILLS_DIR"
|
|
162
|
+
for skill_dir in "$SKILLS_SRC"/*/; do
|
|
163
|
+
[[ -d "$skill_dir" ]] || continue
|
|
164
|
+
local skill_name
|
|
165
|
+
skill_name="$(basename "$skill_dir")"
|
|
166
|
+
local dest_skill="$SKILLS_DIR/$skill_name"
|
|
167
|
+
rm -rf "$dest_skill"
|
|
168
|
+
mkdir -p "$dest_skill"
|
|
169
|
+
cp -r "$skill_dir." "$dest_skill/"
|
|
170
|
+
record_tree "$dest_skill"
|
|
171
|
+
done
|
|
172
|
+
echo "Skills installed ($(find "$SKILLS_SRC" -maxdepth 1 -mindepth 1 -type d | wc -l) skills)"
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# --- Cleanup old files and save new manifest ---
|
|
176
|
+
cleanup_old_manifest
|
|
177
|
+
save_manifest
|
|
178
|
+
|
|
179
|
+
# --- Merge hooks into ~/.claude/settings.json ---
|
|
180
|
+
if [[ -f "$HOOKS_SRC" ]] && command -v node >/dev/null 2>&1; then
|
|
181
|
+
echo "Installing hooks into $SETTINGS_FILE ..."
|
|
182
|
+
node -e "
|
|
183
|
+
const fs = require('fs');
|
|
184
|
+
const hooksPath = '$HOOKS_SRC';
|
|
185
|
+
const settingsPath = '$SETTINGS_FILE';
|
|
186
|
+
const pluginRoot = '$SCRIPT_DIR';
|
|
187
|
+
|
|
188
|
+
// Read new hooks
|
|
189
|
+
const newHooks = JSON.parse(fs.readFileSync(hooksPath, 'utf8'));
|
|
190
|
+
|
|
191
|
+
// Read existing settings or create empty
|
|
192
|
+
let settings = {};
|
|
193
|
+
try {
|
|
194
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
195
|
+
} catch {}
|
|
196
|
+
|
|
197
|
+
// Replace \${CLAUDE_PLUGIN_ROOT} with actual path in hook commands
|
|
198
|
+
const hooksStr = JSON.stringify(newHooks.hooks || newHooks)
|
|
199
|
+
.replace(/\\$\\{CLAUDE_PLUGIN_ROOT\\}/g, pluginRoot);
|
|
200
|
+
const resolvedHooks = JSON.parse(hooksStr);
|
|
201
|
+
|
|
202
|
+
// Merge hooks (overwrite event types from plugin)
|
|
203
|
+
if (!settings.hooks) settings.hooks = {};
|
|
204
|
+
for (const [event, matchers] of Object.entries(resolvedHooks)) {
|
|
205
|
+
settings.hooks[event] = matchers;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Remove event types that are no longer in the plugin
|
|
209
|
+
const pluginEvents = Object.keys(resolvedHooks);
|
|
210
|
+
for (const event of Object.keys(settings.hooks)) {
|
|
211
|
+
if (!pluginEvents.includes(event)) {
|
|
212
|
+
// Check if all matchers in this event reference our plugin
|
|
213
|
+
const matchers = settings.hooks[event];
|
|
214
|
+
const allOurs = matchers.every(m =>
|
|
215
|
+
m.hooks && m.hooks.every(h =>
|
|
216
|
+
h.command && h.command.includes(pluginRoot)
|
|
217
|
+
)
|
|
218
|
+
);
|
|
219
|
+
if (allOurs) {
|
|
220
|
+
delete settings.hooks[event];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
226
|
+
console.log('Hooks merged into ' + settingsPath);
|
|
227
|
+
"
|
|
228
|
+
else
|
|
229
|
+
echo "Warning: node not found or hooks.json missing. Hooks not installed." >&2
|
|
230
|
+
echo " Install Node.js 18+ and re-run to enable hooks." >&2
|
|
231
|
+
fi
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
install_plugin
|
|
235
|
+
|
|
236
|
+
echo ""
|
|
237
|
+
echo "Done. Run '/infi-ecc-helper' in Claude Code to verify."
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ecc_infisense",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Claude Code plugin for C/C++ development — agents, skills, hooks, commands, and rules for component management, release workflow, and C++ coding conventions",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code",
|
|
7
|
+
"cpp",
|
|
8
|
+
"c++",
|
|
9
|
+
"plugin",
|
|
10
|
+
"agents",
|
|
11
|
+
"skills",
|
|
12
|
+
"hooks",
|
|
13
|
+
"rules"
|
|
14
|
+
],
|
|
15
|
+
"author": "ECC InfiSense Contributors",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+ssh://git@172.16.40.222:sunchaoyue/ecc-infisense.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "http://172.16.40.222/sunchaoyue/ecc-infisense",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "http://172.16.40.222/sunchaoyue/ecc-infisense/issues"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"agents/",
|
|
27
|
+
"commands/",
|
|
28
|
+
"hooks/",
|
|
29
|
+
"rules/",
|
|
30
|
+
"scripts/hooks/",
|
|
31
|
+
"scripts/lib/",
|
|
32
|
+
"skills/",
|
|
33
|
+
".claude-plugin/plugin.json",
|
|
34
|
+
"install.sh"
|
|
35
|
+
],
|
|
36
|
+
"bin": {
|
|
37
|
+
"ecc_infisense-install": "install.sh"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"postinstall": "echo '\\n ecc_infisense installed!\\n Run: ./install.sh\\n Docs: http://172.16.40.222/sunchaoyue/ecc-infisense\\n'",
|
|
41
|
+
"lint": "markdownlint '**/*.md' --ignore node_modules",
|
|
42
|
+
"test": "node scripts/ci/validate-agents.js && node scripts/ci/validate-commands.js && node scripts/ci/validate-rules.js && node scripts/ci/validate-skills.js && node scripts/ci/validate-hooks.js && node scripts/ci/validate-version-sync.js && node scripts/ci/validate-cross-references.js && node tests/run-all.js"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"markdownlint-cli": "^0.47.0"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Agent Usage Guide
|
|
2
|
+
|
|
3
|
+
## When to Delegate
|
|
4
|
+
|
|
5
|
+
Use agents for: multi-file operations, component design, plugin analysis, release management.
|
|
6
|
+
Do NOT delegate: single-file edits, simple tasks where you have full context.
|
|
7
|
+
|
|
8
|
+
## Agent Selection
|
|
9
|
+
|
|
10
|
+
| Agent | Use For |
|
|
11
|
+
|-------|---------|
|
|
12
|
+
| `@component-designer` | Design new components, analyze existing ones, rename for clarity |
|
|
13
|
+
| `@plugin-inspector` | Scan directories, generate categorized component index |
|
|
14
|
+
| `@release-executor` | Git commit workflows, npm publish, version status |
|
|
15
|
+
|
|
16
|
+
## Coordination Patterns
|
|
17
|
+
|
|
18
|
+
- Sequential: design components → create → release
|
|
19
|
+
- `/infi-component-creator` delegates to `component-designer`
|
|
20
|
+
- `/infi-ecc-helper` delegates to `plugin-inspector`
|
|
21
|
+
- `/infi-release` delegates to `release-executor`
|
|
22
|
+
|
|
23
|
+
## Best Practices
|
|
24
|
+
|
|
25
|
+
1. Always include file paths, error messages, or design constraints
|
|
26
|
+
2. Be specific: "Analyze agents/ for orphan components" not "analyze project"
|
|
27
|
+
3. Share results between agents in multi-agent workflows
|
|
28
|
+
4. Agent output is a starting point; refine with follow-ups
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Development Workflow
|
|
2
|
+
|
|
3
|
+
## Core Cycle
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Edit → Compile-Check → Test → Commit (iterate)
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
1. Plan before implementing any non-trivial change
|
|
12
|
+
2. After every code edit, verify it compiles
|
|
13
|
+
3. Review your own code before committing
|
|
14
|
+
4. Use `/infi-release git-update` to commit with conventional commits
|
|
15
|
+
|
|
16
|
+
## Always Compile-Check After Edits
|
|
17
|
+
|
|
18
|
+
- After every code edit, verify it compiles
|
|
19
|
+
- Do not accumulate multiple edits without checking
|
|
20
|
+
- Quick check: `g++ -std=c++20 -fsyntax-only -Wall -Wextra file.cpp`
|
|
21
|
+
|
|
22
|
+
## Workflow Rules
|
|
23
|
+
|
|
24
|
+
- Never commit without tests
|
|
25
|
+
- Never push without verification
|
|
26
|
+
- Keep commits atomic (one logical change)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Git Workflow Conventions
|
|
2
|
+
|
|
3
|
+
## Conventional Commits
|
|
4
|
+
|
|
5
|
+
Format: `<type>(<scope>): <subject>`
|
|
6
|
+
|
|
7
|
+
| Type | Use |
|
|
8
|
+
|------|-----|
|
|
9
|
+
| `feat` | New feature |
|
|
10
|
+
| `fix` | Bug fix |
|
|
11
|
+
| `docs` | Documentation |
|
|
12
|
+
| `refactor` | No behavior change |
|
|
13
|
+
| `test` | Tests |
|
|
14
|
+
| `chore` | Build, CI, tooling |
|
|
15
|
+
| `perf` | Performance |
|
|
16
|
+
|
|
17
|
+
Subject rules: lowercase, no period, imperative mood, max 72 chars.
|
|
18
|
+
Body explains **why**, not what. Breaking changes: `!` after type + `BREAKING CHANGE:` footer.
|
|
19
|
+
|
|
20
|
+
## Atomic Commits
|
|
21
|
+
|
|
22
|
+
One logical change per commit. If you can say "X and Y", make two commits.
|
|
23
|
+
|
|
24
|
+
## Branch Naming
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
feature/<issue-id>-<short-description>
|
|
28
|
+
bugfix/<issue-id>-<short-description>
|
|
29
|
+
hotfix/<issue-id>-<short-description>
|
|
30
|
+
release/<version>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Pre-Push Checklist
|
|
34
|
+
|
|
35
|
+
- [ ] Compiles without warnings (`-Wall -Wextra -Werror`)
|
|
36
|
+
- [ ] All tests pass
|
|
37
|
+
- [ ] New code has test coverage
|
|
38
|
+
- [ ] clang-format applied
|
|
39
|
+
- [ ] No debug prints or commented-out code
|
|
40
|
+
|
|
41
|
+
## Protected Branches
|
|
42
|
+
|
|
43
|
+
- `main`: never force push, all changes via PR, requires CI + review
|
|
44
|
+
- `develop`: never force push, feature branches merge here
|
|
45
|
+
- Feature branches: force push OK, rebase on develop, delete after merge
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Hook Development Guidelines
|
|
2
|
+
|
|
3
|
+
## Protocol
|
|
4
|
+
|
|
5
|
+
- Input: JSON from stdin (event, files, context)
|
|
6
|
+
- Output: JSON to stdout with `status`: `"pass"`, `"warn"`, or `"block"`
|
|
7
|
+
- Human messages via stderr (`log()` function)
|
|
8
|
+
- Exit codes: 0 = pass, 1 = hook error, 2 = intentional block
|
|
9
|
+
|
|
10
|
+
## Performance
|
|
11
|
+
|
|
12
|
+
| Hook Type | Max Duration |
|
|
13
|
+
|-----------|-------------|
|
|
14
|
+
| Synchronous (post-edit) | 5 seconds |
|
|
15
|
+
| Asynchronous (post-build) | 30 seconds |
|
|
16
|
+
| Pre-commit | 10 seconds |
|
|
17
|
+
|
|
18
|
+
Only check changed files, not the entire project. Cache results between invocations.
|
|
19
|
+
|
|
20
|
+
## Error Handling
|
|
21
|
+
|
|
22
|
+
A hook's internal failure must never block the developer. On crash: exit 0, log error.
|
|
23
|
+
Only exit 2 for intentional policy violations.
|
|
24
|
+
|
|
25
|
+
## Testing
|
|
26
|
+
|
|
27
|
+
Test hooks with mock JSON input before deploying:
|
|
28
|
+
```bash
|
|
29
|
+
cat mock-input.json | python3 hooks/my-hook.py
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## File Patterns
|
|
33
|
+
|
|
34
|
+
Source: `*.cpp`, `*.c`, `*.cxx`, `*.cc`
|
|
35
|
+
Headers: `*.h`, `*.hpp`, `*.hxx`
|
|
36
|
+
Templates: `*.inl`, `*.tpp`
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PreCompact hook — Save state before context compaction.
|
|
5
|
+
*
|
|
6
|
+
* When Claude Code compacts the context window, important state can be lost.
|
|
7
|
+
* This hook persists the current session state (build config, recent test
|
|
8
|
+
* results, and pending tasks) so it can be restored after compaction.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const {
|
|
13
|
+
readStdinJson, log, output,
|
|
14
|
+
getSessionsDir, ensureDir, getSessionIdShort,
|
|
15
|
+
getDateTimeString, getProjectName, runCommand, readFile, writeFile,
|
|
16
|
+
} = require('../lib/utils');
|
|
17
|
+
|
|
18
|
+
function detectBuildConfig() {
|
|
19
|
+
const config = {};
|
|
20
|
+
const cmake = runCommand('cmake --version');
|
|
21
|
+
if (cmake.success) {
|
|
22
|
+
const match = cmake.output.match(/cmake version ([\d.]+)/);
|
|
23
|
+
config.cmakeVersion = match ? match[1] : 'unknown';
|
|
24
|
+
}
|
|
25
|
+
const buildDirs = ['build', 'cmake-build-debug', 'cmake-build-release', '_build'];
|
|
26
|
+
const fs = require('fs');
|
|
27
|
+
for (const d of buildDirs) {
|
|
28
|
+
if (fs.existsSync(d) && fs.statSync(d).isDirectory()) {
|
|
29
|
+
config.buildDir = d;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return config;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function main() {
|
|
37
|
+
const data = await readStdinJson();
|
|
38
|
+
|
|
39
|
+
const sessionsDir = ensureDir(getSessionsDir());
|
|
40
|
+
const sessionId = getSessionIdShort('default');
|
|
41
|
+
const stateFile = path.join(sessionsDir, `pre-compact-${sessionId}.json`);
|
|
42
|
+
|
|
43
|
+
const existingState = (() => {
|
|
44
|
+
const raw = readFile(stateFile);
|
|
45
|
+
if (!raw) return {};
|
|
46
|
+
try { return JSON.parse(raw); } catch { return {}; }
|
|
47
|
+
})();
|
|
48
|
+
|
|
49
|
+
const state = {
|
|
50
|
+
...existingState,
|
|
51
|
+
timestamp: getDateTimeString(),
|
|
52
|
+
project: getProjectName(),
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
buildConfig: detectBuildConfig(),
|
|
55
|
+
compactionCount: (existingState.compactionCount || 0) + 1,
|
|
56
|
+
env: {
|
|
57
|
+
cc: process.env.CC || null,
|
|
58
|
+
cxx: process.env.CXX || null,
|
|
59
|
+
cmakeGenerator: process.env.CMAKE_GENERATOR || null,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
writeFile(stateFile, JSON.stringify(state, null, 2));
|
|
64
|
+
|
|
65
|
+
log(`[infisense:pre-compact] Session state saved (compaction #${state.compactionCount}).`);
|
|
66
|
+
log(`[infisense:pre-compact] Build dir: ${state.buildConfig.buildDir || 'not detected'}`);
|
|
67
|
+
log(`[infisense:pre-compact] Project: ${state.project || 'unknown'}`);
|
|
68
|
+
|
|
69
|
+
output(data);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
main().catch(() => process.exit(0));
|